Architecture Overview

Two-panel sci-fi comic: Panel 1 'The Copy-Cat' shows robot R-7 copying from a blackboard, thinking 'But what does it mean?' Caption: Attention: perfect listener, zero understanding. Panel 2 'The Lightbulb Moment' shows R-7 studying a notebook with annotations, exclaiming 'Aha! I finally get it!' Caption: Add an FFN: now it can think.
What You’ll Learn

You’ll learn why a Feed-Forward Network (FFN) is needed after attention, and how attention, FFNs, residual connections, and layer normalization form one reusable transformer block. You’ll also compare encoder-decoder, encoder-only, and decoder-only transformers, including why attention’s O(n2)O(n^2) cost limits sequence length.

Attention Can Gather, But Not Think

Attention has just run on “The cat sat.” The word “sat” now carries blended context from “The” and “cat.” It knows the subject is a cat and the sentence is past tense. But what can it do with that knowledge?

If we skip straight from attention to the output layer, the model can only produce weighted combinations of existing token representations. It can copy and blend, but it can’t compute anything new. It couldn’t combine “subject is singular” + “verb should agree” into a grammatical prediction. It couldn’t learn “after [animal] [past-tense verb], predict a location.” It needs a processing step.

That processing step is the Feed-Forward Network: per-token computation that transforms gathered context into useful features.

  • Attention = “gather information from other tokens” (communication)
  • FFN = “think about what you’ve gathered” (computation)

Step through the animation to see how the FFN processes a single token’s vector:

Input
dmodel
0.5
-0.3
0.8
1.2
-0.1
0.4
-0.6
0.9
× W1
8 → 32
Hidden
dff = 4×
ReLU 17/32 zeroed
× W2
32 → 8
Output
dmodel
input
One token's vector. Each bar is one dimension: 8 shown, hundreds or thousands in a real model.

What to look for: The vector expands to 4x its size, giving ReLU room to create sparse activation patterns (about half the neurons fire). Then it contracts back to the original size. Same shape in, same shape out, but the values have been transformed.

The FFN applies two linear transformations with ReLU in between. ReLU is the simplest non-linear activation: negative values become 0, positive values pass through unchanged.

Why expand then contract? ReLU makes a binary decision on each dimension: keep (positive) or kill (zero). Each dimension is one yes/no question about the input. With only 512 dimensions, you get 512 questions. With 2048 dimensions, you get 2048 questions. More questions means finer-grained analysis, the same reason 20 Questions works better than 5 Questions. (Unlike 20 Questions, the FFN’s “questions” aren’t sequential or adaptive: all 2048 ReLU decisions happen simultaneously and independently, without building on each other’s answers.)

Here’s a tiny worked example. Say the input is [1.0, -0.5] and we expand to 4 dims:

StepValuesWhat happened
Input[1.0, -0.5]2-dim vector
Expand (xW₁+b₁)[0.8, -1.2, 0.3, -0.4]4 different linear combinations of the input
ReLU[0.8, 0.0, 0.3, 0.0]4 yes/no decisions: neurons 1,3 fire; neurons 2,4 don’t
Contract (hW₂+b₂)[0.6, -0.1]Combine the surviving signals back to 2 dims

A different input, say [-0.5, 1.0], would trigger different neurons to fire, producing a completely different pattern. With 4 neurons, there are up to 24=162^4 = 16 possible on/off combinations, so the network can treat up to 16 different input regions differently. With only 2 neurons (no expansion), you’d get just 22=42^2 = 4 regions. In the real model: 220482^{2048} possible patterns vs 25122^{512} without expansion. Exponentially more expressive.

Why contract back? The expansion is temporary scratch space. The rest of the model (attention in the next block, the output layer) expects 512-dim vectors. The contraction reads the ReLU activation pattern and writes a 512-dim summary of what was detected.

The FFN has more parameters than the attention layers in each block: roughly twice as many. Most of a transformer’s weights live in FFN layers, not attention. (Here, dmodeld_{\text{model}} is the vector size that flows through the entire transformer: 512 in the original paper, 8 in our toy model. dffd_{ff} is the expanded FFN width, typically 4×dmodel4 \times d_{\text{model}}.)

Quick Check
Why does the FFN expand the dimension to 4x before contracting back?
Your turn
Choose an answer to check your understanding.

Anatomy of a Transformer Block

Now we have both pieces: attention for communication and FFN for computation. But stacking them naively fails. Each sub-layer completely overwrites its input: the attention output replaces the original token vector, then the FFN output replaces that. After 96 blocks, nothing remains of the original signal. Gradients face the same problem in reverse: they must pass through every transformation, shrinking toward zero. Two helpers fix this:

  • Residual connection: add the sub-layer’s input back to its output (x+sublayer(x)x + \text{sublayer}(x)). The original signal always passes through, even if the sub-layer learns nothing useful. Gradients get a clean shortcut that bypasses the transformation entirely. (Forgot why? Review residual connections.)
  • Layer normalization: normalize the vector to mean ≈\approx 0 and std ≈\approx 1, preventing activations from drifting or exploding across layers. (Forgot why? Review LayerNorm.)

Where you place LayerNorm matters. The original 2017 paper put it after the residual add (Post-LN). This worked for 6 layers, but when researchers tried stacking to 96, training became unstable: gradients had to pass through LayerNorm at every layer on the residual path, and the repeated scaling caused them to vanish. The fix was simple: move LayerNorm before the sub-layer (Pre-LN), so the residual path stays a clean identity with nothing blocking gradient flow. Today, Pre-LN is the default (GPT-2, GPT-3, LLaMA).

The diagram below shows the Pre-LN layout. Toggle to Post-LN to see how the order changes. Click any block for details. (The “Want to Go Deeper?” section at the bottom of this page has an animated gradient flow comparison.)

Sub-layer 1: GatherSub-layer 2: ThinkxLN₁Attn+LN₂FFN+out
Click any block for details
Input / Output
Layer Norm
Transform (Attn / FFN)
Residual Add
Residual arc: carries the original signal around the transform
Pre-LN (GPT-2, LLaMA): Normalize before each transform. The residual path stays clean, making training stable without warmup.

What to look for: Data flows top to bottom through two sub-layers (Gather and Think). Each sub-layer has the same pattern: normalize, transform, add back. The dashed arcs on the right carry the original signal around each transformation.

Worked Example: One Token Through a Block

Trace the word “sat” (from “The cat sat”) through a single transformer block. Step through each operation to see how the vector transforms (4-dim vectors for simplicity):

Input vector for "sat"
x
 0.5
-0.3
 0.8
 1.2
The token vector for "sat" entering the block. 4 dimensions shown (real transformers use 512+).

What to look for: The attention and FFN outputs are small nudges, not dramatic rewrites. The residual adds preserve most of the original signal. After both sub-layers, the output has the same shape as the input but carries richer information. This output feeds into the next block, which repeats the same gather-then-think pattern. A typical model stacks 12 to 96 blocks deep. (Why do we need residual connections at all? They keep gradients healthy in deep networks. Full explanation here.)

Fill in the Blanks
Each transformer block has two sub-layers: first lets tokens communicate, then the lets each token process information independently. Both sub-layers are wrapped with connections so the original signal always passes through.
Fill in every blank, then check your answer.

The Three Transformer Variants

A single transformer block can process any sequence. But different tasks have different constraints. Translation needs to read a full sentence before writing the output. Text generation must work left-to-right, never peeking ahead. Sentence classification needs to see the whole input at once. One architecture can’t optimally serve all three. The choice comes down to a single constraint: which tokens can attend to which?

Attention Mask Comparison
Click a token to highlight its attention row
Bidirectional (Encoder / BERT)
Every token sees every other token
The
cat
sat
on
the
mat
The
cat
sat
on
the
mat
Causal (Decoder / GPT)
Each token sees only itself and earlier tokens
The
cat
sat
on
the
mat
The
×
×
×
×
×
cat
×
×
×
×
sat
×
×
×
on
×
×
the
×
mat
Rows = which token is asking (query). Columns = which tokens it can look at (keys). Darker = higher attention weight.

What to look for: Click “sat” in both matrices. In the bidirectional matrix (encoder), “sat” attends to all 6 tokens, including “on”, “the”, “mat” that come after it. In the causal matrix (decoder), “sat” can only see itself and the two tokens before it. The blocked cells (x) are set to negative infinity before softmax, giving them zero weight. This single constraint is what separates the three variants.


Encoder-Decoder (Original Transformer, T5, BART)

Transformer Architecture

Encoder
×N
Add & Norm
Feed Forward
Add & Norm
Multi-Head
Self-Attention
+
Positional
Encoding
Input
Embedding
Inputs
encoder output
Decoder
Output Probabilities
Softmax
Linear
×N
Add & Norm
Feed Forward
Add & Norm
Multi-Head
Cross-Attention
Add & Norm
Masked Multi-Head
Self-Attention
+
Positional
Encoding
Output
Embedding
Outputs (shifted right)

Click any component to learn more about it

The original 2017 “Attention Is All You Need” architecture uses both columns: an encoder to read the input and a decoder to generate the output.

How it works: The encoder processes the full input with bidirectional self-attention: every word sees every other word. It produces a set of context-rich representations. The decoder generates output one token at a time using causal self-attention (can only see previous output tokens), plus cross-attention that reads from the encoder’s representations.

Cross-attention is the bridge: the decoder’s queries ask “what part of the input do I need right now?”, and the encoder’s keys and values provide the answer.

Cross-Attention in Translation Click a French token to see its attention
ENCODEREnglish ↔The5%cat85%sat10%DECODERFrench →Lechatassis
"chat" attends 85% to "cat", 10% to "sat", 5% to "The". The model learns word alignment from data alone.

What to look for: Click each French token. “chat” attends 85% to “cat”, “assis” to “sat”, “Le” to “The”. The model learns this alignment from training data alone, without explicit word-pairing rules. (Forgot cross-attention? Review it here.)

Best for: Tasks where input and output are different sequences: translation, summarization, speech-to-text. T5 showed this architecture works for almost any NLP task by framing it as text-to-text.

Quick Check
In an encoder-decoder transformer, where do the keys and values for cross-attention come from?
Your turn
Choose an answer to check your understanding.

Encoder-Only (BERT)

Transformer Architecture

Encoder
Contextualized Representations
[CLS] → Classification All → Token tasks (NER)
×N
Add & Norm
Feed Forward
Add & Norm
Multi-Head
Self-Attention
+
Positional
Encoding
Input
Embedding
Inputs

Click any component to learn more about it

What if you don’t need to generate text at all? Drop the decoder, keep only the encoder stack.

How it works: Every token sees every other token through bidirectional self-attention. There’s no causal mask, no generation. The model reads the entire input simultaneously and produces contextualized representations for each token.

This matters for understanding tasks. Consider the word “bank” in two sentences: “I sat by the river bank” vs “I went to the bank to deposit money.” A bidirectional model sees “river” to the right and resolves the ambiguity. A causal model processing left-to-right would have to guess without seeing what comes after.

The [CLS] trick: BERT prepends a special [CLS] token to every input. After passing through all layers, this token’s representation captures a summary of the entire sequence. For classification tasks (sentiment, spam detection), you just feed [CLS]’s final vector through a linear layer and softmax.

The [MASK] trick: During training, BERT randomly replaces ~15% of tokens with [MASK] and learns to predict the original. This “fill in the blank” objective (masked language modeling) forces the model to build deep bidirectional understanding. Deep dive into BERT.

Best for: Classification, named entity recognition, sentence similarity, question answering (extractive).

Limitation: Cannot generate text. There’s no autoregressive mechanism, no way to produce one token at a time.

Quick Check
Why can BERT disambiguate the word 'bank' better than a left-to-right model?
Your turn
Choose an answer to check your understanding.

Decoder-Only (GPT, LLaMA, Claude)

Transformer Architecture

Decoder (GPT-style)
Output Probabilities
Softmax
Linear
×N
Add & Norm
Feed Forward
Add & Norm
Masked Multi-Head
Self-Attention
+
Positional
Encoding
Output
Embedding
Outputs (shifted right)

Click any component to learn more about it

The simplest design: just the decoder stack, no encoder, no cross-attention. One job: predict the next token.

Step through the animation below. At each position, the model can only see the tokens before it (causal attention), and it predicts what comes next:

Next-Token Prediction

Thecatsatonseespredicts"cat"62%"dog"15%"big"8%

Position 1: given "The", predict the next word. All 1 token are processed in parallel during training, but only the last position's prediction matters for generation.

What to look for: At position 1, “The” is all the model has, and it guesses “cat.” At position 2, it sees “The cat” and guesses “sat.” Each step adds one more token of context. The curved arrows show which tokens are visible to the current position: always a growing left-to-right window, never peeking ahead. During training, all four positions are computed in parallel (the causal mask blocks future tokens). During generation, they happen one at a time.

“Decoder-only”? But it clearly understands input. The name is confusing, and Karpathy has argued that “autoregressive transformer” would be more accurate. Step through the animation below to see where the name comes from:

Why "Decoder-Only"?

Original Transformer (2017)
EncoderAdd & NormFFNAdd & NormSelf-AttnK, VDecoderAdd & NormFFNAdd & NormCross-AttnAdd & NormCausal Attn

The original paper has two columns: an encoder (bidirectional attention) and a decoder (causal attention + cross-attention that reads from the encoder).

The model absolutely builds rich representations of its input (it “encodes” in the everyday sense), but architecturally its building block descends from Vaswani’s decoder column, not the encoder. The name is about lineage, not capability.

Why it won: Three reasons:

  1. Simplicity. No encoder-decoder boundary, no cross-attention. One uniform stack of blocks. Fewer design choices means fewer things to get wrong.

  2. Scaling. Decoder-only models scale predictably: more parameters, more data, better performance. The scaling laws discovered by Kaplan et al. (2020) showed smooth, power-law improvements across many orders of magnitude.

  3. Emergent abilities. Next-token prediction turns out to be a surprisingly general objective. To predict what comes next in text, the model must learn grammar, facts, reasoning, and even some degree of world knowledge. GPT-3 showed that a large enough decoder-only model can do translation, summarization, and question answering without being specifically trained for them: just provide a few examples in the prompt (few-shot learning).

Deep dive into GPT.

Quick Check
ChatGPT, Claude, and LLaMA are all which type of transformer?
Your turn
Choose an answer to check your understanding.
Fill in the Blanks
Encoder-only models use attention (every token sees all others), while decoder-only models use attention (each token sees only previous tokens). The encoder-decoder variant uses both, connected by -attention.
Fill in every blank, then check your answer.

Computation Cost

Every token must attend to every other token. That means the attention matrix has n2n^2 entries, and the cost grows quadratically with sequence length. Click through the sequence lengths below to feel the blowup:

Attention Cost: n² Growth

What to look for: Start at 512 tokens (our baseline), then click through to 128,000. At true scale, the first two bars are invisible compared to the last one. Toggle log scale to see all four, then switch back to true scale to feel the real gap. Going from 512 to 128,000 tokens means 62,500x more computation in the attention layer alone.

This quadratic cost is why long-context models are expensive, and why researchers developed efficient attention variants: Flash Attention (exact attention with better memory access patterns), sliding window attention (Mistral, attend to a local window only), and linear attention approximations.

The FFN is cheaper per token (O(n⋅d⋅dff)O(n \cdot d \cdot d_{ff}), linear in sequence length) but uses more parameters. Embedding lookup is trivially cheap (O(n)O(n)).

Quick Check
If a model handles 1,024 tokens and you double the sequence length to 2,048, how does the attention computation change?
Your turn
Choose an answer to check your understanding.

Quick Summary

ConceptWhat HappensIntuition
Feed-Forward NetworkTwo linear layers with ReLU: expand to 4x, then contract backAttention gathers; FFN thinks about what was gathered
Transformer BlockLN -> Attention -> Add -> LN -> FFN -> AddA repeatable “gather then think” unit, stacked N times
Encoder-DecoderEncoder reads full input; decoder generates output token by tokenTranslation: different input and output sequences
Encoder-Only (BERT)Bidirectional attention, no generationUnderstanding tasks: classification, similarity
Decoder-Only (GPT)Causal attention, autoregressive generation”Predict next token” is surprisingly general
O(n2)O(n^2) AttentionAttention matrix grows quadratically with sequence lengthDoubling length = 4x the cost

Learning Checklist
  • I can explain the FFN’s role: attention gathers, FFN thinks, and why the expand-then-contract architecture matters
  • I can describe the two sub-layers in a transformer block and how residual connections and layer normalization wrap each one
  • I know the difference between encoder-only, decoder-only, and encoder-decoder architectures and when each is used
  • I understand why decoder-only architectures dominate modern LLMs
  • I can explain why attention’s O(n2)O(n^2) cost matters and name at least one technique that addresses it
  • I can trace the high-level data flow: embeddings + position -> N transformer blocks -> output

Next: Training

You understand the architecture: what each component does and how they fit together. But a freshly initialized transformer produces random noise. How does it learn? Training →