AI & ML interests

None defined yet.

Recent Activity

edurdias  updated a Space 3 days ago
capyctl/benchmarks
edurdias  updated a Space 3 days ago
capyctl/README
edurdias  updated a model 3 days ago
capyctl/FrogNano-4B-2609-NVFP4
View all activity

Organization Card
CapyCTL, control what runs next

Run more models than your GPU can hold.

CapyCTL deploys, parks, wakes and switches models on vLLM, SGLang, TensorFold, llama.cpp or any server you describe, on GPU machines you own, behind one OpenAI-compatible endpoint.

v0.1.10 · Apache-2.0 · one binary, written in Rust · Linux x86-64 and ARM64 · NVIDIA GPUs

$ capyctl list deployments
NAME           STATE    READY   REVISION   HOSTS
coding-small   ready    1/1     3          gpu-box
chat-large     ready    1/1     1          workstation
vision-small   parked   0/1     2          gpu-box

Example output. A parked model releases its GPU memory and wakes on the next request for it.

  • More models than memoryMost GPU machines hold one or two models at a time. CapyCTL parks the idle ones and wakes the one a request asks for, making room by parking or stopping an idle model.
  • One endpointOpenAI-compatible chat completions with streaming and tool calls, and decision models answering /v1/systemone with probabilities, behind an API key. Your apps keep one base URL and pick a model by name.
  • Your engines, your weightsRegister the vLLM, SGLang, TensorFold or llama.cpp installation you already have, or any other server from a manifest. Models come from a directory or from the Hub, pinned to a commit when you deploy.
  • Bigger than one GPUSpread one model across the identical GPUs of a machine, or across two machines over a direct link, with each card's memory accounted for.

Quick start

On Linux with an NVIDIA GPU and a vLLM, SGLang or TensorFold environment, or a llama.cpp build:

curl -fsSL https://edurdias.github.io/capyctl/install.sh | sh
capyctl engine add ~/venvs/vllm   # or SGLang, TensorFold, or ~/llama.cpp/build/bin/llama-server
capyctl start standalone

In another shell, deploy a model from the Hub. Three fields are enough:

# qwen3-4b.yaml
name: qwen3-4b
engine: vllm
model: {hf: Qwen/Qwen3-4B-Instruct-2507}
capyctl deploy model --file qwen3-4b.yaml --activate --wait

Any OpenAI client can now send qwen3-4b as the model name (Make a request). To free its GPU memory, run capyctl park deployment qwen3-4b; the next request wakes it. One server can also drive several GPU machines (Run on several machines).

Measured recipes

capyctl-recipes has 38 deployment files, each run through CapyCTL on the hardware it names. Every recipe gives the engine version, the pinned model revision, the commands from capyctl engine add to a first answer, ready times, memory and a capyctl-bench report. Some of them:

Model and checkpoint Engine Machine and memory Decode, one stream More streams
Qwen3.6-35B-A3B, MLX 4-bit, MTP drafts TensorFold 0.6.5 GB10, 32 GiB 164 tokens/s 368 tokens/s at 8 streams
Qwen3.8-27B NVFP4, MTP drafts (EAGLE) SGLang 0.5.21 GB10, 100 GiB limit 24.9 tokens/s 337 tokens/s at 22 streams
Qwen3.8-Flash-Next, MLX 4-bit, MTP drafts TensorFold 0.6.5 GB10, 110 GiB limit 54.7 tokens/s 122 tokens/s at 8 streams
gpt-oss-120b, MXFP4 experts vLLM 0.30.0 GB10, 96 GiB limit 34.2 tokens/s 107 tokens/s at 8 streams
gpt-oss-20b, MXFP4 experts vLLM 0.30.0 GB10, 32 GiB 46.7 tokens/s 195 tokens/s at 8 streams
Nemotron 3.5 Super VL 120B-A12B, NVFP4, LiLiCorr drafts vLLM 0.31.0 GB10, 108 GiB limit 42.7 tokens/s 70.7 tokens/s at 4 streams
Nemotron 3.5 Bolt 74B-A9B, 2-bit GGUF, LiLiCorr drafts, 262k context llama.cpp v0.7.0 GB10, 35 GiB 78.8 tokens/s one request at a time
Nemotron 3.5 Lightning 30B-A3B, MLX 4-bit, MTP drafts TensorFold 0.6.5 GB10, 32 GiB 137 tokens/s one request at a time
Gemma 4 26B-A4B, NVFP4 vLLM 0.30.0 GB10, 32 GiB 30.3 tokens/s 105 tokens/s at 4 streams
FrogNano-4B-2609, BF16 SGLang 0.5.21 RTX 4090 Laptop, 16 GB 62.5 tokens/s 381 tokens/s at 7 streams

Decision models answer POST /v1/systemone with probabilities instead of generating tokens. Clef-Flash on llama.cpp v0.7.0 decides in 203 ms, and basal-2.0-4.5B, run as a custom engine, in 90 ms (one question about a 200-token text, on a GB10).

Rows that serve different checkpoints are not a one-to-one engine comparison; the comparisons below are.

Comparisons

The same model and machine on several engines, on two engine versions, or through CapyCTL against the engine launched directly. Each one states its method and publishes its evidence.

Comparison What it found
Native TP2, direct vs CapyCTL: Qwen3-30B-A3B on 2x RTX A6000, vLLM 0.32.0 and SGLang 0.5.22 Through CapyCTL, throughput was -5.76% to +3.22% of the engine launched directly at 1, 4 and 8 concurrent requests; all 156 requests succeeded.
Concurrency and native batching: Qwen3-4B and Qwen3-30B-A3B on a GB10, SGLang 0.5.22 and vLLM 0.32.0 313 attempts. Concurrency was the strongest lever: short prompts on the 4B reached 1,477 tokens/s on SGLang and 1,653 on vLLM, confirmed three times. Batch and prefill tuning helped some workloads only. Experimental admission builds; CapyCTL's defaults are unchanged.
Qwen3.6-35B-A3B on three engines, GB10, 32 GiB TensorFold with MLX 4-bit and MTP drafts decoded about twice as fast for one stream as vLLM and SGLang with NVFP4 (162 against 77 and 84 tokens/s), and 368 against 180 and 187 tokens/s at 8 streams. vLLM had the fastest prefill up to 2k.
Qwen3.8-27B NVFP4 on three engines, GB10, DFlash2 drafts TensorFold had the highest aggregate at 1 to 8 streams (194 against 136 and 122 tokens/s at 8) and the fastest prefill; SGLang the lowest time to first token at 5 to 8 streams.
Qwen3.8-27B on SGLang: DFlash2 vs MTP/EAGLE, GB10 No single best setting: DFlash2 for 1 to 4 users, MTP/EAGLE for more (344 tokens/s at 22). CapyCTL matched SGLang launched directly.
Nemotron 3.5 Super VL on vLLM, llama.cpp and SGLang, GB10 vLLM won: 34 to 45 tokens/s for one user and about 3,000 tokens/s of prompt processing against 800 on llama.cpp. SGLang 0.5.21 did not start it.
FrogNano-4B NVFP4 on three engines, GB10 vLLM and SGLang decoded 10% to 18% faster; TensorFold had the fastest prefill, used the least memory (10 GiB at 8 streams) and started warm in 5 s.
Six decision models on llama.cpp v0.7.0 and SGLang 0.5.22, GB10 Clef-Flash is the pick: 15 GiB and 203 ms on llama.cpp, within 3 points of Clef 27B on every test. CapyCTL added 12 to 26 ms per request.
TensorFold 0.6.1 to 0.6.5, four upgrade checks, GB10 Throughput stayed within 2% across each upgrade, apart from one slower one-stream round on 0.6.5 and a Nemotron stream 3.4% faster on it. Outputs were identical, apart from the 32k and 128k replies on 0.6.5.

Every report, with its charts, is in the benchmarks Space, and every measured point is in the bench-results dataset.

In this organization

  • benchmarks: the capyctl-bench report of every recipe and comparison, filterable by engine, model and GPU.
  • bench-results: every point of those reports in one table: decode speed, time to first token, prompt processing and memory by prompt length and streams, and decision-model latency and quality.
  • Models with CapyCTL recipes: 27 Hub checkpoints the recipes and comparisons serve, each with a note linking its numbers.
  • FrogNano-4B-2609-MLX-4bit: MLX 4-bit, text only, for TensorFold on NVIDIA GPUs; 319 tokens/s at 8 streams on an RTX 4090 Laptop GPU.
  • FrogNano-4B-2609-NVFP4: NVFP4 with FP8 attention, for vLLM, SGLang and TensorFold; up to 416 tokens/s at 8 streams on a GB10.

The converted checkpoints' cards say what changed from the original and how it was made. capyctl-bench, the benchmark behind all of the above, is a standard-library Python script: point it at any CapyCTL endpoint to measure your own models.

Status

0.1.10 is early software, and breaking changes are possible between minor versions while the version starts with 0. One model can span the identical GPUs of one machine (qualified on two) or two machines over a direct link; larger groups are not qualified yet. CapyCTL is driven by its CLI and a management API, on Linux with NVIDIA GPUs. Parking relies on engine development controls, kept on loopback behind a per-launch key; they are not production-hardened, and a host can opt out. Questions and bug reports go to GitHub. Licensed under Apache-2.0.