聊一聊青柚这个智能体项目。接到需求的时候,原型阶段连界面都没画,只有一句话:“让员工不用翻各种文档也能办事”。这句话看着朴素,落地起来牵扯的东西非常多——需要理解用户意图,拆解任务,调用系统工具,还要确保每一步输出的可靠性。我们从零开始搭方案、写提示词、接工具、搭评测,最后灰度上线,中间踩了不少坑,也沉淀出一套可以复用的方法论。这篇文章不聊虚的,只讲我们是如何把一个Agent类项目从想法做成可交付系统的,重点放在方案取舍、关键细节和失败复盘上。
如果你正准备做智能体开发,或者已经做了但总觉得效果不稳定、交付遥遥无期,这篇值得看看。我写的都是实战中的做法,不是PPT里的方法论,能直接用到你手头的项目里。
1. 需求拆解:别急着选模型,先把问题定义清楚
1.1 用一句话说清楚智能体到底解决什么
很多Agent项目死在第一步:需求方自己都没想清楚要做什么。
我们当时召集了所有干系人,逼着每个人用一句话描述青柚的最核心价值,最后收敛成三条可验证的目标:
- 员工用自然语言提问,系统能在10秒内给出有依据的回答;
- 能自动触发3类高频流程(报销查询、请假申请、设备报修);
- 回答正确率需要达到90%以上(以内部评测集为准)。
这三句话看着简单,价值极大。后续所有技术选型和资源投入都围绕它们展开,当团队内部产生分歧时,我们只需要问一句“这对三个目标有帮助吗”,就能快速做减法。
我在其他项目上吃过亏,一开始就想做一个“智能客服+知识问答+流程自动化+数据分析”的超级助理,结果做了三个月连核心场景都没跑通,重构了两次。这次学乖了,先缩窄边界,跑通闭环再谈扩展。
1.2 判断一个需求到底适不适合用Agent实现
不是所有问题都应该做成Agent。我们在立项时就做过一次“需求-技术匹配度”评审,核心是问三个问题:
第一,任务是否有明确的工具依赖?比如查询审批状态、创建工单,这些动作需要调用具体系统接口,正好能发挥Agent的工具调用能力。如果需求只是纯问答,不需要操作外部系统,那做一个RAG问答机器人就够了,不需要Agent。
第二,流程中是否有动态决策点?用户的诉求多样化,路径不是固定的。比如“帮我查下我上次报销的发票到哪里了”,这里需要识别用户身份、定位报销单、检查当前节点、再决定是否提醒财务——中间有多步判断。如果流程固定,用传统的工作流引擎更稳,成本也更低。
第三,错误成本是否可接受?Agent的推理过程存在不确定性,哪怕做得再好也不可能保证100%正确。青柚的定位是辅助员工、提供办事入口,所有涉及金钱、审批的操作都只做到“发起申请”而不是“直接执行”,这就把风险控制住了。
这三条筛下来,我们才确定青柚适合用Agent架构来做。
1.3 技术选型背后的取舍逻辑
模型层面,我们评估过继续用通用大模型和微调垂直模型两条路。最后选了前者,原因很现实:通用模型的综合能力更强,且通过提示词和检索增强就能覆盖大部分场景,没必要投入高昂的微调成本。只有在经过评测、发现通用模型在某个特定任务上稳定不达标时,才考虑收集数据做微调。
框架层面,我们选用了成熟的开源Agent编排框架来管理推理循环和工具调用,而不是自己从零写一套状态机。原因很简单:Agent的核心难点在于“推理-行动-观察”循环的稳定性,成熟的框架已经处理好了上下文管理、工具分发、重试机制这些底层逻辑,我们只需要把精力放在业务层。
知识库方面,选择开源向量数据库,配合文档切块和Embedding模型做检索增强。这块在前面几个版本里反复调参,后面我会详细讲。
2. 核心设计:智能体的大脑、手和记忆
2.1 任务编排:从“一个模型”到“三个角色”
青柚在逻辑上拆成了三个角色:路由器、执行器、验证器。这个设计的灵感来源于我自己对人工作业流程的观察——一个复杂任务通常不是被一个人从头做到底,而是先分析、再执行、最后检查。
路由器负责理解用户意图,把请求分类:是知识问答、流程操作还是闲聊。这个角色不直接调用业务工具,只输出分类结果和必要的槽位信息。执行器拿到路由器的输出后,从工具清单里挑选合适的工具,生成调用参数,依次执行。验证器在每一步执行之后做检查,判断结果是否符合预期,如果不满足就触发重新规划或向用户澄清。
这个三阶段设计的价值很直接:每个角色的提示词职责单一,比一个“全能Agent”更容易调优。如果青柚回答错了,我们能够快速定位是路由错了、工具参数错了还是质量验证漏了,而不是面对一个黑盒想破头。
2.2 工具调用:定义清楚比数量重要
青柚目前接入了12个工具,不多,但每个都经过精心设计。系统提示词里我们专门用了一段来强调工具调用规则:不确定参数时优先向用户询问,宁可多问一句也比猜一个错误参数好;如果工具返回异常,要把异常信息完整带回来,不要擅自编造结果。
每个工具都遵循同一套规范,包含名称、用途描述、参数Schema和返回值示例。参数Schema用JSON格式定义,类型、枚举值、必填项都明确标注。举个例子,“查请假余额”这个工具的参数有员工ID和日期范围,员工ID在大多数情况下可以从会话上下文中获取,如果找不到就要求用户提供或从当前登录信息推断。
工具描述文本在这里非常关键,我们写的时候遵循一个原则:描述要说明这个工具是干什么的、什么情况下用、什么情况下不要用。例如“查报销状态”工具的描述里明确写了“仅用于查询已提交报销单的进度,不用于发起新的报销申请”。这是为了减少模型误调用。
2.3 记忆机制:短期记忆和长期记忆的分工
青柚上线第一个月出现过一个尴尬场景:用户刚在对话里提供了自己的部门信息,换个话题再问办事流程时,它又把部门信息忘得一干二净。这暴露出记忆设计的问题。
后来我们把记忆分成两组。短期记忆走普通对话上下文,直接放在模型的消息列表里,控制窗口长度,超出的部分做摘要。长期记忆则通过两种方式沉淀:一类是用户画像信息(如部门、常用审批人),在对话中捕获后写入结构化存储,比如“部门”这个信息一旦确认就缓存起来,后续所有工具调用都能用到;另一类是历史问题归档,把用户问过的问题和青柚的答案做向量化存进知识库,当用户问类似问题时可以召回旧答案作为参考。
长短期记忆结合的效果,在评测中提升比较明显。任务成功率从最初的64%提升到了76%,其中一个重要原因就是模型不再频繁要求用户重复之前说过的信息。
3. 实操过程:从Prompt到可运行的完整管线
3.1 提示词工程:三份核心提示词
青柚的系统提示词拆成了三份:主提示词(定义角色和总体规则)、工具提示词(描述工具调用约定)、输出格式化提示词(规定回答结构和引用格式)。
主提示词的写法有几个要点。第一,明确身份:“你是青柚,企业内部智能助手,你的任务是帮助员工解决人事、行政、财务相关问题。”第二,强调行为规范:“如果信息不足,主动提问澄清,不要猜测。如果是你不确定的业务知识,请明确说明不知道,并引导用户联系对应的支持渠道。”第三,给一个总的工作流程说明:理解意图→调用工具→验证结果→组织回答。
工具提示词放在每次与模型交互时动态拼接。系统先把所有工具的定义传给模型,但我们会控制单次最多让模型“看到”的工具数量。如果12个工具全塞进去,模型的中选率会下降,所以我们让路由器先筛选出相关的一小批工具,再把它们传给执行器调用。
输出格式化提示词也很关键。青柚的所有回答都要求符合固定结构:是否引用了知识库(是/否)、引用文档编号、回答正文、是否需要用户补充信息。这个结构是为了让后续的验证器和日志系统能自动做质量判断,而不是靠人肉看对话记录。
3.2 知识库与RAG:切块、向量化、召回策略
青柚的知识库内容来自公司内部的制度文档和办事指南,原始格式各样,有PDF、Word还有网页。我们做了一套清洗流程:转成纯文本→去掉页眉页脚→按章节切开→过滤掉无意义的表格碎片。
切块大小是最早调参的地方。最初用固定500字切块,结果很多跨页的场景描述被切成了两半,检索时经常少了一半上下文。后来改为按标题结构切块:先解析文档的标题层级,以二级标题作为切片边界,再限制每个切片上限800字,超长的再拆分。这个改动让检索的命中率从61%升到82%。
向量化模型我们对比了几个主流Embedding模型,最后选了召回效果最好的那个,但也不是一劳永逸。中文场景下,同义词问题特别常见,比如员工问“公积金怎么提”,文档里写的是“住房公积金支取”,直接向量检索有概率匹配不上。我们加了两层弥补:一层是查询改写,在路由阶段把用户口语化的问题转成更正式的检索词,同时抽取出实体词做BM25关键词检索;另一层是混合召回,把向量检索和BM25的结果做加权融合排序。
这之后还有个细节——重排序。第一次做只是把Top20的切片全部拼到上下文里,结果prompt被撑得很大,回答质量反而下降。后来加了一个重排序模型,把Top20压缩到Top5,再拼进上下文。效果明显:回答引用了更相关的文档片断,幻觉出现率也低了。
3.3 工具函数的实现:两个必须注意的坑
工具函数本身的代码不复杂,真正麻烦的是两件事:参数校验和超时处理。
参数校验上,我们踩过一个印象很深的坑。当时“查请假余额”工具接受日期范围参数,某次测试发现用户随口说了一句“看一下去年到现在我还有几天假”,模型把起止日期理解成了“2024-01-01到2025-01-01”,但员工实际入职时间是2025年3月,导致查出来的数据完全不对。后来我们在工具函数入口做了业务规则校验:日期范围不能早于员工入职日期,超出则自动纠正并返回修正说明。这里对日期做了一次模糊处理,不影响理解。
超时处理同样重要。某些工具调用第三方接口,耗时可能很久。如果不做超时控制,模型会一直等待,整个对话就卡住了。我们的方案是给每个工具调用设置超时上限,超过则返回一个标准错误信息“系统开小差了,请稍后重试”,同时记录日志供排查。
下面是一个简化的工具函数示例,展示校验逻辑:
def query_leave_balance(employee_id: str, start_date: str, end_date: str) -> dict: # 校验员工ID格式 if not employee_id or not employee_id.startswith("E"): return {"error": "invalid_employee_id", "message": "员工ID格式不正确"} # 校验日期范围 try: s = datetime.strptime(start_date, "%Y-%m-%d") e = datetime.strptime(end_date, "%Y-%m-%d") except ValueError: return {"error": "invalid_date", "message": "日期格式必须是YYYY-MM-DD"} if s > e: return {"error": "invalid_range", "message": "开始日期不能晚于结束日期"} # 调用业务系统接口获取数据 result = hr_system.get_leave_balance(employee_id, start_date, end_date) # 对返回结果做一层包装,统一格式 return {"data": result, "code": 0}这个例子看着简单,但它体现了一个原则:工具函数要像对外API一样设计,入参有校验,出参有统一结构,绝不能让模型面对一个“裸奔”的接口。
3.4 评测集建设:没有评测的智能体等于盲飞
青柚在前面两个月一直处于“感觉还行但说不清哪里不行”的状态。有一次内部演示,连续几个问题都答得不错,大家都很兴奋。但真到了小范围试用,用户反馈却不尽如人意。后来我发现,问题出在缺少评测集——我一直在看过拟合的个例,没有构建一个有代表性的任务集合。
评测集的建设是从真实使用场景反推的。我们找业务方要了近一个月的员工咨询记录,手动整理出120条真实问题,覆盖八个大类,每条问题都标注了:期望使用的工具、期望执行的路径、期望的回答来源、可接受的回答范围。标注工作花了一周,很枯燥,但这是整个项目性价比最高的一笔投入。
评测跑起来之后,每天都能看到详细的失败分类报告。比如某天发现“报销相关问题”的任务成功率只有48%,进而定位到路由器在区分“查报销进度”和“问报销政策”这两个意图时经常混淆。于是我们给这两个意图各补充了十几条few-shot示例,重新评测后成功率提升到82%。
4. 评测与迭代:让智能体“越用越聪明”
4.1 三层评测体系:从单轮到多轮再到线上
青柚的评测体系分成三层,每层回答的问题不同。
第一层是离线单轮评测,用固定的评测集跑一遍,统计任务成功率、工具调用准确率和回答规范性。这一层主要在开发阶段用,每调整一次Prompt或工具描述就全量跑一遍,跑完看对比报告。
第二层是多轮对话评测。智能体的难点不只是单轮回答,而是多轮里保持状态。我们构造了一批多轮对话样例,比如第一轮问“我有几天年假”,第二轮问“那我如果在月底前请三天,还剩多少”。这层评测主要检查记忆能力和状态跟踪能力是否稳定。
第三层是线上灰度评测。上线后随机抽5%的真实流量,先跑了大概两周。在真实流量上,我们只看两个指标:回复被用户“点赞”或“点踩”的比例,以及用户是否发起了转人工处理。数据比离线结果更真实,毕竟评测集很难完全覆盖用户的表达风格。
评测集不是一次建完就结束的。我们每周都从线上对话中抽取新的失败案例,经过人工筛选后补充进评测集。这也变相保证了评测集不会过时——如果音译词、新政策出现,评测集能第一时间覆盖。
4.2 效果调优的杠杆排序:Prompt、知识库还是模型微调?
当智能体效果不达标时,第一反应很容易是“换更强的模型”或者“微调”,但大部分情况下这是高成本低收益的做法。
我从过往经验总结出调优顺序:先调Prompt,再调知识库,最后才考虑换模型或微调。Prompt调整成本最低,见效最快。比如我们发现青柚经常在回答末尾画蛇添足地给出多条建议,导致用户困惑,给Prompt加了一句“只回答当前问题,不要主动推荐不相关的操作”,问题就解决了。
知识库优化排在第二位。很多错误答案的根源是检索没有召回正确的文档,比如内容过期、切块不合理、检索词不匹配。这类问题,即使换一个更强的模型也无法解决。我们在青柚改版时就发现,一次知识库重切分带来的效果提升,比换一个参数规模翻倍的模型还要明显。
换模型和微调是最后的杠杆,不是首选。只有在业务知识严重依赖特定场景、且通用模型无论如何都无法理解时,才值得考虑。青柚目前仍然使用通用模型,没有走到微调那一步。
4.3 A/B实验实践:小步快跑,绝不盲改
青柚的Prompt经历过上百次改动,如果每次直接覆盖线上配置,出问题都找不到元凶。后来我们规范了实验流程:每个改动都走A/B实验。
具体做法是,在线上推出两套配置(基线版和实验版),按用户ID哈希分流,实验流量控制在5%到10%。实验运行一天以上,对比任务成功率、平均轮数和用户点赞率。只有实验组显著优于基线组才全量发布。
这个流程挽救过我们一次。有一版Prompt调整了提问澄清的策略,我们用A/B实验一跑,发现任务成功率确实提高了,但平均对话轮数明显增加,用户体验反而变差。如果直接全量上线,这个副作用可能要几周之后才被用户吐槽我们才发现。
5. 交付阶段的坑与心得
5.1 灰度发布与回滚预案
智能体系统和传统系统在交付上有很大差异。传统系统上线前可以通过测试用例覆盖大部分路径,但智能体的行为空间几乎是无限的,测试阶段永远不会覆盖到所有真实的用户表达。
所以青柚上线时采用了严格的灰度策略:先在内部员工群试运行一周,收集反馈;再开放给一个部门,CTR(点击率)和CSAT(满意度)达标后,才逐步开放给全公司。灰度用的分流逻辑和A/B实验一样,通过用户哈希百分比控制流量比例。
回滚预案我们也做得很充足:每次发布前,把所有涉及到的Prompt、工具定义、知识库版本全部打tag存档,一旦实时监控显示异常比率飙升,直接一键切回上一版本。有一次我们改版了系统提示词的输出格式,导致部分工具的参数提取失败率从5%涨到18%。灰度流量立刻检测到,我们当天就回滚了,影响面被控制在很小范围内。
5.2 可观测性:被低估的救命稻草
智能体系统的调试比传统代码难得多,因为问题往往出在“模型的思考过程”里,而不是代码栈里。青柚上线之初,我们被一个反复出现的bug折磨:用户提到“报销”,青柚偶尔会调用错工具,但无法复现。
后来我们在执行链路里加了结构化日志,记录每个完整请求的所有关键节点:用户原始输入→路由器输出(意图分类+槽位)→候选工具列表→最终选择的工具和参数→工具返回结果→验证器结果→最终回答。这样一来,每一个失败案例都能定位到具体环节。
有一次,我们通过日志发现,用户输入“报销单什么时候能下来”被路由器分类成了“查询流程指南”而不是“查询报销状态”。原因在于“什么时候”一词在培训数据里经常指向时间流程说明。我们针对性调整了意图分类的提示词,加入了这两个意图的辨析示例,问题迎刃而解。
结构化日志还有一个意外的收获——它让团队能离线复跑真实案例。之前出了线上失败案例,我们只能看对话截图猜原因。现在可以把整个链路参数导出来,用一个脚本重放,复现成功率很高。
5.3 成本控制:智能体不是越聪明越好
“用最贵的模型,调最好的效果”在这个项目里是不成立的。青柚上线后的成本主要由三块构成:推理Token费用、Embedding调用费用、向量库存储费用。其中推理费用占大头,而且和模型选择、上下文长度直接相关。
我们的控本手段有几个。第一,在路由器阶段使用更小的模型做意图分类,只有到了执行器阶段才使用大模型。第二,在上下文里只保留必要的工具定义和检索片段,不把所有工具和全部知识片段塞进去,长度控制住以后,Token成本基本下降了一半。第三,对短时间的工具调用结果做缓存,比如同一个员工的余额查询结果在5分钟内可以直接用缓存数据返回,省掉了一次模型调用。
成本和质量需要一起看。我在项目里建立了一个“单次会话成本”监控项,每周复盘一次。如果某类问题虽然回答正确但平均消耗Token数异常多,我们会去检查是不是检索结果混入了太多无关片段,还是Prompt里的few-shot示例太长了。
5.4 从交付到复盘:青柚沉淀了哪些可复用的东西
交付不是终点。青柚项目结束后,我们做了一次复盘,沉淀出几套可以直接复用到下一个项目的资产。
第一套是“工具定义规范模板”,新接入一个系统工具时,照着模板填写名称、描述、参数Schema、返回示例和校验规则,任何人都能在半小时内完成一个合规的工具定义。这个模板为后续新系统的接入省了大量沟通成本。
第二套是“标准评测集构建指南”,包含如何从客服记录中筛选问题、如何标注期望路径、如何划分训练集和回归集。后续新智能体项目上线前,团队能快速搭建基础评测集,不用等到产品做完了才补评测。
第三套是一个“迭代checklist”,任何Prompt或工具变更上线前都要依次走清:离线评测对比→A/B实验→灰度流量→日志检查→全量发布。这套流程帮我们避免了很多“改好了但不知道改坏了什么”的尴尬。
6. 写在最后:AI是易变的产品,不是一次性程序
带青柚从0走到交付,我个人最深的体会是——智能体项目本质上没有“做完”的那一天。模型在更新,业务在变化,用户表达更是千奇百怪。你唯一能依赖的,不是写出一套完美的代码,而是建立起一套持续评测、持续迭代的机制。
另外提醒一点,做这类项目千万不要钻“技术追新”的死胡同。团队里曾经有人提议做多智能体协作架构,为的是“紧跟前沿”,但我们的需求里根本不需要多智能体。判断一个技术是否引入,唯一的标尺是它能不能在合理成本内,让三个核心目标变得更好。引入前先问,引入后评测,不行就果断放弃。
如果你现在正准备开始一个Agent项目,我建议先把精力放在需求定义和评测集建设上,而不是急着选模型、写提示词。以上这套方法,是我自己踩了无数坑才总结出来的,照着做能少走很多弯路。