v1.4.0 — Asymmetric NF4: one robust KV-cache codebook
Asymmetric (zero-point) NF4 — key_nf4_asym / TurboQuantKVCache.robust()
Symmetric NF4 scales each key channel by abs-max about zero, but KV keys carry a large per-channel DC offset — so a symmetric grid wastes ~half its codes. On high-ratio-GQA models this silently collapses generation:
| Qwen2.5-7B (GQA 7:1) | fp16 | NF4 | asym-NF4 |
|---|---|---|---|
| LongBench qasper | 43.8 | 4.7 💥 | 41.9 |
| WikiText-2 ppl | 7.46 | 74.7 | 7.50 |
key_nf4_asym subtracts the per-channel mean, NF4-quantizes the residual, and adds it back — one calibration-free codebook that's near-fp16 on every architecture tested: it ties symmetric NF4 where NF4 already works (Llama-2-7B/13B, Mistral-7B) and rescues the collapse where it doesn't, at no extra bit cost.
cache = TurboQuantKVCache.robust(head_dim=128, n_heads=32) # asym-NF4 + 2% outliers, 4-bit K/VAlso in this release
robust()factory — the recommended calibration-free recipe.- Compact NF4/asym-NF4 storage — per-channel scalars instead of the expanded level table; compression ratio 6.3× → 7.9×.
- Cross-model matrix (
benchmarks/kvquant_matrix/): 4 models × {fp16/NF4/uniform/asym-NF4}, LongBench + WikiText-2, a decision guide, and a TMLR paper draft. ty(Astral type checker) added to CI as an advisory step.
Honest limitation
All 4-bit KV quant — asym-NF4 included — degrades on very-long-generation tasks (e.g. 512-token summarization) as the small residual key error compounds across the decode. This is generation-length-driven and affects MHA and GQA models alike (not a codebook issue).
Full notes: CHANGELOG.md.