Lesson 10 of 16
Section 3: The Complete Transformer Architecture & Optimization25 min read & walkthrough

LLM Architecture Overview & Next-Token Prediction

01 / PREDICTOR
Autoregressive Loop

Predicts P(x_{t+1} | x_1 ... x_t) iteratively across the vocabulary.

02 / COMPACT
250 Lines PyTorch

Zero black boxes. Understand every single tensor operation from first principles.

03 / LOCAL GPU
Zero Cloud Fees

Train directly on your workstation GPU using Dropout Developer Bridge.

The Big Idea

Large Language Models (LLMs) like GPT-4, Llama 3, and Claude often feel magical or intimidating, but beneath the massive scale lies an astonishingly simple game: guessing the next character or word. Imagine sitting with an apprentice storyteller who is listening to you tell a tale. Every time you pause mid-sentence, their job is to guess the exact next sound or letter that should follow. If you say 'Once upon a t...', they should bet heavily on 'i' followed by 'm' and 'e'.

Why does this simple guessing game produce human-like reasoning, code generation, and poetry? Because in order to accurately guess what letter comes next in a medical textbook, a legal contract, or a Python script, the neural network cannot just memorize rhymes. It is forced to understand grammar, syntax, facts about the world, and mathematical logic. Intelligence is the byproduct of optimizing next-token prediction at scale.

Modern generative models are 'decoder-only' Transformers, as pioneered in Attention Is All You Need (Vaswani et al. 2017) and popularized in minimal implementations like Andrej Karpathy's nanoGPT. Unlike older translation systems that read a full sentence in French before translating it into English, a decoder-only model processes text causally from left to right. It reads the past, processes it through stacked layers of attention and neural networks, and outputs scores for what token should arrive next.

💡

Jargon Buster: Plain-English Translations

  • Autoregressive: From 'auto' (self) and 'regressive' (stepping backward). It means the model generates text one piece at a time, feeding its own past predictions back into its input for the next step.
  • Token: The atomic unit of text the model processes. In this course, each token is a single character (like 'a', '7', or a space), though production models use subwords.
  • Logits: The raw, unnormalized numerical scores produced by the model's final linear layer before they are transformed into probabilities.
  • Probability Distribution: A set of percentage chances across every character in our vocabulary, where every number is between 0 and 1, and all numbers sum up to exactly 1.0 (100%).

Architecture Blueprint & Tensor Mechanics

The entire GPT architecture boils down to four distinct stages: embedding tokens and positions into continuous space using PyTorch Tensor & Broadcasting rules, passing them through stacked Transformer blocks, normalizing activations, and projecting to vocabulary logits. In Lesson 1.2, we start by engineering the character tokenizer.

import torch
import torch.nn as nn
from torch.nn import functional as F

class GPTLanguageModel(nn.Module):
    def __init__(self, vocab_size, n_embd, block_size, n_layer, n_head):
        super().__init__()
        # 1. Token embedding table: maps token IDs to vectors of size n_embd
        self.token_embedding_table = nn.Embedding(vocab_size, n_embd)
        # 2. Position embedding table: gives each sequence index a unique vector
        self.position_embedding_table = nn.Embedding(block_size, n_embd)
        # 3. Stack of Transformer blocks (attention + feed-forward)
        self.blocks = nn.Sequential(*[Block(n_embd, n_head, block_size) for _ in range(n_layer)])
        # 4. Final layer normalization
        self.ln_f = nn.LayerNorm(n_embd)
        # 5. Language model head: projects n_embd back to vocabulary scores
        self.lm_head = nn.Linear(n_embd, vocab_size)

    def forward(self, idx, targets=None):
        B, T = idx.shape
        # idx and targets are both (B, T) tensors of integers
        tok_emb = self.token_embedding_table(idx) # (B, T, C)
        pos_emb = self.position_embedding_table(torch.arange(T, device=idx.device)) # (T, C)
        x = tok_emb + pos_emb # (B, T, C) - via PyTorch tensor broadcasting
        x = self.blocks(x)    # (B, T, C) - through all transformer blocks
        x = self.ln_f(x)      # (B, T, C) - final layer norm
        logits = self.lm_head(x) # (B, T, vocab_size)

        if targets is None:
            loss = None
        else:
            B, T, C = logits.shape
            logits = logits.view(B * T, C)
            targets = targets.view(B * T)
            loss = F.cross_entropy(logits, targets)

        return logits, loss
⚠️

Beginner Traps & Gotchas

1. Generating an entire sentence in a single forward pass

The Gotcha: Beginners often expect a model to output a complete sentence at once. A Transformer forward pass only predicts logits for the next token at each position.

The Fix: Wrap generation in an autoregressive loop that crops context, samples the next token, appends it to the sequence, and repeats.

2. Confusing Decoder-Only GPT with Encoder models like BERT

The Gotcha: In BERT, tokens can look forward and backward simultaneously, which destroys autoregressive text generation because the model peeks at future answers.

The Fix: Always enforce a lower-triangular causal attention mask so tokens can only communicate with past and present positions.