Skip to content
LLM Inference

Reference

Run it locally

Every chapter but the last ships a self-contained Python file: it runs in under two seconds, prints what it measured, and asserts the claims the chapter makes. The only dependency is NumPy. The final chapter is TypeScript and runs with Node.

Setup

terminalbash
git clone <this repository>
cd learn-llm-inference-from-scratch

python3 -m venv .venv && source .venv/bin/activate
pip install numpy

Python 3.10 or newer, with no GPU, no model download and no PyTorch. The early chapters use a word-level bigram model, which lets the engine mechanics be exercised end to end without weights. Where the architecture itself matters (S03), the code is the real architecture with randomly initialised weights.

Running a chapter

terminalbash
python code/s01_generation_loop.py
python code/s06_paged_attention.py
python code/s14_speculative_decoding.py

python code/run_all.py

Two files do more than print. s19_server.py --serve starts a real OpenAI-compatible streaming server on localhost:8000, using the standard library alone rather than FastAPI. s20_complete_engine.py assembles everything and runs a leave-one-out ablation on your machine.

the serverbash
python code/s19_server.py --serve &

curl -N http://127.0.0.1:8000/v1/chat/completions \
  -H 'content-type: application/json' \
  -d '{"messages":[{"role":"user","content":"hi"}],"max_tokens":8}'

curl http://127.0.0.1:8000/metrics

The files

ChapterFileLines
S01The Generation Loopcode/s01_generation_loop.py137
S02Tokenizationcode/s02_tokenizer.py232
S03The Transformer Forward Passcode/s03_transformer.py251
S04Samplingcode/s04_sampling.py206
S05The KV Cachecode/s05_kv_cache.py205
S06PagedAttentioncode/s06_paged_attention.py283
S07Prefix Cachingcode/s07_prefix_caching.py263
S08Quantizationcode/s08_quantization.py252
S09Continuous Batchingcode/s09_continuous_batching.py244
S10The Schedulercode/s10_scheduler.py442
S11Chunked Prefillcode/s11_chunked_prefill.py190
S12FlashAttentioncode/s12_flash_attention.py183
S13Kernel Fusion & CUDA Graphscode/s13_cuda_graphs.py185
S14Speculative Decodingcode/s14_speculative_decoding.py188
S15Structured Outputcode/s15_structured_output.py338
S16Mixture of Expertscode/s16_moe.py152
S17Tensor & Pipeline Parallelismcode/s17_parallelism.py216
S18Disaggregated Prefill/Decodecode/s18_disaggregation.py186
S19The Serving Layercode/s19_server.py363
S20The Complete Enginecode/s20_complete_engine.py421
S21picoLM, in Pythoncode/s21_picolm.py495
S22mini-picoLM, in TypeScriptcode/src/lib/minipicolm/4018

A few files import from earlier ones: s07 uses the block manager from s06, and s20 uses both. Run them from inside code/, or through run_all.py, which sets the working directory for you.

Going further with real weights

When you want the same code running a real model, the smallest useful step is Llama-3.2-1B in fp16 with transformers for weight loading only. Keep your own forward pass from S03, and check it against HuggingFace generate() at temperature 0. If the first twenty tokens match, your RoPE layout and your attention masking are both right, and those are the two things most likely to be wrong.