The Full Architecture
Everything from days 1–6 clicks together into one stackable block — then you count the parameters of a real model.
Key terms
| Term | Meaning |
|---|---|
| Transformer block | One repeatable unit: attention + feed-forward, each wrapped in a residual and a LayerNorm |
| Residual stream | The running vector each sub-layer reads from and adds back into (day 5) |
| Pre-LN | LayerNorm applied before each sub-layer, then the result is added to the residual |
| Causal mask | A rule that stops a position from attending to later positions |
| Decoder-only | A stack of masked blocks that only look leftward (the GPT shape) |
| Encoder-decoder | An encoder that reads all input plus a decoder that also attends to it |
| GPT-2 small | A 12-block, 768-dim, 124M-parameter reference model |
| d_model | The width of the residual stream (768 in GPT-2 small) |
Assembling one block
On days 3–6 you built the pieces separately: masked self-attention, LayerNorm, the residual add, and the feed-forward network. A transformer block is just those pieces in a fixed order, repeated. Nothing new is introduced here — you only wire them up.
A modern block is pre-LN: normalize first, run the sub-layer, then add the result back into the residual stream. Each sub-layer is a small detour off the residual highway; the highway itself is never overwritten, only added to.
In words: x -> LN -> attention -> add x, then -> LN -> FFN -> add again. The two add steps are the residual connections from day 5; the two LayerNorms are the normalizers from that same day. The attention detour mixes information across tokens; the FFN detour transforms each token on its own (day 6).
Stacking N blocks
One block can only do so much. Depth comes from stacking many identical blocks: the output of block 1 becomes the input of block 2, and so on. Because every block reads and writes the same-width residual stream, they clip together like identical bricks.
The flow start-to-finish: turn token ids into vectors and add positions (days 1–2), push them through N blocks, apply one final LayerNorm, then project each position's vector to a score (logit) for every word in the vocabulary. GPT-2 small uses N = 12.
Causal mask
A language model must predict the next token from the tokens so far — it may never peek at the answer. Self-attention, left alone, lets every position see every other position, including future ones. The causal mask fixes that by blocking any position from attending to positions to its right.
Concretely, before the softmax (day 3) we set the score for every "future" key to negative infinity. Softmax turns those into weight 0. Here 1 marks an allowed attention edge and 0 a blocked one, for four tokens:
| query \ key | t1 | t2 | t3 | t4 |
|---|---|---|---|---|
| t1 | 1 | 0 | 0 | 0 |
| t2 | 1 | 1 | 0 | 0 |
| t3 | 1 | 1 | 1 | 0 |
| t4 | 1 | 1 | 1 | 1 |
Token t1 attends only to itself; t4 attends to all four. The mask is a lower-triangular pattern. Mechanically, a blocked cell's raw score becomes -inf, so softmax gives it weight 0 and it contributes nothing to the weighted sum of values:
masked score -> -inf
softmax(-inf) -> 0
weight 0 => value ignored
Decoder-only vs encoder-decoder
The original 2017 Transformer had two halves: an encoder that reads the whole input and a decoder that writes the output. Most modern LLMs drop the encoder and keep only the masked decoder stack — the shape you just assembled.
| Architecture | Blocks | Masking | Example |
|---|---|---|---|
| Decoder-only | One stack of masked blocks | Causal (each token sees only earlier ones) | GPT family |
| Encoder-decoder | Encoder stack + decoder stack | Encoder: none; decoder: causal + cross-attention | T5, original Transformer |
Cross-attention is the one new idea in the encoder-decoder shape: the decoder runs an extra attention step whose queries come from the decoder but whose keys and values come from the encoder's output — letting the output attend back to the input. Decoder-only models skip it, which is why this course focuses on the GPT shape.
Counting GPT-2 small
"124 million parameters" sounds mysterious until you add it up. GPT-2 small has d_model = 768, N = 12 blocks, a feed-forward width of d_ff = 3072 (the 4× expansion from day 6), a vocabulary of 50257, and a context length of 1024. Every parameter lives in one of a few buckets.
First, one block. The attention sub-layer has four 768 × 768 projections (Q, K, V, and the output projection W_O from day 4), each with a 768 bias. The FFN has the 768 -> 3072 and 3072 -> 768 weight matrices with biases. Two LayerNorms contribute a scale and shift per dimension.
| Sub-layer | Formula | Parameters |
|---|---|---|
| Q, K, V, O projections | 4 × (768×768 + 768) | 2,362,368 |
| 2 × LayerNorm | 2 × (2 × 768) | 3,072 |
| FFN (768 -> 3072 -> 768) | (768×3072 + 3072) + (3072×768 + 768) | 4,722,432 |
| Block total | 7,087,872 |
Now the whole model. The two embedding tables and the final LayerNorm sit outside the blocks. GPT-2 ties the output projection to the token-embedding table (reuses the same weights), so the head adds nothing new.
| Component | Formula | Parameters |
|---|---|---|
| Token embedding | 50257 × 768 | 38,597,376 |
| Positional embedding | 1024 × 768 | 786,432 |
| 12 transformer blocks | 12 × 7,087,872 | 85,054,464 |
| Final LayerNorm | 2 × 768 | 1,536 |
| Output head | tied to token embedding | 0 |
| Total | 124,439,808 |
That last number, 124,439,808, is the "124M" everyone quotes. Notice how much of it is the token embedding — nearly a third — simply because the vocabulary is large. Scaling up the model means mostly growing d_model, d_ff, and N, which quadruple the block cost.
Key takeaways
- A transformer block is days 3–6 wired in a fixed order: pre-LN, attention, residual add, pre-LN, FFN, residual add.
- Depth is just N identical blocks reading and writing the same-width residual stream.
- The causal mask sets future-token scores to
-infso softmax gives them weight0. - Decoder-only (GPT) keeps only the masked stack; encoder-decoder adds cross-attention to the input.
- GPT-2 small = 12 blocks + embeddings + final LayerNorm = 124,439,808 parameters, and the arithmetic is fully checkable.
Checklist
- [ ] Can you draw one pre-LN block from memory, marking both residual adds?
- [ ] Can you explain why blocks stack cleanly (same-width residual stream)?
- [ ] Can you fill in a 4×4 causal mask and say what softmax does to a
-infscore? - [ ] Can you state the one new operation an encoder-decoder adds (cross-attention)?
- [ ] Can you reproduce the 124M parameter count bucket by bucket?