From text to vectors
A decoder never sees words. A tokenizer first splits text into a sequence of integer IDs \(t_1, t_2, \dots, t_n\) drawn from a vocabulary \(\mathcal{V}\) (typically 32k–256k entries). Each ID indexes a row of a learned embedding matrix, giving every position its starting vector:
At this instant the sequence is just a matrix \(X^{(0)} \in \mathbb{R}^{n\times d}\): one row per token, and every row is context-free — the vector for ball is identical wherever it appears. Two problems must now be solved: the model needs to know where each token sits, and each token's vector must come to reflect what surrounds it.
Position: rotate, don't add
Classic transformers added a learned or sinusoidal position vector, \(x_i^{(0)} = W_E[t_i] + p_i\). Modern decoders mostly use RoPE (rotary position embedding): inside attention, queries and keys are rotated in 2-D planes by an angle proportional to their position,
with per-plane frequencies \(\theta_j = 10000^{-2j/d_k}\). Because rotations compose, the score between positions \(m\) and \(n\) satisfies \(\tilde{q}_m^{\top}\tilde{k}_n = q_m^{\top} R_{\Theta,\,n-m}\, k_n\): attention sees only the relative offset \(n-m\), which is why RoPE generalizes across sequence lengths far better than absolute positions.
The residual stream
The cleanest way to read a decoder is not "layer feeds layer" but as a residual stream: each token keeps a running vector \(x_i \in \mathbb{R}^d\), and every sublayer merely reads from it, computes something, and adds the result back. With pre-normalization (the modern default), one layer \(\ell\) is:
Three consequences fall out of this additive design:
- Identity by default. A sublayer that outputs \(0\) leaves the stream untouched, so gradients flow unimpeded through \(L\) layers — the \(+x\) path is a gradient highway: \(\frac{\partial (x + f(x))}{\partial x} = I + \frac{\partial f}{\partial x}\).
- A shared bus. Anything layer 3 writes into token \(i\)'s vector is readable by layers 4…\(L\). Layers communicate through the stream, not around it.
- Strict locality — except attention. Norms, MLPs, and the final unembedding all act on one row at a time. The only operation in the entire network whose output for token \(i\) depends on token \(j\neq i\) is self-attention.
Normalization, precisely
Before each sublayer, every token vector is rescaled independently. Most current models use RMSNorm:
This keeps the stream's magnitude controlled even as dozens of sublayers keep adding to it (in practice the raw residual norm still grows steadily with depth — normalization happens on the read, not on the stream itself).
+.Self-attention: how tokens share information
Here is the core question: token \(i\) has a vector; tokens \(1,\dots,i\) have vectors; how should \(i\) pull in what it needs? Attention answers with a content-addressed, differentiable lookup. Each token emits three linear projections of its (normalized) stream vector:
Compatibility between a query and every key is a scaled dot product, with a causal mask that forbids looking at the future:
The \(\sqrt{d_k}\) matters: if \(q,k\) have roughly unit-variance i.i.d. coordinates, then \(\mathrm{Var}(q\cdot k)=d_k\); dividing by \(\sqrt{d_k}\) keeps scores \(\mathcal{O}(1)\) so softmax doesn't saturate and gradients survive. The mask's \(-\infty\) becomes exactly \(0\) after softmax — future tokens don't just get small weight, they get none.
Scores become weights by a row-wise softmax, and token \(i\)'s update is the weighted sum of value vectors:
Because \(\alpha_{i,\cdot}\) is a probability distribution (\(\alpha_{ij}\ge 0,\ \sum_j \alpha_{ij}=1\)), \(o_i\) is a convex combination of value vectors — token \(i\)'s update literally lives inside the convex hull of what earlier tokens offer. In one matrix form over the whole sequence:
Rows = query token i (reading).
Cols = key token j (being read).
Multi-head: many conversations at once
A single softmax pattern is one routing scheme. Real layers run \(h\) heads in parallel, each with its own small \(W_Q^{(h)},W_K^{(h)},W_V^{(h)}\) acting in a subspace of size \(d_k = d/h\):
Because each head owns an independent \(n\times n\) pattern, one layer can simultaneously copy the previous token, track a pronoun's referent, park excess attention on a “sink” token, and link a verb to its arguments:
The MLP: computation inside one token
After attention has gathered context into token \(i\)'s vector, the second sublayer processes it — strictly per token. The same two (or three) weight matrices are applied to every position independently; no lane ever touches another here:
A productive way to read this block is as a giant key–value memory: each row of \(W_1\) is a pattern detector (“does the vector currently encode capital-city-of?”), the nonlinearity gates which detectors fire, and the corresponding columns of \(W_2\) are the vectors written back into the stream when they do (“then add Paris-flavored features”). Attention moves information; the MLP transforms and enriches it — lookup and reasoning divided cleanly between the two sublayers.
Layer by layer: what happens to an embedding
Stack \(L\) of these layers and iterate. Formally, each token's trajectory through the network is:
Depth buys composition. One attention layer can only move information one hop: \(j \to i\). Two layers can chain hops — layer 1 writes something about token \(j\) into token \(k\), layer 2 reads it from \(k\) into \(i\). After \(L\) layers, the receptive field is every path of length \(\le L\) through the causal graph, and later attention patterns are computed from vectors that already contain earlier attention's output — routing decisions become context-dependent in a way no single layer can express. The classic example is the induction circuit: a layer-1 previous-token head plus a layer-2 “find where this happened before and copy what came next” head, which is how models complete …A B … A → B for patterns never seen in training.
Empirically, a token's vector migrates through recognizable regimes: early layers sharpen local syntax and detokenization, middle layers build semantic and relational features, late layers rotate the vector toward the output vocabulary — from “what this token is” to “what comes next.” You can watch this with the logit lens: unembed the stream at every layer and see what it would predict.
Out the other end: logits and generation
After the final layer, only the last position matters for generating the next token. Its vector is normalized once more and projected against the unembedding matrix, scoring every vocabulary entry at once; a temperature-scaled softmax turns scores into a sampling distribution:
Sample a token, append it, and run again — that loop is text generation. Naively this re-processes the whole prefix each step, but notice what actually changes: keys and values of past tokens are functions of past stream states, which the causal mask guarantees can never be affected by the new token. So they are computed once and stored in the KV cache:
| component | acts | time (full seq) | time (1 step, cached) | parameters |
|---|---|---|---|---|
| attention (QKᵀ, ·V) | between tokens | O(n² · d) | O(n · d) | 4d² per layer |
| MLP | within token | O(n · d²) | O(d²) | ≈ 8d² per layer |
| norms | within token | O(n · d) | O(d) | d per norm |
| un/embedding | within token | O(n · d · |V|) | O(d · |V|) | |V| · d (often tied) |
The one-sentence summary
A decoder is \(n\) parallel vector pipelines, each repeatedly rewritten in place by two alternating moves: a content-addressed convex mixture over the past (attention — the only cross-token step, made honest by the causal mask), and a shared per-token feature memory (the MLP). Stack the pair \(L\) times so hops compose, then read the last vector against the vocabulary. Everything else — RoPE, RMSNorm, multi-head splits, KV caches — is engineering to make those two moves stable, expressive, and fast.