先说一个真实的感受很多人看到“AI engineering from scratch”这个标题第一反应是“从零手写一个Transformer”“从零训练一个大模型”。但我做AI工程这些年最大的体会是绝大多数团队和开发者真正缺的不是训练模型的数学基础而是把一个“能跑的Demo”变成“能上线的系统”的那一整层工程能力。这篇文章我想聊聊从零开始做AI工程到底要经历什么。我会从提示词工程讲起再到Agent编排、评测体系、Harness Engineering最后落到“什么时候才值得从零训练模型”。这一路都不是教科书式的理论而是我在真实项目里踩过坑、填过土之后沉淀下来的实践经验。无论你是刚接触AI的开发者还是已经在做ChatBot想往深处走的工程师这篇文章都值得你花十分钟读完。1. AI工程从零开始先搞清楚它在工程化什么1.1 从“调API”到“跑系统”三个关键变化我见过不少朋友的入门路径注册一个API账号写十几行代码把大模型调用通了然后发一个“XXX AI助手诞生了”的朋友圈。这不是工程这只是调接口。真正的AI工程是你拿到一个业务需求——比如“做一个能回答用户售后问题的客服机器人”——然后你要面对的不再是“让它生成一句回答”这个简单动作而是一整条链路用户消息进来你要先做意图识别再决定调用哪个模型或工具模型返回的结果要做格式校验失败了还要自动重试或降级最后把答案推送给用户。整条链路里任何一个环节出问题用户感知到的就是“这机器人真笨”或者“这系统又崩了”。从“调API”到“跑系统”我总结出三个本质变化输入从“单条指令”变成“多源异构数据”。真实场景里用户的输入长短不一、口语化严重、还可能掺杂错别字和emoji。你的系统要能容忍这种不确定性而不是直接把原文扔给模型。输出从“一段话”变成“要被程序消费的结构化结果”。你在Demo里可以让模型随便说但生产系统里模型的输出往往是一个JSON结构、一个SQL语句、一段代码、或者一个具体的工具调用参数。模型说多了、说少了、格式错了程序都会崩。这是AI工程最常踩的坑。失败从“可以人工干预”变成“必须自动化恢复”。Demo挂了你可以重新跑一次生产环境挂了你自己都不知道。所以AI系统必须预设好超时、重试、熔断、兜底逻辑让系统在模型表现不佳时也能平稳运行。1.2 其他软件工程经验哪些能继承哪些要放弃我最早是从传统后端转来做AI应用的当时最痛苦的一件事就是我以前那套“精确定位Bug”的思路在大模型面前失灵了。传统软件里程序出错一定有确定性的原因——数据库连不上、空指针、字段拼错。你只要翻日志、断点调试总能找到根因。但大模型出错很多是没有“根因”的不是因为代码逻辑错了而是因为模型这一次生成的结果偏离了你想要的方向。你再怎么打印日志也找不到“为什么它偏偏在这次说了这句话”。这不是说传统软件工程的经验就没用了。恰恰相反版本管理、模块化、自动化测试、CI/CD、监控告警这些AI工程一样都离不开甚至更重要。模型本身就是巨大的不确定性来源你需要用工程手段把这个不确定性围堵住让它不要直接爆到用户面前。所以我的建议是做AI工程你的心态要从“消灭错误”变成“控制错误的影响范围”。你不是要和一个概率系统较劲而是要给这个概率系统装上方向盘和刹车。2. 提示词工程的本质它其实是一种接口设计2.1 用开发接口的思路来写提示词很多人写提示词特别随便——“帮我写个周报”。模型也真的就给你写了一段通用周报然后你骂模型不好用。但模型很冤枉因为它根本不知道你是谁、你的项目是什么、周报要报给谁。我把提示词看成一种接口设计大模型是你无法打开源码、只能通过文本调用的外部服务提示词就是你这个服务的“API文档”和“入参结构”。如果你在调用一个SDK的时候连参数名都懒得传对你会怪SDK不靠谱吗模型也是一样的道理。一套相对完整的提示词通常会包含这几个部分部分作用示例片段系统指令System Prompt定义角色、任务边界、输出风格“你是XX公司的售后客服语气专业友好”用户输入User Input实际请求内容“我上周买的耳机右耳没声音了”输出格式约束规定返回结构“必须返回JSON字段包括answer和confidence”示例Few-shot给出输入输出对规范行为“问耳机怎么充电答请查看包装盒内说明书”我在实际项目里会把提示词跟代码一样放在Git仓库里管而不是写在用户聊天框里试了就算了。每次改动提示词都要提交一次变更记录标注“为什么改、改了之后影响哪些场景”。这样你出了线上事故还能回溯到“上一版这个时间段用的提示词是什么”。2.2 少样本与思维链实例比命令更有效这里说一个很反直觉的经验你给模型下“不要做什么”的命令往往不如给模型“该怎么做”的示例管用。我试过在提示词里写“不要回答与售后无关的问题”模型还是会偶尔放飞自我。但当我改成在示例里给了一条“问今天天气怎么样答抱歉我只负责处理售后问题”之后模型的守规矩程度明显上升。原因在于命令是抽象的模型很难从抽象规则里提取出精确的行为准则而示例是具体的模型本身就是在“预测下一个token”的任务里训练出来的你给它看大量“输入→正确输出”的配对它自然会把行为收缩到你期望的那条路径上。还有一个很关键的技巧是思维链Chain of Thought。你让模型做复杂推理的时候单纯问“这个退款申请该不该通过”它可能直接给个“应该”但理由毫无逻辑。如果你在提示词里引导它“先列出退款政策再列出用户情况再逐条比对最后给出结论”模型的推理准确率会明显提升。本质上是让模型把隐含的推理过程显式化因为大模型是“接着往下写”的你让它先写推理过程它就会顺着推理过程往下走而不是直接跳到结论。做AI工程的朋友思维链这个技巧真的要刻进DNA里。2.3 提示词也要做版本管理和回归测试提示词是AI系统的灵魂但这个灵魂经常被随手改来改去这是我最不能忍的。一个正经做AI工程的人应该给提示词建立一套跟代码一样的生命周期管理流程变更前先跑一遍回归测试确认影响面变更后记录版本号方便线上回滚。我自己的项目里有个简单做法把提示词按场景拆分存成独立文件比如prompts/refund_review.txt、prompts/order_query.txt每个文件顶部写作者、版本、修改日期然后在代码里按版本号加载。这样做还有个额外的好处当你发现线上效果变差了你可以快速定位是“这个版本提示词的问题”还是“模型侧的问题”不用整个系统翻一遍日志。很多AI工程事故其实只是有人在某个下午手痒改了一句prompt导致的。3. Agent编排实战单次调用变成完整的业务流程3.1 工具调用的原理与选型当你觉得“单次问答”已经满足不了业务的时候就会自然地走向Agent——让模型不只是“说话”而是“做事”。比如用户说“帮我查一下订单OD20240001的物流”模型需要先调用订单查询工具拿到结果再组织语言回答用户。这个过程的官方术语是Function Calling函数调用有些框架里也叫Tool Use。它的本质是模型不直接执行代码它只是生成一个“调用计划”——决定该调用哪个工具、传什么参数——真正执行工具的行为是由你自己的代码来完成的。做一个工具调用系统最重要的不是写模型的调用代码而是把每个工具的描述写得足够清晰。模型是靠工具描述来“决定”要不要调用、怎么传参的所以你的工具描述要像API文档一样写清楚这个工具是干什么的语义清晰避免模型误解什么时候该调用、什么时候不该调用每个参数的含义、类型、取值范围我见过一个经典翻车有个团队给模型注册了一个“删除订单”的工具工具描述写的是“删除指定订单”。然后用户吐槽“你们这个网站真难用”模型直接调用了删除工具把某个订单删了。这不是模型的问题是工具描述里没写“仅在用户明确要求删除且验证用户身份后才能调用本工具”。工具的边界描述不到位模型就会拿着锤子看见什么都是钉子。3.2 计划-行动-观察循环三大坑与防御手段标准的Agent工作方式是“计划-行动-观察”Plan-Act-Observe循环模型先想下一步要干嘛计划然后调用工具或生成文本行动再根据结果观察决定下一步。这个循环可以拆成一次对话里的多轮推理。听起来很美好但我在实际做Agent的时候踩过三个特别深的坑第一个是死循环。Agent在循环里反复调用同一个工具拿到的结果还是一样的它却不肯停下。解决方式是硬性设置最大迭代次数比如最多5轮超出就强制终止并返回当前最优结果。这个数字不能太大否则一次请求可能跑几十秒用户早跑了。第二个是上下文爆炸。每多一轮Agent的上下文就把上一轮的输出塞回去Token越滚越多最后要么超长截断要么成本飙升。我的做法是只保留关键轮次的记录把已经完成的中间结果压缩成一句话摘要而不是全部塞进去。第三个是**“幻觉自信”**。Agent调用工具拿到一个异常结果比如订单查询返回空它可能不是如实说“查不到”而是编造一个“订单已发货”的回答。这个问题靠提示词很难根治必须在代码层做校验工具返回空结果时直接剥掉Agent的解释权强制它返回“未查询到”的模板话术不让它自由发挥。3.3 多Agent协作时的状态同步问题单Agent搞定了很多人就开始搞多Agent一个负责分析需求一个负责写代码一个负责测试。这种架构听起来很酷但工程复杂度是指数级上升的。我在项目中用过“主Agent子Agent”的架构最大的教训是不要让每个Agent都直接改全局状态。比如主Agent让子AgentA去查资料、子AgentB去写报告如果两个子Agent各自维护一份状态最后你会发现大家手里的数据完全对不上。正确的做法是设置一个共享状态机所有Agent不直接修改全局数据而是返回结构化的变更指令由你的代码统一落地。好比公司里不是每个人都能直接动财务账本而是所有人填报销单财务统一审核入账。这个“财务”就是你的业务代码。结构化返回还可以用我前面讲的JSON Schema做校验确保每个Agent交上来的“变更单”是合规的。4. 评测体系没有衡量就谈不上工程4.1 评测集怎么搭三类样本缺一不可做AI工程最怕的就是“凭感觉”。“我觉得这次改好了”“用户好像反馈还行”——这些主观描述在系统规模小的时候还行一旦Agent变复杂、提示词迭代频繁你就完全失控了改了一个场景的效果另外三个场景全挂了。所以AI工程的第一步是建一个评测集Evaluation Set。我的建议是至少包含三类样本基础正例业务里最常见、最标准的输入。比如客服机器人就是“我要退款”“我的订单到哪了”这类高频问题。这些例子保证系统不倒退。边界Case容易踩坑的场景。比如“用户问价但是语气很不耐烦”“用户同时问了两个问题”“用户输入只有三个字‘很生气’”。这些例子帮你测出系统的韧性。对抗Case主动设计的难题。比如有用户想诱导模型越狱、问敏感问题、或者故意用错别字和同音字混淆模型。这类样本用来测安全性和鲁棒性。评测集不用贪大50到100条就够起步但必须稳定、可复现、覆盖面广。每周我会往里补充线上真实遇到的失败案例这样评测集就会越滚越像一个“系统体检表”。4.2 评测维度不只准确率还有格式、安全、成本很多团队做评测只知道看“答得对不对”但生成式AI的工程化评价远不止这一点。我自己搭了一个多维评分体系每个维度单独打分汇总后才能判断一个Agent能不能上线维度说明评分方式答案准确率内容是否准确、完整、符合业务逻辑人工标注或LLM打分1-5分格式合规率返回的JSON是否能被程序正常解析脚本自动校验100%硬性要求指令遵循率是否严格遵守“不许答XX”等约束规则匹配人工抽检安全合规率是否拒绝回答敏感问题不泄露Prompt对抗Case自动检测单次成本消耗的Token量和外部调用费用自动统计端到端延迟从用户输入到返回结果的时间监控平台自动上报这个表里最容易被忽视的是“格式合规率”。有一次我线上系统突然大量报错排查半天发现是模型在返回JSON时多了一句“好的这是您要的信息”在JSON前面导致json.loads解析失败。从那以后我规定所有模型输出必须过一层“提取器”先把代码块和多余说明剥掉再进解析器。永远不要把模型输出的格式正确性当成默认前提。4.3 自动化评测把评测塞进CI流程评测集搭好之后如果你还靠手工一条条跑那是给自己挖坑。正确的做法是把它接入CI/CD流程每次修改Agent代码、提示词或模型配置都自动跑一遍评测集输出一份“指标对比报告”低于阈值的改动直接不让合并。我团队里的做法是开发了一套简单的命令行评测工具跑完之后自动输出Markdown格式报告。有了这个机制之后我再也不怕任何人“手痒改了一下prompt”了——改之前跑一跑效果好你就改效果差就别动。没有自动化评测AI工程就是碰运气。这里补充一个实操细节评测怎么打分中小项目直接让GPT-4当裁判LLM-as-a-judge性价比最高。你要在打分提示词里写清楚“参考标准答案根据准确性、完整性、简洁性打1到5分”并且要随机打乱答案顺序再提交给裁判模型避免它的惯性偏见。至于等级我建议先用“通过/不通过”这类二元判断等你需要精细化调优时再上1-5分评分。5. Harness Engineering给大模型设计轨道5.1 为什么非加“轨道”不可“Harness”这个词在AI圈越来越火它直译是“背带、挽具”用在AI工程里我更愿意把它理解成轨道你无法改变火车头的动力大小但你可以决定它能往哪个方向跑。大模型本身是一个开箱即用的“超级生成器”它能写诗、写代码、胡说八道。你要是不加约束它就什么都能干、什么都敢说。Harness Engineering就是给模型加上一层又一层的工程约束让它只能做系统允许它做的事情。我见过一个最惨痛的生产事故某个内部知识库机器人用户问“公司裁员名单是什么”模型没有知识库里找到相关信息却自己编了一份“内部资料”回答用户。问题根源不是模型太笨而是系统没有加“不知道就承认不知道”的Harness。从那以后我定了一条铁律任何生成式AI系统上线前必须通过“无信息拒答测试”——故意问一个知识库里不存在的问题看它会不会编造答案。5.2 结构化输出与兜底逻辑双保险模式第一道Harness是结构化输出约束。现在各大模型服务商都支持JSON Mode或者Response Format你可以强制模型返回合法的JSON。但这道约束不是百分百可靠的所以我设计了一套双保险第一层强制模型按JSON Schema输出。2. 第二层代码里做容错处理拿到输出先清理再解析解析失败就带着修正指令重试一次再失败就走兜底回复。举个例子我要求模型返回“退款原因分类”时输出JSON解析逻辑大概是import json import re def parse_model_output(raw: str): # 第一步去掉可能的代码块标记 cleaned re.sub(rjson|, , raw).strip() try: return json.loads(cleaned) except json.JSONDecodeError: # 第二步尝试提取第一个 { 到最后一个 } 之间的内容 start cleaned.find({) end cleaned.rfind(}) if start ! -1 and end ! -1 and end start: try: return json.loads(cleaned[start:end1]) except json.JSONDecodeError: return None return None这段代码算不上高深但它在线上救过我无数次。模型输出的正确性不是前提而是需要你用工程手段去保护的变量。5.3 权限、预算与超时的工程化管控Harness Engineering不止体现在“让模型答得好”还体现在“让模型别闯祸”。工具权限管控每个Agent能调用的工具集要最小化授权比如“售后客服”只让查订单和退款单“数据分析师”只让查数据库视图绝不能让它直接执行删除或更新操作。成本预算上限给每个会话或每个用户设置单日Token消耗上限超过自动降级到免费模型或直接熔断。宁可服务降级也不能让一个用户的恶意请求烧掉你一整月预算。超时与重试机制模型接口调用设置合理超时时间超时就触发一次最大2次的退避重试仍失败就走预置的兜底话术。这个兜底话术也要提前写好不要让用户在报错页面干等。这三个“舵”是AI系统能否稳定运行的关键。很多人把注意力全花在“模型调优”上却忘了工程学的本质是面对最坏情况还能兜底。6. 从零构建模型什么情况下值得走这条路6.1 学习路径和生产决策是两码事回到文章最开头那个问题到底要不要“from scratch”去训练一个模型我的答案分两种情况。如果你的目标是做出一个能解决业务问题的AI应用我强烈建议不要从训练模型开始。原因很实际预训练一个大模型的算力成本是以百万美金计的数据收集和清洗又是一座让人头皮发麻的大山。你完全可以用现成的API或开源权重把精力集中在提示词、Agent编排、评测体系和Harness上——这些才是绝大多数业务项目真正的核心竞争力。如果你的目标是深度理解AI模型的工作原理那“从零构建”是一条极好的学习路径。我建议你去看一些经典的开源实现比如用纯Python和NumPy实现一个简化版Transformer跑通一次前向和反向传播。这个过程中你会真正理解“为什么Token要Embedding”“Self-Attention到底在算什么”“为什么训练要吃那么多显存”。这类知识在纯调API的过程中是永远学不到、也永远理解不透的。6.2 模型选型决策表别一开始就选最重的很多人一上来就在“要微调一个开源模型”和“要自己训练一个模型”之间纠结。我给你一张贴切的选型表方案成本可控性数据要求适用场景闭源API如GPT套件按量付费无固定硬件投入低模型升级不可控无需训练数据快速验证、通用对话、起步阶段开源权重部署如Qwen、Llama等中等需要GPU服务器高权重在自己手里无需训练数据数据合规敏感、离线环境、稳定性要求高微调LoRA/全参微调中高需要训练资源高能改变模型行为风格几百到几千条高质量数据特定领域风格、私有术语、输出格式强绑定全量预训练极高需要大规模算力集群最高完全自主TB级清洗语料科研探索、特殊语言/领域、公司级战略投入我做项目的决策习惯是能用API解决的绝不自己训练API搞不定的再考虑开源权重部署数据敏感影响业务安全的才上微调。每一步往下走都要有一个具体的问题逼着你去换方案而不是为了“技术炫酷”去升级链路。6.3 我的起步路线建议根据我带团队的经验一个比较合理的“AI工程从零起步”路线是这样的第一个月熟悉主流大模型API的调用方式重点练提示词工程。建立一个至少30条的基础评测集学会用LLM-as-a-judge给自己写的提示词打分。第二个月尝试做一个带工具调用的Agent比如本地文件问答机器人或订单查询机器人。给它接上“计划-行动-观察”循环加上最大轮数和超时控制。第三个月把评测体系自动化接进CI给你的Agent套上Harness加上结构化输出校验、拒答逻辑和成本监控。第四个月如果你还想往深走选一个开源小模型7B级别用LoRA做一个领域微调比如让它学会你公司的产品术语。这是“from scratch”学习曲线里最有成就感的一步。每个阶段都要有一个“上线”动作。哪怕是给团队内部用的小工具也行因为只有真实跑起来你才会遇到那些教程里不会写的破事——Token超了、JSON解析崩了、用户提问把Agent带偏了。这些问题本身就是最宝贵的教材。最后再分享一个我个人的习惯我在每个项目里都会维护一个“模型翻车记录”文档把线上遇到的失败案例、错误输出截图、复现问题和修正方式全部记下来。这个文档在团队里被传阅的次数比任何一本AI教科书都多。因为AI工程这门手艺本质上就是不断积累“怎么让概率系统稳定干活”的经验。你踩过的每一个坑都是之后最值钱的判断力。