
我给自己定过一条规矩每进入一个新领域都要强迫自己整理一份能从零讲起的笔记。这条规矩最终催生了一个叫 ai-engineering-from-scratch 的系列项目——它不研究怎么训练大模型也不逼你从推导 Transformer 结构开始它只解决一个特别现实的工程问题在模型能力唾手可得的今天怎么把一个能聊天的模型变成稳定、可交付、能上线的产品功能。为什么想写这个因为两年前我第一次带 AI 产品项目时发现团队里人人都会写两行调用模型的脚本可一遇到真实用户问题就全都暴露了同一段提示词这次对下次错输出格式说变就变上下文越塞越乱账单越跑越高。不是大家不会写代码而是大家把精力全花在了模型调用上忽略了模型应用背后那套完整的工程系统。这篇文章就是那条路线的展开版适合两类人看一类是零基础想转 AI 方向的开发者想找一条不绕远路的路径另一类是已经在写 AI 功能、但正被稳定性、成本、评估问题折磨的工程师。1. 动手之前先把AI工程四个字拆清楚1.1 它和机器学习研究不是一回事很多入门者最大的认知偏差是把 AI 工程和机器学习研究划等号一上来就买深度学习课程、啃论文结果三个月后发现自己既不会训练模型也做不出能用的产品两头都没落着。实际上这个领域里有三种分工完全不同的角色。算法研究员的目标是提出新模型、新方法他们需要扎实的数学功底和实验能力机器学习工程师的目标是让训练和推理跑得动、跑得快他们要懂分布式、GPU、模型压缩而 AI 工程师的目标是基于现成的模型能力构建应用——选择合适的模型、设计提示词、组织数据、做好评估、控制成本、完成上线。ai-engineering-from-scratch 这条路线瞄准的正是第三种。它的核心不是我能不能训练一个模型而是我能不能把一个模型用成可靠的生产组件。打个比方引擎是别人造好的你要解决的是怎么把它装进车里让它符合安全标准、油耗可接受、用户体验不拉胯。这是完全不同的技术栈也是目前市场缺口最大的方向。1.2 这份路线里分层的能力结构我把 AI 工程师需要的能力拆成三层后面所有章节都按这个结构展开。底层是软件工程基本功。包括 Python 写得干净、Git 用得熟练、懂 API 设计、会写测试、会部署服务。这层决定了你做出来的东西能不能被别人用、被系统稳定地调用。中间层是模型运行直觉。不需要你能复现一篇论文但你必须理解 Token、Embedding、Attention 各自在干什么知道温度参数调的是什么知道为什么同样的输入输出会变动。这层决定了你遇到异常时有没有排查方向。上层是 LLM 应用模式。包括提示词工程、结构化输出、RAG 检索增强、Agent 工具调用、评估体系、成本控制。这层是 AI 工程师区别于普通后端工程师的核心增量也是这份路线真正要训练的部分。1.3 先用一个可检验目标代替热血口号学这种大而广的领域最怕开头喊口号学两周就失去方向。所以我建议你先定一个非常具体的检验标准整个学习过程都拿它当靶子六到八周之后你能独立交付一个带有真实用户场景的 AI 功能自己完成需求拆解、模型选型、提示词设计、必要时接入检索、做一轮离线评估、算清楚每次调用的成本、把它部署成可访问的服务。这个目标不需要你训练模型不需要你发论文但它逼你把 AI 工程的每个环节都走一遍。后面所有章节都是围绕实现这个目标来展开的。2. 地基不是重读数学而是够用就好2.1 编程这门课重点其实只有这么几样零基础的人听到从零开始就容易慌以为要把 Python、高等数学、机器学习全学完才能动手。我踩过这个坑所以先说清楚你不需要精通 Python但有几样东西必须熟练。第一是类型注解和数据类。AI 应用的数据流转非常复杂没有类型约束就是灾难。你要能熟练写出from dataclasses import dataclass或者用 Pydantic 定义数据模型让输入输出边界一目了然。第二是异步编程的基础认知。真实应用里耗时都在等你发出去的模型请求返回能理解async/await、知道什么时候该用并发后面做批量处理、流式输出会轻松很多。第三是环境管理和 Git。每条命令都配一个.env文件管密钥每个实验都在分支里做这些习惯比任何算法知识都更早决定你项目的生死。不需要啃完一本书能上手写、遇到问题会查就够。如果非要推荐一个练习方式去写一个 JSON 处理脚本要求自己加上类型校验和异常处理比做题有用十倍。2.2 数学三块知识对应到的是三个使用现场很多教程让你系统学线代、微积分、概率论我承认体系化学习是好的但对于 AI 工程的实际工作你其实只需要在三个场景里用到数学直觉。线性代数的使用现场是 Embedding 和注意力机制。你要理解向量点积衡量相似度是什么感觉知道为什么两个语义相近的句子向量夹角小。你不需要手推矩阵分解但当你调试检索召回时你会立刻用到这两个向量近不近这种直觉。微积分的使用现场是梯度下降。你要理解模型更新参数的方向是沿着损失下降最快的方向走理解学习率大了会震荡、小了会龟速。做 AI 工程你几乎不会训练完整的大模型最多做微调所以微积分到这层直觉真的够了。概率统计的使用现场是采样和评估。模型输出 logits 过 softmax 变成概率temperature 控制概率分布的形状这就是为什么温度越高输出越发散。评估时你会用准确率、召回率这些统计指标你要知道它们各自会骗人的方式。这些直接用的场景比刷一百道课后习题更值得投入。2.3 用三个类比记住大模型的三块基石Token、Embedding、Attention 这三个概念几乎每天都会出现在 AI 工程的对话里。我习惯这样给新人讲Token 是把文本切成模型能处理的碎片。中文里一个词可能被切成一两块英文一个单词可能被切成两三块。你的每一分钱、每一个上下文窗口长度都直接和 Token 数量挂钩。这个理解直接影响你对成本的控制。Embedding 是把文本映射成一个向量让语义相近的内容在向量空间里靠得近。你可以把它理解成图书馆给每本书贴的索书号——不是一个精准主题标签而是一组决定它在书架哪一层的坐标。检索、聚类、去重全建立在它上面。Attention 是模型在生成每个词时对之前内容的加权回顾。它在每个生成步骤里决定现在最该关注哪些位置的信息。理解了这一点你就明白为什么上下文越长、需要关注的东西越多模型越容易走神也越费算力。2.4 卡住时的正确姿势学技术最怕卡在某一步死磕。我的建议是永远以用带学遇到一个概念先看它在我接下来要做的功能里怎么落地用一次比读十遍书都牢。真读不懂的标记一下跳过去等项目做回来再回头补那时候你会惊叹当初怎么会被这个概念卡住。3. 第一笔看得见的代码从 API 调用到应用骨架3.1 准备环境时最容易忽略的两个小点动手写第一行代码前把环境收拾干净。我用 Python 会建一个专用的虚拟环境密钥放在.env里用python-dotenv加载绝不写死在代码里——这条习惯我到现在都在用它救过我不止一次比如不小心把代码提交到仓库的时候。另一个容易被忽略的点是模型名称。很多人写死一个模型名等模型下线或者换版本时才发现代码崩了。我习惯把模型名做成配置项系统环境变量或者配置文件里统一定义方便切换和对比。3.2 一个最简 Chat 调用以及接口背后发生了什么第一段代码不求复杂先跑通一次完整的往返。下面这段是几乎所有 AI 应用的最小单元import os from openai import OpenAI client OpenAI(api_keyos.environ[OPENAI_API_KEY]) resp client.chat.completions.create( modelgpt-4o-mini, messages[ {role: system, content: 你是客户支持助理回答必须简洁不超过三句话。}, {role: user, content: 我的订单三天没发货怎么办}, ], temperature0.3, ) print(resp.choices[0].message.content) print(resp.usage.total_tokens)别看它简单背后已经跑完一整条链路你的消息被切成 Token拼上系统提示词送进模型做一次前向计算然后按温度参数采样出回复文本。返回结果里除了文字还有usage字段告诉你这次调用消耗了多少 Token这就是你今后每一项成本计算的起点。我建议你跑通之后立刻做一个小实验把temperature分别设成 0、0.7、1.2分别调用十次观察同一问题的输出差异。这个实验会让你真正理解随机性这个 AI 应用里最磨人的特性。3.3 从读文本到要结构化结果调用接口谁都会工程化的第一个台阶是让模型输出你能程序化处理的结构化结果。你不可能用正则去解析聊天文本所以从一开始就要养成习惯让模型输出 JSON。resp client.chat.completions.create( modelgpt-4o-mini, messages[ {role: system, content: 你是订单客服。请只输出 JSON包含 status 和 solution 两个字段。}, {role: user, content: request_text}, ], response_format{type: json_object}, ) data json.loads(resp.choices[0].message.content)光让模型输出 JSON 还不够稳下一步要用 Pydantic 校验字段、类型、枚举值校验不通过就带着错误信息重试一次。这套结构化输出 校验 重试的模式是你后面所有 AI 功能的可靠性地基。3.4 搭一个五分钟后还能维护的最小后端有了模型调用和结构化输出就可以把脚本升级为服务了。我用 FastAPI 搭最小后端from fastapi import FastAPI from pydantic import BaseModel app FastAPI() class SupportRequest(BaseModel): question: str user_id: str app.post(/support) def support(req: SupportRequest): answer generate_support_answer(req.question, req.user_id) return {answer: answer}这一步的意义在于你把业务逻辑封装成函数把输入输出变成有约束的接口别人包括未来的你自己就能像调用普通后端一样调用 AI 能力。从这开始AI 不再是一个可以聊天的脚本而是你系统里一个可测试、可替换、可监控的服务组件。4. 工程化三件套提示词、结构化输出、可观测性4.1 把提示词当成代码来管理大部分人在 AI 项目里的第一个失控点就是提示词。今天在 notebook 里改两句明天在线上代码里改一个字后天又有新版需求——最后谁也没法说清线上跑的是哪个版本的提示词。我的做法是把提示词抽成独立的模板文件用配置文件或数据库管理起来并且带版本号version: 1.3 model: gpt-4o-mini temperature: 0.3 system_prompt: | 你是客户支持助理。规则 1. 只处理订单与物流问题 2. 回答不超过三句话 3. 无法回答时引导用户联系人工客服这样每次改动都看得见 diff出了问题能快速回滚还能对同一个功能用 A/B 两组提示词做对比测试。我在实际项目里见过太多提示词养蛊的现场——上线前谁都不敢动那块输入就是因为没有版本化。这一点早点做到后面省下的时间按周计算。4.2 结构化输出是可靠性的起点不是加分项如果让我给 AI 工程排优先级结构化输出一定排在前三。因为只要下游有代码消费模型的输出非结构化文本就是随时埋雷的地方。完整做法是四步第一步定义输出 JSON Schema尽量把字段类型、枚举值都锁死第二步在请求里要求 JSON 格式第三步拿到输出后用 Pydantic 校验第四步校验失败时把错误信息回传给模型让它自己修正一次。这套流程跑下来格式错误率能从十几个百分点降到百分之一以下。from pydantic import BaseModel, ValidationError class OrderInquiry(BaseModel): intent: str # shipping | refund | other priority: int # 1-5 suggested_reply: str try: parsed OrderInquiry.model_validate_json(raw_output) except ValidationError as e: # 把 e 的错误信息拼进新的请求让模型重来一次 ...很多人以为这是过度设计直到上线后遇到模型突然多输出一句客套话导致解析崩溃才会回头补。我建议你从一开始就做因为补的时候通常是在线上压力完全不同。4.3 可观测性先回答它为什么错了AI 应用调试和普通程序最大的区别是普通程序错了有报错堆栈AI 应用错了往往就是答案不对而你根本不知道是哪一次调用、哪一步逻辑出了问题。所以从第一天起我就在代码里埋结构化日志每条记录带上这些字段字段说明prompt_version当前提示词模板版本model实际调用的模型名input_tokens / output_tokensToken 消耗latency_ms端到端耗时request_id关联上下游的追踪 IDoutput_preview模型原始输出片段cost_usd本次估算成本不要小看这张表。有了它用户反馈答案不对时你能用 request_id 拉出完整链路这是成本优化、质量评估、问题归因的唯一依据。没有日志的 AI 项目出了错就只能靠猜而靠猜找 bug 是效率最低的排错方式。另外一个细节日志里记录的是估算成本。我常用的公式是(输入 Token × 输入单价 输出 Token × 输出单价) / 1,000,000模型价格表会变所以在代码里把价格表也做成配置。5. RAG 和 Agent不急着上在对的位置用对5.1 先回答为什么要检索RAG 是现在最热的话题但我要先泼一盆冷水不是所有问题都需要 RAG。如果模型需要的信息在它的训练知识里已经足够准确你直接调用就行如果信息会频繁变化、需要实时性如果回答必须带可追踪的来源如果涉及企业内部私有文档——这些场景才真正需要把外部知识检索进来再交给模型合成答案。我见过不少团队一上来就搭完整的知识库系统结果发现业务场景根本用不上向量检索还白白增加了延迟和复杂度。判断标准就一条你的模型在缺少外部资料时能不能给出可接受的答案如果不能再上 RAG。5.2 RAG 最小闭环拆块、召回、重排、合成一个能跑的最小 RAG 闭环包含四个环节。文档切块时我习惯先按语义段落做粗分再按固定大小兜底块大小通常设 300 到 800 个 Token。太大召回精度差太小丢失上下文这个区间是大多数场景的经验值。切好后用 Embedding 模型转成向量写入向量数据库。召回阶段不要只依赖向量相似度。我强烈建议做混合检索向量召回负责语义相似关键词召回负责精确匹配比如订单号、型号两者合并后再用重排模型打分。这样既能找到意思相近的内容又不会漏掉字面完全一致的信息。合成阶段最容易被低估。不是把检索结果一股脑塞进提示词就行而是要在提示词里明确只依据资料回答不知道就说不知道回答末尾标注来源编号。前者治幻觉后者建立用户信任这两条规则对几乎所有 RAG 应用都适用。5.3 检索质量怎么量化很多人调 RAG 全靠感觉回答变好了这是致命的。检索质量必须量化做法是在开发阶段准备一份测试问题集每个问题都人工标注出应该在哪个文档片段里找答案然后上线前跑一遍统计召回率。比如 100 个问题有 85 个问题能在召回的前五条结果里找到对应片段那 Hit5 就是 85%。这个数字以后每次调切块大小、换 Embedding 模型、加重排都能拿来对比。没有这个基准你对 RAG 的每一次优化都只是自我安慰。5.4 Agent把会调用工具变成系统的能力Agent 是 RAG 的自然延伸RAG 让模型能查资料Agent 让模型能用工具。最经典的实现是 ReAct 循环——模型推理现在需要做什么调用对应工具观察结果再决定下一步。下单查库存、查天气、算运费本质都是把外部能力包装成函数让模型决定何时调用。这个模式很强大但也很容易失控。我的建议是一开始手写工具函数和循环别急着上框架。手写一个让模型选择工具、执行、再交回模型的循环总共几十行代码你却能完全理解每一步发生了什么。框架可以节省时间但框架隐藏的细节会在你排错时全部找回来。工具设计的核心是边界清晰每个工具的入参校验、权限范围、可接受的失败情况都要严格定义。我见过最典型的失控是让模型直接调 SQL 查询接口结果模型生成了一串危险的查询语句。工具设计得像接口规范一样严谨Agent 才可能可控。6. 评估、成本与上线能不能交付全看这里6.1 先建评估集再谈优化AI 应用让人最头疼的一点是没有编译错误。功能能跑但没人能告诉你它答得好不好。所以评估集必须建在最前面而不是最后面。我通常从三个维度建评估集正确性——回答在事实上对不对忠实性——回答有没有依据资料还是自己在编格式合规——输出是不是能被下游稳定解析包含字段类型、枚举值等硬性要求。集子不用大100 到 200 条覆盖典型场景和边界情况的样本已经足够支撑日常优化。关键是每条样本都要有标注好的标准答案或评分规则。有了这个集子每一次改动提示词、换模型、调整检索参数都能跑一遍回归用数字说话。我多次靠这个集子拦下感觉变好了、实际变差了的错误改动它是我所有 AI 项目里性价比最高的投资。6.2 用模型评模型的实践人工评估质量高但成本重所以实践中常用模型评模型。做法是让一个能力更强的模型按照你定义的评分标准对另一个模型的输出打分。打分标准必须写得很具体否则评出来的分数毫无意义。evaluation_prompt 你在评估客服回复的质量。评分标准 1分存在事实错误或答非所问 2分事实正确但遗漏关键信息 3分事实正确、信息完整、表达清晰 请只输出 JSON{score: 1或2或3, reason: 一句话理由} 模型评模型要注意两个坑一是打分模型容易被长答案带偏所以我会要求它先引用原文再给分二是同一个评分任务换个模型结果可能有差异所以评估模型要固定变更时要单独验证。这套方法不是完美替代人工但能把每次改动都要人工读几十条回答变成几分钟跑完一组客观对比效率差距是数量级的。6.3 成本与延迟的三级控制AI 功能上线时成本和延迟经常成为拦路虎。我把控制手段分成三级按效果和成本从低到高排列。第一级是模型选型和输入瘦身。能用小模型解决的问题绝不用大模型能精简的系统提示词绝不多放内容。一个 300 Token 的提示词和 1200 Token 的提示词成本差四倍延迟也会明显上升。第二级是缓存和并发。对固定历史会话可以启用上下文缓存对相同问题的请求可以做语义缓存离线批量任务用异步并发把几十个请求打包并行发出延迟总量能下降一个量级。第三级是模型路由。在入口处先判断请求难度简单的走小模型复杂的才走大模型。我碰过的一个真实案例在加了路由之后整体成本降了 60%用户几乎无感知。这个优化空间在越大的流量下越明显值得先做分级评估。6.4 上线前必须过的工程关最后是上线。模型调用不是普通的 API 调用它在超时、重试、容错上都更敏感。我会强制自己在代码里处理好这几类问题请求要设超时并支持重试指数退避模型更替要有降级策略比如主模型不可用时切到备用模型输出要做长度上限限制避免模型陷入冗长输出输入输出都要有基础的内容安全检查防止用户输入打印到日志或把数据外传。这些事都不难但它们决定了功能到底是Demo还是产品。我见过太多辛苦做出来的 AI 功能因为一个没处理的超时重试而在生产环境天天报错然后被整条业务线放弃。工程关没有捷径每一项都要在项目早期就排进计划。7. 踩过的坑和一份可抄的 12 周路线7.1 最容易翻车的四个坑这几年我观察到的入门者翻车方式高度重复总结成四个坑希望你能绕开。第一个坑是囤课式学习。收藏夹里放了几十个小时的课程知识点越学越密代码一行没写。解决办法是给自己定死规矩每学一个概念当天必须用它写一段代码或调一个接口。第二个坑是框架早用症。上来就装各种 Agent 框架最后代码库里全是抽象层出了问题根本不知道是哪层出的。解决办法是先手写一个月再考虑引入框架那时候你才有判断力知道框架替你解决了什么、带来了什么新问题。第三个坑是不建评估就优化。没有评估集所有优化都靠感觉改了一周参数最后可能比起点还差。解决办法我已经说过了第一轮功能跑通后第一个要做的增量就是那 100 条评估样本。第四个坑是RAG 万能论。幻觉来了就上 RAG上下文不够就硬塞最后系统复杂到没人敢动。解决办法是回到问题本身先确认模型直接答到底哪里不行再选对应手段而不是先上最重的方案。7.2 一条可以直接抄的 12 周节奏如果你有一定编程基础想按这份路线系统性走一遍我建议的节奏是这样周次任务产出物第 1-2 周Python 环境、类型注解、Git、FastAPI 基础一个能跑的最小后端服务第 3 周跑通模型 API实验 temperature、结构化输出一个带 JSON 输出的问答脚本第 4 周提示词模板化、日志埋点、成本估算一个可观测的小型 AI 服务第 5-6 周搭建 RAG 最小闭环建 100 条评估集一个带引用来源的文档问答功能第 7-8 周手写一个工具调用循环做一次模型路由一个能查库存 / 算运费的 Agent 原型第 9-10 周系统跑评估、做成本优化、处理超时重试一份评估报告和成本优化记录第 11-12 周部署上线接一层真实用户反馈一个可以给真实用户用的完整功能每周的产出必须是能演示的东西。如果一周结束你只能说我学了很多知识那这一周其实没有完成。我自己的项目就是这么推进的节奏感比内容量重要得多。7.3 我最后想留给你的一条建议如果你只记住这一条我希望是它把你每周的产出定义为可演示的 AI 功能而不是读完的章节和积累的知识。这个领域变化太快模型半年一代框架三个月一轮唯一能沉淀下来的是你亲手完成的那一串功能、那一套评估方法、那一次事故复盘。ai-engineering-from-scratch 这套路线真正的价值不是我列了多少知识点而是它逼着每一个照着走的人在最短时间内把知识变成系统、把系统变成能被别人使用的东西。