AI & ML interests
None defined yet.
Recent Activity
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.
$ 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/systemonewith 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.

