Module 03 — KDA I: The Delta-Rule Recurrence¶
Collection: GLM-5.3-Flash Architecture Mastery | Previous: ← Module 02 | Next: Module 04 →
Kimi Delta Attention is the mechanism this course asks you to master most deeply, and the reason is structural: it is the one mechanism where a subtly wrong implementation still produces fluent-looking text, still passes a casual smoke test, and is still a different model. Getting the update rule exactly right — including the order of two operations that do not commute — is the entire module.
Learning objectives¶
By the end of this module you should be able to:
- State what KDA's state matrix represents, and what it explicitly is not.
- Derive the five-step update and expand it into the closed-form recurrence, from memory.
- Explain, using the algebra, why the decay and correction operations cannot be reordered.
- Reproduce a worked numeric example of one update step by hand.
- Explain why the state is per-request serving data, not a checkpoint parameter.
1. What the state matrix stores¶
For one attention head, define query, key, and value vectors and an evolving state matrix:
q_t, k_t ∈ R^{d_k} key/query space
v_t ∈ R^{d_v} value space
S_t ∈ R^{d_k × d_v} the state — an associative memory, NOT a list of past (k, v) pairs
GLM-5.3-Flash configures 64 KDA heads with head dimension 128, so each head maintains a 128 × 128 state matrix. Throughout this module, treat q_t and k_t as already carrying whatever normalization and query scaling the model applies before the recurrence — the update below is the recurrence itself, not the full sublayer (that is Module 04's job).
The critical framing: S_t is a compressed, fixed-size summary of everything seen so far, continuously overwritten — the opposite of a KV cache, which grows by appending and never overwrites. This is the same "recurrent state replaces a growing cache" trade that Mamba/SSM architectures make (MLSys Deep Dives — Lecture 04 works the general version of this argument with concrete state-vs-KV-cache numbers); KDA is one specific, delta-rule instance of that family.
2. The five-step update¶
Let D_t = Diag(α_t) supply a separate decay factor for each key channel — not one scalar decay for the whole state, which is what distinguishes KDA from a coarser gated linear attention variant. Then one step reads as five named operations:
S̃_t = D_t · S_{t−1} (1) FORGET SELECTIVELY — per-channel decay
v̂_t = S̃_tᵀ · k_t (2) PREDICT — what the memory currently says v_t should be
e_t = v_t − v̂_t (3) CORRECT — the prediction error
S_t = S̃_t + β_t · k_t · e_tᵀ (4) WRITE — the correction, scaled by a write gate β_t
o_t = S_tᵀ · q_t (5) READ — the updated memory, queried
Read step (2)–(4) as a sentence, because it is the conceptual heart of the delta rule: "what does my memory already predict for this key, and what remains to be corrected?" An ordinary additive linear-attention memory would instead do S_t = S_{t-1} + k_t v_tᵀ — blindly accumulating associations forever, with no mechanism to notice or fix a stale one. KDA's write is proportional to the error, not to the raw value, which is what lets a single state matrix track a changing world instead of just averaging over its entire history.
3. Expanding to the closed form — and why order matters¶
Substitute (1)–(3) into (4) and expand fully:
S_t = S̃_t + β_t · k_t · e_tᵀ
= S̃_t + β_t · k_t · (v_t − v̂_t)ᵀ [substitute e_t]
= S̃_t + β_t · k_t · v_tᵀ − β_t · k_t · v̂_tᵀ [distribute]
Now expand v̂_tᵀ. Since v̂_t = S̃_tᵀ k_t, its transpose is v̂_tᵀ = k_tᵀ S̃_t — a standard transpose-of-a-product flip:
S_t = S̃_t + β_t · k_t · v_tᵀ − β_t · k_t · (k_tᵀ S̃_t)
= S̃_t − β_t · k_t · k_tᵀ · S̃_t + β_t · k_t · v_tᵀ
= (I − β_t · k_t · k_tᵀ) · S̃_t + β_t · k_t · v_tᵀ
Substituting S̃_t = D_t · S_{t-1} gives the closed form:
┌──────────────────────────────────────────────────────────────────────┐
│ │
│ S_t = (I − β_t · k_t · k_tᵀ) · D_t · S_{t−1} + β_t · k_t · v_tᵀ │
│ │
└──────────────────────────────────────────────────────────────────────┘
This is the KDA recurrence in the order an implementation actually applies it. Now the warning that this whole derivation exists to justify:
IN GENERAL: (I − β k kᵀ) · D ≠ D · (I − β k kᵀ)
because k depends on t and D_t is diagonal but NOT a multiple of the identity —
the two matrices do not commute except in special cases.
Both expressions look almost identical on the page, and a re-implementation that swaps their order will compile, run, and produce a state matrix that is subtly wrong from the very first token with nonzero decay and a nonzero correction — an error that compounds silently across every subsequent step, because each S_t feeds the next. This is precisely why Module 04 requires validating a chunked implementation against both output and final state, not output alone: an order-of-operations bug can leave short-sequence outputs looking nearly correct while the carried state has already diverged.
4. A worked example, by hand¶
Take decay disabled (D_t = I, so S̃_t = S_{t-1}), a 2×2 state, and:
Step 2 — predict. v̂_t = S̃_tᵀ k_t. Since S_{t-1} is diagonal, its transpose equals itself:
Step 3 — correct.
Step 4 — write. S_t = S̃_t + β_t · k_t · e_tᵀ:
k_t · e_tᵀ = [ 1 ] [ 4 1 ] = [ 4 1 ]
[ 0 ] [ 0 0 ]
β_t · k_t · e_tᵀ = [ 2 0.5 ]
[ 0 0 ]
S_t = [ 2 0 ] + [ 2 0.5 ] = [ 4 0.5 ]
[ 0 4 ] [ 0 0 ] [ 0 4 ]
┌──────────────────────────────────────────────────────────────┐
│ S_t = [ 4 0.5 ] │
│ [ 0 4 ] │
│ │
│ The association touched by k_t moved HALFWAY toward the │
│ requested value (4 → nearly the corrected direction, with │
│ an off-diagonal term of 0.5 appearing where k_t and e_t │
│ interact). The unrelated row (second row) is untouched — │
│ k_t = [1, 0] never reads or writes it. │
└──────────────────────────────────────────────────────────────┘
Reproduce this exact example in code as your first correctness check before touching a real model — if your five-line implementation doesn't produce this S_t, do not proceed to Module 04.
5. State vs. checkpoint weights — a distinction that matters for serving¶
CHECKPOINT WEIGHTS RECURRENT STATE S_t
───────────────────────── ──────────────────────────────
W_q, W_k, W_v, decay/write gate params one S_t PER (request, head, layer)
fixed after training changes every token, every request
shared across every request belongs to a specific sequence prefix
loaded once allocated, cached, evicted per-request
S_t is request-scoped serving state, exactly analogous to a conventional KV cache slot — not a training update to the model. This distinction has an immediate, practical consequence for anyone building a serving system: S_t must be tracked, cached across a multi-turn conversation's turns, correctly evicted, and correctly copied or reconstructed on any operation that duplicates or forks a request (speculative rollback, prefix sharing, request migration). Treating it as ephemeral scratch space that "doesn't matter once the forward pass returns" is a serving bug waiting to happen — Module 08 covers exactly this failure mode for speculative decoding rollback, and Module 09 sizes the VRAM budget this state requires across a full multi-GPU deployment.
Checkpoint¶
You should now be able to:
- State what
S_trepresents and why it is not a list of past key/value pairs. - Write the five-step update from memory and expand it into the closed-form recurrence.
- Explain, using the transpose-of-a-product identity, exactly where the closed form comes from.
- State the non-commutativity warning and describe a concrete bug it predicts.
- Reproduce the worked numeric example without referring back to this page.
- Explain why
S_tmust be treated as per-request serving state rather than transient scratch memory.
Ship it¶
This is Stage 2 and the first milestone of the capstone ladder: implement the five-step update as a small FP32 reference (NumPy is sufficient — no GPU, no batching, one head) and reproduce §4's worked example exactly. Then process a short random sequence step by step and print the resulting S_t at each step. Do not proceed to Module 04 until this reference implementation exists and matches the hand-worked example bit for bit (up to floating-point rounding).
Current as of¶
- Timeless: the five-step update, its closed-form expansion, the non-commutativity of the decay and correction operators, and the delta-rule motivation (write the error, not the raw value) — this is the KDA recurrence from the underlying delta-rule/KDA formulation, expressed here in an implementation-friendly operation order.
- Checkpoint-specific: 64 heads, head dimension 128 (so a
128×128state per head) are properties of this checkpoint's configuration.
Next: Module 04 — KDA II: Chunked Parallelism & the Full Sublayer →