← 研究 RE · 0006 · 2026-05-28
系统实现 · From Scratch · 零外部 LLM API

从一行 query
到一次 GPU 乘法

一套完全从零构建的 LLM 全栈系统。8 层、核心约 3,300 行代码、零外部 LLM API、零外部模型权重—— 预训练、指令 SFT、Agent SFT、推理服务、KV cache、手写 BPE、CUDA + Triton。 在 RTX 5090 上 70 秒从随机权重训出一个会调工具的 agent。

agent.py — AGENT_MODE=1 · 我们自己训的 124M model
70 s
L3+L4+L5 端到端训练(5090,不含权重下载)
10.815
L3 step-0 loss = ln(50257),验证权重初始化
8.4×
Triton flash-attn vs PyTorch 三段式
<1e-6
手写 KV cache vs full-forward 数值误差
Agent 的本质不是更聪明的模型
而是模型 + 外部工具的协调。

124M 的小模型自己绝对算不对 4 位数加法(chat 版本会答 "13")。但给它一个 7 行 Python 写的 calc 工具,它就能答对——而且这个具体数字从没出现在训练数据里。

query: 1234 + 5678 🔧 calc(1234 + 5678) ✓ 6912
架构

八层,每一层都看得见

按构建顺序排列:先有模型结构,再训练,最后服务出来。每层 < 300 行核心代码、独立可跑、有实测数字。运行时数据反向流动——从浏览器一路下到 GPU 指令。

模型结构
L1
L1 · GPU 基础层
GPU Kernels
手写 CUDA naive / tiled matmul,Triton fused flash-attention。一次矩阵乘在 SM 上到底怎么跑。
8.4×05_gpu/ · ~165 行
L2
L2 · Transformer 架构
GPT-2 + BPE
330 行手写 GPT-2(embed / MHA / FFN / LN / KV cache)+ 230 行手写 BPE,与 tiktoken bit-for-bit 等价。
7/704_transformer/ · ~560 行
训练
L3
L3 · 预训练
Pretraining
从随机权重在 1.1MB 莎士比亚语料上训出 7.24M 参数的 GPT。loss 从 10.815 (=ln 50257) 降到 4.55。
12 s00_train/ · ~140 行
L4
L4 · 指令 SFT
Instruction Tuning
242 条手写 Q/A + prompt 上的 loss masking,把"续写莎翁"调成"看到问题就回答"。
28 s00b_sft/ · ~140 行
L5
L5 · Agent SFT
Tool Use · ReAct
258 条程序合成的 ReAct trace 教模型调 calc / lookup。关键细节:OBSERVATION 前缀学、内容 mask。
33 s00c_agent_sft/ · ~150 行
推理与应用
L6
L6 · 推理服务
Inference Server
FastAPI + 自实现 KV cache + SSE 流式输出。零 transformers runtime,prefill 1.8ms / decode 2.6ms。
SSE03_model/ · ~140 行
L7
L7 · App / Web UI
Browser Frontend
~80 行原生 HTML/JS 前端 + FastAPI 后端。浏览器一个 token 一个 token 收到 thought / action / answer。
~13001_app/ · 行
L8
L8 · Agent 循环
ReAct Loop
generate → stop → parse → execute → inject 循环。把工具真实输出注回 prompt,再继续生成。
~20002_agent/ · 行

↑ 构建顺序 L1→L8 | 运行时一条 query 反向穿过:L7 浏览器 → L8 客户端 → L6 推理服务 → L2 Transformer → L1 GPU 矩阵乘,再把 token 逐个流式送回浏览器。

训练

70 秒:从随机权重到会用工具

三段训练串起来,在一张 RTX 5090 上不到 70 秒跑完。每一步都从上一步的 checkpoint 接着训。

Step 1 · 预训练
随机权重 → GPT
12s
1000 步,learns 莎翁的结构(角色名 + 冒号 + 台词),但还不懂"问答"。
Step 2 · 指令 SFT
续写 → 听话
28s
242 条 Q/A 后,"What is the capital of France?" → "Paris."。SFT 教格式不教知识。
Step 3 · Agent SFT
听话 → 用工具
33s
258 条 ReAct trace 后,模型会 emit ACTION 让外部工具来给答案。1234+5678 → 6912。

三段相加 ≈ 70 秒(5090)· 也可在 M1 CPU 上跑完整 from-scratch 路径(~7 分钟)

诚实清单

"完全 from scratch" 有多 from scratch

每个 token 经过的代码都在仓库里:算法、权重、tokenizer、KV cache、SSE 路由、UI 全是自家的。借的只有底座。

模型架构 GPT-204_transformer/model.py · 330 行
自家代码
BPE Tokenizer230 行手写 · 验证 bit-for-bit ≡ tiktoken
自家代码
模型权重L3 在莎士比亚语料上从随机初始化训出
自家训练
指令 / Agent 微调SFT + Agent SFT,loss masking 自己实现
自家代码
推理服务 + KV cacheFastAPI + 自家 GPT.step(),零 transformers runtime
自家代码
GPU kernelCUDA matmul + Triton flash-attention(可选)
自家代码
PyTorch / FastAPI / regextensor + autograd + web server 底座,不重写
借用库
transformers仅 L2 from_pretrained() 下载 OpenAI gpt2 权重时用;runtime 不用
可选回退
实测验证

每个数字都能复现

三台不同 GPU、中国大陆网络环境下独立 cold-start 验证。每个 TFLOPS、loss、latency 都有对应源码 + 实测命令。

权重初始化
step-0 loss = 10.815 ≈ ln(50257) = 10.825,吻合到小数点后两位,验证 N(0,0.02) 初始化正确。
BPE 等价性
手写 BPE 与 OpenAI tiktoken 在中/日/emoji/标点上 7/7 bit-for-bit 一致。
KV cache 正确性
手写 KV cache 与 PyTorch full-forward 数值严格等价,最大差 < 1e-6
flash-attention
Triton fused kernel 比 PyTorch 三段式(Q@Kᵀ→softmax→@V)快 8.4×
GPU架构区域L3 训练Agent 端到端
RTX 5090sm_120autodl 西区12.2 s✓ 6912
RTX 5090sm_120westc / westd13.8 s✓ 6912
RTX 4080 SUPERsm_89CN~18 s✓ 6912
资源

读代码 · 跑起来 · 看数字