Recommended resources
The freely available resources this lesson will direct you to.
- Decoder-Only Transformers, ChatGPTs specific Transformer, Clearly Explained!!!www.youtube.com
- Let's build GPT: from scratch, in code, spelled out.www.youtube.com
- Decoder-Only Transformers: The Workhorse of Generative LLMscameronrwolfe.substack.com
- Meet GPT, The Decoder-Only Transformertowardsdatascience.com
Hello! Welcome to the fifth lesson in our module on LLM and Transformer Fundamentals.
In our last lesson, we tackled a critical piece of the puzzle: positional encodings. We now understand how to inject information about sequence order into our token embeddings, creating position-aware input vectors.
This lesson is about assembling all the pieces. We'll move from individual components to a complete, functional Transformer decoder block, which is the fundamental repeating unit of powerful generative models like GPT. Our learning goal is to diagram a full transformer decoder block, explaining the role of each component (attention, FFN, layer norm, and residuals).
By the end of this lesson, you'll understand how these components work in concert to process information and transform an input sequence into a representation ready for generating the next token.
1. The Anatomy of a Decoder Block
A decoder-only Transformer, like the one used in GPT, is essentially a stack of identical blocks. The output of one block feeds into the input of the next. Let's start by looking at the overall structure of a single block.

As you can see, a decoder block consists of two main sub-layers:
- A Masked Multi-Head Self-Attention layer.
- A Position-wise Feed-Forward Network (FFN).
These core computational layers are wrapped with two other crucial components that enable stable training of deep networks: Residual Connections and Layer Normalization. Let's break each of these down.
2. Component 1: Masked Multi-Head Self-Attention
We have covered this mechanism in detail in previous lessons. Its role within the decoder block is to allow each token to look at all preceding tokens (and itself) and decide which ones are most important for understanding its own meaning in context. The key aspects to remember here are:
- Self-Attention: Queries, Keys, and Values are all derived from the same input sequence.
- Multi-Head: The attention mechanism is run multiple times in parallel with different learned weights, allowing the model to focus on different types of relationships (e.g., syntactic, semantic) simultaneously.
- Masked (Causal): This is the defining feature of a decoder. The attention mask ensures that a token at position t can only attend to tokens at positions 0 to t. It cannot "see into the future." This is essential for the autoregressive, next-token-prediction task.
Andrej Karpathy provides an excellent, code-first explanation of how the attention mechanism is implemented, including the crucial scaling factor and the causal mask.
Let's build GPT: from scratch, in code, spelled out.
This section of Andrej Karpathy's 'Let's build GPT' video provides a deep, practical dive into implementing a single head of self-attention. His explanation of how keys and queries produce data-dependent affinities is particularly insightful.
Watch from 01:01:37 to 01:19:17. Focus on these key points: How queries ('what I'm looking for') and keys ('what I contain') interact via dot products to create data-dependent attention weights. The implementation of the triangular mask to enforce causality. The role of the scaling factor (1/sqrt(head_size)) in stabilizing training, especially with softmax. The concept of 'decoder block' vs. 'encoder block' (the presence or absence of the causal mask).
3. Component 2: Position-wise Feed-Forward Network (FFN)
After the attention sub-layer has aggregated relevant information from across the sequence, the output is passed to a Feed-Forward Network (FFN).
The FFN's role is to provide additional computational depth. You can think of it as giving the model "time to think" about the information it just gathered via attention. Unlike the attention mechanism, which mixes information across the sequence, the FFN processes each token's vector independently and identically.
It's typically a simple two-layer multilayer perceptron (MLP):
- A linear layer that expands the embedding dimension (e.g., from
d_modelto4 * d_model). - A non-linear activation function (like GELU or SwiGLU).
- A linear layer that projects the dimension back down (e.g., from
4 * d_modeltod_model).
Let's build GPT: from scratch, in code, spelled out.
Let's return to Karpathy's video, where he explains the FFN's role and adds it to the model.
Watch from 01:24:13 to 01:26:46. Notice his intuition: attention is for communication, and the FFN is for computation or 'thinking' on that communicated data individually for each token.
The article "Decoder-Only Transformers: The Workhorse of Generative LLMs" also provides a concise description and a clean PyTorch implementation of this component.
Decoder-Only Transformers: The Workhorse of Generative LLMs
This article gives a clear textual explanation of the FFN, including the common practice of expanding the hidden dimension by 4x.
Read the subsection titled 'Feed-Forward Transformation'. It includes a diagram and a PyTorch code snippet that cleanly implements the FFN.
4. Components 3 & 4: Residual Connections and Layer Normalization
Simply stacking attention and FFN layers would make a network that is very difficult to train. Two key innovations, typically used together, solve this: Residual Connections and Layer Normalization.
Residual Connections (Add)
A residual connection is a "shortcut" that adds the input of a sub-layer to its output. The operation is simply x + SubLayer(x).
Its primary purpose is to combat the vanishing gradient problem in very deep networks. By providing a direct path for gradients to flow from the final output back to the initial input, it acts as a "gradient superhighway," dramatically improving training stability.
Let's build GPT: from scratch, in code, spelled out.
Karpathy's visualization of residual connections as a 'gradient superhighway' is one of the best explanations available.
Watch from 01:28:27 to 01:30:29. Focus on his diagram and explanation of how the addition operation distributes gradients, allowing them to flow unimpeded through the main pathway.
Layer Normalization (Norm)
Layer Normalization (LayerNorm) stabilizes the network by ensuring that the inputs to each layer have a consistent distribution (e.g., zero mean, unit variance). Unlike Batch Normalization, which normalizes across the batch dimension, LayerNorm normalizes across the feature (embedding) dimension for each individual sequence in the batch. This makes it independent of batch size and better suited for variable-length NLP tasks.
Let's build GPT: from scratch, in code, spelled out.
Continuing with Karpathy, he gives a practical demonstration of LayerNorm, showing how it differs from BatchNorm and where it's applied in the block.
Watch from 01:32:24 to 01:35:19. Pay close attention to his demonstration of switching the normalization dimension from columns (BatchNorm) to rows (LayerNorm) and his explanation of why LayerNorm doesn't need running buffers like BatchNorm.
5. Putting It All Together: The Pre-Norm Architecture
Now we can assemble the full block. The arrangement of these components matters. While the original Transformer paper used a "Post-Norm" architecture (LayerNorm(x + SubLayer(x))), modern GPT-style models almost universally use a "Pre-Norm" architecture: x + SubLayer(LayerNorm(x)). This has been found to be more stable for training very deep models.
The data flow for a pre-norm decoder block is as follows:
- The input
xis first passed through Layer Normalization. - The normalized output is processed by the Masked Multi-Head Attention sub-layer.
- The output of the attention sub-layer is added to the original input
x(the residual connection). - The result of this addition is then passed through a second Layer Normalization.
- This normalized output is processed by the Feed-Forward Network.
- The output of the FFN is added to the result from step 3 (the second residual connection).
- The final result is the output of the block.
The article "Meet GPT, The Decoder-Only Transformer" provides an excellent visual and code-based comparison of the Post-Norm (used in GPT-1) and Pre-Norm (used in GPT-2/3) architectures.
Meet GPT, The Decoder-Only Transformer
This article highlights a key evolution in Transformer design: the shift from post-normalization to pre-normalization. Your experience with system migrations will make the importance of such design changes for stability and performance very clear.
Read the section 'GPT-2 Implementation: Decoder'. It explicitly contrasts the pre-norm architecture of GPT-2 with the post-norm of GPT-1, providing both a diagram and a PyTorch implementation (DecoderGPT23) that shows the LayerNorm calls happening before the attention and FFN blocks.
Finally, let's look at a complete, clean implementation of a Block class that combines all these elements using the pre-norm structure.
Decoder-Only Transformers: The Workhorse of Generative LLMs
This resource provides the definitive, modern implementation of a decoder block, putting all the pieces we've discussed into a single PyTorch nn.Module.
Read the section 'Putting It All Together!'. Study the diagram and the Block class implementation. Trace the forward pass: x = x + self.attn(self.ln_1(x)) and x = x + self.ffnn(self.ln_2(x)). This perfectly encapsulates the pre-norm architecture.
Conclusion
In this lesson, we have constructed a complete Transformer decoder block from its constituent parts. We saw that it isn't just a random assortment of layers, but a carefully engineered unit where each component plays a vital role.
Key Takeaways:
- A decoder block is composed of two main computational sub-layers: Masked Multi-Head Self-Attention (for communication across tokens) and a Position-wise Feed-Forward Network (for independent computation on each token).
- Residual Connections (
Add) act as gradient shortcuts, enabling stable training of very deep networks by adding a layer's input to its output. - Layer Normalization (
Norm) stabilizes training by normalizing the activations for each token across its embedding dimension. - Modern architectures like GPT use a Pre-Norm structure (
x + SubLayer(LayerNorm(x))), which applies normalization before the main sub-layers, as it generally leads to more stable training. - A full decoder-only Transformer is simply a stack of these identical blocks, allowing the model to build progressively more abstract and complex representations of the input sequence.
Next Lesson Preview
We now have a complete, functional decoder block. But how do we use it to actually generate language? In our next lesson, we will explore the training process: autoregressive language modeling. We'll see how the model is trained to predict the next token in a sequence and how this simple objective, when combined with the powerful architecture we've just dissected, leads to the emergent capabilities of Large Language Models.