
“ai-engineering-from-scratch”从零开始搞 AI 工程。这个标题我盯了很久因为它戳中了太多人的软肋市面上讲 Prompt、讲大模型原理的文章满天飞可真要一个人从零开始搭出一套能落地、能迭代、能扛住真实需求的 AI 系统大多数人会被卡死在第一步。我这篇博文就把自己从零跑通整套 AI 工程实践的路径做个复盘从最底层的 Prompt 基本功到 Agent 工作流编排、本地部署环境搭建、再到测试评估一条线捋下来。它不仅适用于想转行 AI 应用开发的程序员对做产品、做运营、做内容生产的非技术背景读者同样友好——只要你愿意按工程化的思路组织 AI 能力就不需要从线性代数重新学起。1. 项目定位把“用 AI”升级成“造 AI 系统”1.1 核心需求解析为什么“会聊天”不等于“会工程”很多人第一次写出能跑通的 AI Demo 时会产生一种错觉我已经会 AI 了。但真实业务里AI 要解决的不是“帮我写一段广告文案”这种一次性请求而是“每天自动处理 2000 条用户反馈识别情绪、生成回复、标记紧急工单并推送负责人”这种持续运转的系统需求。这时候考验的才真正接近“AI 工程”。我复盘自己从零起步的整个项目核心不是模型选型——今天用 GPT 系明天用 DeepSeek 系模型本身已经是商品。真正的核心难点在四层第一把模糊的业务需求翻译成模型能理解的精确指令这层属于 Prompt Engineering是地基中的地基第二把单次调用组装成多步骤工作流让 AI 能自主规划、调用工具、处理中间结果这层是 Agent 与工作流设计第三让整套系统能在自己可控的环境里稳定运行涉及本地部署、接口封装、配置管理第四用测试手段保证 AI 系统的输出质量可度量、可回归避免每次改一个参数就全盘失控。这四层正好对应我这篇博文的主干结构。做这个项目的过程中我踩过最深的坑是以为模型强大就万事大吉结果花了两周搭出来的系统被一个极其简单的输入格式坑到崩溃——用户用全角冒号分隔字段模型解析错了后续所有环节跟着错。这就是工程问题不是模型问题。所以“from scratch”真正的含义不是从神经网络原理重新推导而是从工程实践的基础层开始一个组件一个组件地搭建。1.2 方案选型逻辑先跑通单点再设计系统从零起步最忌讳上来就画一个巨大的架构图。我的做法是严格遵循一条路径先在单个 Prompt 上做到稳定输出再考虑封装函数再组合成多 Agent 协作最后才做系统级容错。每一步都是上一步的充分条件跳级必翻车。选型时我给自己定了三个约束第一优先用国内可直接访问的大模型 API 和开源模型保证合规可控第二所有代码用 Python 3.10因为 AI 生态的库几乎都优先支持它第三不引入重量级框架初期只用 requests、json 这类标准库搞定最小闭环避免被框架的抽象层混淆核心逻辑。等到后期才引入 Spring AI 这类 Java 生态框架进行评估考虑的是团队技术栈统一的问题——但那是另一个分支了项目中只做了预研。这个思路和“harness engineering”的概念也有关联。所谓“harness”原本指给马匹套挽具工程上引申为给模型套上规范化的输入输出框架输入侧做标准化、输出侧做校验、中间用可控的流程约束模型行为。它的价值在于让模型的不确定性被限定在一个可管理的盒子里。我做的第一版“提示词模板系统”本质上就是一个极简的 harness——它保证了即使换模型、换参数业务代码不用跟着重写。2. 地基工程Prompt Engineering 的实战姿势2.1 一套可复用的提示词层级结构我见过太多人把 Prompt 写成长段落作文开头铺垫背景、中间夹带任务、结尾又来一句“请确保回答专业”。这个做法看似全面实际上是在考验模型的语义理解能力——而大模型对长文本的注意力是分散的越往后越容易丢失前面的关键约束。我的做法是把 Prompt 拆成五个固定区块角色定义、任务陈述、输入变量、约束条件、输出格式。每个区块用分隔符明确分开。这个结构的好处有三层对模型来说指令区块化之后更容易被 token 级注意力机制捕捉到关键信息对开发者来说改需求时只需替换对应的区块不用整体重写对整个工程链路来说输出格式区里定义的 JSON Schema 可以直接作为后续代码解析的接口契约。举个例子一个用户情绪分类任务我这样组织[角色] 你是一名资深用户研究分析师专长是文本情感分类。 [任务] 判断以下用户反馈的情绪倾向输出为严格 JSON。 [输入] 用户反馈{feedback_text} [约束] - 情绪分类仅限positive、negative、neutral三选一 - 如反馈中包含投诉关键词无论语气多礼貌一律归为negative - 不要输出任何解释性文字 [输出格式] {emotion: 分类结果, confidence: 0到1之间的数字}实测下来这套结构化模板的稳定输出率比自由文本 Prompt 提升了将近一倍。关键经验是你给的约束越明确模型发挥的空间越窄输出跑偏的概率就越低。很多人怕管太死会限制模型的“智能”但在工程场景里稳定性优先于创造性你需要的是手术刀不是瑞士军刀。2.2 参数调优temperature 和 top_p 的决定逻辑Prompt 写得好参数调不对一样翻车。创业公司常犯的错误是所有请求都用一个默认参数结果需要严谨数字的任务输出了一堆天马行空的“可能原因”。我的参数选择逻辑是基于任务类型做二分法生成类任务文案、创意、头脑风暴temperature 设在 0.7 到 0.9 之间让模型有足够的随机性去探索不同表达抽取与分类类任务 temperature 直接拉低到 0.1 甚至 0。为什么后者要接近 0因为分类任务的正确答案是确定的随机性只会带来噪声。我用 0.05 的 temperature 测试过一组 500 条的用户反馈分类错误率在 3% 左右把温度拉到 0.7同样数据错误率飙到 9%——这个差异足够影响业务决策。top_p 我通常保持默认 1只在模型输出出现明显重复或困在一个循环时才会调低到 0.9 附近。这里要特别提醒temperature 和 top_p 是两种不同维度的随机性控制官方文档建议不要同时大幅修改两者否则输出分布会变得不可预测。我在实践中只调 temperaturetop_p 永远作为兜底手段用。迭代过程中的标准化记录也很重要。团队有人问“为什么上个版本效果好这个版本差”如果你没有记录参数和 Prompt 版本根本没法回答。从第一天起就要建立 Prompt 版本记录表像追代码 Commit 一样追 Prompt 的变更。版本任务类型temperature核心变更验证集准确率V1.0情绪分类0.1初版模板91.2%V1.1情绪分类0.1增加投诉关键词约束94.6%V1.2情绪分类0.05降温度提置信度阈值95.1%这套表格的价值在后面做回归测试时体现得淋漓尽致。我建议任何从零开始做 AI 工程的人都从第一天就养成这个记录习惯。3. 从单次调用到 Agent 工作流让 AI 从“回答问题”变成“完成项目”3.1 Agent 到底是什么一次讲清规划、记忆与工具调用很多教程一上来就贴 LangChain 代码“初始化一个 Agent给它两个工具它就会自己干活了”——但读者根本不知道 Agent 内部发生了什么。我用最简单的方式拆解Agent 本质上是一个“循环执行以下三步的机器”——第一步规划模型根据当前目标和已有信息决定下一步做什么第二步执行调用外部工具搜索引擎、数据库、代码解释器等获取新信息第三步观察把工具返回的结果拼回对话上下文再看是否达成目标没达成则回到第一步。这个循环就是“ReAct”模式——Reasoning推理与 Acting行动交替进行。理解了这个原理你根本不需要任何高深的框架用 while 循环就能实现一个最基础的 Agent。我在项目里做了一个可复用的最小 Agent 骨架核心逻辑用三十行 Python 就能跑起来import json def run_agent(goal, tools, max_steps5, modeldeepseek-chat): system_prompt 你是一个任务执行者。请根据目标拆分步骤逐步调用可用工具完成目标。每次回答必须以JSON格式输出。 messages [{role: system, content: system_prompt}, {role: user, content: goal}] for step in range(max_steps): response call_model(messages, tools_schematools.schema()) parsed json.loads(response) if parsed[action] finish: return parsed[result] tool_result tools.invoke(parsed[action], parsed[args]) messages.append({role: assistant, content: response}) messages.append({role: user, content: f工具返回{tool_result}}) return messages这段代码的逻辑非常朴素每轮让模型输出一个 JSONJSON 里包含 action要做什么和 args参数如果是 finish 就返回结果否则调用工具拿回结果再喂给模型。这个循环就是所有复杂 Agent 框架的底层原子操作。你掌握了它再看 LangChain、AutoGen 这类框架的源码会发现它们做的事情本质上只是多加了状态管理、记忆持久化和并发调度——架构复杂了思想没变。3.2 完整实例用三阶段工作流实现“自动生成地形”热词里有“ai自动生成地形 科学原理”这个方向我用 Agent 工作流的方式完整实现过一个最小版本很适合讲清楚 Agent 编排的价值。单次 Prompt 生成地形的问题是一次生成的细节有限难以兼顾全局轮廓、局部起伏、水文分布和生态覆盖。我把它拆成三阶段工作流阶段一AI 根据用户输入的“山地湖泊森林”关键词生成全局高度图描述与气候参数阶段二基于阶段一的输出生成局部细节补丁每个补丁对应一个坐标区域用代码控制坐标重叠区域的平滑过渡阶段三汇总所有补丁数据和环境参数统一交给渲染引擎生成最终地形网格。这里的核心不是“三步调用模型”而是“如何设计阶段之间的数据契约”。阶段一的输出不仅是一段描述文本还是一个结构化的 JSON包含高度图尺寸、噪声频率、湿度参数、随机种子。阶段二拿到这个 JSON才能在自己负责的坐标域内生成一致的细节。工作流设计与函数式编程一样关键是定义好中间数据结构的形状而不是处理流程本身。我实测了三阶段方案和单次 Prompt 方案的效果对比。单次生成地形轮廓得花 15 秒且细节残缺三阶段方案虽然总耗时到 35 秒但每个阶段的结果都可检查、可重放、可单独改进。这个取舍在工程上几乎是不需要考虑的——可维护性永远优先于单次速度。如果你的 AI 能力不是一个流水线的一部分而只是一次性输出那它不叫工程叫玩具。3.3 工作流编排的三个关键原则原则一串行与并行要合理分布。阶段之间有数据依赖必须串行无依赖的支线任务尽量并行调用。我在地形项目里阶段二的 8 个细节补丁完全独立为了加速我用了 Python 的 asyncio 并发调用 API8 个补丁的耗时从 60 秒压到 10 秒出头。这里有个容易忽略的坑OpenAI 系和 DeepSeek 系的 API 都有并发限制盲目加大并发会触发 429 限流错误。稳妥的做法是设置一个信号量控制并发数我常用的上限是 5 到 8具体看接口文档的限制。原则二中间产物全部落盘。工作流跑一半挂了如果中间产物没有保存就得从头跑。我给每个阶段都加了一个缓存层——用 JSON 文件或轻量级数据库记录阶段输出出现异常时直接从最近成功阶段恢复。这样做的一个额外收益是坏输入无法复现的 bug可以通过直接读中间产物来定位。原则三失败重试要有边界。模型调用返回超时或格式解析失败最简单粗暴的策略是重试三次每次间隔时间递增。但重试必须是幂等安全的——不要在重试中产生重复的外部副作用比如多次扣费或多次写入数据。输出侧我会做一个幂等键以请求哈希作为唯一标识保证重试不会导致上游系统的重复处理。4. 本地部署与开发环境从 API 调用到可控运行4.1 为什么这套系统需要本地部署与开源模型项目推进到第三周我遇到了一个绕不开的问题业务方反馈大量数据涉及敏感信息不能传到外部 API 平台做分析。这几乎是所有做产业级 AI 应用必然会撞上的墙。方案选择需要考虑三个约束。约束一是数据隐私原始文本不允许出本地网关所以推理必须在本机或私有云完成。约束二是运行成本如果只是 API 按量付费高频请求的月度账单会高得吓人而且无法估算长期成本。约束三是针对特定任务定制微调的可能本地化模型可以基于私有数据做 LoRA 微调API 服务大多只能靠 Prompt 硬撑。我最终的做法是“双轨制”第一常规任务继续走云端 API保证高质量第二涉及敏感数据的任务一律走本地部署的开源模型链路。这个折中的投资回报率实际上比全量本地部署更划算——因为云端 API 不需要你管 GPU 集群省掉大量运维成本。本地部署我推荐 Ollama 这类开源工具作为第一站原因是它的硬件门槛极低CPU 推理都能跑起来只是慢一点。我在一个只有 32GB 内存的普通笔记本上通过 Ollama 部署了一个 7B 参数的量化模型单次推理 3-5 秒做数据分类、抽取这类任务完全够用。等到真的需要更高吞吐时再考虑 GPU 服务器或集群方案。4.2 环境搭建实战Python 虚拟环境、模型拉取与版本管理本地部署环境搭建有好几个细节容易踩坑我按步骤复盘一遍。第一步Python 环境隔离。绝对不要用全局环境跑 AI 项目——依赖冲突会把你的开发效率拖到零。我的做法是给每个项目单独建虚拟环境python -m venv ~/venvs/ai-eng source ~/venvs/ai-eng/bin/activate pip install --upgrade pip第二步拉取并测试模型。Ollama 的优势是模型管理像 Docker 一样简单ollama pull qwen2.5:7b-instruct ollama run qwen2.5:7b-instruct 请回复一条测试消息需要强调的是本地模型和云端模型的输出风格差距明显。本地模型因为参数量小对 Prompt 格式的敏感度更高同一个模板在云端表现稳定搬到本地后输出 JSON 格式可能频繁出错。所以本地部署后第一步不是跑业务逻辑而是用你的测试集把 Prompt 模板全部重跑一遍逐个修复。第三步版本管理本地模型。很多人忽略模型文件的版本控制。Ollama 用标签管理不同版本但项目代码里必须写清楚“当前使用哪个模型标签”。我从一个退化的模型事故中得出的教训是代码库的 README 里必须明确定义“生产环境模型标签”每次升级模型都要跑一遍全量回归测试。在 AI 工程里模型升级的风险几乎等价于数据库 Schema 变更的风险——绝不能拍脑袋升。三个环境要素缺一不可Python 依赖清单用 requirements.txt 锁定精确版本、模型标签用文档锁定、AI 接口的适配层用统一封装的函数对外暴露。这样模型升级时只需改一处配置业务代码完全无感。4.3 开发工具链智能化IDE 插件与 AI 编程辅助写 AI 工程的代码自己的工作台最好也先 AI 化。我用的 PyCharm 配合 AI 插件让我在开发效率上至少提升了三成。不过这里要区分两种辅助模式插件自带的代码补全能力和面向项目上下文的问答能力。前者适合写常规的胶水代码比如定义函数、解析 JSON、写单元测试——让 AI 帮你生成“模板感很强”的重复代码注释都能一并带出。后者适合排查问题比如给插件指定“当前项目错误日志怎么定位”、“某个函数的依赖关系是什么”它能基于代码库结构性回答比搜索引擎精准得多。但 AI 编程辅助有个边界它擅长重构和生成独立模块不擅长做架构设计。我最深的体会是——AI 写的代码你必须先读懂再合入尤其是涉及并发、异常处理、资源释放的部分。有一次 AI 帮我生成的异步队列处理代码表面逻辑正确实际上每轮循环都会新建一个 session 对象运行时间一长就内存泄漏。这种问题不读代码根本发现不了。5. 质量保障体系AI 测试开发与迭代评估5.1 为 AI 系统编写测试从断言到场景回归AI 系统的输出具有概率性传统软件那套“单元测试必须 100% 通过”的逻辑直接套用会让人崩溃——因为同一个输入模型两次输出可能不同。这恰恰是 AI 测试与传统测试最本质的区别。我建立了一套“概率式测试”框架核心思想是不能断言模型必须输出某个精确值而是断言输出满足某些约束条件。有三种测试类型最常用。第一类是结构测试断言模型输出是合法的 JSON、包含必要的字段、字段类型正确。这类测试是稳定性的第一道防线不依赖具体内容。第二类是语义测试断言模型分类结果与人工标注一致用准确率作为指标设定阈值例如准确率必须大于 90%。第三类是回归测试维护一个标准测试集每次调整 Prompt、参数或模型版本后全量跑一遍对比变化。实现上我用 pytest 自定义断言函数组合把人工标注数据集和断言逻辑写成测试用例让 AI 系统的评价结果变成可执行的测试报告def test_emotion_classification(): dataset load_test_set(feedback_200.jsonl) results [classify(item[text]) for item in dataset] accuracy sum(r item[label] for r, item in zip(results, dataset)) / len(dataset) assert accuracy 0.90, f分类准确率不达标{accuracy:.2f}这个“测试”跑完如果失败不是告诉你一个 bug 在哪一行而是告诉你整个系统的质量水位低于预期。接下来你要做的不是修代码而是重新审视 Prompt 设计或数据结构。5.2 DeepSeek 公开的智能体训练方法论对工程实践的启发前面提到 DeepSeek 公开过一套智能体训练的新方法这个行业动态对从零做 AI 工程的人很有参考价值。它的核心思路是不直接让模型学习最终任务而是先把任务拆解成若干子能力逐项训练再组合成完整的智能体行为。简单说就是“积木式训练”。这个思路在工程实践里同样成立。我在做 Agent 时一直坚持的准则是“先验证每一个工具调用的独立正确性再组装成 Agent 流程”。比如要让 AI 自动查数据库、算指标、写报告我会先把“查数据库返回结果是否正确解析”“计算逻辑是否准确”“报告模板是否能正确填充”这三个环节分别做成独立模块验证任何一个出问题直接定位到该环节。如果直接跑完整流程失败时你根本分辨不清是模型规划错了、工具调用格式错了还是数据解析错了——这种“不可定位”的问题在工程上最致命。DeepSeek 的这个方法论印证了我一直相信的一个判断系统越复杂越要保证底层组件的可靠性然后把复杂度集中在编排层。5.3 评估指标怎么定不要让模型自己评价自己做 AI 系统评估时我走过弯路用“让模型给模型打分”的方式评估输出质量。初衷是省人工标注成本实测下来却非常不可靠。模型对同一个输出在不同轮次给出的打分浮动很大而且普遍存在“宽大偏向”——模型倾向于给其他模型的输出打高分即使内容有明显缺陷。后来我改用三个客观指标量化质量任务完成率即任务在规定轮数内成功完成的比例工具调用准确率即 Agent 找到并执行正确工具的比例格式合规率即输出严格符合预设 JSON Schema 的比例。这三个指标全部来自程序自动检查不依赖模型主观判断。每个指标都有明确的业务含义任务完成率对应产品能不能交付工具调用准确率对应 Agent 的可靠性格式合规率对应后续链路会不会崩。主观质量评估只能作为辅助参考而且必须由人参与。我从热词“教别人用 AI 赚翻了”想到一个点——做自由职业的 AI 应用开发者最容易犯的错误就是不建立评估体系靠“感觉效果不错”交付。客户一旦要求证明系统稳定你拿不出数字项目就黄了。评估体系不是学术要求是商业要求。6. 常见问题与排查技巧实录6.1 输出不稳定格式化与重试逻辑的组合拳现象同一个 Prompt 连续调用十次三到四次返回的 JSON 格式破损或者字段缺失。这种现象在切换模型后尤其常见本地小规模模型的格式稳定性比云端大模型差一截。排查思路分四步第一步简化 Prompt检查是否有复杂的嵌套指令干扰了输出格式第二步在输出格式区块中给出一个具体的 JSON 示例而不是只写“输出 JSON”——给示例比给描述有效得多第三步设置“格式解析 自动重试”机制发现 JSON 解析失败就要求模型重新生成重试时在 Prompt 中追加“注意上一次输出格式错误请严格按格式要求重新输出”第四步全部重试都不行降级到规则化解析方案用正则提取关键字段。我见过很多人卡在第三步就放弃了原因是“重试浪费 token”。但考虑到一次完整任务流程消耗的 token 远大于一次重试的 token——重试是成本最低的容错手段。我的经验值是在解析失败率达到 15% 以上时就不要依赖重试了必须回到 Prompt 层的重构去解决。6.2 上下文溢出Agent 跑着跑着丢失早期信息Agent 在长流程中后段忘掉最初的指令是本项目让人最头大的问题。原因在于对话上下文窗口有限早期信息被中后期的大量工具返回结果挤出了有效范围。解决方案有两条路子。方案一显式压缩上下文定期将对话历史摘要化把此前的关键结论浓缩进一个新的 summary 消息替换掉原始长历史。这条是通用做法尤其适合推理类 Agent。方案二外部状态存储把 Agent 的关键状态已完成步骤、已获得的重要数据存入外部字典或数据库Agent 每轮只读当前状态快照而不是依赖记忆对话历史。后者更像工程解法因为它把“记忆”从模型参数里移到了代码里——后者是靠得住的。我现在的项目默认调用了外部状态存储。这个决定把 Agent 从上下文窗口大小的限制中解放出来跑几十步的长任务不再中途“失忆”。6.3 成本失控Token 消耗高于预期该怎么压模型调用成本往往不是突增的而是“温水煮青蛙”式地涨。最典型的浪费是 Agent 在循环里反复调用工具、反复输出长文本每轮都是钱在燃烧。我的成本控制三板斧第一设置最大步数就是我在 Agent 骨架代码里的 max_steps——强制限定一个任务最多跑多少轮超出即失败重来而不是无限循环第二输出长度限制在调用 API 时显式设置 max_tokens例如分类任务最大只给 50 token防止模型输出大段解释性文本第三精简 Prompt 冗余信息Prompt 每多 1 个无效 token在每天 10 万次调用下就是实打实的浪费把角色描述压缩到必要信息为止。要注意的是这三个手段不是优化一次就完了。我每月底都会导出调用日志按任务类型统计每任务的平均 token 消耗找出去环比增长异常的任务重点排查——成本控制必须做成持续的运营动作而不是发布前的优化动作。6.4 本地模型幻觉与业务风险最后一道人工防线本地模型参数量小幻觉率明显高于云端大模型。所谓幻觉就是模型输出看起来合理但实际错误的内容比如它会在分类任务里“编造”一条用户反馈中不存在的关键词作为依据。这在数据处理场景里影响不大但在生成分析报告场景里可能直接带偏业务决策。我的处理原则是分级信任高风险场景涉及财务、法务、医学信息提取强制要求模型给出可信度评分同时附加“来源引用”——模型必须指出来自哪条输入的哪个字段评分和引用不可靠时直接置为人工复核队列允许核心结果由人工确认后再释放。这个设计牺牲了一点自动化率但保住了系统底线。工程化不是追求极限自动化而是让自动化在一个可信的边界内运作。写在最后一点个人的工程体感从零搭建这一整套 AI 工程系统前后跨了将近四个月。回头看最关键的转变不是学会了多少新工具而是彻底扭转了对 AI 的认知不要把一个概率性的、会犯错的系统当成确定性的 API 函数来“调”反过来所有工程手段——Prompt 结构化、Agent 编排、本地部署、测试评估、成本控制——本质上都是在和不确定性共处给它划出边界把它驯化成能交付价值的工具。如果你正在从零开始走这条路我给一个最朴素但最有用的建议先手写一个三十行的 ReAct 循环再用这套循环去解决一个真实的小问题不要用任何框架。这个“笨功夫”会让你扎扎实实理解 Agent 的每一环之后你再上手任何工具都会觉得通透。这个项目到这里后续我还会继续在“多 Agent 协作模式”和“私有数据微调”上深挖——那是从零到一之后从一到十的事了。