
1. 为什么我决定从零开始搞AI工程先聊点实在的。过去两年我身边不少朋友转型做AI相关的工作最开始都是先跑去学Transformer结构、啃反向传播公式结果半年下来还没碰过一行能上线的代码。后来我去复盘那些真正能在公司里把AI项目落地的人发现他们根本不是算法天才而是“能把模型跑起来、接进业务、还能稳住线上效果”的工程人。这个标题“ai-engineering-from-scratch”与其说是一份学习路线图不如说是我给自己定下的一个规矩不走捷径、不跳过基础、用做传统软件工程的标准去对待AI系统。我知道市面上有太多号称“三天上手大模型应用开发”的速成课但真正能把一个RAG检索增强生成系统从零搭出来并且回答准确率稳得住、费用控得住、故障查得清的人靠的绝对是扎实的工程能力。这篇文章不打算给你画一张覆盖所有AI知识点的地图我写的是我自己执行下来的一条完整路径先搞清楚AI工程和传统软件工程在思维上的差别再按“基础语言能力 → 模型调用原理 → RAG实战 → Agent编排 → 评估上线”这条主线往下走每一层都有我能直接复用的工具、参数和避坑记录。适合谁看如果你有普通后端或脚本开发基础想进入大模型应用开发方向或者你已经在做AI功能但总觉得像在“黑盒调参”这篇内容会给你一个可执行的参照系。我先说一个关键认知AI工程的核心不是“训练模型”而是“用工程手段把预训练模型能力稳定地变成产品功能”。这两件事对绝大部分人来说是两套完全不同的技能树。我们不需要会从零训练一个大模型但必须非常熟练地做这些事写高质量的提示词、设计Agent的任务链路、管理上下文窗口、评估生成内容的质量、压低API成本、处理模型输出不稳定带来的线上问题。2. 先破一个误区AI工程不是算法岗2.1 “工程师”和“研究员”在做事方式上的分岔路我见过很多新手一上来就买深度学习课本把大量时间花在了一个他们实际上用不到的方向上。现在的应用层AI开发绝大多数工作内容是在和大语言模型的API打交道用工程手段约束它的行为而不是去改动模型本身的权重。真正需要你从头训练或者微调模型的场景在公司里通常只是一个很小比例而且往往有专门做算法的人负责。我做了几年后端转过来做AI应用之后最大的体会是这个岗位的本质还是工程只是代码要服务的对象从“确定性的业务逻辑”变成了“具有概率性的模型输出”。传统后端写好一个接口输入相同参数返回结构基本稳定可预期但在AI系统里同样的输入提示词模型返回的内容可能有差异甚至会有幻觉、答非所问、格式漂移这类问题。你写的代码很多精力是用在“约束不确定性、兜住边界情况、稳定输出质量控制”上。所以“从零开始学AI工程”的第一步不是去背Attention机制的各种公式而是先把工程底座打牢Python语法和异步编程玩得转不HTTP接口、JSON数据处理、正则表达式、字符串清洗这种基本功扎不扎实还有一个往往被忽略的点——你愿不愿意反复调试同一个问题二十遍以上。AI开发的日常就是和“不可控输出”搏斗没有这种耐心和排查耐力后面会非常难受。2.2 AI工程对知识结构的要求与传统开发不完全一样我整理过一张对照表能比较清晰地展示AI工程师和前后端工程师在技能重心上的区别能力维度传统软件工程师侧重AI应用工程师侧重编程语言多种语言系统底层原理Python为主脚本化、快速迭代能力强数据结构复杂算法、内存管理字符串处理、向量检索、JSON结构设计存储知识MySQL、Redis、MQ等向量数据库、传统数据库混合使用核心思维逻辑确定性、状态一致概率思维、不确定性容忍、兜底策略调试能力打断点、查日志、追踪事务提示词排查、向量召回质量分析、生成内容校验系统设计微服务、高并发、容灾多模型编排、Agent链路、缓存与控制成本这并不是说传统开发的技能就没用了恰恰相反传统工程的那种严谨性正是AI工程最稀缺的东西。很多翻车案例都是因为AI调用没有加超时控制、没有做内容格式校验、没有设计降级方案导致线上出了问题。一个真正优秀的AI工程师往往是一个“非常懂传统工程的人”再加上AI专项知识。3. 从零起步的完整学习路线我把阶段拆成了五层3.1 第一阶段把Python“真正”练到能干活我知道很多人会用“会写Python”和“能用Python干活”当成一回事但实际上差距相当大。第二阶段开始之前我自己做了一个检测清单你可以拿来对照能不能用Python写一个支持并发请求的脚本能不能用requests或httpx完成包含认证、重试、超时控制的API调用对json模块的loads/dumps是否熟悉到可以随手处理各种嵌套结构正则表达式用来清理模型生成的文本时能不能一次写对这里面我强调三件事。第一是异步编程很多AI应用的接口动辄需要几秒甚至更长的响应时间如果你用串行方式批量调用API几十条文本就要等好几分钟后面做评估集和批量测试时会痛苦到怀疑人生。第二是类型和异常处理写AI相关代码一定要习惯“任何输入都可能长得很奇怪”每个解析环节都要用try-except接住异常不然生产环境一条非预期格式就能拖垮整个任务链路。第三是“写代码的速度”AI开发是高度迭代试错的过程一个念头从冒出来到写成代码验证切换越快效率越高。这个阶段我的建议是不要看太多书直接找一个小目标项目练手比如写一个命令行工具输入一段英文文本自动调一个翻译接口翻成中文再做成批量文件处理。完成这个过程中你会自然补上requests、argparse、文件IO这些基础拼图。3.2 第二阶段搞懂LLM的调用原理和非结构化的魅力很多人把调用大模型这件事想得太简单觉得不就是发个POST请求带上prompt吗其实里面有大量值得深挖的细节。我从零开始梳理沉淀出了四个关键层上下文结构System/User/Assistant三方的角色分工、Token的计算方式与费用关系、温度等采样参数对输出的影响规律、函数调用Function Calling协议的设计。先说角色分工。System消息负责设定人设、边界与风格User消息是用户输入Assistant消息通常承载历史对话记录或者模型先前输出。新手最常见的错误就是把所有指令全部塞进User里导致系统行为在各轮对话中出现漂移。我的经验是System部分的权重很大几乎所有“必须遵守”“绝对禁止”的约束都要放在这一层并且要写得具体可执行不要说“回答要准确”要写“如果无法确定答案明确回复‘信息不足’”这种带边界的指令比模糊宏大的要求有效得多。再谈参数。Temperature这个参数很多人只知道“越高越随机越低越确定”但实际使用中它的作用范围是有限度的调低温度并不能完全消除幻觉只能让输出分布更集中在概率较高的路径上。还有max_tokens这个参数如果不设置或者设置过小长文本生成时会莫名其妙被截断而且不报错。我在线上系统里吃过这个亏用户要一份长报告输出到一半就安静地断掉了排查了很久才发现是max_tokens设置不到位。Function Calling值得专门花时间去吃透。它是让模型从“对话闲聊”走向“真正做事”的桥梁——模型本身不做计算、不查数据、不执行操作但它能根据用户的意图输出一个结构化的调用指令由你的代码去真正执行再把执行结果以“工具响应”的形式回传给模型由模型组织最终回答。这个模式是所有Agent系统的基础底座学会了它你才算真正入行了AI工程。3.3 第三阶段RAG不是把文档塞进去就完事RAG是我认为整个应用层AI工程里最值得投入时间去精通的模块。为什么因为在企业真实场景中让模型基于私有知识库回答问题是最普遍、最刚需的需求。但RAG的落地效果差距非常大有人做出来的系统引用准确、回答可靠有人做出来的系统答非所问、张冠李戴差别往往不在模型本身而在“索引质量”和“检索策略”这两个工程环节。索引质量的核心是“切分策略”和“向量化效果”。很多新手拿着PDF一顿解析按固定字数把文本咔咔切断然后往向量库里一丢就算完事结果用户提问时召回的内容支离破碎。我在项目里踩过的坑包括表格内容被切断导致语义丢失一个完整方案被拆分到两段导致答案不完整专有名词被切分后向量表征异常。后来我沉淀出一套自己的切分经验优先按Markdown标题结构和段落语义做切分而不是无脑按字数每个切块尽量控制在语义完整可以适当重叠上下文块与块之间如果有关联关系用附加元数据字段记录下来。向量化效果的核心是Embedding模型选型和文本规范化。工业落地我是强烈建议用专门的Embedding API服务不要自己本地部署一个效果很差的模型省成本最后召回率低到你想哭。文本在入库之前要统一清理格式包括去除多余换行、规范全角半角、处理超长段落等。就是这些看起来不起眼的预处理工作对最终检索质量的影响比你在提示词里雕花大得多。检索策略上纯向量检索通常在复杂问答上表现不够稳定我后来引入了“混合检索”方案向量召回找语义相近的内容同时用关键词匹配找精确命中的片段尤其是型号、人名、编号这类实体两者结果做加权融合。这个改动让我的项目检索准确率直接提升了不止一个档次具体融合权重需要你在自己的数据集上做实验来确定但没有这个思路的话不少场景会一直卡在瓶颈上。3.4 第四阶段Agent与工作流编排——让模型学会“干活”当你能够稳定地让模型回答单轮问题后下一步就是让它完成多步骤任务也就是Agent。我对Agent的理解很简单它是一套“大脑手脚”的结构。大脑是LLM负责理解任务、拆解步骤、决定调用哪个工具手脚是外部函数比如搜索引擎、数据库查询、内部API甚至是另一个模型。模型本身不具备“执行”能力但它可以通过思考输出工具调用指令由工程代码来真正完成动作循环往复直到任务结束。在动手写Agent框架之前我强烈建议你先在“单轮工具调用”上完全熟练再考虑多轮循环。拆解一个真实场景用户说“帮我查一下上周华东区的销售额并对比前一周的变动”。Agent需要先调用一个“销售数据查询”工具工具返回原始数据后模型可能觉得数据还不够详细需要再调一次工具获取明细然后综合所有信息生成最终结论。整个编排过程中你作为工程师需要管理模型上下文里的工具描述、控制调用次数上限、设定异常终止条件。我用的一个比较稳定的编排模板是“计划-执行-反思”循环。第一轮先让模型输出一个执行计划然后逐步执行每个步骤每步执行完后做一次校验最后给模型一次“反思”的机会让它检查结果是否完整、是否需要额外补充。用这套结构跑了很多场景成功率比直接让模型“一步到位”要稳定得多。代价是多了几轮调用、多了些成本但对业务确定性要求高的场景值得。Agent领域现在工具和框架很多我的建议是保持克制先用自己的代码把核心循环写一遍彻底理解每个环节的输入输出和失败模式再考虑是否引入框架。很多框架抽象度高出了问题你连日志都看不明白不如自己维护一个几百行的核心循环把每步的状态和上下文都显式打印出来排查起问题来非常顺手。3.5 第五阶段评估和上线——AI工程真正拉开差距的地方我见过太多AI项目死在“Demo效果好但线上不敢用”的阶段。本地测试的时候怎么问怎么答一上线就各种翻车原因就是缺少系统性的评估环节。这一阶段是整个AI工程链路里最容易被人忽视但恰恰是价值最大的部分。先建立一个朴素的评估集把业务场景里最常出现的20到50个问题整理出来每个问题配好参考答案、评估要点和预期引用的知识来源。然后定期跑批量评估逐条记录模型的回答对照参考答案做打分。打分维度我一般拆成三个准确性事实是否正确、完整性用户的需求点是否全部覆盖、忠实度回答是否严格基于知识库内容还是出现了编造。前两个好理解第三个对于RAG类项目尤其关键模型再流畅的表达如果是基于幻觉生成的在这个维度上也应该给零分。上线环节要注意的基础配置也很多逐一说一遍所有模型API调用都要有超时和重试配置用户输入要做长度限制和简单的内容合规校验模型输出要接一层“结构化校验器”比如我要求必须返回JSON格式的地方会在代码里做一次真实解析解析失败就触发重试成本监控要做起来记录每天的总Token消耗和按用户维度的用量分布防止异常调用把预算烧穿。这些细节单看都不复杂但它们决定了一个AI功能是“能用的玩具”还是“可靠的功能”。4. 我的实操记录从零搭起一个RAG问答系统的全过程4.1 我选择的技术栈和一件重要的事情理论说了一堆我用一个实际做过的项目串一遍全部环节。这个项目是一个内部知识库问答机器人知识源是几十篇产品文档和售后手册目标是让员工用自然语言提问机器人基于文档内容给出带引用的准确回答。技术栈我做了一个比较务实的选型。向量数据库我选了Qdrant原因是它支持混合检索同时做向量相似度和关键词匹配部署轻量、Python客户端写起来顺手。Embedding模型用的商用API。LLM用的也是商用API。框架方面我刻意没有使用当下流行的Agent框架核心代码全部自己写总共大概700行Python维护成本很低每一行我都知道它在干什么。这里要强调一个我特别想分享的经验在AI项目里不要过度工程化。刚开始不要上来就设计复杂的Agent、多模型协作、知识图谱这些东西。我见过太多人第一版就搞得很复杂结果连最基础的主链路文档入库→检索→生成回答的准确率都没验证过架构再炫也没有意义。先把最简单的版本跑起来拿到评估数据再决定哪些复杂机制是真正有必要的。4.2 文档处理与入库这一步偷懒后面全是泪原始文档五花八门有Word版的产品手册、有PDF格式的售后流程、还有Markdown格式的内部Wiki。我做的第一件事是写一个统一解析脚本把它们全部清洗成干净的标准Markdown。这个环节看起来不起眼但对于后续所有效果起到了决定性作用。清洗内容包括去除页眉页脚噪声、把Word里的表格转换为Markdown表格、统一标题层级、修正PDF解析产生的乱码和断裂行、删除大段无意义的重复版权声明。我当时统计了一下光是“去除页眉噪声”这一步就让最终检索命中率明显改善因为之前向量库里索引了大量“第X页共X页”这类垃圾片段干扰了语义匹配。切分策略上我没用固定字数切分而是先按Markdown结构切到二级标题再对每个大块内部做语义段落合并。每个切块保留了两类元数据来源文档ID和原文中的标题路径。这些元数据在后续的引用溯源和答案验证阶段发挥了重要作用没有它们生成的回答只能给出内容却无法提供可靠的引用出处。4.3 写入向量库和检索链路的细节文档切分好后每段文本调用Embedding接口转成向量然后写入Qdrant的collection。这里有几个参数我反复调过向量维度由Embedding模型决定写入时设置的distance我用的是Cosine写入batch size设到32太大会超时太小则效率低每条点point的payload里包含原文文本、元数据、以及一个文档ID字段。检索阶段我用了混合检索。具体的比例如下向量相似度召回30条候选关键词匹配召回20条候选两组候选基于“文档ID去重后合并打分”的方式做融合。融合规则我用了加权归一化向量相关性得分占0.7的权重关键词命中得分占0.3的权重最终组合后取Top 5片段作为上下文送给LLM。这个比例不是拍脑袋定的是我在30个测试问题上做了几组对比实验后选出来的。检索完成之后还有一个细节要检查召回的片段之间是否存在内容冲突。比如一个片段说某功能支持A方式另一个片段说仅支持B方式这种冲突如果不加处理直接塞给LLM模型可能选择性融合两头信息生成一个看似合理其实两边都不符合的答案。我在这个问题上吃过亏后来加了一步“段落冲突检测”把冲突情况作为元信息一并提示给LLM让它在回答中明确指出不同文档的差异。4.4 Prompt设计没有技巧只有反复实验和记录很多人把Prompt工程当成一种魔法我觉得它更像是一门“结构化写作”任务。拿我最后稳定使用的System Prompt模板举例它由五个部分组成角色定义、能力范围、回答规则、引用要求、禁忌清单。每部分都写得像一份执行手册而不是一句口号。比如“引用要求”我写的是“回答末尾必须列出引用的文档名称和章节标题。所有事实性陈述必须来自给定上下文。如果上下文中没有相关信息明确回复‘根据现有资料无法确认’禁止推测。”这句看起来很平常但它实际上就是后面回答质量的保障线。我也试过更宽松的表达比如“请尽量引用来源”效果差了很多模型会经常忘记带引用或者在一个句子上编一个有模有样的来源标题。Prompt实验的工程方法我推荐“每次只改一个变量”。把历史所有的Prompt版本和对应的评估结果记录下来要改就一次改一个变量比如把“必须”改成“禁止”就是一次完整的实验。千万不要同时改三个地方不然效果变好或变坏了你根本不知道是哪一个变量起了作用。这一点和传统开发里做性能优化时的控制变量法一模一样。4.5 项目上线后我如何评估效果上线不是结束而是评估的开始。我建立了一个自动化评估脚本核心是“离线测试集人工抽检线上日志监控”三层结构。离线测试集有50个问题覆盖产品介绍、参数查询、故障排查、操作指南四类场景。每天跑一次输出一份Markdown格式的评估报告每条记录包含输入问题、模型回答、命中引用、自动打分结果。自动打分我实现了一个“裁判模型”的做法用一个更强的LLM根据预设的评分标准对“问题-回答-参考片段”三元组打分并输出理由。再定期人工抽查错例修正裁判模型的评分逻辑或者调整检索链路。这个方法能极大提升迭代效率以前改一个Prompt想验证效果要手动测半天现在一条命令全量跑完十几分钟后就能看到各类问题的通过率变化。线上日志监控的重点是“无效回答率”和“平均响应时长”。无效回答率指的是模型明确回复“无法确认”“信息不足”的用户请求占比这个指标如果过高说明要么知识库覆盖不足要么检索召回质量差。平均响应时长则主要受检索耗时和生成耗时影响如果前期没做缓存每次相同的重复问题也会完整跑一遍检索生成浪费成本我这套系统后来加了一层结果缓存命中缓存的请求响应时间直接从8秒降到几百毫秒。5. 我踩过的坑整理成一张速查表给你这一路下来有不少教训挑出最典型的整理成了下表每条都对应着一次真实的线上事故或长时间排查问题现象根本原因解决方案回答中途被截断max_tokens设置过小根据业务内容长度估算设置合理上限并做截断检测温度很低依然有幻觉温度只能约束分布不能杜绝幻觉用引用校验强制约束生成内容边界重试或拒绝回答检索结果明显不相关文本切块过碎、语义断裂改用结构感知切分增加上下文重叠同一问题不同答案未设置缓存且上下文漂移加回答缓存锁定System Prompt版本API调用偶尔超时未配置重试机制加入指数退避重试与超时熔断模型返回JSON解析失败输出格式不稳定增加重试和格式修复提示词解析失败时自动要求模型修正成本异常飙升循环调用未设置上限Agent循环加最大轮数限制调用前后做预算检查线上效果与本地Demo差很多评估集过小、场景覆盖不足建立贴近真实分布的评估集定期回归第一条截断问题我当时排查了好久。用户问了一个很正常的操作问题模型答到一半就停了日志里没有任何报错看起来就是正常结束。后来我发现是因为生成内容长度刚好超过了max_tokens的设定值而API对这种情况不会抛出异常只会默默截断输出。当时我设置的max_tokens是800觉得问一个操作问题足够了但产品文档里有一段步骤描述特别长加上引用格式总长度超过了限制。现在的代码里我每次生成后都会检查输出是否到达截断边界如果有截断就自动用剩余配额补一次续写请求。还有一条关于Agent死循环的经验特别值得说。我早期跑Agent时遇到过一个情况模型反复调用同一个查询工具因为每次查询结果都不让它满意它就换个关键词再查一次始终停不下来。如果不限制调用轮数一次任务能产生几千个Token的费用。后来我在Agent循环里加了三重保险最大工具调用次数限制、单轮总Token预算限制、以及“结果没有任何新增信息时强制终止”的逻辑。这个兜底逻辑对于真实场景至关重要毕竟模型对“自己已经尽力了”这件事没有什么自觉性。6. 最后再分享几个压箱底的建议如果你正打算照着“ai-engineering-from-scratch”这条路走我的经验可以浓缩成几条建议比任何技术细节都重要。第一条用项目驱动学习而不是用课程驱动。我学得最扎实的部分全都是在真实项目里遇到问题、逼着自己去查资料解决的时刻。看一百遍向量数据库的文档不如亲手把一批烂数据灌进去再想办法查出来。建议你就找一个自己工作里最痛、最重复的任务试着用LLM做一个最小原型把它跑通再去逐步完善。这个过程里遇到的每一个问题都会变成你真正内化的经验。第二条保持一个“迭代实验”的习惯。AI应用开发没有一个一劳永逸的最优配置算法、模型、数据、业务变化都会让效果漂移。我现在每个项目都维护一个实验记录文档某个参数改动后效果变化了多少、为何做出这个决定、后续如何验证全部记录下来。几个月后回看这些记录你能清楚看到自己成长的轨迹也能避免重复踩同一个坑。第三条“写注释”这件事在AI工程里变得更加重要。我在代码里习惯在每一段关键逻辑上写清楚“为什么要这样做”——不是为了装样子而是因为AI相关的代码逻辑太容易让人迷惑。比如一段普通的文本清洗代码光看代码你完全不知道它是在处理哪个PDF解析工具产生的特定乱码格式半年后你自己回来看都会一脸茫然。注释里把背景、触发条件、预期效果写清楚后期维护成本会低非常多。最后想说一点心得体会。AI工程这个方向看起来门槛很高但真正做下来你会发现它考验的主要不是天赋而是耐心和系统化思维。你能不能在模型输出不理想的时候冷静地拆解问题、分步实验、记录数据很大程度上决定了你能在这条路上走多远。我见过不少天赋很高的人因为总想一步到位、受不了反复失败的挫败感中途放弃了反而是那些踏踏实实一个坑一个坑填的人最终搭建出了稳定可用的AI系统。从零开始从来都不晚但一定要带着工程思维去开始——这也正是“ai-engineering-from-scratch”这个命题里比“AI”更重要的那个词“engineering”。