Write an LLM yourself.
Eight short coding steps in learn/build/. In each you fill in a few marked blocks and run its checks, which compare your code with PyTorch's own. By step 6 you have a working transformer with Qwen3's block design that learns to write.
How it works
Read the top comment, then find each raise NotImplementedError("TODO"). The comment above it gives the formula.
From learn/build: ../../.venv/Scripts/python -m pytest -k s01. Each failing check says what is wrong.
Every step prints something worth seeing. After step 6, train_tiny_gpt.py trains your own model.
The eight steps
- 1Autograd from scratch
s01_micrograd.pyA Value that records how it was computed, five operations with their derivatives, and backward(). Then train a tiny network on XOR with it.
- 2A counting language model
s02_bigram.pyCount which character follows which, turn counts into probabilities, score text with cross-entropy, and sample.
- 3A byte-level BPE tokenizer
s03_bpe.pyPair counting, merging, training merges, encoding and decoding, with a perfect round trip on any Unicode text.
- 4Attention by hand
s04_attention.pyA numerically stable softmax, the causal mask, scaled dot-product attention and GQA's repeat_kv, checked against PyTorch.
- 5RMSNorm, RoPE, SwiGLU
s05_parts.pyQwen3's three distinctive parts, with checks that RoPE keeps lengths and makes scores depend only on distance.
- 6A tiny Qwen-style GPT
s06_tiny_gpt.pyAssemble the block and the full model with Hugging Face's Qwen3 module names, then train it to write sentences.
- 7Sampling and the KV cache
s07_generate.pyTemperature, top-k and top-p, plus a KV cache whose logits match the uncached model exactly.
- 8LoRA fine-tuning
s08_lora.pyA low-rank add-on that starts as a no-op, trains a tiny fraction of the weights and merges back exactly.
What step 6 gets you
A real run of the reference solution: a 796,800-parameter model trained on a small synthetic story corpus. The loss falls from 3.581 to 0.163 nats per character.
cd learn/build ../../.venv/Scripts/python -m pytest -k s06 ../../.venv/Scripts/python train_tiny_gpt.py
The tlSZbeTolwbrwIMniyLSLTTglbTiIgp.vZBureydiSkmipodp.ZdrbAgwdBeM.ihvnmor,hwcpck,
The fox was curious, so it slept. Sam was hungry and the bear was curious. Zoe was brave and the dog was brave.
Stuck?
solutions/has the reference answers. Try for 20 minutes first: the struggle is where the learning happens.python make_exercises.py --forceresets every exercise and keeps your old files as.py.bak.BUILD_IMPL=solutions python -m pytestshows what passing looks like.