1. 为什么“从零开始”这条路最难也最值如果你关注AI工程有一阵子大概率见过“ai-engineering-from-scratch”这个名字。它不是某个大佬的课程链接也不是一本抢到断货的实体书而是一类以“手写、亲建、梯式递进”为特征的学习与实践路线的总称。一个标题背后承载的是“不靠调包侠、坚持造轮子”的工程信仰。说白了就是从数据准备到模型训练、再到推理部署每一个环节都不跳过全部亲手过一遍。我最早入坑时也图省事直接hf pipeline一把梭跑通一个分类任务就觉得自己懂了大模型。但实际一追问分词器里的BPE是怎么合并的训练时梯度裁剪值为什么设1.0推理时temperature从0.7调到0.2为什么效果差别那么大全答不上来。直到我决定用三个月时间从零搭一个小规模的推理模型才把这些问题一个一个搞清楚。今天这篇就把这条“从零开始”的路拆开来讲包括整体设计思路、核心环节的细节、实操过程里会踩的坑以及我实际跑实验的记录。适合两类人一是刚入门但不想停留在“会用API”阶段的初学者二是已经在做应用但想补齐底层能力的开发者。什么算“from scratch”我个人给它的定义是不依赖现成的模型权重和封装好的训练框架靠开源组件和基础库自己完成数据处理、模型结构搭建、训练循环、评估与推理部署。这不是排斥PyTorch或Transformers这类工具——它们是生产级工程的一部分而是说你的核心竞争力在于“知道每一层下面是什么”。2. 整体设计一条推理模型从零到一的思路拆解2.1 为什么要自己造轮子直接使用开源模型然后再微调看起来效率高得多。但这条路有个隐蔽问题你对模型内部一无所知遇到问题只能查issue、问社区没有能力独立判断。自己从零构建等同于把“黑盒”打开看清楚里面的每一条线。这个过程会让你建立真正的工程直觉面对显存溢出、loss震荡、生成重复这些难题时能在一开始就判断问题出在数据侧、模型侧还是训练策略侧。用盖房子来类比别人给你交付精装修房你住进去很舒服但墙里的水电你完全不懂自己从毛坯开始每一根钢筋怎么排、每一路电线怎么走你都门儿清。日后装修升级你是有决策能力的。AI工程同理从零构建的价值不在于最终那个小模型本身而在于你获得了“任何一个环节出问题都敢于下手”的底气。2.2 选择“小模型推理任务”作为起点“ai-engineering-from-scratch”项目里有各种方向我当时选择的是“构建一个小规模推理模型”。推理任务本身对模型能力的挑战很综合它要求模型具备逻辑链、上下文理解和多步计算能力这比单纯做文本分类更能暴露架构和训练策略中的问题。而且推理任务数据可以做构造性生成不需要像我这种个人开发者去海量爬数据训练目标也容易量化评估——准确率就是准确率容不得含糊。参数量控制在1.5亿约150M这个量级是我评估了显存预算后的选择。单张24GB的消费级显卡就能完成训练训练时间可控而模型容量又足够体现推理行为的涌现——虽然不如大模型那么明显但已经能观察到“思维链带来的准确率变化”这类有趣现象。这给了后续扩展的信心如果你能在一个小模型上把推理能力调教出来那这套方法论迁移到大模型上同样有效只是成本和数据量等比放大。2.3 技术选型不迷信最热门只选最可控我见过不少人一上来就上FSDP、DeepSpeed、混合专家模型结果环境配置都花了一周。我的思路反着来同时在手写的训练循环里用上标准库和PyTorch原语保证自己对每一步有掌控力。选择如下框架层PyTorch 2.x不用封装过度的Trainer手写训练循环。这样梯度更新、学习率调度、梯度裁剪这些过程就都在自己眼皮底下。模型结构标准的decoder-only Transformer配合RoPE位置编码、RMSNorm和SwiGLU激活函数这基本是目前开源小模型的通用配方参考价值高踩坑资料多。分词器自己训练一个BPE词表词表大小1.6万覆盖中英文。自己训分词器这件事很多人会跳过但它恰恰是理解tokenize机制的最好入口。训练策略两阶段先做预训练next token prediction再做指令微调SFT和偏好优化用GRPO这种轻量策略而不是依赖全套RLHF管线。这套选型下来整条链路没有一步是“某个库里自动完成的魔法”每一步都有对应的代码和日志可以观察。3. 核心细节解析数据、架构与训练的实操要点3.1 数据准备从零开始搭一个推理数据管线数据永远是大模型工程的起点。我构造推理数据的核心思路是“程序化生成人工校验”。具体来说我写了一套Python脚本自动生成三种类型的推理样本数学推理比如“小明有5个苹果给了小红2个又买了3个问现在有几个”这类题可以用随机参数生成无数变体。逻辑推理比如“已知A大于BB大于C问A和C的关系”这类题考察模型对传递性关系的理解。多步常识推理我基于一些常识知识库构造带多个约束条件的判断题目。生成规则本身写起来不难难点在去重和质量控制。自动化生成会带来大量相似句式一旦语料单一模型会学成“复读机”。我是这样解决的模板里加入至少5种句式变体、插入干扰信息比如题目中故意加入对解题无用的条件并要求模型在答案中显式写出推理步骤再用规则自动校验答案正确性。这样清洗下来得到约50万条预训练语料加10万条指令数据。关于数据配比经验值是这样预训练语料中通用文本占70%推理专项占30%。这个配比我调过好几次推理专项比例太低模型学不会推理比例太高模型会变得“只会推理不会说人话”通用能力退化。30%是我试下来比较平衡的点。注意自动生成数据一定要做“对抗验证”。我第一版生成的数学题有个bug两个随机数相等时答案恒为“相等”模型学到这个捷径后遇到AB的题正确率100%其他题直接崩。后来我专门写了一套测试集覆盖边界条件相等、负数、零、大数才把这个问题暴露出来并修正了生成规则。3.2 分词器BPE不是黑魔法是一套统计规则很多人觉得分词器无足轻重直接加载一个现成词表就完事。但从零构建的意义恰恰在于亲手训一次BPE。BPE的核心逻辑一句话就能讲清楚从字符级开始每一次迭代找出最高频的相邻字节对把它们合并成一个新token直到达到目标词表大小。实操中我写了大约200行代码实现BPE训练然后发现一个容易被忽略的细节训练分词器的语料必须和模型训练语料分布一致。如果拿纯英文语料训分词器去做中文推理中文长词会被切得稀碎模型输入序列被无意义拉长训练效率直线下降。我用的训练语料里含10%中文数据确保中文字符和常见词在词表里占有合理比例。训练BPE时的两个关键参数值得记录词表大小我选了16000。太小的话长词表达受限序列过长太大则嵌入层参数量膨胀对150M的小模型不划算。16000是“空间换时间”的中间态。最小频次阈值合并时要求一个字节对至少出现2次才允许合并否则词表会被低频噪点污染。分词器做好后一定跑一遍中文和英文的编码结果检查。我见过有人训练完分词器一编码“人工”这个词居然被切成“人”和“工”两个token这种情况模型很难学到稳定的语义映射需要靠提升词表覆盖率来解决。3.3 模型架构150M参数下的逐层拆解模型结构上我采用的是接近现代小模型标配的配置参数数值说明层数12层深度适中便于观察中间层行为隐藏维度768和BERT-base一致参考成熟经验注意力头数12头单头维度64词表大小16000自己训练的BPE词表上下文长度1024足以承载多步推理题参数量约1.52亿刚好落在150M量级这个配置逐一细说位置编码用RoPE旋转位置编码。相比绝对位置编码RoPE的优势是外推性更好且能天然表达相对位置关系这对推理任务的关键序列关系建模很有用。实现RoPE时最容易出错的点是旋转角度矩阵的维度要按“两两一组”计算且query和key都要施加旋转否则相对位置关系会被破坏。注意力部分采用标准多头注意力加上GQA分组查询注意力变体。GQA把KV头数量减少到总头数的1/4显存占用和计算量都能降下来而推理性能几乎无损。对个人开发者来说这意味着同样的显卡可以塞下更大的batch非常实用。前馈网络用SwiGLU激活替换传统ReLU。SwiGLU引入了一层可学习的门控实验下来对训练稳定性和模型表现都有正向帮助。注意实现SwiGLU时门控线性层的维度通常是4倍隐藏维度但需要按“2/3-4/3规则”调整即中间层维度设为约2048然后再扩到3072这样能在FLOPs和效果之间取得更优平衡。3.4 推理能力训练两阶段走预训练阶段比较简单直接next token prediction标准的交叉熵损失。但要让模型具备“推理能力”关键在于后训练——SFT阶段教模型“思考后回答”把思维链写进训练目标GRPO阶段教模型“写出更优的思考链”。SFT的做法对每条推理题我让人工和规则共同生成标准答案答案中必须包含一段逐步推理过程最终用“因此答案是 ”这样的格式收尾。训练时把这整段当作目标文本计算损失模型学的是“先推理后作答”的输出模式。GRPOGroup Relative Policy Optimization是相对轻量的偏好优化方法它不需要单独训练一个价值模型critic而是通过一组采样结果的相对优劣来更新策略。实操中我每次提问生成8条候选推理链用规则答案正确性、推理步骤完整性打分然后让模型向得分高的输出靠拢。这一步做完最直观的变化是模型不再“跳跃式输出答案”而是能写出有条理的中间推理步骤。补充一个实操经验GRPO的训练稳定性依赖KL散度约束的系数这个系数我调了好几个量级最终锁定在0.02附近。太小模型会迅速“贪便宜”只优化奖励输出千篇一律的模板太大模型根本不更新奖励曲线纹丝不动。每次调整系数后需要重新跑一次部分验证集看奖励变化速度这比盯训练集loss更有参考价值。4. 实操过程从零训练一个小推理模型的完整记录4.1 整体环境与资源配置我用的是一台自组机器单张RTX 4090 24GBCPU是32核内存64GB。这个配置在个人实践场景下属于“比上不足比下有余”但完全够用。如果你只有16GB显存也不是不能跑需要把batch size再调小、梯度累积步数加大或者把上下文长度压到512。软件环境上我用的是Python 3.11、PyTorch 2.1.2分布式训练甚至都没开——单卡单进程代码简单调试方便。这一阶段刻意避开“分布式复杂度”把全部精力聚焦在模型本身。4.2 第一周把数据管线和分词器跑通第一周实际推进的数据工作如下写生成脚本约800行Python覆盖三种推理题型的生成逻辑和校验逻辑。训练BPE分词器用全部预训练语料40轮迭代合并输出词表文件。做编码验证随机抽500条中文和500条英文样本人工检查切词结果的质量。第一周最容易出的问题是数据量看起来很大但去重后实际有效数据少得可怜。我在生成数学题时用了大量随机数去重后发现相似度高达70%以上。后来我在生成时加入种子变量和句式变体才把有效数据量提上来。4.3 第二到第四周预训练跑通预训练阶段我采用的超参数如下优化器AdamWbeta(0.9, 0.95)权重衰减0.1峰值学习率3e-4配合余弦退火调度warmup步数占总步数的3%全局batch size128单卡batch 16梯度累积8步序列长度1024梯度裁剪1.0训练总步数约30000步约3个epoch训练时我坚持手写训练循环核心代码结构大致如下# 训练启动脚本的关键部分伪代码逻辑说明 # 1. 加载数据按长度分组并填充到1024 # 2. 每个step前向计算logits计算交叉熵损失忽略padding位置 # 3. 反向传播后先做梯度裁剪再更新参数 # 4. 每500步记录一次loss定期保存checkpoint # 5. 每2000步在验证集上跑一次生成人工观察文本质量这代训练跑了约40小时最终验证损失在2.1附近。预训练做得好不好光看loss不够还要做“文本生成抽查”。我记得第一次看到模型能生成语义连贯的句子时说实话挺兴奋的但一眼就看出来它还不能做多步推理。这个阶段模型只是在“学语言”推理能力是后训练阶段才被激活的。4.4 第五到第六周SFT与GRPO后训练SFT阶段我用了10万条指令数据学习率降到1e-5只训练3个epoch。这阶段绝不能训太久否则模型会过拟合到指令格式一旦输入稍有偏差就崩溃。SFT训练结束的标志是验证集回答格式正确率稳定在95%以上但推理正确率仍有波动。然后进入GRPO阶段。我每次生成8条候选答案其中有些对的有些错的。用规则打分器答案正确性加推理步骤打分作为奖励训练8轮。GRPO对batch组织比较敏感我实际的做法是每条问题独立采样8次生成把8次输出当成一个group用组内相对优劣计算优势值再更新策略。这样一来不需要训练额外的价值模型代码实现难度一下子降低很多。4.5 评估结果我得到了什么训练完成后我在独立的2000条测试集上做了评估。结果如下数学推理准确率72.4%基座模型预训练后直接测试只有18%SFT后提升到46%GRPO后达到72.4%逻辑推理准确率68.9%多步常识推理准确率63.2%回答格式正确率98.5%这个结果对150M的小模型来说已经不错了。更重要的是它证明了“从零训练”的路线图是可复现的而不是只有大型团队才能做的事。你看基座到SFT到GRPO的准确率阶梯每一步的增量都很清晰这就是实践中最有说服力的东西。5. 常见问题与排查技巧实录5.1 训练不收敛loss居高不下这是从零训练里最容易遇见的问题。排查路径有顺序先看数据再看模型最后看训练策略。数据侧看分词质量如果tokenizer切词有问题序列长度分布异常loss会一直偏高模型侧用“小数据过拟合测试”自查拿100条数据如果模型连这100条都过拟合不了那就是模型实现的bug优先检查attention mask和位置编码训练策略侧则看学习率峰值学习率超过1e-3时小模型常常直接震荡发散。我自己就栽在batch size上手动梯度累积的逻辑里忘记除以累积步数等效batch直接变大了8倍优化器在隐式增大的batch下行为剧变loss曲线呈现明显震荡。这个问题如果没有“小数据过拟合测试”这个自查步骤排查起来会很费劲。5.2 生成结果重复陷入循环推理模型训练后最常见的failure mode就是“复读机”。原因通常是温度系数太低低于0.3或者训练数据缺乏多样性。处理办法有三层生成时把temperature从0.7降到0.5配合top-p0.9可以减少无意义循环。训练数据里去重加入更多句式变体。如果模型还是复读考虑是SFT阶段过拟合降低epoch数重训。5.3 推理能力弱答“全对”的题目不对了准确率上不去时我的排查顺序是先看100条失败case统计错误类型。是逻辑步骤缺失、计算错误还是格式崩溃如果是逻辑步骤缺失多半是SFT阶段思维链训练不够模型没学会“展开推理再作答”如果推理步骤写全了但最终答案错了那就是中间计算能力不足需要更多同类数据。GRPO阶段我会调整奖励函数的权重提高“答案正确”的权重0.7降低“推理格式完整”的权重0.3。因为格式再完美答案错了也没有意义。5.4 显卡显存不够怎么办显存OOM是从零训练的老大难问题。我的降显存顺序表手段显存节省效果代价减小batch size线性增加训练时间开启梯度累积几乎不省配合上一条等效batch控制用GQA替代MHA约20%稍微调整代码混合精度训练bf16约40%梯度裁剪值需微调减小序列长度线性上下文变短混合精度训练是我最推荐优先开的。bf16在RTX 4090等Ampere以上架构上有原生加速显存直接砍半训练速度反而提升。需要留意的只有一点如果用bf16梯度裁剪阈值建议从1.0降到0.5因为低精度下梯度范数波动会更大。5.5 复现不出别人论文里的结果“build a large language model from scratch”或“build a reasoning model from scratch”这类项目网上讨论热度一直很高除了一些经典书籍的官方代码仓库有完整实现外更多人面对的是一次次复现失败的打击。我的建议是别一上来就复现7B或13B模型先把100M~200M级别跑通。参数量上去后复现难度急剧上升超参数敏感性、数据分布差异、随机种子影响都会被放大。先在小模型上建立“踩坑地图”再等比放大成功率会高很多。6. 学习路线与配套资源不必到处找网盘先把这几件事做好考虑这个标题的时候很多人会去搜“build a large language model from scratch”这本书或代码甚至有人在网上翻百度云网盘分享。其实这条路有些绕——作者在官方页面直接开放了全书代码按章节组织得很好完全不需要去碰来路不明的资源。对你最要紧的不是囤资料而是把实践顺序理顺。我推荐的实践顺序是这样的手写BPE分词器哪怕实现得笨一点把过程跑通。用PyTorch手写一层Transformer在前向传播上多花时间熟悉张量形状流动。用小数据集100万token级跑一次完整预训练只求流程跑通。加推理构造数据做SFT观察模型行为变化。上GRPO体验偏好优化的调参过程。在动手之前建议先读一位前辈的开源项目README里关于“minimal implementation”的设计说明再对照经典的“nanoGPT”仓库理解代码组织方式。很多人读完就忘因为缺少自己的项目主线。把“ai-engineering-from-scratch”当成你自己的项目名README自己写代码自己提交每完成一个阶段就记录实验结果这种做法比收藏任何网盘资源都有用。既然题图已经摆出了roadmap我最后再分享一个执行层面的体会把这条学习路线当成一个季度项目来做。我当时的节奏是前两周读源码加搭环境后面每两周交付一个可运行模块。电子商务领域常讲“小步快跑”从零构建AI工程也是一样不必憋大招。先让训练循环跑起来即使loss高得离谱也没关系跑通本身就是里程碑。然后一步步把loss降下来、把推理准确率提上去、把生成质量调好——当你完整走完一遍后再回头看任何教程和开源项目都会有一种“原来如此”的通透感这种感受是任何速成路径都给不了的。