“ai-engineering-from-scratch”这个标题翻译过来就是“从零开始搞AI工程”。好多朋友看到这类标题第一反应是“又要从头手写一个Transformer了”第二反应是“这得学多少数学”。我当初也是抱着这种忐忑入坑的但一路实践下来发现真正的“from scratch”不是让你从矩阵乘法推起而是让你亲手走完一个AI应用从想法到落地的全流程把那些被封装好的概念一个个拆开看明白。这篇文章不打算给你画大饼就是把我自己从零搭建AI工程能力、做出可运行项目的完整路线和踩坑记录摊开讲。如果你是个想入局AI但一直被各种术语劝退的开发者或者已经会调API但总觉得心里没底的工程师这篇内容应该能帮你省下不少瞎摸索的时间。1. 为什么选择“从零开始”这条路1.1 这个项目到底想解决什么问题先说个普遍现象现在很多人学AI路径是“装个库、复制一段代码、跑通、结束”。这样学完遇到真实需求时依旧一脸懵因为AI工程根本不是单点技能而是数据、模型、提示词、检索、评测、部署这一整条链路的协同。我见过两类人卡得最狠。一类是只会调包出了问题不知道怎么排查模型输出不对也不知道从哪个环节下手。另一类是理论控抱着花书啃了三个月数学推导都会但一行能跑的应用代码都写不出来。“ai-engineering-from-scratch”想解决的就是这两类人的共同痛点缺一条把理论和实践串起来、从零到一完整走通的路线。它不要求你先成为算法专家而是要求你在动手做的过程中把“模型为什么这么输出”“检索为什么召不回”“提示词为什么不稳定”这些问题逐个弄明白。1.2 “from scratch”不等于重复造轮子这是我踩过最大的认知坑必须讲清楚。“from scratch”很容易被理解成“所有东西都自己写”。真要这么干光是把一个像样的Transformer从零训到能用就得烧掉大几千GPU小时个人开发者根本玩不起。我自己的理解是分层式的“从零”应用层你完全可以用现成的框架和库机制层你要能说出输入输出和基本流程实现层你至少要亲手写过一个最小版本。打个比方学做饭不一定要从种地开始但你必须亲手洗过菜、切过肉、盯过火候否则给你一袋米你也煮不出能入口的饭。这套路线的具体做法是大模型用开源的但你要自己完成数据处理、微调脚本、提示词设计、检索接入、评测集构建。每一步都动手做一遍但不需要从零写Attention。等你把这条链路跑通那些天花乱坠的概念就再也唬不住你了。1.3 用“最小可行项目”驱动学习光说概念太虚我讲讲自己是怎么设计学习路线的。我的做法是先给自己定一个足够具体、又不可能一步到位的目标用本地部署的小模型做一个能回答私有文档问题的问答助手并且让它具备调用工具完成简单任务的能力。定了目标之后我把技能树拆成六个模块每个模块对应一个必须亲手完成的最小实验。技能模块你需要弄懂的核心问题最小实验数据工程模型吃什么格式的数据清洗并用脚本格式化一批指令数据模型原理输入输出之间发生了什么微调一个小模型并观察输出变化Prompt工程怎么让模型稳定输出想要的结果用结构化模板解决一个具体任务RAG检索怎么把外部知识接进模型搭建一个文档问答的最小RAG管线Agent编排怎么让模型自主调用工具实现一个能查时间、算算术的Agent循环评测体系怎么量化回答的好坏构建20条基准case并跑分每个最小实验都在一到两天内完成不强求完美但必须留下可复盘的笔记。这六个模块做完你对AI工程的整体认知框架就立起来了。后面所有进阶内容都能挂到这个框架上而不是像海绵一样什么都吸收不了。2. 从零搭建AI工程的核心知识地图2.1 数学与机器学习基础学多少才算够想起“from scratch”里的数学要求很多人直接被吓退。我可以用自己的经验给你吃颗定心丸做AI工程需要的数学远没有你想象的那么多但几样核心的一样都不能少。线性代数你需要真正理解矩阵乘法因为一句话放进模型最终就是向量和矩阵在计算。概率统计你要懂条件概率尤其在RAG场景里“给定问题找到最相关的文档片段”本质上就是一个条件概率问题。微积分你不需要会手推复杂公式但要知道梯度是“损失函数下降的方向”否则调学习率就是纯玄学。机器学习基础反而比数学更重要。训练集、验证集、测试集为什么要分开过拟合是什么准确率和召回率有什么区别这些概念支撑着你后续每一个决策。我见过不少代码能力很强的开发者在这些概念上吃亏模型在训练集上表现完美一到真实场景就抓瞎这就是数据划分没搞明白的锅。我的建议很直接数学用“够用就行”的标准来要求自己但机器学习核心概念必须吃透。不懂梯度推导不影响你调模型不懂过拟合和评估指标会直接影响你判断模型好不好。2.2 大模型原理解读Transformer到底在干什么从零理解大模型不需要背住原论文的每一个公式但几个核心机制必须建立直觉。Token是模型读文本的最小单位一句话会被切成许多小段每个token都会转成数字向量。Embedding就是这个转换过程你可以把它理解为每个词在模型“脑海”里的坐标。注意力机制是模型在生成每个词时会回头看输入序列里哪些词和自己当前的任务相关类似做小组作业时翻了翻别人写的那几段重点而不是闭着眼睛自己瞎写。搞清楚预训练和指令微调的区别尤其重要。预训练是让模型学会“接龙”看到前半句预测后半句所以它懂语法、懂常识但不会听话。指令微调是在大量“问题-答案”对上进行训练让模型学会“你问什么我答什么”这才是我们日常用的“助手感”来源。推理阶段的温度参数也值得亲手试一试。温度越低输出越确定适合抽取信息类的任务温度越高输出越发散适合让你眼前一亮但可能胡说八话的创意场景。做AI工程的人要是连温度都调不明白就相当于开车不知道油门深浅。2.3 工程新范式Prompt、RAG与Agent这一节是AI工程区别于传统软件工程的核心增量我按依赖顺序一个个拆。Prompt工程不是“写个好看的提示词”而是通过结构化的上下文约束模型的输出行为。干得多了你会发现清晰的指令、明确的格式要求、加几个示例few-shot效果远好于玄学式调词。RAG解决的是模型知识过时和幻觉的问题。模型训练完后就冻结在某个时间点了你拦不住它乱编不知道的事情。RAG的做法是在模型回答之前先到外部知识库里检索相关片段塞进上下文让模型看着资料回答。用开卷考试来理解最贴切以前模型是闭卷硬编RAG是允许它带资料进考场。Agent是更进一步。模型不再只是“生成一句话”而是像一个项目经理拆解任务、调用工具、看结果、决定下一步。模型周围那一圈负责“工具调度、循环控制、结果校验”的逻辑现在业内经常叫harness那个不停的“规划-执行-观察-再规划”的循环过程就是loop engineering。这层工程能力的价值我在后面的实操环节会详细展示。这一整套范式里最容易被忽略的是评测。Prompt改一个词、检索换一个库输出都可能翻天覆地。没有一套自己的评测机制你根本不知道改动是变好还是变坏。AI工程里评测体系就是传统软件开发里的单元测试它的优先级应该排在一切优化之前。3. 实操落地一个可复现的从零到一项目3.1 第一步搭好环境选对实验对象讲完地图正式开始施工。我做的项目是一个本地知识问答助手并能调用两个简单工具查当前时间、做四则运算。整体技术栈选的是Python加上开源小模型全部代码跑在一张消费级显卡上。环境搭建我推荐直接用uv来管理Python依赖比conda快很多一条命令就能建好环境。Python版本选3.11及以上PyTorch安装时一定注意CUDA版本要和驱动匹配这个问题困扰过无数新手。实验对象我选的是Qwen系的小尺寸模型比如Qwen2.5-0.5B或1.5B版本。选小模型的原因非常现实显存要求低推理速度快迭代实验只需几秒就能看到效果。等你在小模型上把流程跑通了再切到大模型就是改个模型名的事。显存估算有个实用技巧加载模型所需显存大约等于参数数量乘以每个参数占用的字节数FP16精度下大概就是参数量乘以2。0.5B参数模型用FP16加载大约需要1GB显存加上推理过程的中间激活实际留2到3GB就够用。这个估算方法在选型时非常实用。3.2 第二步从零训练一个小型模型的完整路径说好的“from scratch”这里就是核心环节。我分三次递进实验来走完整条路径。第一次实验是验证基座模型能力。直接加载预训练的Qwen2.5-0.5B-Instruct给它几个提示词看看它能不能正常对话。这个阶段你要记录下模型在未针对你的场景微调前的表现后面你才知道微调到底带来了什么变化。第二次实验做了继续预训练用自己的领域语料让模型“见更多世面”。我把一批技术文档和问答记录整理成纯文本喂给模型做自监督训练。最关键的是数据预处理把所有文本按512个token的长度切块防止超长截断造成语义断裂。第三次实验才是真正的指令微调也是最出效果的环节。我准备了一份大约两千条的指令数据集每条数据是标准的“system instruction response”结构格式就用JSON维护。训练配置用的是LoRA技术只训练一小部分参数大幅降低显存压力。我用的参数是学习率5e-5、批次大小8、训练3个epoch。训练目标就是让模型学会“针对问题给答案”的格式。整个微调过程跑完后我用几个没见过的测试问题进行对比基座模型可能答非所问微调后的模型能稳定地按你期望的格式回答。这种肉眼可见的变化是理解“训练到底在干什么”最好的教材。3.3 第三步把模型接进RAG与Agent应用模型微调好了它依然回答不了私有知识库里的具体问题这时候就要接RAG。RAG管线拆开就四步先把本地文档切块用嵌入模型把每一块转成向量再把这些向量存进向量数据库里用户提问时把问题也转成向量在库里做相似度检索最后把召回的几段文本拼到提示词里交给大模型生成答案。我的实现里嵌入模型用了BAAI的bge-small-zh-v1.5向量库用了Chroma因为它在本地文件模式下零配置、够轻量。核心检索代码长这样from chromadb import Client from sentence_transformers import SentenceTransformer embed_model SentenceTransformer(BAAI/bge-small-zh-v1.5) client Client() collection client.get_or_create_collection(doc_qa) def add_documents(docs): ids [fdoc_{i} for i in range(len(docs))] vectors embed_model.encode(docs).tolist() collection.add(idsids, documentsdocs, embeddingsvectors) def retrieve(query, top_k3): q_vec embed_model.encode([query]).tolist() results collection.query(query_embeddingsq_vec, n_resultstop_k) return results[documents]提示词模板是整个应用里最需要反复打磨的部分。我采用的模板包含三段角色定义“你是知识问答助手”、参考资料你检索到的内容、用户问题。经验是必须在模板里写明“请仅根据参考资料回答如果参考资料中没有相关内容请直接回答不知道”否则模型综合看多了还是会自己编。Agent循环是最后一步。我为模型准备了两个工具get_current_time和calculator每个工具都有名字、描述和输入输出格式。模型根据用户问题生成一段结构化的工具调用指令我的代码负责解析指令、执行对应函数、把结果返回给模型循环判断是否需要继续调用。这个“模型思考、代码执行、结果回传”的循环就是前文提到的loop engineering在Agent应用里是核心骨架。3.4 第四步部署与简单上线本地实验跑通后我建议再花半天时间把它做成一个Web服务这个环节会逼着你处理很多真实工程问题。我用FastAPI包了一层HTTP接口把“接收问题、检索、调用Agent循环、返回结果”串成一个函数然后用uvicorn启动服务。部署过程中至少要解决两个问题一是多用户并发时模型推理要排队我在代码里加了一个简单的任务队列二是生成参数的设置经过几轮测试我的项目里温度和max_tokens分别定在0.4和512既保证输出稳定又不至于答到一半被截断。还有一个容易被忽略的点上线服务必须记录日志包括用户输入、检索到的文档、模型原始输出、最终返回结果。这些日志是你后续优化数据闭环的基础没有日志的AI应用等于没有黑匣子的飞机出事根本无法排查。4. 工程化必备评测、监控与迭代4.1 没有评测就没有AI工程做AI工程和做传统开发最大的区别就是代码逻辑是确定的模型输出是不确定的。你改一行代码传统项目要么对要么错而AI项目这次答得好下次可能答得差。没有一套评测体系你根本无法判断改动到底是优化还是劣化。我的做法是从项目一开始就构建评测集。第一批case只有二十条但类型覆盖很全有简单的事实问答有需要从文档中归纳的复杂问题有知识库完全没有的未知问题还有故意绕弯子的陷阱问题。评测指标我分两层来跑。硬指标是格式正确率比如模型有没有按要求的格式输出、工具调用有没有被正确解析。软指标用LLM-as-judge让一个更强的模型当裁判对回答质量打1到5分。具体做法是写一个评测脚本批量跑完所有case输出一个分数表每次改动后都跑一遍。这个习惯的价值在你调几次提示词之后会体现得淋漓尽致。你以为这次改动把效果“优化”了评测分数告诉你整体其实下降了因为它在另一个case上变差了。评测集就是你的AI项目的“考试大纲”没有它学习进步就无从谈起。4.2 日志、监控与数据闭环评测是开始监控是持续数据闭环才是真正的迭代引擎。我在服务上线的同时接入了日志系统每次都记录完整链路信息。每周我会花一个下午翻看日志里的失败案例把它们汇总成新的评测case加进评测集。比如我发现日志里有不少用户问“最近的项目进度怎么样”而知识库里根本没有对应的内容模型却煞有介事地编了一段。这个badcase进评测集之后我针对性修改了提示词要求模型“无法从参考文档获得答案时明确说不知道”再跑一轮评测这类问题明显减少。迭代决策上我总结出一个优先级参考表你可以直接当工具用。症状优先排查方向常见解法回答内容不对检索质量换嵌入模型、调top_k、改进切块策略回答格式不稳定Prompt设计加few-shot示例、明确输出格式约束答非所问上下文组织调整提示词模板、限制上下文长度幻觉严重系统提示词强制要求“仅依据资料回答”工具调用失败Agent编排检查工具描述、修正解析逻辑这条数据闭环跑起来之后整个系统才真正进入可进化状态。每一次用户的“不满意”都会变成你的训练素材你的评测集在变厚你的模型和提示词在跟着变强。这就是AI工程和一次性脚本的根本区别。5. 常见问题与避坑实录5.1 训练阶段的三大坑训练小模型过程中我踩过不少坑挑最有代表性的三个说。第一个是显存溢出。这个问题八成出在序列长度上模型一次能处理的token数量越多显存占用指数级上涨。后来我把最大序列长度从1024降到512批次大小调小配合梯度累积一张8GB显存的卡就能稳定跑微调了。第二个是数据泄漏。我第一次整理训练数据时把测试集的问题也混进了训练数据里导致验证表现分虚高。这个错误很隐蔽因为你不会主动犯而是因为数据清洗脚本写得粗心。建议在预处理阶段就对每条数据打上来源标记从机制上杜绝泄漏。第三个是损失下降但生成效果差。这种情况通常不是模型的问题而是数据问题。我第一版数据里好几条“问题-答案”实际是重复的造成模型对少数样本过拟合。后来我做了去重和数量均衡效果立刻变好。记住小模型微调数据的质量永远大于数据的数量杂乱的二千条不如干净的一千条。5.2 RAG与Agent阶段的高频问题RAG和Agent阶段的坑比训练更隐蔽。召回为空或者召回错误我遇到过好多次。最常见的原因是查询和文档的表述差异太大比如文档里写的是“模型参数量”用户问的是“这个模型有多大”。解法是改进切块策略让每块文本自带更多上下文同时调高top_k有时候召回五段比召回三段靠谱得多。上下文塞满导致的答非所问是RAG的经典坑。当检索到的内容多而杂时强相关的内容被弱相关的内容淹没模型抓不住重点。我在提示词里会加一个排序指令“从参考资料中优先使用与问题最相关的部分”并且限制检索结果数量让上下文保持精简。Agent死循环是另一个常见灾难。我遇到过模型在工具调用结果不符合预期时反复调用同一个工具停不下来的情况。解决的办法是给循环加了一个最大轮数限制比如五轮同时在提示词里明确告诉模型“如果调用结果已经足够就该给用户答复了”。工具调用格式错误也好办就在工具描述里写清了JSON格式样例模型出错率直线下降。我把这些坑整理成一个速查表放在手边随时查。问题症状排查顺序显存溢出训练中断序列长度→批量大小→精度策略召回为空生成的答案明显没依据切块大小→top_k→嵌入模型Agent死循环工具被反复调用最大轮数→工具描述→结果校验逻辑输出被截断回答到一半没了max_tokens→输出长度→批量处理格式不稳定有时带标题有时不带提示词模板→few-shot示例→温度设置5.3 学习路径上的现实建议最后讲点心态相关的经验。很多人学AI工程最大的问题不是笨而是贪。今天看RAG明天看微调后天研究多Agent协作每一个都浅尝辄止三个月后什么也没沉淀下来。我自己的经验是一段时间只吃透一个项目。一个项目能同时覆盖数据、模型、提示词、检索、评测和部署这六个环节已经足够你消化好几个月。把这一个项目做深做透比草草做十个项目有价值得多。动手之前建一个实验笔记把每次改动的动机、操作、结果都记下来。这不仅是复盘工具更是你建立“工程直觉”的燃料。AI工程里的很多经验比如“温度调到0.3以下更稳定”“切块粒度在200个token左右效果最好”都不是从教程看来的而是你自己一次次实验试出来的。这些记录就是你的个人知识库是你从一个只会跟教程走的人转变为一个能独立做决策的工程师的关键。从我个人的体会来说完成这个从零到一的项目带给我的远不止“会搭一套系统”这个结果。更重要的是它替我把AI工程里那些听起来很高级的词汇一一落地让我清楚地知道每一个环节的输入是什么、输出是什么、在哪一步出了问题应该往哪里查。这种亲手拆解过的踏实感是看再多的教程和数据都换不来的。如果你也想走这条路我的建议很明确今天就选一个最小的项目把环境搭起来。不用等完整学会所有理论因为AI工程本来就是一门“先动手、再补课”的手艺。你先跑起来问题会自己找上你而你只需要在解决这些问题的过程中不断地记录、调整、再记录。你会发现所谓“from scratch”其实没那么吓人它要的只是你敢于从第一步开始走。