Instructions to use GenomaLabs-com/kv-cache-eviction-mla with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use GenomaLabs-com/kv-cache-eviction-mla with Transformers:
# Load model directly from transformers import AutoModel model = AutoModel.from_pretrained("GenomaLabs-com/kv-cache-eviction-mla", device_map="auto") - Notebooks
- Google Colab
- Kaggle
File size: 8,635 Bytes
a8d4591 1ba26d6 a8d4591 1ba26d6 aac6c2e 1ba26d6 aac6c2e 1ba26d6 a8d4591 1ba26d6 a8d4591 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 | ---
license: apache-2.0
tags:
- kv-cache
- h2o
- mla
- long-context
- inference-optimization
- deepseek
- kimi
library_name: transformers
---
# KV Cache Eviction for MLA-based Long-Context LLMs
A reference implementation of **H2O-style heavy-hitter + recency KV cache eviction** for transformer architectures that use **Multi-head Latent Attention (MLA)** as introduced in DeepSeek V3 and used in Kimi K2 / K2.6.
Maintained by **GENOMA LABS / research**.
---
## What this is
A drop-in monkey-patch for `DeepseekV3Attention` layers in HuggingFace `transformers` that adds importance-based KV cache eviction at inference time. **No retraining required.** The model loads normally; you call `install_kv_eviction(model, budget=4096)` and from that point eviction runs automatically during generation.
The technique is the canonical H2O recipe from Zhang et al., 2023 (NeurIPS 2023, [arXiv:2306.14048](https://arxiv.org/abs/2306.14048)) adapted to MLA's specific cache layout. Heavy hitters (tokens with the highest accumulated attention mass across all heads and layers) plus a small set of attention-sink tokens at the start and a recency window at the end are retained; the rest are evicted when the cache exceeds the budget.
## Why this matters
HuggingFace's reference MLA implementation caches the **expanded** K/V tensors, not the compressed latent. The cache footprint grows quickly:
| Context length | Full KV cache (canonical 61-layer DeepseekV3 layout) |
|---|---|
| 32K | ~82 GB |
| 128K | ~328 GB |
| 1M | ~2.5 TB |
These numbers exceed available VRAM well before the model's nominal context window is reached. KV cache eviction is the lever that makes long-context inference economically viable on existing dense models without architectural changes or retraining.
| Eviction budget | Cache size (61 layers) |
|---|---|
| `budget=4096` | ~10.2 GB |
| `budget=8192` | ~20.4 GB |
| `budget=16384` | ~40.8 GB |
A 4096-token budget leaves ~70 GB free that would otherwise be cache. That headroom is where you fit longer prompts, larger batch sizes, or just keep more concurrent requests live on the same hardware.
## Compatible architectures
Verified against HuggingFace reference implementations of:
- **DeepSeek V3** and **V3.2** family
- **Kimi K2** and **K2.6** (uses the DeepseekV3Attention layer pattern)
- Any future MLA-based model that subclasses `DeepseekV3Attention`
For non-MLA architectures (standard MHA, GQA, MQA), the same H2O recipe applies, but the cache-management code paths differ and the patch in `src/kv_eviction_mla.py` would need adapting. Pull requests welcome.
## Quick start
```python
from transformers import AutoModelForCausalLM, AutoTokenizer
from kv_eviction_mla import install_kv_eviction, reset_eviction_scores
model_id = "deepseek-ai/DeepSeek-V3" # or moonshotai/Kimi-K2 etc.
model = AutoModelForCausalLM.from_pretrained(model_id, torch_dtype="auto", device_map="auto")
tok = AutoTokenizer.from_pretrained(model_id)
# Patch the model in-place. Eviction runs automatically from this point.
install_kv_eviction(
model,
budget=4096, # max KV tokens kept per layer (excluding sinks + recent)
n_sink=4, # tokens at start always kept
n_recent=512, # tokens at end always kept
evict_every=1, # evict every N generated tokens (1 = every step)
)
# Generate normally
inputs = tok("Your long prompt goes here...", return_tensors="pt").to(model.device)
out = model.generate(**inputs, max_new_tokens=512)
print(tok.decode(out[0]))
# Between independent generations, reset accumulated scores
reset_eviction_scores(model)
```
## How to choose a budget
The right budget depends on your workload's distribution of attention mass. Some recipes from the H2O paper and follow-on literature:
- **Streaming chat / code completion:** `budget=2048, n_sink=4, n_recent=256`. The recent window dominates; the budget acts as a memory of earlier-session context.
- **RAG / long-document QA:** `budget=4096, n_sink=4, n_recent=512`. Larger budget preserves the heavy-hitter facts in the middle of the document.
- **Code review / agent loops over large diffs:** `budget=8192, n_sink=4, n_recent=1024`. More budget for long technical context where the relevant facts can be anywhere.
Stress-test on RULER 128K NIAH or your own task-level evaluation before deploying. Eviction policies are workload-sensitive and the elbow of the quality-vs-budget curve moves with the distribution.
## What this is NOT
- Not a from-scratch attention reimplementation. The forward path of `DeepseekV3Attention` runs as-is; only the cache management changes.
- Not a training-time technique. This applies at inference. Training-time KV compression is a different toolset.
- Not an architecture replacement. This composes with sub-quadratic attention, hybrids, sparse mechanisms, etc. The point is to address the cache-bandwidth bottleneck, which is orthogonal to the choice of attention mechanism.
For background on where this sits in the broader long-context-optimization landscape, see GENOMA LABS' [research handbook on sub-quadratic attention](https://github.com/genoma-labs/subquadratic-research) (link will activate once the handbook flips public; sibling repository to this one).
## What's in this repository
```
src/
kv_eviction_mla.py # the patch + smoke test (277 LOC)
notebooks/
01_smoke_test_walkthrough.md # annotated explanation of the smoke test + memory model
docs/
HOW_IT_WORKS.md # architectural notes: where eviction hooks into the layer
LICENSE # Apache 2.0
README.md # this file
```
## Roadmap
- [x] H2O eviction patch for DeepseekV3Attention (transformers 4.x API)
- [x] Smoke-test on a fake-attention layer (no GPU required)
- [x] **Multi-step validation across 1,000 generation steps × 4 layers** — eviction logic verified, cache stabilizes at expected bound, no overshoot, 913 steps/sec on CPU. See [`notebooks/02_validation_results.md`](notebooks/02_validation_results.md) and [`results/validate_eviction_random_init.csv`](results/validate_eviction_random_init.csv).
- [x] **Real-weights demo on Kimi K2.6 layer 0** — loaded actual published Kimi K2.6 attention weights (101M params, all 7 weights: q_a/b_proj, q_a_layernorm, kv_a_proj_with_mqa, kv_b_proj, kv_a_layernorm, o_proj), ran a single full-prefix forward over 256 tokens on TITAN RTX, applied H2O policy. Result: kept heavy-hitters score 3.66x higher than evicted tokens on real Kimi attention distributions. See [`notebooks/03_kimi_real_weights_demo.md`](notebooks/03_kimi_real_weights_demo.md) and [`results/kimi_layer_eviction_demo.csv`](results/kimi_layer_eviction_demo.csv).
- [ ] **API port to transformers 5.x** — patch currently targets the `DynamicCache.key_cache / value_cache` list API; transformers 5.x uses `DynamicCache.layers[i]`. The eviction logic is unchanged across versions; only the cache-plumbing differs.
- [ ] **RULER 128K benchmark on a real MLA model** with eviction at 4 budget levels — planned target: Kimi K2.6 (BF16) once full-model integration via the 5.x port lands. Will publish CSV + analysis as a sibling repository (`GenomaLabs-com/h2o-eviction-ruler-bench`).
- [ ] SnapKV-style prompt-end compression composed on top of H2O eviction.
- [ ] Port to standard MHA / GQA attention classes (Llama, Qwen, Mistral, Gemma).
Pull requests for any of these are welcome. Issues, especially with reproducible failure cases, are even more welcome.
## transformers version compatibility
Currently aligned with **transformers 4.x** KV cache API. The validation script `scripts/validate_eviction_random_init.py` validates the eviction *logic* against a mock cache and runs on any Python 3.10+ environment with PyTorch — no transformers dependency. Real-model integration (`install_kv_eviction(model, ...)`) on transformers 5.x is on the roadmap; the rework is mechanical (port the cache-slicing code paths from `key_cache[i]` to `layers[i]`) but not yet shipped.
## Citation
If this implementation is useful for your work, please cite the underlying H2O paper:
```bibtex
@inproceedings{zhang2023h2o,
title={H2O: Heavy-Hitter Oracle for Efficient Generative Inference of Large Language Models},
author={Zhang, Zhenyu and Sheng, Ying and Zhou, Tianyi and others},
booktitle={NeurIPS},
year={2023}
}
```
And optionally this implementation:
```
GENOMA LABS / research. KV Cache Eviction for MLA-based Long-Context LLMs.
HuggingFace, 2026. https://huggingface.co/GenomaLabs-com/kv-cache-eviction-mla
```
## License
Apache License 2.0. See [LICENSE](LICENSE).
|