
1. 从零开始不是低效复读而是建立不可迁移的工程认知最近总有人问我一个问题现在市面上现成的开源模型、API 调用、推理框架一堆直接拿来用不就行了为什么还要折腾什么ai-engineering-from-scratch从头手写一个语言模型这个问题的答案得从一次面试说起。我之前面试过一个候选者简历上写着精通大模型应用开发聊到 LoRA 为什么能省显存时他说是因为只训练了一部分参数。再追问哪一部分的时候答案是不知道反正调库就行。这不是个例。大量所谓的 AI 工程师本质上只是 Prompt 工程师加 API 封装工程师。你问他 GPT 的 next token prediction 是怎么变成对话能力的他说不出来你问他为什么 batch size 从 2 变到 4 训出来的模型效果差异巨大他说不出来你问他 RLHF 里那个 reward model 到底在拟合什么他也只能含糊带过。当然我不是说调库没有价值工程本身就是组合与调度艺术。但如果你完全没有从零构建的底层认知遇到超出库里封装范围的问题你就彻底抓瞎。显存不够你知道梯度累积怎么配吗训练 loss 出现 NaN 你知道去检查哪几个位置吗分布式训练卡住你知道是 NCCL 通信还是数据加载器的问题吗这些都不是调库能调出来的东西。所以我把ai-engineering-from-scratch定位成一整套认知基建你理解数据如何被分词、嵌入、注意力计算、归一化理解 loss 为什么震荡、梯度为什么消失、tokenizer 的 vocab size 为什么必须对齐当你再回去用任何框架时你看到的就不再是一个个 magic 的黑盒函数而是一层薄薄的封装纸。反过来你也能判断哪些问题值得自己动手造轮子哪些直接用开源实现就够了。这条路线不仅仅适合想搞 AGI 的研究人员。就算你的目标是做一个 AI 产品的应用工程师亲手把一个小语言模型从零训起来也会让你对显存预算、推理延迟、微调测试集划分这些日常操作有完全不同的直觉。这是一笔稳赚不赔的投资。提示这篇文章不是教你一行行抄代码的教程而是一份把从零构建 AI 工程这条路的关键节点、原理认知、避坑方向讲清楚的地图。我默认你已经有一点 Python 基础和基本的机器学习概念但即便你是刚入门的小白跟着章节走也能建立起清晰的道路感。2. 手写 Transformer 之前先摸清整套技术链路在你打开 PyTorch 开始写nn.Transformer之前必须先搞清楚一个基本问题一个大语言模型从零到能被人使用到底要经过哪几步。很多人的误区是一上来就盯着transformer 架构怎么实现死磕代码敲了一晚上模型问世的幻想却离现实越来越远。实际上完整的链路远比搭个网络要长得多。2.1 八个环节一个都不能少我们把大语言模型的工程链路拆开大概是这样的环节关键动作输出了什么最容易出问题的地方数据采集爬取/整理文本语料原始语料库重复数据、噪音文本、版权问题数据清洗去重、过滤、格式化干净语料过度清洗损伤模型表达能力Tokenization训练BPE分词器tokenizer 词表vocab mismatch、特殊token未处理预训练在语料上做自监督训练base modelloss 不降、显存溢出、梯度问题后训练SFT、DPO/RLHF 对齐chat/reasoning model数据质量差导致模型学坏评估跑基准测试和人工评测评估报告测试集污染、指标过拟合优化量化、蒸馏、剪枝轻量化模型精度掉太多、推理加速不明显部署拉起服务、接入流量线上API并发抖动、延迟超标、cost失控这八个环节里任何一个做不好最后交付的模型都可能是废的。但绝大多数从零开始的项目把 90% 的精力砸在了第四步预训练上。这很自然因为写 transformer 最有我要造出 GPT 的感觉。可是你很快会发现数据质量不够好、分词器词汇表有问题、评估环节缺失你在第四步折腾得越久后期返工就越痛苦。我自己带过一个仿照 GPT-2 做的小模型项目当时花了整整两周调整 decoder 层数和注意力头数结果发现效果提升不如把语料里的中文乱码片段好好清洗一遍来得显著。这就是链路思维的重要性你的模型性能瓶颈往往不在模型架构本身而在整个链路最薄弱的那一个环。2.2 先搭一个能跑的通路再逐步优化我建议从零开始的第一个里程碑根本不是训练出一个好的大模型而是把上面的八个环节用最简版本全部串起来。举个例子你不需要上来就搞几百 GB 的语料你可以取一段几 MB 的公开小说比如古登堡计划里的英文小说作为语料你不需要训练一个 70B 的 tokenizer你手写一个简单的 BPE词表控制在 5000 以内你的模型可以是 6 层 decoder、4 个注意力头、embedding 维度 128 左右预训练几步之后直接在验证集上看看困惑度和 loss。这个最简通路跑通了你才算真正把大语言模型从神话变成了工程对象。之后每一次只优化一个环节。比如先把 tokenizer 换成 SentencePiece或者把语料扩展到 10GB或者加上学习率预热和余弦衰减。你每优化一个环节都要能观察到下游评估指标的变化。这种单变量实验的思维会让你对整个系统工程产生极强的掌控感。如果你一上来就想搞个大新闻直接复刻 GPT-3 的架构和训练规模大概率你的 GPU 会先哭给你看然后你的心态会迅速崩塌。这个思路参考了 Sebastian Raschka 的《Build a Large Language Model (From Scratch)》的核心框架。那本书好就好在它不是把一个巨大的模型直接怼给你而是让你从最小实现开始像一个工程师一样一步步搭出完整的系统。尤其是它把 tokenizer、架构、预训练、微调讲的非常细。不过要说句公道话那本书更偏研究和教学真到生产环境的工程细节比如量化部署、服务编排它涉及得不多那是我们要在后面自己补的课。3. 数据工程与 Tokenizer训练曲线崩盘的元凶我们常说垃圾进垃圾出。在从零训练一个模型的场景里这句老话以非常残酷的方式显灵。绝大多数新手训练出来的模型输出前言不搭后语第一反应通常是模型还不够大训练步数不够多然后疯狂堆算力。但实际上问题 60% 的概率出现在数据和 tokenizer 上。这一节我把最容易翻车的地方掰碎了讲。3.1 原始语料质量决定模型智力上限的暗线先放下模型架构不谈我们说语料。很多人从网上随便下载了一个中文语料包30GB感觉很多了直接开训。训到一半发现 loss 下降到了一个平台就再也不动了模型生成的内容像乱码又不完全是乱码。后来一查看数据发现语料里有大量的 HTML 标签残留、版权页重复内容、甚至是半个 UTF-8 编码切碎的行。我给你的建议是第一版语料一定要做严格的清洗流水线。这不是什么高深 ML 技术就是工程素养。你可以按这几步走统一编码格式UTF-8剔除无法解码的字节。去除全角/半角符号内的 HTML 实体比如nbsp;、p。按段落下拉过滤掉长度小于 50 个字符的碎片行。做全局去重对有大量重叠文本的句子对做 MinHash LSH特别是新闻类语料转发的重复率极高。敏感词和低质内容过滤这一步不展开说策略但原则就是宁缺毋滥。如果你嫌手工写麻烦可以直接用现成的工具比如datasets库里的load_dataset配合cleanlab做初步质量评估或者直接复用开源社区如 RedPajama 的清洗脚本思路。但我依然建议你手动过一遍因为你对数据的感觉会影响后续所有决策。3.2 BPE 分词器为什么 vocab size 对齐这么重要Tokenizer 是大多数手写 Transformer 教程一笔带过的地方但它坑起来真的会把你坑到自闭。很多人直接调tokenizers库训练一个 BPE然后开开心心把vocab_size32000塞进模型。但有几个细节你几乎肯定会踩第一tokenizer 的 vocab size 必须和模型的 embedding 矩阵维度严格对应。nn.Embedding的第一个参数默认是vocab_size如果你换了 tokenizer 但没有同步改模型配置轻则报错重则索引越界直接跑挂。这个看起来低级但在复杂的实验管理流程里模型配置文件和 tokenizer 文件分别存储忘同步的情况太多了。第二特殊 token 的顺序要固定。bos、eos、pad、unk放在词表最前面还是最后面会影响训练的随机初始化和生成。它的固定顺序必须写进一条 config 里任何加载代码都要校验。第三不要在训练完模型之后再换 tokenizer 重训。你可能看到某些项目先训 tokenizer再微调词表。对新手来说这只会制造无尽的痛苦。最简单可靠的方案是一开始定好 tokenizer训练永远不再改。实践中我经常用一个非常直观的检查方式把语料里一个词表之外的生僻字单独收集出来调用 tokenizer 后看它们被拆成了什么子词。如果大量生僻字被拆成单字节乱码或吐出了一堆[UNK]那说明你的词表和语料分布严重不匹配。这时候不要硬着头皮训先把词表或者语料换掉。3.3 让tokenization 不崩溃落地的实操清单我在本地训练一个最小的 GPT 时tokenizer 配置是这样一套组合可以作为参照选择分词算法BPE或 SentencePiece unigram中文场景我更喜欢 unigram它可以处理多语言混排不生硬。training corpus至少 100MB 左右文本太少词表碎片化严重。vocab_size训练 1 亿参数级别模型时我常用 8000~12000 之间。不要一上来就搞 32000 甚至 50000词表太大 embedding 矩阵占显存而小模型根本学不满这么多参数。min_frequency2低频 token 直接摈弃。special_tokens[unk, s, /s, pad]。训练好后跑一遍自检代码确认语料中 99% 的 token 都不是[UNK]并且平均 token 长度字符数/token 数在 2~4 之间。这一步你大概需要花半天时间但它能在后续几百小时 GPU 训练里给你省下无数返工时间。数据清洗和 tokenizer 这种不起眼的脏活正是 AI engineering from scratch 这条路上最考验耐心也最锻炼工程直觉的部分。4. 从语言模型到推理模型对齐这一步到底在做什么你费了九牛二虎之力训出了一个预训练语言模型。它看起来能续写文本但你还远不能把它当成 ChatGPT 那样直接对话。如果不做对齐alignment你对它说你好请介绍一下你自己它大概率会接一句我的名字叫 Transformer我是一种基于自注意力机制的模型或者干脆写出下一篇新闻稿。为什么会这样因为预训练的目标函数是下一个 token 预测它只学到了语料统计规律没学到人类在对话中期望的说话方式。所以第二个大节点就是对齐。这也是build a reasoning model from scratch的热搜词背后大家真正关心的部分怎么让模型不仅会说人话还能像人一样思考推理。4.1 SFT 阶段不是简单的喂人话监督微调 SFT是把预训练模型从文本续写器改成对话助手的第一件事。做法看起来很简单收集指令-回答对然后继续用交叉熵训练模型让它输出回答。但细节里全是坑数据配比如果你只喂 1 万条高质量对话模型容易过拟合到特定表达方式如果你混合了 100 万条杂七杂八的网聊数据模型又会丢掉对话的优雅。常见做法是 80% 高质量指令数据 20% 通用预训练数据混入防止灾难性遗忘。数据多样性不只是 QA 对还要有拒绝回答、多轮对话、格式错误恢复等边界样本。比如用户连续追问三次相同问题模型的回答应该略有差异而不是复读机。这些都要靠 SFT 数据里的人为设计。训练超参SFT 学习率通常比预训练低一个数量级比如预训练用3e-4SFT 用2e-5epoch 数通常 1~3 个。这个阶段的核心是微调行为模式而不是重新灌输知识。你训练得太久模型反而会忘掉预训练阶段学到的东西。我踩过的一个具体教训是SFT 数据里大量出现了好的我来帮你解答这种 AI 腔开头。结果训练出来的模型无论用户问什么问题第一句话都是好的我来帮你解答。看起来热情实则蠢得要命。后来我在构造 SFT 数据时强制要求 30% 的回答直接进入核心内容不客气、不寒暄才把这个毛病掰回来。4.2 RLHF 与 RLAIF让模型学会什么事该做SFT 之后模型会跟着指令走了但它还是不知道自己哪些话是对的哪些话是不该说的。这就是强化学习人类反馈RLHF登场的地方。我不打算在这里把 RLHF 的数学公式抄一遍而是用一个更容易理解的框架讲清楚它到底在优化什么。你可以把 RLHF 想象成一个老饲养员驯海豚你手里有两个网络一个是正在被训练的策略网络就是你的语言模型一个是奖励模型reward model。奖励模型观察人类对海豚表演的评分学会预测人类大概会喜欢怎样的一跃怎样的表演是让观众皱眉的。然后策略网络在生成回答时奖励模型给它打分策略网络就朝着分数高的方向更新。在实现上有几个最常见的坑奖励模型的数据集构建做人类偏好标注时对同一个 prompt 要准备多个模型的输出让标注员排序。排序的一致性Krippendorffs alpha太低说明标注指南不明确reward model 也学不好。PPO 算法的 rollout 稳定性策略模型一旦更新过快生成的 rollout 会在一两轮内质量骤降。一般建议 rollout 时对旧策略做 KL 散度约束把更新幅度压住。reward hacking模型会钻空子去生成看起来讨喜但是空洞无物的回答比如长篇大论地表达礼貌。这是 RLHF 最经典的奖励欺骗行为。缓解手段之一是给奖励模型输入加一个答案长度惩罚或重复度惩罚。如果说 SFT 是教模型说人话那 RLHF 就是教模型办人事。它让模型学会拒绝不合适的请求、在不确定的时候承认自己不知道、在长回答中保持一致性。这个过程非常烧钱也极消耗耐心所以很多中小团队更倾向于直接用 RLAIF——用另一个更强的模型比如一个 API 背后的大模型来给回答排序省去人工标注环节。虽然 RLAIF 的效果上限取决于教师模型的水平但在工程效率上确实是巨大解放。4.3 通向推理模型从对答如流到停下来思考最近build a reasoning model from scratch这个词很火我觉得它对准了一个新趋势光能流利对话已经不够了我们需要模型做数学推导、代码调试和复杂逻辑推理。为什么一个大模型会做错9.11 9.9这种题因为它走的是概率续写路线不真正执行规则推演。目前最主流的方法是给模型引入思维链Chain-of-Thought和强化学习推理训练。具体落地参考 DeepSeek-R1 那套思路构造带详细推理步骤的数据做 SFT让模型学会在输出正式答案前先输出一段[thinking]...[/thinking]的推理草稿。然后设定可验证的奖励信号比如代码题的测试用例通过率、数学题的最终答案是否正确。这些奖励信号不需要人类逐条标注而是可以由程序自动判定因此可以大量生成数据。用 GRPO/PPO 类算法专门优化推理得分同时用格式奖励约束模型必须输出[thinking]推理块防止模型跳过思考直接给答案。最后通过拒绝采样和微调蒸馏把推理能力压缩成更小的模型。听起来挺顺畅但实操里有个非常头痛的问题模型会为了奖励而表演推理。我见过某个模型在[thinking]块里写我需要逐步分析……不对或者直接猜一个答案吧然后真的输出一个错误的最终答案。奖励模型要是没抓住它假推理它就会越来越擅长装模作样。所以推理模型的对齐比普通的 RLHF 更依赖奖励信号的严格性。它要求你设计的 reward model 对过程有感知能力而不只是看最终结果。如果你从零开始做推理模型我的建议是别一上来就搞多模态、长期记忆这些花活。你先把自动可验证的数学题/代码题这一条赛道跑通把 RL 训练流程调稳再去看更复杂的场景。5. 评估、量化和部署模型能跑只是第一步很多时候大家把模型训练出来loss 很低对话也很流畅便觉得大功告成了。实际上在工程视角里模型才刚刚从实验室展品变成待交付的半成品。真正的 AI 工程后半段才开始。5.1 评估体系不要只盯着 loss 看我遇到过一个团队在训练日志里看到 loss 从 3.2 降到 2.1兴奋得不得了直接上线上服务。结果用户反馈回答驴唇不对马嘴。为什么因为 loss 衡量的是 token 级预测概率它降了只能说明模型在字形和常见搭配上越来越熟练不代表逻辑正确、不表示事实可靠。更好的做法是同时跟踪三类指标生成质量指标BLEU / ROUGE 对语序敏感不适合对话对生成模型我更看重人工抽样评分、GPT-4 打分、以及格式合规率比如 JSON 输出能否被解析。这些指标能告诉你模型在真实使用时好不好用。事实一致性指标对问答和摘要场景用 FactCC、QAFactEval或者干脆拿另一个模型交叉验证答案和语料中的证据能发现模型一本正经胡说八道的情况。行为约束指标比如拒答率友好度敏感内容拦截率RLHF 后这些指标一定要做回归测试防止对齐被后续微调破坏。评估集也不是随便从训练集中抽几条就行。我倾向于为每个任务类型单独构建 small expert evaluation set比如 500 条数学题、500 条代码题、500 条客服对话每次模型变更后固定跑一遍形成可以对比的回归记录。注意如果你要拿公共榜单比如 MMLU、GSM8K的测试题来评估请一定要记住这些题目可能已经泄入训练语料。不要盲目迷信基准分数。最好是保留一份内部私有测试集永远不放进训练数据。5.2 量化与部署从能跑到跑得起一个 7B 参数的模型用 FP16 跑光权重就是 14GB 显存加上 KV cache 和中间激活单卡 24GB 大概只够处理很短上下文。你训练的模型要真正落地量化几乎是必修课。我最常用的是 4-bit 量化比如用 GPTQ 或 AWQ。量化之后 7B 模型的权重体积降到约 3.5GB推理速度可以提升两到三倍。代价是输出质量和事实准确率会略降。对于低资源场景我还常用更激进的 2-bit 或 3-bit 量化但这时模型很可能开始胡言乱语。所以量化的核心原则是每次都要带着私有评估集测一遍看精度损失是否在可接受范围内。部署时还有两个容易忽略的点批量推理的动态延长LLM 的单条请求生成长度不可预测最好用 continuous batching连续批处理来提升吞吐而不是固定 batch 尺寸。vLLM、TGI 这些框架都内建了这个能力。流式输出与超时控制生产环境必须支持 SSE 流式输出否则用户首 token 延迟TTFT会高得难以忍受。同时要设置 max tokens 和超时时间防止用户一次性请求炸掉你的 KV cache。5.3 线上监控没有捷径部署只是起点真正的 AI 工程还要考虑线上模型漂移和用户反馈闭环。记录每次请求的 prompt、response、延迟、token 数、命中的业务指标。定期随机抽样让人工或更强大的模型对线上输出评分并把低分样本回溯到评估集合里。一旦分数跌破阈值触发离线重训或回滚到上一个稳定版本。这些听起来有点像运维的活但它是 AI 工程和算法研究最本质的分界线算法研究可以只关心 bench 数字AI 工程必须关心整个系统的稳定和收益。6. 我的路线图与三个血泪教训在正文的最后我想把前面这些经验浓缩成一份可以直接参考的路线图以及我自己在实践中踩过的三个大坑。这份路线图不一定适用于所有人但它至少能帮你避免那种东一榔头西一棒子的迷茫感。6.1 阶段化路线图参考按照 3~4 个月的业余时间算大致可以这么分配阶段时长目标关键产出热身期1~2周熟悉 PyTorch、Transformer 基础能用手写 attention 机制完成小任务最小通路2~4周复现一个极简 GPT几千万参数完成数据处理、tokenizer、训练、生成的闭环扩展优化3~6周训练一个 1 亿参数级别模型观察到 loss、生成质量随规模/数据提升对齐微调2~3周SFT 简单 DPO/RLHF模型能稳定进行多轮对话推理强化1~2周尝试数学/代码推理 RL 训练完成一个可自动验证的推理小任务工程化1~2周量化、部署、评估回归把模型包装成一个可调的 API这个路线图的关键在于每个阶段都有一个可以看得见的产物而不是我学完了某个算法。所有阶段之间的衔接都要有可验证的实验结论做支撑。这样你上一步的产出就是下一步的输入整个学习过程就不会流于空谈。6.2 三个血泪教训第一不要跳过数据工程去追求更高级的架构。我犯过的最大错误就是一上手就研究 MoE、稀疏注意力这类花哨组件结果基座模型本身连基础 loss 都降不下去。后来把注意力拉回数据质量效果立刻起飞。从零开始的项目数据质量几乎永远是最优先的改进方向。第二不要把能复现开源代码当成自己会了。有一种沉浸感是你 clone 了别人的仓库pip install之后跑通了 demo就误以为模型是你自己构建的。真正的from scratch意味着你能够在没有原仓库的前提下从空目录开始一项项把数据流、训练循环、推理逻辑写出来。只有在写不出来的地方你才会遇到真正的知识死角。第三RLHF/RL 的乐趣在于炼丹痛苦的在于复现。如果你发现同样的代码和同样的超参数今天训练出来的模型和明天训练出来的模型表现差很多不要慌先检查随机种子、显存波动、数据加载顺序再去怀疑算法本身。百分之八十的情况下问题出在实验环境不一致而不是 RL 的数学推导。6.3 最后再说两句心里话ai-engineering-from-scratch这条路它不是最快的路甚至很多人在走了一半的时候会怀疑自己是不是在重复造轮子。但走到后面你会发现那些真正能在大模型应用层做出创新的人一定不是只会调包的人。他们对底层机制的体感决定了他们能在什么高度的抽象上做决策。我个人在实际操作中最深的体会是每一次动手从零实现一个模块无论是一个 tokenizer 还是一个注意力层都会让你在使用开源工具时多一分底气少一分恐惧。这种感觉积累起来会让你在面对新模型、新框架、新训练范式时不再焦虑自己会不会跟不上因为你已经拥有了一套可以随时拿来拆解问题的底层框架。最后分享一个小技巧不要一开始就给自己定一个野心过大的目标比如我要从零训练出媲美 GPT-4 的模型。请把目标缩小成我要训练出一个能写藏头诗的模型我要训练出一个能解一元二次方程的模型。当你把这些微型模型一个个从零构建成功你会逐渐从 AI 的使用者变成 AI 的构建者。这个转变才是ai-engineering-from-scratch真正的意义所在。