参考
在本地运行
除最后一章外,每章都配一个自包含的 Python 文件:两秒内跑完,打印它测到的数字,并断言本章给出的结论。依赖只有 NumPy 一个。最后一章是 TypeScript,用 Node 运行。
环境准备
terminalbash
git clone <this repository>
cd learn-llm-inference-from-scratch
python3 -m venv .venv && source .venv/bin/activate
pip install numpyPython 3.10 或更新版本,不需要 GPU,不用下载模型,也不用 PyTorch。前几章用的是词级 bigram 模型,没有权重也能把引擎机制端到端跑一遍。到了架构本身要紧的地方(S03),代码写的就是真实架构,只是权重随机初始化。
运行某一章
terminalbash
python code/s01_generation_loop.py
python code/s06_paged_attention.py
python code/s14_speculative_decoding.py
python code/run_all.py有两个文件不只是打印。s19_server.py --serve 会在 localhost:8000 上启动一个真正的 OpenAI 兼容流式服务器,只用标准库,不依赖 FastAPI。s20_complete_engine.py 则把所有部件装到一起,在你的机器上跑一次留一消融实验。
服务器bash
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文件清单
| 章节 | 文件 | 行数 |
|---|---|---|
| S01生成循环 | code/s01_generation_loop.py | 137 |
| S02分词 | code/s02_tokenizer.py | 232 |
| S03Transformer 前向传播 | code/s03_transformer.py | 251 |
| S04采样 | code/s04_sampling.py | 206 |
| S05KV 缓存 | code/s05_kv_cache.py | 205 |
| S06PagedAttention | code/s06_paged_attention.py | 283 |
| S07前缀缓存 | code/s07_prefix_caching.py | 263 |
| S08量化 | code/s08_quantization.py | 252 |
| S09连续批处理 | code/s09_continuous_batching.py | 244 |
| S10调度器 | code/s10_scheduler.py | 442 |
| S11分块 Prefill | code/s11_chunked_prefill.py | 190 |
| S12FlashAttention | code/s12_flash_attention.py | 183 |
| S13算子融合与 CUDA Graph | code/s13_cuda_graphs.py | 185 |
| S14投机解码 | code/s14_speculative_decoding.py | 188 |
| S15结构化输出 | code/s15_structured_output.py | 338 |
| S16专家混合(MoE) | code/s16_moe.py | 152 |
| S17张量并行与流水线并行 | code/s17_parallelism.py | 216 |
| S18Prefill/Decode 分离部署 | code/s18_disaggregation.py | 186 |
| S19服务层 | code/s19_server.py | 363 |
| S20完整的引擎 | code/s20_complete_engine.py | 421 |
| S21用 Python 重写 picoLM | code/s21_picolm.py | 495 |
| S22用 TypeScript 写 mini-picoLM | code/src/lib/minipicolm/ | 4018 |
有几个文件会 import 更早的文件:s07 用到 s06 的 block 管理器,s20 两个都用。所以请在 code/ 目录内运行,或者交给 run_all.py,它会替你设好工作目录。
再进一步:换上真实权重
想让同样的代码跑真实模型,最小的一步是:用 fp16 的 Llama-3.2-1B,transformers 只负责加载权重,前向传播仍用你自己在 S03 里写的那份,再在 temperature 0 下与 HuggingFace 的 generate() 对拍。如果前二十个 token 一致,说明 RoPE 布局和注意力掩码都对了,而这两处恰恰最容易出错。