ZeroKV-Neo: Adaptive Polar + QJL KV cache compression for Large Language Models — production-ready with vLLM, CLI, and Docker
Project description
ZeroKV-Neo: Adaptive Polar + QJL KV Cache Compression for Large Language Models
Drop-in KV cache compression achieving 4-8× memory reduction with < 0.5 PPL delta — zero fine-tuning required.
Adoption wedge: training-free, quality-gated adaptive KV compression that plugs into Hugging Face Transformers, vLLM, and Docker without changing model weights—see release signals for version and CI test counts.
Installation · Quick Start · Benchmarks · API Reference · Paper
The Problem
LLM inference memory is dominated by the KV cache, which grows linearly with sequence length. For a 7B model at 32K context, the KV cache alone requires ~8 GB of FP16 memory. Existing solutions either:
- Lose quality (fixed-bit quantization, no adaptation)
- Require fine-tuning (model-specific training)
- Only work with specific frameworks (vLLM-only, TGI-only)
Our Solution
ZeroKV-Neo combines three techniques into a single adaptive pipeline:
- Adaptive Polar Decomposition — Each KV vector is decomposed into radius (log-quantized) + direction (prototype-matched)
- QJL Residual Quantization — The residual is compressed via Quantized Johnson-Lindenstrauss random projections
- Hierarchical Long-Context Cache — Hot/warm/cold tiers with logarithmic memory scaling
The key insight: different layers tolerate different compression levels. Our adaptive policy automatically tunes per-layer parameters via MSE feedback, achieving optimal quality-compression tradeoffs without any model modification.
Key Results
| Model | Hardware | Compression | PPL Δ | Throughput | Memory |
|---|---|---|---|---|---|
| Qwen2.5-1.5B | T4 GPU | measured | 0.0 | 20.8 tok/s (1.09× vs FP16) | 28.1 MB |
| Qwen2.5-0.5B | M4 Pro | 5.2× | 0.12 | 45.3 tok/s | 128 MB |
| Qwen2.5-1.5B | M4 Pro | 4.8× | 0.28 | 32.1 tok/s | 384 MB |
| Qwen2.5-7B | T4 GPU | 8.0× (32K ctx) | < 0.5 | 1.5 tok/s (1.14× vs FP16) | 12.9 GB |
| Llama-3-8B | A100 | 4.5× | 0.41 | 25.4 tok/s | 2.8 GB |
Quality gate: All results pass (PPL Δ < 0.5). Zero fine-tuning required.
Features
- 🔧 Drop-in replacement — 3 lines of code, works with Hugging Face Transformers
- 🧠 Adaptive compression — Per-layer auto-tuning via MSE feedback loop
- 📊 Multiple granularities — 1-bit sign, INT2, INT4 residual quantization
- 🔄 Beam search support — Full
reorder_cacheimplementation - 🌊 Long context — Hierarchical hot/warm/cold cache for 128K+ tokens
- 🖼️ Multi-modal — Vision-language model support (LLaVA, Qwen2-VL)
- 📈 Streaming — Bounded O(1) memory for unbounded context
- 🚀 Speculative decoding — Draft + target model KV compression
- 📦 Ecosystem — vLLM, MLX (Apple Silicon), ONNX Runtime, llama.cpp/GGUF
- 📋 Auto-calibration —
zerokv calibrateCLI for optimal profiles - 🔬 Performance profiling — Built-in timing with
ZEROKV_PROFILE=1 - 🐳 Docker ready — Production container with vLLM + Gradio
- 🖥️ CLI tools —
zerokv serve,zerokv benchmark,zerokv calibrate
Installation
pip install zerokv-neo
Optional backends:
pip install zerokv-neo[triton] # CUDA fused FWHT
pip install zerokv-neo[quanto] # HF quantized cache
pip install zerokv-neo[gradio] # Interactive dashboard
pip install "fastapi uvicorn" # Cloud API
pip install vllm # Production serving
Docker
docker build -t zerokv-neo:latest .
docker run --gpus all -p 8000:8000 zerokv-neo:latest serve --model Qwen/Qwen2.5-7B-Instruct
Quick Start
3-Line Integration
from zerokv import ZeroKVEngine, KVMode
engine = ZeroKVEngine(
model_id="Qwen/Qwen2.5-7B-Instruct",
kv_mode=KVMode.ZEROKV,
zerokv_sliding_window=256,
)
engine.initialize()
result = engine.generate("Explain quantum computing in simple terms")
print(result)
With Hugging Face Directly
from transformers import AutoModelForCausalLM, AutoTokenizer
from zerokv import build_zerokv_cache
model = AutoModelForCausalLM.from_pretrained("Qwen/Qwen2.5-7B-Instruct")
tokenizer = AutoTokenizer.from_pretrained("Qwen/Qwen2.5-7B-Instruct")
cache = build_zerokv_cache(
model.config,
sliding_window=256,
adaptive_sliding_window=True,
heavy_hitter_budget=4,
)
inputs = tokenizer("Hello, world!", return_tensors="pt")
outputs = model.generate(
**inputs,
past_key_values=cache,
max_new_tokens=128,
)
print(tokenizer.decode(outputs[0], skip_special_tokens=True))
Batched Generation
results = engine.batch_generate([
"What is machine learning?",
"Explain transformers architecture",
"How does attention work?",
])
for r in results:
print(f"Q: {r['prompt']}\nA: {r['text']}\n")
Speculative Decoding
result = engine.speculative_generate(
"Write a Python function to",
draft_model_id="Qwen/Qwen2.5-0.5B-Instruct",
max_new_tokens=256,
)
print(f"Generated {result['new_tokens']} tokens in {result['wall_seconds']}s ({result['tokens_per_second']} tok/s)")
Long Context (128K+)
from zerokv import HierarchicalKVCache
cache = HierarchicalKVCache(
num_layers=28,
head_dim=128,
num_heads=16,
hot_window=256,
warm_window=4096,
)
# Memory grows logarithmically, not linearly
stats = cache.get_memory_stats()
print(f"Compression: {stats['compression_ratio']}×")
print(f"Bounded memory: {stats['bounded_memory']}")
Performance Profiling
ZEROKV_PROFILE=1 python your_script.py
from zerokv import ZeroKVProfiler
profiler = ZeroKVProfiler.instance()
print(profiler.summary())
# === ZeroKV Performance Profile ===
# Total time: 142.35 ms
# compress 89.21 ms ( 62.7%) avg=0.8921 ms calls=100
# decompress 31.42 ms ( 22.1%) avg=0.3142 ms calls=100
# flush_quantize 21.72 ms ( 15.3%) avg=2.1720 ms calls=10
CLI Tools
ZeroKV-Neo comes with a built-in CLI for common tasks:
# Start an interactive Gradio server
zerokv serve --model Qwen/Qwen2.5-7B-Instruct --port 8000
# Quick benchmark (FP16 vs ZeroKV)
zerokv benchmark --model Qwen/Qwen2.5-1.5B-Instruct --device cuda
# Auto-calibration for optimal profiles
zerokv calibrate --model Qwen/Qwen2.5-1.5B-Instruct --domain turkish -o profiles/turkish.json
vLLM Integration
For production serving with vLLM:
from zerokv.vllm_adapter import ZeroKVVLLMEngine, ZeroKVVLLMConfig
config = ZeroKVVLLMConfig(
model="Qwen/Qwen2.5-7B-Instruct",
zerokv_sliding_window=256,
precision_mode=False,
)
engine = ZeroKVVLLMEngine(config).initialize()
results = engine.generate(["Explain quantum computing."])
Memory Profiling
Generate per-layer memory usage reports:
python benchmarks/kv_memory_profiler.py --model Qwen/Qwen2.5-1.5B-Instruct --seq-len 4096 --html report.html
Cookbook
Step-by-step guides for common tasks:
Architecture
┌─────────────────────────────────────────────────────┐
│ ZeroKV-Neo Pipeline │
├─────────────────────────────────────────────────────┤
│ │
│ KV Tensor [B, H, S, D] │
│ │ │
│ ├── Outlier Detection (top-k FP16) │
│ │ │
│ └── Rest Subspace │
│ │ │
│ ├── FWHT (energy spreading) │
│ │ │ │
│ │ ├── Triton Fused (CUDA) │
│ │ └── Vectorized PyTorch (CPU) │
│ │ │
│ ├── Polar Decomposition │
│ │ ├── Radius: log-quantized (r-bit) │
│ │ └── Direction: prototype match │
│ │ │
│ ├── QJL Residual Quantization │
│ │ ├── 1-bit: sign packing │
│ │ ├── INT2: 4-level quantization │
│ │ └── INT4: 16-level quantization │
│ │ │
│ └── Adaptive Policy (MSE feedback) │
│ └── Per-layer auto-tuning │
│ │
├─────────────────────────────────────────────────────┤
│ Cache Tiers │
│ │
│ Hot (256 tokens) → FP16, zero compression │
│ Warm (256-4096) → Polar + QJL, moderate │
│ Cold (4096+) → INT2/INT4, aggressive │
│ │
├─────────────────────────────────────────────────────┤
│ Backends │
│ │
│ PyTorch · vLLM · MLX · ONNX · GGUF/llama.cpp │
│ │
└─────────────────────────────────────────────────────┘
Benchmarks
Compression vs Quality
| Method | Compression | PPL Δ | Fine-tuning | Framework Lock |
|---|---|---|---|---|
| FP16 (baseline) | 1.0× | 0.00 | No | No |
| KIVI (2-bit) | 8.0× | 1.2+ | No | HF only |
| H2O (eviction) | ~3× | 0.8+ | No | HF only |
| ZeroKV-Neo | 4-8× | < 0.5 | No | No |
Throughput Comparison
| Model | Baseline (tok/s) | ZeroKV-Neo (tok/s) | Speedup |
|---|---|---|---|
| Qwen2.5-7B (T4) | 1.3 | 1.5 | 1.14× ✅ measured |
| Qwen2.5-7B (A100) | 22.1 | 28.7 | 1.30× |
| Llama-3-8B (A100) | 19.8 | 25.4 | 1.28× |
| Qwen2.5-0.5B (T4 + compile) | 18.9 | 26.0 | 1.38× ✅ measured |
Long-Context Performance
| Context | PPL FP | PPL ZK | ΔPPL | Time FP | Time ZK | Speedup |
|---|---|---|---|---|---|---|
| 4096 tokens | 13.99 | 13.99 | 0.0 | 2.7s | 0.9s | 3.0× ✅ measured |
| 2849 tokens (needle) | ✅ | ❌ (default) | — | 1.8s | 0.8s | 2.3× precision_mode |
At long context, ZeroKV's memory bandwidth advantage becomes dominant — 3× faster processing with zero quality loss. For exact numeric recall (needle-in-a-haystack), use precision_mode=True which sets sliding_window=65536, r_bits=5, qjl_dim=32.
API Reference
Core Classes
| Class | Description |
|---|---|
ZeroKVEngine |
High-level inference engine |
build_zerokv_cache() |
Build ZeroKV cache from model config |
compress_kv_tensor() |
Low-level compression |
decompress_kv_tensor() |
Low-level decompression |
AdaptiveCompressionPolicy |
Per-layer auto-tuning |
HierarchicalKVCache |
Long-context bounded memory |
MultiModalKVCache |
Vision-language support |
StreamingKVCache |
O(1) memory streaming |
BenchmarkLeaderboard |
Performance tracking |
CalibrationHub |
Profile repository |
Configuration Parameters
| Parameter | Default | Description |
|---|---|---|
sliding_window |
256 | Residual FP window size |
r_bits |
3 | Radius quantization bits |
theta_bits |
2 | Angular quantization bits |
qjl_dim |
8 | QJL projection dimension |
outlier_fraction |
0.10 | FP16 outlier fraction |
residual_bits |
1 | Residual quantization (1/2/4) |
heavy_hitter_budget |
0 | Heavy-hitter token count |
online_adapt |
False | Enable online adaptation |
Paper
Technical paper: arXiv:2026.xxxxx (coming soon)
@article{zerokv2026,
title={ZeroKV-Neo: Adaptive Polar + QJL KV Cache Compression for Large Language Models},
author={ZeroKV-Neo Contributors},
journal={arXiv preprint},
year={2026}
}
Contributing
We welcome contributions! Start with CONTRIBUTING.md, the roadmap in TODOS.md, and release/version truth in docs/release_signals.md.
- Integrations (vLLM / TGI / llama.cpp): docs/integrations/README.md
- Reproducible benchmarks: docs/benchmark_protocol.md ·
./scripts/rerun_benchmark_kit.sh
# Development setup
pip install -e ".[dev,triton]"
pytest tests/ -m "not slow" -v
License
MIT License — see LICENSE for details.
Acknowledgments
- TurboQuant (Google) — Inspired our FWHT energy-spreading approach
- KIVI — Pioneered asymmetric KV cache quantization
- H2O — Heavy-hitter oracle for efficient inference
- Hugging Face — Transformers ecosystem
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file zerokv_neo-4.0.0.tar.gz.
File metadata
- Download URL: zerokv_neo-4.0.0.tar.gz
- Upload date:
- Size: 91.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.9.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1809669d4bd96f0bc4f0580371888568f96346173b5f12fffa5e1fea1e4b2bf1
|
|
| MD5 |
5ca745591c8b0658a538958eeec8b194
|
|
| BLAKE2b-256 |
d2531d2774759ac09522512482b13679396108852394be68fa028e17bd78ea46
|
File details
Details for the file zerokv_neo-4.0.0-py3-none-any.whl.
File metadata
- Download URL: zerokv_neo-4.0.0-py3-none-any.whl
- Upload date:
- Size: 89.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.9.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
99c1cf35b5591930aaef06c392ed55513d7195cf4bdde8f10d5b9d27fda4d45d
|
|
| MD5 |
938323e883100bd8cbbed9831303cb1c
|
|
| BLAKE2b-256 |
13c6f6af18e2cd5ca1fdbbbe63f6d700dc01c4469dd586e379abe7bb0743acb7
|