Skip to content

Commit e4bc82a

Browse files
docs: add Kakeya Inference Engine Build Skill (SOP) + review fixes
Distills the full KIE build journey (v0.4 -> KIE-v1.x -> KIE-v2 -> v0.5-cuda) into an actionable SOP: architecture + code map, CUDA/MLX run procedures (incl. the Vast.ai SSH-key PEM reconstruction + tiny-disk gotchas), milestone roadmap, hard-won bugs+fixes table, engineering workflow, and the validation/honesty standards (do NOT validate the engine on a model without trained f_theta/ proposer; gemma-4 S5 free-lunch caveat; decode-speed needs the vLLM runtime). Reviewed against ADR 0015 + reports + code; fixed: KIE-v1.1 N=16 (not N=24; N=24 is v1.1.x chunk-tuning), added KIE-v1 #135 to the PR stack, corrected v0.4 throughput bound (~1.79x committed / up to ~2.2x co-located), fixed broken §8 path, clarified v0.5 product concurrency (N=70 KakeyaVLLM) vs eager N=75, and reconciled the 'on vLLM' interim vs bounded-KV-native north star. Co-authored-by: FluffyAIcode <FluffyAIcode@users.noreply.github.com>
1 parent 6bde294 commit e4bc82a

1 file changed

Lines changed: 269 additions & 0 deletions

File tree

Lines changed: 269 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,269 @@
1+
# Kakeya Inference Engine — Build Skill (SOP)
2+
3+
**Audience / when to use this skill.** Read this before building, extending,
4+
benchmarking, or *validating* any part of the Kakeya Inference Engine (KIE) — on
5+
CUDA or Mac/MLX. It distills the full build journey (v0.4 → KIE-v1.x → KIE-v2 →
6+
v0.5-cuda) into: what the engine is, where the code lives, how to run/benchmark
7+
it, the milestone roadmap, the hard-won bugs+fixes, and — most important — the
8+
**validation honesty standards** (the rules that keep claims defensible).
9+
10+
> If you only read one section, read **§7 Validation & honesty standards**. The
11+
> most expensive mistakes in this project were *overclaims*, not bugs.
12+
13+
---
14+
15+
## 1. North star (governs everything)
16+
17+
The Kakeya Inference Engine is a **product-grade inference engine whose goal is to
18+
replace vLLM**, with **Kakeya Attention as its native, first-class attention
19+
algorithm**. It is **not** a research script, **not** a technique bolted onto HF
20+
transformers, and **not** "vLLM with a different cache". The whole engine
21+
(prefill, KV management, admission/scheduling, kernels) is designed
22+
**bounded-KV-native**: the full history is never resident; evicted context is
23+
reconstructed on demand. Authoritative source: `docs/adr/0015-kakeya-attention-and-engine-substrate.md`
24+
and `docs/design/kakeya-inference-engine-architecture.md`.
25+
26+
### Kakeya Attention (the algorithm — one primitive)
27+
28+
**sink+window bound + f_θ KV-projection + dLLM-proposer restoration, taken as one
29+
primitive.** It is a peer / drop-in replacement for eager attention,
30+
FlashAttention, vLLM PagedAttention, SGLang RadixAttention. Those keep the *whole*
31+
KV (memory grows with the conversation); Kakeya Attention bounds *how much* is
32+
resident and **reconstructs evicted context on demand** (proposer + f_θ), so the
33+
resident footprint does not grow with the session.
34+
35+
- **Compute axis**: composable with FlashAttention (a flash kernel can compute a
36+
Kakeya window).
37+
- **Storage axis**: composable with paged/radix stores (they can hold the bounded
38+
window).
39+
- **The Kakeya-only axis**: the *total itself* is bounded. Cost = restoration
40+
compute (a proposer forward at prefill).
41+
42+
---
43+
44+
## 2. Architecture & where the code lives
45+
46+
| Component | Role | Code |
47+
| --- | --- | --- |
48+
| **AR verifier** (Gemma-4 26B-A4B, frozen) | the model being served; carries recall | `inference_engine/v04/dlm_restored_verifier.py`, `build_restored.py` |
49+
| **dLLM proposer** (DFlash) | reconstructs evicted K/V (restoration) | `inference_engine/v04/dflash_drafter.py`, `cross_model_dlm_verifier.py` |
50+
| **f_θ projection** | trained map from proposer hidden → verifier K/V | `inference_engine/v04/f_theta.py`; training: `docs/design/k3-f-theta-training-pipeline.md` |
51+
| **KV capture / merge / compress** | capture own K/V at prefill; pack/quantize | `inference_engine/v04/kv_capture.py`, `kv_merge.py`, `kv_compressor.py` |
52+
| **Engine runtime** (KIE-v1.x) | chunked restoration prefill + bounded-KV decode | `inference_engine/engine/kakeya_engine.py` |
53+
| **Admission / bounded-KV math** | peak-window admission, concurrency ceiling (pure stdlib) | `inference_engine/engine/admission.py` |
54+
| **Quantized attention** | tiled online-softmax over int8 KV (no bf16 transient) | `inference_engine/engine/quant_attention.py` |
55+
| **KakeyaVLLM (v0.5 entrypoint, KIE-v2)** | Kakeya window **on the vLLM runtime** | `inference_engine/engine/kakeya_vllm.py` |
56+
| **MLX backend** | Apple-Silicon port (`v0.4-mac`) | `inference_engine/backends/mlx/*` |
57+
| **gRPC session runtime** | session-bound serving (ADR 0008) | `inference_engine/session/*`, `inference_engine/server/*` |
58+
59+
**Two engine substrates exist — know which you're touching:**
60+
1. **`KakeyaEngine`** (`engine/kakeya_engine.py`) — the eager HF-transformers
61+
research/feasibility substrate. Wins the **memory/concurrency** axis (N=75 @62k,
62+
recall 1.0) but decode speed is weak (eager 26B-MoE forward dominates). **Never
63+
ship or benchmark this as "Kakeya performance"** — it is a correctness probe.
64+
2. **`KakeyaVLLM`** (`engine/kakeya_vllm.py`) — the **product** path: Kakeya's
65+
bounded window **on vLLM**, inheriting vLLM's (Apache-2.0) fused-MoE Triton
66+
kernel + CUDA graphs + continuous-batching scheduler. This is the v0.5-cuda
67+
release artifact.
68+
69+
> **Not a contradiction with §1's "not vLLM with a different cache".** The
70+
> *north-star* engine is bounded-KV-native and does not live inside vLLM.
71+
> `KakeyaVLLM` (KIE-v2 / v0.5) is the **pragmatic interim**: rebuilding vLLM's
72+
> fused-MoE + graphs + scheduler from scratch was attempted (KIE-v1.1.z2) and
73+
> shown to be a multi-week kernel project, so v0.5 wins the **decode-speed axis
74+
> now** by running Kakeya Attention *on* vLLM. ADR 0015 reconciles this
75+
> explicitly: vLLM's runtime is inherited; Kakeya owns the bounded-KV attention
76+
> layer; the native bounded-KV engine matures alongside.
77+
78+
---
79+
80+
## 3. Platforms & how to run
81+
82+
### 3.1 CUDA (Vast.ai H200) — the primary benchmark platform
83+
84+
GPU access is via SSH to a Vast.ai instance. Connection details live in injected
85+
secrets: `vast_ssh_host`, `VAST_SSH_PORT`, `VAST_SSH_USER`, `vast_ssh_key`. The
86+
**host/port changes between sessions** — the user supplies a fresh
87+
`ssh -p <port> root@<host>` each time; trust the user's latest details over the
88+
stale env vars.
89+
90+
> **GOTCHA — the SSH key's newlines are collapsed.** `vast_ssh_key` is stored as a
91+
> single line (PEM newlines stripped) → `ssh` fails with `error in libcrypto`. You
92+
> MUST reconstruct a valid PEM before use:
93+
> ```python
94+
> import os, re
95+
> k = os.environ["vast_ssh_key"]
96+
> b, e = "-----BEGIN OPENSSH PRIVATE KEY-----", "-----END OPENSSH PRIVATE KEY-----"
97+
> body = re.sub(r"\s+", "", k.split(b,1)[1].split(e,1)[0])
98+
> pem = b + "\n" + "\n".join(body[i:i+70] for i in range(0,len(body),70)) + "\n" + e + "\n"
99+
> open("/tmp/vk","w").write(pem); os.chmod("/tmp/vk",0o600)
100+
> ```
101+
> Validate with `ssh-keygen -y -f /tmp/vk`. Then `ssh -i /tmp/vk -p <port> root@<host>`.
102+
103+
> **GOTCHA — disk is often tiny.** Some instances have ~4 GB free on the overlay
104+
> (`/workspace`, `/root`); the multi-TB devices shown by `df` are bind-mount
105+
> artifacts (NVIDIA libs, `/etc/hosts`), **not usable dirs**. Check
106+
> `findmnt`/writable space before assuming you can download a 26B model (~52 GB).
107+
> A pre-existing venv with vLLM is usually at `/root/venv-vllm`; HF cache under
108+
> `$HF_HOME` (e.g. `/workspace/.hf_home`). Set `HF_HUB_OFFLINE=1` to use cached models.
109+
110+
Provisioning helper: `scripts/research/run_on_vast.sh` (creates `.venv-vast`,
111+
installs CUDA torch + transformers, verifies GPU). Run scripts on the host with
112+
`PYTHONPATH=.:sdks/python`.
113+
114+
### 3.2 Mac / MLX (`v0.4-mac`)
115+
116+
MLX runs only on Apple Silicon; the cloud agent reaches a Mac M4 via the **Mac
117+
bridge** (`docs/design/mac-bridge-cloud-agent-access.md`, `docs/mac-bridge.md`).
118+
Port lessons: `docs/mlx-port-lessons.md`.
119+
120+
### 3.3 Key benchmark / test entrypoints
121+
122+
| Goal | Command |
123+
| --- | --- |
124+
| vLLM vs Kakeya-on-vLLM (KIE-v2 / v0.5) | `scripts/research/vllm_multitenant_parallel_bench.py --sliding-window 68` |
125+
| KIE eager engine throughput/concurrency | `scripts/eval/kakeya_engine_throughput_eval.py` (`--quant-attn`, `--compile-attn`, `--decoupled`) |
126+
| CUDA multi-tenant feasibility probe | `scripts/research/k3_cuda_multitenant_parallel_bench.py` |
127+
| MLX batched multi-tenant | `scripts/research/mlx_batched_multitenant_bench.py` |
128+
| Admission math unit tests | `pytest tests/inference_engine/engine/test_admission.py` |
129+
| v0.5 wrapper config unit tests | `pytest tests/inference_engine/engine/test_kakeya_vllm.py` |
130+
131+
---
132+
133+
## 4. Milestone roadmap & current status
134+
135+
| Code | What | Status |
136+
| --- | --- | --- |
137+
| **v0.4-cuda / v0.4-mac** | restored Gemma-4 verifier + fused DFlash spec-decode | shipped — CUDA fused **1.79× AR** (committed scorecard); up to **~2.062.20× co-located** (ADR 0014). MLX **AR parity (~0.931.05× AR)** — a memory win, not a Mac speed win |
138+
| **KIE-v1** (#135) | engine core: chunked restoration prefill + bounded-KV decode + peak-window admission | done (core); concurrency gated on v1.1 |
139+
| **KIE-v1.1** (#136) | realize the bound at runtime: sliding-window-**evicting** StaticCache, graph capture OFF | done — 62k N=4→**N=16** (recall 1.0) with the evicting cache alone; **N=24** (1.55× vLLM) only after **prefill chunk-size tuning** (1024/512), see §below |
140+
| **KIE-v1.1.x** (#137) | int8/int4 exact-layer KV quant toward N=34+ | partial — recall-safe + halves stored bytes, but **N=34 OOMs** (dequant-on-read transient). The N=16→N=24 chunk-tuning lives here too |
141+
| **KIE-v1.1.y** (#138) | **quantized attention** (tiled online-softmax over int8, no bf16 transient) | done — **N=60 @62k** (peak 111.7 GB), recall 1.0, ~3.9× vLLM's ≈15.5 |
142+
| **KIE-v1.1.z** (#139) | throughput + N=75 | **N=75 MET** (recall 1.0, 126.7 GB, ~4.8× vLLM; ~31 tok/s aggregate); **decode ≥ vLLM NOT met** (eager 26B-MoE wall) |
143+
| **KIE-v1.1.z2** | rebuild fused-MoE + graph forward | **abandoned** — superseded by KIE-v2 (run *on* vLLM) |
144+
| **KIE-v2** (#140) | **Kakeya Attention on vLLM** | decode **≥ vLLM (1.15–1.23×)** @16k, recall 1.0, measured to N=70 — inherits vLLM runtime |
145+
| **v0.5-cuda** (#141) | release `KakeyaVLLM` + consolidated reports | done (gemma-4 instantiation). Product concurrency claim = **`KakeyaVLLM` N→70 @16k** on vLLM; the **N=75 @62k is the *eager* `KakeyaEngine` substrate**, not the v0.5 product path — do not conflate. See §7 for exact validation scope |
146+
| **v0.6** (= ADR 0015 KIE-v1.2) | **restoration backend on full-attention models** (Qwen/Llama): train f_θ/proposer + inject restoration at vLLM prefill + graph-capturable quantized-exact kernel | **planned — the real memory differentiator (~6×)** |
147+
148+
> **N=16 vs N=24 (KIE-v1.1 precaution).** The evicting StaticCache alone at the
149+
> default prefill chunk (2048) tops out at **N=16** @62k; **N=24** required smaller
150+
> prefill chunks (1024/512) and is tracked under KIE-v1.1.x. Don't credit N=24 to
151+
> the evicting cache alone (`docs/reports/kakeya-engine-vs-vllm-h200.md`,
152+
> `docs/design/kakeya-inference-engine-architecture.md` §9).
153+
154+
---
155+
156+
## 5. Hard-won bugs & fixes (don't re-discover these)
157+
158+
| Symptom | Root cause | Fix |
159+
| --- | --- | --- |
160+
| MLX batched decode recall 0.125 | MLX **core kernel** bug for `B>1, L=1` quantized/rope decode (confirmed `0.31.2/0.31.3`) | `L>=2` padded decode workaround (recall 1.0, 0.67× tput); upstream bug, not ours |
161+
| MLX O(T²) throughput collapse | `restored_logits` did a full-sequence forward **per token** | Gap-A: capture restored K/V into native cache at prefill, decode incrementally (`mlx_lm.generate_step`) |
162+
| Eager prefill OOM (16k N=2, 32k N=1) | O(T²) scores + full-vocab logits + redundant forwards | SDPA + `logits_to_keep=1` + bf16 f_θ K/V |
163+
| StaticCache CUDA-graph **segfault** (chunked + long) | gemma-4 has non-graph-capturable ops (windowed `copy_` eviction; data-dependent MoE routing) — **structural** | pre-build StaticCache, `TORCHDYNAMO_DISABLE=1` (run evicting cache eager) |
164+
| `StaticSlidingWindowLayer` `AttributeError: device` | manual cache stacking dropped metadata | copy all metadata attrs in `_stack_caches` |
165+
| int8 exact-layer misclassified as `LinearAttention` | not subclassing `CacheLayerMixin` | lazy factory subclassing `transformers.cache_utils.CacheLayerMixin` |
166+
| `KakeyaLatticePackedCache` `expected last dim 256, got 512` | codec assumed uniform head_dim; gemma-4 full layers = 512, sliding = 256 | `kakeyalattice` v1.6.1 per-layer lazy head_dim (upstream) |
167+
| int8 storage halves bytes but **N=34 still OOMs** | cache `update()` returns **bf16** → each exact layer dequantizes full K/V on read; transients coexist | the real fix is **quantized attention** (KIE-v1.1.y) — attend on int8 without materializing bf16 |
168+
| `torch.compile` attention 6.6× but **0% e2e decode gain** | decode dominated by **eager 26B-MoE full-model forward**, not attention | need fused-MoE + full-forward graph capture → that's vLLM's job → **KIE-v2** |
169+
| fused-MoE port blocked | HF `kernels` incompatible w/ transformers 5.12; vLLM `fused_moe` cross-venv surgery; from-scratch = multi-week | **run Kakeya ON vLLM** instead of rebuilding it (KIE-v2) |
170+
| `KakeyaVLLM` crash on text-only model | unconditional `text_config` nesting (gemma multimodal) breaks Qwen/Llama (`num_attention_heads` missing) | **auto-detect** `text_config` via `AutoConfig`: nested for gemma-4, flat for Qwen/Llama |
171+
172+
---
173+
174+
## 6. Engineering workflow (how this project ships)
175+
176+
- **One milestone = one PR, stacked.** KIE-v1 (#135) → v1.1 (#136) → v1.1.x (#137)
177+
→ v1.1.y (#138) → v1.1.z (#139) → KIE-v2 (#140) → v0.5-cuda (#141), each based on
178+
the previous branch so the diff stays per-task. Branch prefix `AgentMemory/…`.
179+
- **ADR + report discipline.** Every milestone updates `docs/adr/0015-…` milestone
180+
table and a report under `docs/reports/`. Decisions and *honest caveats* are
181+
written down, not just code.
182+
- **Hypothesis-driven, runtime-evidenced.** Never claim a fix from code alone —
183+
reproduce, instrument, measure on the real GPU. Each optimization revealed the
184+
*next* bottleneck (eager prefill OOM → bf16 KV floor → dequant transient → MoE
185+
forward → vLLM runtime). Expect this ladder; don't skip rungs.
186+
- **Pragmatism over heroics.** Python-only workarounds and leveraging existing
187+
libraries (vLLM, kakeyalattice) beat multi-week from-scratch kernels within a
188+
session — *as long as the claim matches what was actually built*.
189+
190+
---
191+
192+
## 7. Validation & honesty standards (READ THIS)
193+
194+
The single most damaging error pattern in this project is **overclaiming a
195+
validation**. Follow these rules rigidly.
196+
197+
### 7.1 What counts as validating "the engine" vs "the plumbing"
198+
199+
- **Engine/algorithm validation** = the actual claim (recall, memory, throughput)
200+
measured **on the release model, through the release code path, exercising the
201+
mechanism being claimed.**
202+
- **Plumbing/smoke test** = "the wrapper constructs, the config is applied, it
203+
generates" — proves the code runs, proves **nothing** about the algorithm.
204+
- **Label every artifact as one or the other.** Never let a smoke test masquerade
205+
as engine validation. (Case study: a Qwen3-4B run of `KakeyaVLLM` was wrongly
206+
presented as "end-to-end validation". It was plumbing-only — see §7.3.)
207+
208+
### 7.2 The Gemma-4 "S5 free lunch" — and why it does NOT generalize
209+
210+
- On **gemma-4-26B-A4B**, recall is **1.0 at `sliding_window=68` with NO
211+
restoration**, because **5 of 30 layers are native full-attention and carry
212+
recall**. So the gemma-4 instantiation (v0.5-cuda) is honest **without a trained
213+
f_θ/proposer** — restoration is *bypassed*, not exercised.
214+
- Therefore the gemma-4 **memory win over vLLM is small (~7% @62k)**: vLLM already
215+
hybrid-bounds the 25 sliding layers, and the 5 full layers dominate both engines.
216+
- **The large bounded-KV win (~6×) requires a FULL-ATTENTION model** (Qwen/Llama,
217+
all layers full), where shrinking the window **without restoration destroys
218+
recall** — so restoration is the *only* way to bound memory at full recall, and
219+
vLLM (no restoration) must keep full KV.
220+
221+
### 7.3 HARD RULE: never validate Kakeya Attention on a model without trained f_θ/proposer
222+
223+
A bounded window **without** trained restoration is **naive truncation, not Kakeya
224+
Attention.** On a full-attention model with no trained f_θ/proposer:
225+
- restoration never runs;
226+
- short prompts (< window) never even trigger eviction → the mechanism is untested;
227+
- long prompts lose recall (expected — that's *why* restoration is needed).
228+
229+
So you **cannot** demonstrate the engine on such a model. The v0.6 work is exactly
230+
"train f_θ/proposer for a full-attention model **then** validate". Until then, the
231+
only defensible engine evidence is gemma-47.2).
232+
233+
### 7.4 Decode-speed honesty
234+
235+
- The **eager `KakeyaEngine`** wins memory/concurrency but is slow at decode
236+
(~2531 tok/s aggregate; the eager 26B-MoE forward dominates). Report decode-only
237+
tok/s **separately from prefill** — the `aggregate_tps_e2e` figure folds in the
238+
sequential 62k prefill and looks like ~2 tok/s, which is a harness artifact, not
239+
the decode rate.
240+
- The **product** decode-speed story is **KakeyaVLLM** (≥ vLLM), because it
241+
inherits vLLM's fused-MoE + CUDA graphs + scheduler. Don't claim product decode
242+
speed from the eager engine.
243+
244+
### 7.5 Checklist before writing "validated" anywhere
245+
246+
1. Did the **release code path** run (not a side script that approximates it)?
247+
2. Was the claim's **mechanism actually exercised** (restoration ran? eviction
248+
triggered? quant attention hit?)?
249+
3. Is it on the **release model**, or are you extrapolating from a proxy? If a
250+
proxy, say so and say what's still unproven.
251+
4. Is recall measured with a **real NIAH/needle test**, not vibes from a short prompt?
252+
5. Is the **artifact labelled** smoke-test vs engine-validation?
253+
6. Are the **caveats** (model-dependence, prefill-vs-decode, untrained components)
254+
in the report, not just the happy numbers?
255+
256+
If any answer is "no", write the weaker, true claim.
257+
258+
---
259+
260+
## 8. Pointers
261+
262+
- North star + algorithm + milestones: `docs/adr/0015-kakeya-attention-and-engine-substrate.md`
263+
- Engine architecture: `docs/design/kakeya-inference-engine-architecture.md`
264+
- KIE-v2 feasibility (decode-cost decomposition): `docs/design/kakeya-vllm-backend-feasibility.md`
265+
- v0.5-cuda scorecard (+ honest §5): `docs/reports/kakeya-inference-engine-v0.5-cuda.md`
266+
- Engine vs vLLM long-context journey: `docs/reports/kakeya-engine-vs-vllm-h200.md`, `docs/reports/kakeya-vs-vllm-longcontext-h200.md`
267+
- MLX port lessons: `docs/mlx-port-lessons.md`
268+
- f_θ training pipeline: `docs/design/k3-f-theta-training-pipeline.md`
269+
- Session capacity / cross-host: `docs/adr/0014-agent-connection-capacity-and-cross-host-topology-tests.md`

0 commit comments

Comments
 (0)