The course

From text to a tiny language model

Each localized chapter adds one tested idea to the same Rust implementation.

  1. A map of a modern LLM

    See how tokenization, embeddings, decoder blocks, attention, feed-forward layers, training, sampling, and caching fit together in a decoder-only LLM.

    Content revision: 5
  2. Text units and vocabulary IDs

    Compare UTF-8 bytes, Unicode scalar values, and a demo-only scalar vocabulary before byte-level BPE replaces it.

    Content revision: 6
  3. Learning deterministic BPE merges

    Learn an ordered byte-pair merge table from training documents with explicit rules for overlap, replacement, ties, and document boundaries.

    Content revision: 7
  4. From assigned probability to perplexity

    Turn the probabilities assigned to observed target tokens into mean negative log-likelihood and perplexity while keeping the target count, document boundaries, and evaluated data splits explicit.

    Content revision: 7
  5. Shared views and explicit tensor copies

    Follow fixed-context word features into Q/K/V tensors and split attention heads, then compare shared tensor views with explicit copies in the course implementation.

    Content revision: 6
  6. Check gradients before trusting backpropagation

    Cross-check selected LLM-training derivatives from actual floating-point probes, with a local-smoothness requirement, scale-aware error, and deterministic tensor coordinates in Rust.

    Content revision: 6
  7. Initialize trainable weights reproducibly

    Initialize model weight matrices reproducibly, compare zero, oversized, and Xavier scales, and track expected variance through stacked linear layers.

    Content revision: 4
  8. Give token IDs trainable vectors

    Build a trainable token table, validate public token IDs once, pass owned selectors through a private validated gather plan, and scatter-add repeated-token gradients.

    Content revision: 7
  9. Let one learned branch gate another

    Build a position-wise SwiGLU feed-forward layer, follow its activated gate and linear up branches, and verify exact outputs and gradients.

    Content revision: 3
  10. Keep decay out of the gradient moments

    Build AdamW from named parameter gradients, bias-corrected moments, and a separate weight-decay path, then commit every checked update together.

    Content revision: 7
  11. Train a fixed-context neural language model

    Assemble embeddings, a SwiGLU hidden layer, indexed next-token loss, mini-batches, and AdamW into a deterministic neural n-gram whose held-out loss improves.

    Content revision: 4
  12. Create query, key, and value views

    Learn how Transformer self-attention creates query, key, and value tensors from one hidden-state sequence through three independent bias-free projections.

    Content revision: 2
  13. Compute one unmasked self-attention head

    Learn how one unmasked Transformer self-attention head scores queries against keys, normalizes each row, and mixes values with inspectable Rust evidence.

    Content revision: 2
  14. Block future keys with a causal mask

    Learn how an inclusive lower-triangular causal mask blocks future Transformer keys, assigns them exactly zero attention probability, and preserves earlier outputs.

    Content revision: 2
  15. Turn query and key pairs with RoPE

    Learn how rotary position embeddings turn query and key feature pairs by absolute position so relative offsets appear in attention dot products, with a tested Rust implementation.

    Content revision: 3
  16. Train every step, select with validation

    Learn how a decoder training loop orders backpropagation, gradient clipping, scheduled AdamW updates, graph-free validation, and checkpoint selection without using test data.

    Content revision: 10
  17. Open one local test gate, keep the report

    Learn how one local final-evaluation gate isolates an already selected state, compare graph-free decoder and bigram scores fairly, and distinguish a deliberately selected fixed regression fixture from independent generalization evidence.

    Content revision: 7
  18. Save decoder state, replay one specified update

    Learn how a versioned checkpoint stores the tokenizer, decoder, trainer-paired AdamW state, and a separate sampling RNG, rejects corrupted bytes, and matches one update whose inputs, targets, and learning rate the caller supplies.

    Content revision: 5
  19. Shape the choices, then draw once

    Learn how positive temperature, stable top-k filtering, and a restored random-generator state turn decoder logits into controlled, replayable uncached LLM generation.

    Content revision: 5
  20. Prefill once, then advance one token

    Learn how one KV cache per decoder block and one checked model/cache session support prompt prefill followed by coherent one-token decoding, then compare newest-position logits and generation decisions with complete-prefix references.

    Content revision: 6
  21. Run the whole tiny LLM

    Trace a tiny decoder-only language model in Rust through validation-selected training, a fixed-fixture comparison over overlapping window-target slots, exact reload, and KV-cached generation. Distinguish that comparison from the unreported policy that would score 442 within-document transitions once each with the longest causal prefix capped at four tokens and only its newest-position distribution; numeric NLL and PPL are not reported for that policy.

    Content revision: 9