The exact shapes, layouts, and gotchas that matter when you stop reading and start building.
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ Magic: "GGUF" โ โ Version: 3 โ โ Metadata KV pairs (architecture, โ โ n_layers, n_heads, d_model, ...) โ โ Tensor info (name, shape, offset) โ โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ โ Tensor data (aligned, contiguous) โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
prompt text โ normalize / template subwords from merge table โ if unknown span appears byte fallback tokens 0x00..0xFF โ token IDs + special IDs (BOS / EOS / PAD / <|system|> ...)
token_ids [5] โ E[128000 ร 4096] โ X[5 ร 4096]
(copy 5 rows)Input [batch ร 4096]
โ
RMSNorm
โ
Q = x ร W_Q [4096 ร 4096]
K = x ร W_K [4096 ร 1024] (GQA: fewer K heads)
V = x ร W_V [4096 ร 1024] (GQA: fewer V heads)
โ
Split Heads
Q: [batch ร 32 heads ร seq ร 128]
K: [batch ร 8 heads ร seq ร 128]
V: [batch ร 8 heads ร seq ร 128]
โ
RoPE (applied to Q and K only)
โ
Attention (per head)
โ
Merge Heads (concatenate back)
[batch ร seq ร 4096]
โ
Wo = attn_out ร W_O [4096 ร 4096]
โ
+ Residual (add input back)
โ
RMSNorm
โ
Gate = x ร W_gate [4096 ร 11008]
Up = x ร W_up [4096 ร 11008]
โ
SiLU(Gate) ร Up (element-wise)
โ
Down = result ร W_down [11008 ร 4096]
โ
+ Residual (add input back)
โ
Output [batch ร 4096]4096 hidden dimension
โ
32 Q heads ร 128 dims/head = 4096 โ
8 K heads ร 128 dims/head = 1024 (GQA)
8 V heads ร 128 dims/head = 1024 (GQA)cache[layer][head][position][dimension]
Example for Llama-7B:
32 layers ร 8 KV heads ร max_seq ร 128 floats
At position 5 with 2048 max context:
Total cache per sequence:
32 ร 8 ร 2048 ร 128 ร 2 (K+V) ร 2 bytes (FP16)
= 256 MB
โ 2 GB at batch size 8During decode (generating token N+1):
Only Q is recomputed for the new token.
K and V come from cache.
That's it. That's why decode is fast per-token
but slow in wall-clock: you're only computing
one row of Q, but reading ALL cached K and V
for the attention comparison.
New token โ Q_new [1 ร 32 ร 128]
Cache โ K_all [32 ร 8 ร (N) ร 128] (all previous)
Cache โ V_all [32 ร 8 ร (N) ร 128] (all previous)
Attention: score Q_new against all K_all
blend V_all by those scores
โ one new output rowfor each token_id in 0..131071:
score[token_id] = dot(hidden_state, vocab_row[token_id])
That's literally it.
131,072 dot products of length 4,096.
The highest score wins.1. logits โ the raw scores from lm_head (131,072 numbers) 2. masking โ set banned tokens to -infinity 3. รท temperature โ divide scores to sharpen or flatten 4. top-k โ keep only the K highest, zero the rest 5. softmax โ convert to probabilities (0โ1, sum to 1) 6. top-p โ keep tokens until cumulative prob โฅ p 7. sample โ pick one randomly, weighted by probability (or greedy: just take the highest)
load โ read GGUF, allocate weight memory, parse tokenizer prefill โ forward pass on all prompt tokens, fill KV cache decode โ loop: forward 1 token, score vocab, sample, emit stream โ send each token to the client as it's produced stop โ EOS token, max_tokens, or stop sequence hit destroy โ free KV cache, free weight memory, close connection