从零开始构建AI工程:提示词协议、上下文管理与工具调用实战

发布时间:2026/9/28 15:17:45
从零开始构建AI工程:提示词协议、上下文管理与工具调用实战 “ai-engineering-from-scratch”这个话题我琢磨了很久才敢动笔。半年前我开始带着团队做AI应用落地最大的感触不是模型能力不够而是身边大多数人连“AI工程”这三个字到底意味着什么都没想清楚。很多人以为AI工程就是会调接口、会写Prompt可真把一个AI功能做成能上线、能维护、能兜底的产品系统中间隔着的是提示词协议设计、上下文管理、工具调用链路、评估体系、资源成本控制这一整套工程方法。这篇东西就是我从零开始搭建AI工程能力的一份实践总结不聊玄乎的架构只讲我真实踩过的坑、验证过的方法以及可以直接抄走的路径。1. 为什么我会把“从零开始”当成AI工程的第一课1.1 会用AI和能交付AI系统是两种完全不同的能力我面试过不少候选人简历上写着“熟练使用ChatGPT、熟悉Prompt Engineering”可一聊到实际落地就露馅了。你问他如果模型返回的JSON字段偶尔缺失你的下游逻辑怎么处理如果同一套Prompt在用户换了一种说法之后就答非所问你的系统靠什么兜底大多数人的反应是愣住——因为他们只把AI当成一个“问答工具”在用没把它当成一个“有概率输出的运行时组件”来设计。这恰恰是我想说的第一件事会用AI和能交付AI系统是两种完全不同的能力。前者是消费者视角后者是工程视角。工程视角的核心就是默认模型会犯错、会不稳定、会超时、会胡说八道然后围绕这些不确定性设计一套可控的流程。举个例子我让AI从一段客服对话里提取用户意图和情绪标签如果只是调API把结果打印出来那是Demo但我会把输出强制约束成JSON Schema加一层解析失败兜底再对关键字段做枚举校验命不中就走人工复核队列——这才叫交付。从零开始学AI工程第一步不是学某个框架而是先扭转这个认知。1.2 工程化的本质是让不确定性变得可管理我经常用一个比喻写传统代码你在和确定性的逻辑打交道做AI工程你在和一群“能力很强但偶尔抽风”的实习生协作。你怎么管理一个能力很强的实习生不能只丢给他一句话任务要给他标准作业流程他交上来的活你要复核重要的环节你要留出人工确认位他一旦跑偏你要能随时叫停。Prompt Engineering、结构化输出、模型评估、人工审核回流——本质上都是这套管理手段。工程化的目标从来不是让AI永远不犯错这不现实。目标是让AI犯错的方式可控、可发现、可修复。我在设计AI功能时通常会问自己三个问题这个环节如果AI答错了会造成多大损失有没有办法在AI输出之后、影响用户之前拦截错误模型能力不够的时候我能不能靠流程设计来补位只要这三个问题有答案哪怕模型本身不是最顶级的系统整体依然是可靠的。反之就算把模型换成最新的旗舰版没有工程封装照样会在线上出事故。2. 从零起步的三块核心拼图提示词、上下文、工具调用2.1 Prompt不是写话术是在定义输入协议很多人把Prompt Engineering理解为“把话问得更清楚一些”这是被各种网文带偏了。我在实际工作中最深的体会是Prompt不是聊天话术它是你定义给模型的“输入协议”和“输出契约”。一份合格的生产级Prompt至少要包含角色边界、任务目标、输入变量说明、约束条件、输出格式、失败时的兜底指令还要配一两个示例few-shot让模型理解你的期望粒度。我写Prompt有一个习惯先写“输出格式”再写“任务描述”。因为对模型来说输出格式就是最强的约束指令。比如我做客服工单分类Prompt里会这样写system_prompt 你是一个工单分类引擎。你的任务是判断用户诉求属于哪个类别。 可选的类别严格限定在本列表内 - refund: 退款/费用异议 - shipping: 物流/配送问题 - product: 商品质量/使用问题 - account: 账号/权限问题 - other: 无法归入以上类别 输出要求 - 只输出一个JSON对象不要输出任何解释文字。 - 字段格式{category: 类别英文名, confidence: 0.0-1.0, reason: 不超过20字的原因} 规则 - 如果信息不足category填otherconfidence不得超过0.6。 - reason必须来自用户原话不允许发挥。 这个格式你可以直接拿去改成自己的场景。它的核心价值是把模型输出变成了可程序校验的数据。confidence低的情况走人工字段不在枚举内的情况直接告警reason必须来自原话防止模型“脑补”。我见过太多线上翻车案例根因全是Prompt里没写输出契约下游程序拿到的是一堆自由文本解析逻辑天天崩。2.2 RAG和上下文管理别一上来就堆向量库上下文管理是AI工程里最容易被低估的模块。我见过有团队一上来就搞向量库、搞RAG结果效果还不如直接把知识库全文拼在Prompt里丢给模型。为什么因为他们的问答场景文档量就几万字塞进上下文完全没问题做了RAG反而因为切片检索不准把关键信息弄丢了。我的经验是先搞清楚你的上下文到底有多大再决定要不要上RAG。上下文管理有一个基本优先级文档总量小于上下文窗口的50%直接全文注入最简单也最稳定文档量中等先做“分层摘要关键段落动态拼装”用规则或小模型做初筛文档量很大或需要跨文档推理才轮到向量检索而且必须配合rerank重排和召回评估。即便真要做RAG也不要迷信“切块越细越精确”。我在项目里吃过亏按固定512字符切块把一段完整的技术说明拦腰切断语义丢失检索出来的片段全是残句。后来改成按标题、段落边界做结构切分再给每个片段生成摘要并存metadata召回质量明显提升。这里分享一个实用思路检索召回之后一定要加一步“相关性判断”——把召回的片段连同用户问题一起交给模型先让模型判断“这段内容是否真的能回答这个问题”不相关就丢弃。很多人只做召回不做判断结果检索系统把完全无关的内容拼进Prompt模型一本正经地胡编反而比不带上下文更差。2.3 工具调用是Agent的“手脚”也是最大的不可控源所谓AI Agent我理解并不神秘就是让模型在对话循环中拥有“工具调用”的能力——它分析用户意图后决定去调用哪个函数、传什么参数拿到工具返回结果后再组织回答。这里有一个工程上的坑工具调用给了模型“行动力”也给了它“闯祸空间”。一个只有对话能力的模型说错话顶多被吐槽一个有工具调用能力的模型一旦解析参数错误、调用顺序混乱、循环不终止可能真的会去给用户发消息、下单、改数据库。所以我的建议是新手做Agent一定要先把“工具权限”做小。工具函数的设计原则是宁可增加一个确认步骤也不给模型一杆子捅到底的权限。比如模型想调用“发送邮件”工具那就先走一个“生成邮件草稿并返回给用户确认”的工具用户点了确认才真正触发发送。这个中间层只有几行代码但能把事故率降一个数量级。工具调用的入参也一定要做Schema校验模型给的参数哪怕有一丁点不符合类型、超出枚举范围都不要直接塞给函数。我在内部的Agent框架里规定模型调用工具返回的参数先过一遍Pydantic校验不过就重新要求模型修正最多重试两次还不行就放弃本次调用并转人工。3. 一条可复制的AI工程实操路径3.1 第一步在不动架构的前提下跑通最小验证很多团队做AI项目上来就画架构图向量数据库、Agent编排、消息队列、微服务……画得天花乱坠结果连“用户的核心问题模型能不能答好”都没验证过。我的习惯是反着来先用最土的方式把一个最小闭环跑通。所谓最小闭环就是拿一个简单的Python脚本读一条用户问题拼一个写死的Prompt调一次模型打印出结果人工看一眼对不对。这一步的价值不是演示是快速回答一个致命问题当前模型在真实输入上的基线表现到底能不能打。我会把这一步当成一次正式的测评来做准备20到30条覆盖典型场景的用户输入用最朴素的Prompt跑一遍记录每一条的输出质量分三档——可以直接用、需要后处理才能用、完全不能用。如果“完全不能用”的比例超过30%别急着调Prompt大概率是任务本身超出了模型当前能力要么换更强的模型要么把任务拆小。如果大部分结果“需要后处理才能用”恭喜你这恰恰是工程可以发挥作用的空间设计解析规则、补全逻辑、格式修正把可用率从60%拉到95%这就是AI工程师真正的价值。3.2 第二步用Schema把输出变成可校验的数据当我确认模型在自由文本输出上“基本能用”之后下一个动作永远是加上结构化约束。现在的模型API基本都支持response_format或者工具调用式结构输出我强烈建议生产环境全部启用。我之前做一个文档信息抽取功能第一版让模型自由输出结果同一份合同模型有时候输出“甲方XXX公司”有时候输出“甲方是XXX公司”解析脚本写了一个星期天天被字段格式变化折磨。后来切换到类似structured_output的方式直接定义好数据模型让模型返回JSON再配合Pydantic做运行时校验问题直接消失。你不需要在意用的是什么SDK核心思路是一致的from pydantic import BaseModel from enum import Enum class PartyRole(str, Enum): party_a 甲方 party_b 乙方 guarantor 担保方 class ContractEntity(BaseModel): role: PartyRole company_name: str unified_social_code: str | None None sign_date: str | None None # 模型输出先校验校验失败就重新抽取一次 result ContractEntity.model_validate(json.loads(raw_output))这样做的另一个好处是结构化字段天然形成了后续业务的接入点。你可以直接拿字段去做匹配、入库、触发流程而不是再写一堆正则去猜模型在讲什么。3.3 第三步用工作流把多个AI步骤串成闭环单个模型调用稳定之后就要考虑组合多个AI步骤甚至让Agent在步骤之间做决策。我做的很多业务其实不是“一个大Prompt解决所有问题”而是拆成几个小步骤每个步骤由一个专门的模型调用完成每一步的输出校验通过后才进入下一步。举个实际例子我做一个“智能售后处理流”第一步检测用户情绪等级如果情绪分高于阈值先走安抚话术再进入正式处理第二步从对话里抽取订单号、问题类型第三步查库存和售后政策把结果组装进答复模板第四步让模型根据模板生成个性化答复。这四个步骤如果用一个大Prompt做一方面上下文互相干扰另一方面单点出错很难定位。拆开之后每一步都能单独评估、单独降级。比如第二步抽取失败就直接转人工而不是硬着头皮生成答复。工作流编排上有两个我踩过的坑提醒大家注意。第一步骤之间传递数据要“显式传参、显式校验”不要指望模型在上文里记住第二不是每一步都必须用大模型能用代码规则完成的步骤比如查库存、拼模板就用代码写死大模型只做它擅长的语义理解和生成。这样既省钱又稳定。3.4 第四步按真实场景建评估集持续迭代AI工程和传统软件工程最大的区别之一就是它没有一个“编译通过就完成任务”的验收线。模型换了版本、Prompt改了几个字、用户的说话方式变了一种线上表现都可能波动。所以从项目第一天起就应该维护一份评估集。我的评估集分三层第一层是“回归集”选50到100条典型输入每次改Prompt或换模型都要全量跑一遍确保质量不倒退第二层是“边界集”收录那些容易让模型翻车的输入比如用户故意分叉话题的专业表达、之前线上出过错的问题第三层是“线上回流集”定期从真实日志里采一些新问题加进去持续补充覆盖度。跑评估集的时候光看“答没答对”不够还要按场景分维度打分。我常用的维度包括信息完整度、格式合规率、幻觉率模型答了原文里没有的信息、拒绝率模型什么都不答的比例。这些分数是驱动迭代的没有数据就没有方向。我见过太多团队调整Prompt全凭感觉今天加一句话觉得好明天反过来又删了折腾一个月原地踏步。有评估集之后哪怕效果暂时变差也能立刻知道问题出现在哪个维度、哪一批case上。4. 本地部署与模型选型的实战建议4.1 判断是否需要本地部署的三个问题“本地部署AI”是一个听起来很酷但经常被误解的需求。我先泼一盆冷水如果你只是觉得本地部署“安全、可控、免费”建议先冷静三分钟。本地部署真实要付出的代价包括显卡采购、显存规划、推理性能调优、模型更新维护以及最容易被忽略的——同级别效果的开源模型和商业API之间存在肉眼可见的效果差距。我在决定要不要本地部署时只问三个问题。第一数据是不是真的不能在网络环境下处理比如企业内部合同、隐私性的医疗数据这类场景没得选必须本地。第二稳定性要求是不是高到不能依赖外部服务比如产线控制、离线环境。第三成本模型是否划算如果日请求量不大买一张昂贵显卡的摊销成本远超按次数付费的API账单。三个问题都是否那本地部署就是给自己找麻烦。只要有一个答案是肯定的再考虑本地。选型上我的建议也简单直接先从同级别开源模型里选经过社区验证的中等规模版本不要一上来就追最大参数量。对大多数业务场景推理速度和部署成本比那一点质量提升重要得多。4.2 资源估算、量化方式与并发调优本地部署最核心的数学题是显存。我之前被问得最多的问题就是“我这台机器能跑多大的模型”学生党以为8G显存能跑70B模型这是不可能的。你至少得知道一个估算公式模型显存占用粗略按参数量乘以每参数字节数算。FP16精度下每个参数占2字节所以7B模型大约需要14GB显存再加上KV Cache和推理中间态开销实际要预留20GB以上。想用8G显存跑则只能走4-bit量化一个7B模型量化后大约4GB上下勉强能塞进去但生成质量和速度都会有损失。另外我要特意强调显存够不够不仅看模型权重还要看并发。如果同时有4个用户请求每个请求的上下文都很长KV Cache会成倍吃掉显存。我的实测经验是长上下文场景下KV Cache比模型权重还吃显存这是大家最容易算漏的一项。建议先用单路请求做基准测试测出显存占用再按“总显存预留30%”的余量倒推并发上限。推理引擎方面目前主流选择已经比较成熟优先用带优化和量化支持的推理服务框架业务还没到瓶颈前我不建议在自研推理引擎上浪费时间。4.3 多模型混合编排与降级兜底本地部署真正发挥威力是在“多模型混合编排”的架构里。我喜欢的做法是把不同难度、不同敏感度的任务分到不同模型上。比如简单的意图分类和内容提炼用本地小模型处理响应快且不需要把数据传到外部需要高质量生成的最终答复再调用更大的模型敏感任务永远走本地链路。这个混合架构必须配一套降级策略。我在生产线上是这样设计的本地模型请求超过2秒没返回自动切换外部API外部API连续出错三次熔断并切回本地两边都不行的时候返回一个编辑好的兜底文案然后进人工队列。这层逻辑用代码写也就几十行但有没有这层逻辑决定了你的AI服务是“偶尔不可用的Demo”还是“可以长期值守的生产系统”。所有依赖大模型的功能都应该默认假设它会故障没有降级方案的AI功能上线就是埋雷。5. AI工程线上问题排查与经验沉淀5.1 输出质量波动先查这几处线上AI系统最常见的问题是“昨天还好好的今天突然变笨了”。这种事别慌跟着清单查就行。我的排查顺序是先看模型版本有没有被平台悄悄更新再看网络链路和重试逻辑超时重试导致的语言模型重复输出经常被误判为质量问题然后查Prompt里的动态部分很多Prompt会拼当前时间、用户输入原文这些变量一旦带了脏数据输出质量立刻下滑最后才是评估集跑分确认是普遍退化还是个别case。我对团队的硬性要求是每个线上请求都要全链路留日志——原始Prompt、模型原始输出、后处理结果、用户反馈链路缺一不可。没有日志质量波动就只能靠猜。我见过最典型的案例一次线上效果大跌排查半天最后发现是某个上游系统把用户昵称拼接进了Prompt昵称里包含一段恶意文本把模型带偏了。这种问题不抓日志根本无从查起。5.2 Agent工具调用失控排查思路和应急开关Agent系统因为引入工具调用故障模式比纯对话系统多一截我把常见的失控情况整理成了一张速查表故障现象常见原因排查手段Agent反复调用同一个工具停不下来工具返回结果没有让模型满意模型想重试设置循环上限观察调用参数是否重复把参数传错给工具Schema约束不严模型自由发挥校验入参枚举把非法请求挡在函数外不该调工具的时候调了工具Prompt边界指令不够硬加前置意图判断非必需场景禁止工具执行工具返回了结果但Agent胡说模型忽略工具结果凭训练记忆回答在Prompt中强化“只依据工具结果作答”多工具顺序错乱缺少工作流状态机把多步操作改成显式状态流转不要全交给模型最重要的不是事后排查而是事前给你的Agent装一个“急停开关”。我的做法是所有工具在执行实际副作用发消息、改数据、扣款之前必须经过一个统一的审批接口。这个接口在联调阶段直接模拟放行上线初期则切到人工确认等积累了足够多的可信样本再逐步放开。这个思路虽说保守但能省掉无数次事故善后工作。5.3 成本、延迟和安全边界上线前必须设置护栏很多从零开始做AI工程的人第一步就栽在成本上。大模型调用是按Token计费的Token单价看着不高但乘上反复重试、长上下文、并发增长月底账单会非常吓人。我见过一个团队做内部知识问答每条用户问题都要把整本手册塞进Prompt单次成本高得离谱。后来加了缓存层把用户问题做语义相似度匹配命中就直接返回历史答案成本直接降到原来的十分之一。除了成本护栏还有两个边界必须设置。一个是输入侧的内容边界你的系统接的是什么形态的输入、允许处理什么类别的信息、不允许碰什么都要在入口就拦截而不是等模型生成之后再补救。另一个是输出侧的行为边界哪些话不能说、哪些操作不能触发要在Prompt和工具权限两层同时约束。安全这件事在AI系统里不是附加项是架构的一部分。毕竟模型不是你团队的人它没有“常识”你不给它焊死护栏它就能在各种边界上来回试探。我个人在实际操作中的体会是做AI工程最大的倚仗往往不是最新最强的模型而是一整套关于输入、输出、工具、评估的纪律。模型能力可以靠换版本快速提升但工程纪律只能靠在真实场景里一次次踩坑来积累。从零开始不是指你得先弄懂所有底层原理而是指你要愿意从一个最小闭环出发不断给系统加约束、加校验、加兜底。这套方法虽然不性感却是我见过能真正把AI用稳、用久、用出价值的唯一路径。如果你现在正要启动一个AI项目别急着画大架构先拿一条真实数据跑通最小闭环再用工程手段把它焊成铁桶——这条路我替你走过确实走得通。