Experimental llama.cpp fork for inference research and development
Experimental llama.cpp fork for inference research and development
This is a highly experimental fork of llama.cpp. Use at your own discretion.
A research and development fork of llama.cpp, providing unique KV cache codecs, inference techniques, and bleeding edge features.
Why pay 3-bit or 4-bit quality for a context length you only sometimes reach? VBR quantizes the KV cache dynamically as your session grows — giving you the highest-quality cache possible at any given depth. It quantizes the cache layer by layer, using our best KV codecs, from the least-sensitive layers to the most-sensitive, and only as far down the ladder as your VRAM and context actually require.
The cache starts at FP16 and stays there until there is real budget pressure; then it degrades one
(layer, side) tensor at a time — first to an aggregate 15.75 bits/value, then 15.51, and so on down the
ladder (f16 → turbo8 → turbo4 → turbo3_tcq → turbo2_tcq → turbo1_tcq), following a per-model price
order measured on KLD panels. For Qwen35 (16 attention layers) that is 160 distinct steps from FP16
down to turbo1_tcq; for Gemma4-31B (60 layers), 600 — the finest-grained quality control we can give
you at every moment of a session.
And because VBR always draws from the best codecs on the ladder, you never have to track KV formats again: new codecs and research roll straight into VBR, so the default cache will always use the best available ladder.
On a dedicated GPU, just run:
llama-server -m model.ggufVBR is the default cache. Codec selection is automatic: models whose complete KV geometry supports Turbo use a turbo4 quality floor, while BailingMoE3/Ling falls back to the classic F16→Q8_0→Q4_0 ladder. VBR derives a KV VRAM budget from whatever is left after weights and compute, advertises the largest context that fits without going below the selected codec's default floor (capped at the model's training length), and degrades tiers on the fly as context fills. The cache is still FP16 until memory pressure actually requires compression.
For maximum context, explicitly use -ct vbr. That deliberate opt-in opens the selected codec's complete
ladder (turbo1_tcq for Turbo, q4_0 for classic) unless you also set --vbr-floor:
llama-server -m model.gguf -ct vbrRun with -v to watch the VBR degrade #… steps fire.
VBR balances three quantities: context length, KV VRAM, and minimum quality. Usually specify at most two and let VBR solve the third:
| You know | Use | VBR determines |
|---|---|---|
| How many tokens you need and how much KV VRAM you can spare | -ct vbr -c N --vbr-vram SIZE |
The highest-quality terminal layer mixture that fits. Explicit -ct vbr leaves the full ladder available. |
| How many tokens you need and the lowest quality you will accept | -c N --vbr-floor TIER |
The safe KV VRAM budget available on the machine. |
| How much KV VRAM you can spare and the lowest quality you will accept | --vbr-vram SIZE --vbr-floor TIER |
The largest fillable context. |
Setting all three usually just over-constrains the same calculation. Pick the two requirements you actually know; VBR can then optimize the remaining dimension instead of receiving three potentially contradictory answers.
| flag | meaning |
|---|---|
-ct vbr (or -ctk vbr / -ctv vbr) |
VBR is already enabled by default. Explicitly selecting it opens the selected codec's full ladder when no --vbr-floor is supplied. Explicitly pinning a side (-ctv q8_0) holds it at fixed bits and never degrades it. Use -ct f16 or another concrete type to opt out of VBR. |
-c |
Cap the context at N tokens; VBR then spends your whole VRAM budget running that window at the highest quality it can, instead of advertising the max floor-tier capacity. E.g. -c 30000 = the best-quality cache that fits a 30k window. |
--vbr-vram |
Explicit KV VRAM budget (e.g. 8G). Default auto = whatever VRAM is left after weights and compute. |
--vbr-codec |
Representation ladder. auto (default) prefers Turbo when every KV layer supports the complete ladder, then falls back to classic for BailingMoE3/Ling. Explicit families are strict. |
--vbr-entry |
Dynamic VBR entry tier. Default f16 preserves maximum quality; t8 (or a lower tier) explicitly trades some quality for lower KV bandwidth and memory from the first token. |
--vbr-floor |
Literal aggregate bits/value floor for dynamic mode. Implicit VBR defaults to t4 (4.125); explicit -ct vbr without this flag uses t1 (1.25). Degrades stop at the last step still ≥ the floor. |
--vbr-budget |
Default dynamic (runtime controller). A tier (t8/t4/t3/t2/t1) or a number instead selects a fixed static tier — no runtime degrades. |
Auto selects the classic ladder for BailingMoE3/Ling models whose head geometry is not supported by TurboQuant:
llama-server -m model.ggufClassic keeps the model's native KV width and uses ordinary Q8_0/Q4_0 codecs; it does not allocate Turbo rotations or interpret Turbo model-price tables. Its generic order is still strictly banded: every movable KV layer reaches Q8_0 before any layer advances to Q4_0. Portable projected prompt artifacts are currently Turbo-only, so classic mode retains live KV but cold-prefills when a live prefix is no longer available instead of restoring that prefix from the host cache.
Requirements: a CUDA or ROCm backend (turbo-typed KV needs the TurboQuant interface; layers whose KV
lands on the CPU fall back to q8_0). Flash attention is required and force-enabled. Dynamic mode uses
unified KV (forced automatically with -np > 1). Context-shift / self-extend and slot/session
save-restore are disabled in dynamic mode (they would snapshot tier-typed KV that can't restore across a
degrade — tier-aware save-restore is planned); context checkpoints stay enabled on hybrid models. Generation stops cleanly when the context
fills. Models without a baked price order use a generic cross-model order.
Standard KV cache quantization treats each value independently. TCQ constrains the quantization indices to follow a 512-state trellis, giving a much larger effective codebook at the same bit rate (with FWHT rotation and context-adaptive norm scaling on top). At the 3-bit setting, the trellis cuts median KL-divergence by ~40% versus scalar quantization while using slightly fewer bits (3.25 vs 3.50 bpv), and lands perplexity on par with an f16 KV cache.
Paper: Closing the Gap: Trellis-Coded Quantization for KV Cache at 2-3 Bits
turbo3 is scalar 3-bit, turbo3_tcq the trellis-coded version at fewer bits — the gap is exactly what
the trellis buys. pp = prefill t/s on a 16K prompt, tg = decode t/s at 16K depth.
| Codec | bpv | PPL | median KLD | pp (t/s) | tg (t/s) |
|---|---|---|---|---|---|
| turbo3 (scalar) | 3.5 | 5.730 | 0.00279 | 1015 | 28.1 |
| turbo3_tcq | 3.25 | 5.668 | 0.00163 | 818 | 26.6 |
The trellis cuts median KLD ~40% (and edges PPL below f16) at fewer bits. Its cost lands in prefill — the Viterbi re-encode drops prompt processing to ~818 t/s vs ~1015 for scalar turbo3; decode is barely affected on a dedicated GPU.
The trellis cost is compute, so it depends on hardware. On dedicated GPUs (e.g. RTX 3090) the fused
tensor-core decode path keeps generation at essentially vanilla / f16 speed (the tg numbers above). On
weaker-compute hardware (e.g. the Strix Halo iGPU) the cost is exposed and the TCQ types can be up to
~40% slower than their scalar counterparts — there, prefer the scalar or higher-bit codecs.
Trained codebooks are included in codebooks/. The defaults are compiled into the CUDA kernels, but you can override them:
TURBO_TCQ_CB=codebooks/3bit/product_aware_iter080.bin \
TURBO_TCQ_CB2=codebooks/2bit/product_aware_iter090.bin \
./build/bin/llama-server -m model.gguf -ngl 99 -fa \
-ctk turbo3_tcq -ctv turbo3_tcqCodebook training scripts are in scripts/tcq_train_*.py.
These are the individual KV cache codecs the fork ships. In practice you rarely pick one by hand — dynamic VBR mixes them per layer automatically and is the recommended default; the codecs below are mainly for testing and comparison.
Measured on Qwen3.6-27B Q6_K at 16K context (18 chunks of the wikitext-2 test set) on an RTX 3090.
Median KL-divergence is versus an f16 KV cache (0 = identical logits); pp is prefill throughput on a
16K prompt and tg is decode throughput at 16K depth. Ordered by KL-divergence (quality) — lower is
better.
| Codec | bpv | PPL | median KLD | pp (t/s) | tg (t/s) |
|---|---|---|---|---|---|
| f16 | 16.0 | 5.683 | 0 (ref) | 1104 | 30.7 |
| q8_0 | 8.5 | 5.698 | 0.00020 | 1050 | 27.4 |
| turbo8 | 8.125 | 5.693 | 0.00020 | 1013 | 28.6 |
| turbo4 | 4.125 | 5.723 | 0.00090 | 1017 | 28.4 |
| q4_0 | 4.5 | 5.705 | 0.00115 | 1033 | 26.9 |
| turbo3_tcq | 3.25 | 5.668 | 0.00163 | 818 | 26.6 |
| turbo3 | 3.5 | 5.730 | 0.00279 | 1015 | 28.1 |
| turbo2_tcq | 2.25 | 5.711 | 0.00561 | 985 | 28.5 |
| turbo2 | 2.5 | 5.964 | 0.01083 | 1013 | 28.2 |
| turbo1_tcq | 1.25 | 6.012 | 0.02633 | 991 | 28.5 |
--mmproj-gpu-swap)On VRAM-constrained GPUs, a speculative context and the vision encoder (mmproj) may not fit in VRAM simultaneously. For example, Qwen3.6-27B Q6_K + MTP uses ~22.6 GiB on a 24 GiB RTX 3090, leaving no room for mmproj's ~1.1 GiB GPU footprint.
--mmproj-gpu-swap solves this by keeping mmproj on CPU at startup, then temporarily unloading MTP or an external draft-dflash sidecar when an image arrives, loading mmproj to GPU for fast encoding (~1-2s instead of 30-60s on CPU), and restoring speculation afterward. MTP is recreated from the target model; an external DFlash sidecar is reloaded from its GGUF.
./build/bin/llama-server -m Qwen3.6-27B-Q6_K.gguf \
--mmproj mmproj.gguf --spec-type draft-mtp \
--mmproj-gpu-swap -ngl 99When combined with auto-fit (no -c flag), the server automatically sizes context to leave room for the swap. With a single slot, it also auto-enables --kv-unified to avoid splitting the KV cache into separate streams, which doubles usable per-slot context.
DeepSeek V4 Flash is much larger than a typical consumer-GPU model, but its routed experts can stay in system RAM while the hot expert tensors are cached in spare VRAM. On a multi-GPU machine, use layer splitting: tensor splitting was substantially slower for this CPU-expert workload even with NVLink.
Start with --fit on --moe-cache auto on both single- and multi-GPU hosts. This is the recommended
adaptive path for large CPU-expert models. It preserves normal placement when the complete model
fits, and otherwise selects canonical CPU experts when the remaining VRAM can form useful cache
pools. Explicit tensor overrides, GPU layers, tensor splits, CPU affinity, and thread counts remain
authoritative.
Leave the other resource knobs unset for the first run. The defaults now:
No open issues yet, or sync has not completed.