# A minimal KV-cache laboratory: build state reuse first

This runnable companion laboratory, version 1.0, was prepared on 2026-10-09.
**It is neither a reproduction of Appendix A's Qwen3-0.6B experiment nor a pretrained language model.**

## What it runs

With a fixed random seed, `kv_lab.py` constructs a three-layer causal Transformer: four Q heads, two KV heads, head dimension eight, RoPE, RMSNorm, a feed-forward network and vocabulary projection. The vocabulary contains 41 integer IDs. There is no tokenizer, external dataset, model download or paid API.

It includes full-prefix caching in 16-token blocks with chained SHA-256, weight and namespace identities and private copies; online softmax; actually packed INT4; and a separate shared-page/copy-on-write simulator.

## Run

Python 3.10 or later is required. The supplied execution record used Python 3.13.5, NumPy 2.3.5 and CPU. If NumPy is installed, run directly. Install it yourself when needed:

```bash
python -m pip install numpy==2.3.5
python -m unittest -v
python kv_lab.py --output my_results.json
```

On macOS/Linux, `OPENBLAS_NUM_THREADS=1 python kv_lab.py --output my_results.json` fixes the BLAS thread count; the supplied record used that setting. Tests check FP64/FP32 tolerances rather than requiring every platform to match the supplied JSON bit for bit. NumPy 2.3.5's supported Python versions depend on the installation environment. Python 3.10 users may use a compatible NumPy version and must record the actual version.

## Predict before inspecting results

1. Two inputs share 42 tokens, while the cache retains only full 16-token blocks. The second input has 47 tokens: hit 32, compute 15, rather than reuse all 42.
2. Splitting the input into two passes without a cache-table lookup is an essential control. It separates execution-shape numerical differences from cache-management bugs.
3. Splicing old document K/V after different content of the same length can be invalid even with unchanged positions. Replaying the document is an exact-repair control; **CacheBlend is not implemented here**.
4. In `PagePool`, let two users share a page, then finish one. It must remain protected until the other finishes. Copy a shared writable tail before branching.
5. Two INT4 codes are actually packed into one byte. One FP32 scale per 16 numbers makes 2,048 numbers occupy 1,024 + 512 = 1,536 bytes. **This is not NVFP4** and excludes Python objects, alignment and workspace.

## Files

- `kv_lab.py`: complete model and cache experiments; writes the result JSON you specify.
- `test_kv_lab.py`: 15 automated tests.
- `results.json`: actual recorded values and environment, not invented examples.
- `tests.txt`: raw output from the recorded test run.
- `requirements.txt`: NumPy version used for that run.
- `SOURCE_NOTES.md`: mechanism references and experiment scope.

Download the executable scripts, requirements and raw records from the article's shared download links, and save them alongside these English instructions. English and Chinese editions use identical executable files and numerical records.

## Deliberately outside scope

There are no real GPU kernels, asynchronous transport, cross-process concurrency, language-quality evaluation, production security isolation, persistent caches or training. `PrefixCache` copying and eviction are fully serial. `PagePool` is an independent lifetime simulator, not `TinyDecoder`'s paged-attention backend. This laboratory does not establish a reproduction of vLLM, FlashAttention, NVFP4, CacheBlend or a cloud service.

Cache weight identity includes SHA-256 of the actual arrays, not just a model name. The local namespace example does not replace production authorization or a secret salt. JSON `run_date` is the record's preparation date. Keep your own execution date, versions and environment when rerunning.
