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

    Trace UTF-8 text into a fixed scalar vocabulary, distinguish IDs from text positions, and see why unknown scalars lose information.

    Content revision: 7
  3. Learning deterministic BPE merges

    Learn reusable byte tokens from training documents with explicit rules for overlapping counts, numeric ties, non-overlapping replacement, and document boundaries.

    Content revision: 8
  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. 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: 8
  8. 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
  9. 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: 8
  10. 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: 5
  11. 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
  12. 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
  13. 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
  14. 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
  15. 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: 12
  16. 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
  17. 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
  18. 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
  19. 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