上线前最后一天,我盯着测试日志里的一条回答,差点没把水喷到屏幕上——我负责的智能客服 Agent 对用户说“您的退货申请已经通过”,可这个订单根本没有提交过退货申请。更离谱的是,它在给出这个答复之前,还一本正经地引用了“平台规则第 12 条”,而资料库里压根没这条。
这种经历做过 Agent 的人都懂。跑 Demo 的时候一切正常,一旦进入真实业务场景,模型就开始“自由发挥”了。乱编、连锁、失忆,这三个毛病几乎是所有 Agent 的通病。乱编是凭空捏造事实,连锁是一步错后面步步错,失忆是聊着聊着把关键信息全忘了。这篇文章我把自己沉淀的一套“五维体检”方法论完整写出来,从体检样本构建、打分规则、执行流程,到典型病例的诊断逻辑和修复手段,全部是可复制、可落地的实操路径。如果你正在调试 AI Agent,或者准备把 Agent 接入真实业务,这份体检手册可以直接拿去用。
1. 先把三个病认清楚:乱编、连锁、失忆
很多人拿到一个跑不通的 Agent,第一反应是改 prompt,第二反应是换模型,但改来改去问题还是一样。我个人的经验是:改之前,先花点时间把病灶分类。Agent 的故障并不全是模型能力问题,更多时候是特定的机制性缺陷。
1.1 乱编:模型把想象当事实输出
乱编,业内常说的幻觉,指的是模型产出了和输入上下文、知识库、真实数据不一致的内容,但语气却极其笃定。客服 Agent 里最常见的表现形式是伪造订单状态、杜撰售后条款、凭空生成一个不存在的转人工入口。比如用户问“退货后多久能退款”,模型可能回答“3-5 个工作日”,但业务真实规则是“材料审核通过后 7-15 个工作日”。
这个问题的麻烦之处在于:模型对自己的编造通常没有任何“心虚”的迹象。在问答场景里,用户还能凭常识判断;但在 Agent 自动化执行业务动作的场景里,乱编就直接变成线上事故。我遇到过真实案例,Agent 根据一段并不存在的“用户授权记录”给后台系统提交了改地址请求,这种错误如果不靠日志留痕,几乎没法追溯。
1.2 连锁:一步错,后面全跟着错
连锁错误是 Agent 特有的故障模式,也是和普通聊天机器人最大的区别。普通问答模型只对单轮输出负责,错了也就错了,影响范围有限。但 Agent 是多步骤流水线——先做意图识别,再做槽位填充,然后调工具,最后生成回答。每一环的输出都是下一环的输入,误差沿着链路逐级放大。
举个很简单的例子:客服 Agent 的第一步是把用户问题分类成“售前咨询”和“售后维权”。如果这一步判断错了,后续的售后知识检索、流程查询、答复生成全部基于错误的方向运行。有时候用户问的明明是“我想买一个支持快充的手机”,如果意图识别成了“投诉产品质量问题”,那 Agent 就会去翻质量投诉的应答模板,最后给用户车轱辘话绕圈子。更麻烦的是,中间环节的错误不一定立刻在即时回答里暴露,可能要到最终答案生成时才“病情发作”。
1.3 失忆:上下文被截断或重要性感知不足
失忆,字面意思是 Agent 把之前说过的内容忘了。最典型的表现是:用户第 5 轮说过“我的收货地址是 B”,第 12 轮 Agent 还在按第 2 轮的地址 A 校验订单。你以为是模型能力不行,打开日志一看——上下文早就被截断了,或者是窗口里塞了太多无关内容,模型在注意力分配上主动忽略了早期信息。
这种失忆还有更隐蔽的一种:模型不是完全没有看到历史信息,而是对“关键约束”和“普通聊天内容”的重视程度没有区分。比如用户在对话中明确说“不要自动给我发短信通知”,但这条约束藏在第 20 轮,前面全是闲聊。到第 26 轮模型直接默认用户接受短信通知,触发了一次外呼。这类问题用单纯的“扩大窗口”很难解决,因为窗口越大,信息密度越低,模型反而更容易忽略关键项。
把三类病摸清楚之后,下一个问题是:怎么量化?没有量化,你没法知道自己改完 prompt 到底是变好了还是变差了,也没法在团队里用同一套语言讨论 Agent 质量。
2. 五维体检:给 Agent 定一套可以量化的健康指标
我自己做 Agent 调试时最大的痛点,就是“好不好全靠感觉”。同样一条问题,今天测通过,明天换一种问法就崩;自己调没问题,交给同事一跑就乱。要解决这个问题,必须先定义“健康”,不能等出 bug 再排查。我花了很长时间整理出一套五个维度的度量体系,它覆盖了 Agent 从输入到输出全链路的关键质量属性。
2.1 为什么先设计维度,而不是直接开写测试用例
很多人一听“给 Agent 做测试”,第一反应是准备 500 条问题,逐个跑一遍,看回答好不好。问题在于:单条问题的“好与坏”没有可积累的判断依据,你只能得到一堆零散的失败案例,得不到一个可以横向比较的“分数”。
五个体检维度的本质,是把“Agent 表现好”这个大概念拆解成可以分别打分、分开优化的指标。每个维度都有相对独立的改进手段。准确性低,优先查知识库和输出校验;连贯性差,优先改流程编排和工具调用;记忆力差,优先改上下文管理;稳定性差,优先查 prompt 里的随机性和工具超时;效率差,优先压缩提示词和减少不必要调用。不分维度,你面对一个失败案例时根本不知道该动哪一块。
2.2 五个维度定义与度量方式
我最终敲定的五个维度是:准确性、连贯性、记忆力、稳定性、效率。为了自己好记,我把它们打包叫 ACMSE 五维。
| 维度 | 它度量什么 | 客观度量参考 | 健康时应该呈现的表现 |
|---|---|---|---|
| 准确性 | 回答与事实、知识库、业务数据的一致性 | 无中生有的比例;关键实体错误数 | 无编造;每个断言都能追踪到资料来源或工具返回结果 |
| 连贯性 | 多步骤链条上各环节的一致性与递进关系 | 中途转向次数;重复提问数;流程中断率 | 从意图识别到工具调用再到最终答复,链条完整且方向一致 |
| 记忆力 | 关键信息跨轮次保持能力 | 关键约束遗忘次数;重复确认次数 | 跨越多轮对话的关键实体、约束、偏好都能在需要时被唤起 |
| 稳定性 | 同一输入下多次执行结果的一致性 | 相同用例重复执行的结果漂移率 | 同一用例跑多次,答案方向与技术细节不随随机性大幅变化 |
| 效率 | 完成目标所需的计算与调用开销 | 总 token 消耗;工具调用次数;完成时长 | 用最少的中间步数达成相同质量结果,无冗余自问自答 |
这个表格我建议你打印出来贴在工位边上。原因有两个:其一,五个维度之间的边界经常会重叠,有了这张表,团队评审用例时可以快速对齐口径;其二,打分时最怕主观,每个维度下面一定要有“客观度量参考”这一列,先看数据再看感受。
2.3 评分规则:五分制量规与加权总分
单维度打分我用 1-5 分,每个分数档位都做了锚点描述,避免“我觉得还行”这类无效打分。
- 5 分:完全符合该维度的健康表现,无扣分项。
- 4 分:整体健康,存在 1-2 个轻微瑕疵,但不影响业务正确性。
- 3 分:存在部分错误,但通过触发兜底逻辑可以恢复,错误不扩散。
- 2 分:明显错误,且错误的根因是结构性缺陷(例如上下文丢失、意图识别方向错误)。
- 1 分:完全不可用,输出会导致业务事故。
最终总分是加权和。我最常用的权重方案是:准确性 30%、连贯性 25%、记忆力 20%、稳定性 15%、效率 10%。这个权重不是拍脑袋定的,而是根据真实业务中“错误造成的损失程度”反推的。如果你的业务对成本极度敏感,可以把效率权重提到 20%,准确性和连贯性各降 5%,所有权重加起来保持 100% 就可以。举例说明计算方式:某 Agent 体检后五维得分分别为准确性 4、连贯性 4、记忆力 5、稳定性 3、效率 4,加权总分是 4×0.3 + 4×0.25 + 5×0.2 + 3×0.15 + 4×0.1 = 4.05,对应百分制约 81 分,属于“亚健康,需局部修复”。
2.4 体检样本集:30 条基线用例怎么设计
有了维度体系,还要有统一的“考试卷”。我给每一次体检准备 30 条基线用例,既不贪多,也能覆盖主要风险面。用例分三类,每类 10 条:正常主线、边界输入、对抗输入。
正常主线覆盖业务中的高频场景,比如客服 Agent 的“查订单”“改地址”“申请退货”。边界输入覆盖模糊表述、多条件叠加、超长输入、生僻术语,比如用户把地址和收件人打包在一句话里。对抗输入覆盖诱导性提问、否定表达、反复追问、多轮后修改条件,专门用来测试 Agent 在高压和混乱输入下会不会乱编或失忆。
每个用例不光要有“输入”,还要有“基线答案”。基线答案不是随意写的,而是由两条路径独立产出:一条是业务专家按业务规则手工填写,另一条是让 Agent 在没有额外干扰的条件下跑出来的最优回答。两个版本做交叉核对,一致的部分作为参考答案,不一致的部分择期再对齐。这个双轨制很关键,因为有些业务问题本身没有唯一标准答案,你必须有可追溯的基线才能给 AI 打分。
3. 体检实操:从回放脚本到诊断报告
维度体系和样本集准备好之后,就进入执行环节。体检不是把 30 条用例手工跑一遍再人工评个分,那样既不科学也不可持续。我的做法是搭一套轻量回放框架,把执行、记录、初筛、人工复核流水线化。
3.1 回放工具与执行流程
我不会为体检单独开发一套复杂平台,现有条件下的最小闭环是:体检驱动脚本 + Agent 框架的 SDK + JSONL 日志存储。体检驱动脚本负责逐条读取用例,调用 Agent 的接口,把整个执行过程完整记录下来。
下面这个伪代码展示了回放脚本的核心逻辑,你可以直接照着在自己的项目里改改跑起来:
import json import time TEST_CASES = load_cases("cases/golden_set.jsonl") AGENT_CONFIG = load_config("agent_config.yaml") results = [] for case in TEST_CASES: trace = { "case_id": case["id"], "category": case["category"], "input": case["input"], "timeline": [], "final_answer": "", "token_usage": 0, "tool_calls": [], "error": None, } start = time.time() try: final = run_agent_with_trace( agent_config=AGENT_CONFIG, input=case["input"], history=case.get("history", []), trace_sink=trace["timeline"], ) trace["final_answer"] = final except Exception as exc: trace["error"] = str(exc) trace["elapsed"] = time.time() - start results.append(trace) write_jsonl("report/execution_trace.jsonl", results)这段脚本重点看三点细节。第一,trace_sink参数把内部每一步推理、工具调用、中间结果全部放进 timeline 数组,这是后续归因分析的原始证据。第二,异常被吞掉并记录成 trace 里的 error 字段,说明体检测试不能容忍直接崩溃,因为 Agent 的真实用户会在各种异常下继续和它对话。第三,执行过程中没有做任何回答后的规则过滤,先把原始行为完全保留下来,看的就是不加干预下的真实表现。
3.2 客观数据自动汇总
执行完成后,脚本会输出一份客观指标汇总表。这部分不需要人看,直接由代码生成:
| 指标 | 数值 | 说明 |
|---|---|---|
| 平均完成时长 | 6.8s | 从请求发出到最终响应返回 |
| 平均 token 消耗 | 1542 | 含工具返回内容 |
| 平均工具调用次数 | 2.4 | 每次完整任务执行中的工具调用链 |
| 无输出率 | 3.3% | 转人工插件的确定性跳转不计入 |
| 超时重试率 | 6.7% | 调用外部服务部分的超时占比 |
| 结果漂移率 | 13.3% | 同一用例重复执行 3 次后答案关键要素不一致率 |
这些客观数据是我用来快速定位的“第一筛网”。比如结果漂移率过高,稳定性維度基本不可能及格;平均工具调用次数偏高,效率维度大概率扣分。客观数据不直接生成主观质量分,但它告诉你应该把人工精力投到哪几条用例上,不用每条都精读。
3.3 质量评分怎么打:客观筛选 + 人工复核
30 条用例全部跑完后,我不会让人去逐条打分,时间和精力都撑不住。我的流程是两级筛查:先由脚本根据几个硬性规则过滤,把明显异常的用例捞出来,再交给两个标注者独立给这些异常用例打“质量分”。
硬性过滤规则包含四类:其一,回答中出现了知识库里不存在的规则编号或条款,直接划入“疑似乱编”,转人工打分;其二,多步任务出现中间环节返回异常或工具调用失败,自动标记“疑似连锁”;其三,跨多轮用例中关键约束出现两次以上丢失,直接标记“疑似失忆”;其四,重复执行的答案关键差异超过阈值,进入“疑似漂移”池。被标记的用例统一由两个标注者背靠背评分,再把分数取平均。如果两个人的分差超过 1 分,就说明这条用例的评估口径没对齐,需要一起复盘统一标准。
这个流程解决了 AI 评测里最大的坑:纯客观脚本过于死板,纯人工又不可持续。两级筛查的核心思想是“用机器省人力,用人力看本质”。
3.4 输出一张体检报告
所有评分完成后,汇总输出体检报告。报告结构不复杂,但信息密度要高:顶部是总分和各维度的雷达数据,中间是客观指标对照表,下面是问题用例清单,每条问题用例附上“病例链接”——指向执行日志里对应的 trace 片段。
报告里最值钱的部分是“高频问题归类”。我会把问题用例按根因打标签,比如“先误判再误答”“发生在第 6 轮后的记忆衰退”“工具返回空值后自创默认答案”。标签聚合以后,修复方向的优先级就非常清楚:如果 80% 的问题集中在同一类根因,那一个针对性改动就能大幅提升总分,而不是零敲碎打地修个案。
4. 真实体检记录:一次跑完 30 条用例后发现的 8 个错误
方法论说再多,都不如看一次完整记录。下面我把自己做的一次客服 Agent 体检全过程拆给你看,项目代号“某客服 Agent v0.9”,基座用的是通用 LLM,知识库接了售后规则和订单查询接口。这次体检跑了 30 条基线用例,最终发现 8 个有效错误,包含乱编、连锁、失忆三类。
4.1 业务场景与样本准备
该 Agent 的职责范围是三件事:查订单状态、查询售后政策、提交售后申请。样本集按 2.4 的规则构建,正常主线 10 条覆盖高频问法,边界 10 条覆盖一句话里塞多个信息点的情况,对抗 10 条覆盖用户连续修改条件、否定前面结论的极端场景。每条用例都提前写好了基线答案,整个准备过程花了两个工作日,其中第三个时间项花在“基线答案的口径对齐”上——业务专家和 AI 跑出的最优答案在“退回运费由谁承担”这类细节上存在分歧,最后以业务规则文案为准。
4.2 五维得分汇总
30 条用例跑完后,汇总结果如下:
| 维度 | 得分 | 主要扣分原因 |
|---|---|---|
| 准确性 | 3.3 | 2 条回答编造了不存在的售后条款编号 |
| 连贯性 | 3.7 | 1 条意图识别错误导致后续流程整体跑偏 |
| 记忆力 | 4.0 | 2 条跨轮次用例出现关键约束遗忘 |
| 稳定性 | 4.2 | 同一退货咨询重复执行 3 次出现 2 种不同表述 |
| 效率 | 4.4 | 部分用例多调用了一次订单查询接口 |
总分算下来是 3.78,百分制约 76 分,属于需要局部修复的状态。单纯看这个数字可能觉得“也没那么糟”,但你要注意准确性只有 3.3——在这个业务里,准确性是权重最高的一指标,任何一条无中生有的输出都可能导致用户投诉或资金风险。
4.3 三个典型病例的完整现场
挑三个最有代表性的病例详细展开,你会看到同一个结论:错误不是突然产生的,而是沿着某条链路慢慢滚大的。
病例 A(乱编):用户问“申请售后后多久能收到处理通知”。该 Agent 的回答是“根据平台规则,售后处理通知将在 2 个工作日内发出,紧急情况可在 1 个工作日内获得反馈”。但基准确认后,实际规则是“3-5 个工作日”,且不存在“紧急情况加急”条款。打开 trace 一看,根因是知识库检索阶段未返回有效结果,模型于是“合理想象”了一个看起来合理的数字。这个病例清楚地说明:当检索模块返回空值时,模型倾向于用默认的“业务常识”填充,造成编造。
病例 B(连锁):用户输入“我上周买的东西坏了,想退掉,地址是上海”。意图识别模块把它归类成了“订单查询”,于是该 Agent 去调订单查询接口,拿到订单后机械地展示物流状态,没有进入退货流程。后续再追问的时候,它已经带着错误的流程方向做下一步,越走越远。这条病例里每一环单独看都“不严重”,但把它们串联起来,用户体验就是灾难。
病例 C(失忆):用户在第 6 轮说“不要自动给我发短信通知”,第 11 轮询问“现在进度怎么样了”。该 Agent 回复时默认把“通过短信告知”列为已选通知方式,而实际上用户已经在 5 轮前明确拒绝。追溯 trace 发现在第 9 轮时上下文窗口被压缩,第 6 轮的约束项被截掉。这个病例最有教学意义:不是模型不聪明,而是工程层面的窗口压缩策略把关键信息当作无用内容丢弃了。
4.4 从病例反推根因:日志轨迹怎么读
拿到三个病例后,归因不要只盯着“最终回答哪里不对”,我一般沿 trace timeline 逐层回溯,回答三个问题:在哪一步开始出现偏差?偏差的那一步输入了什么内容?为什么那一步没有触发兜底校验?
以病例 C 为例:偏差最早发生在第 9 轮上下文压缩时。压缩策略是“截断最早的用户消息”,这个策略对普通聊天内容有效,但不区分“闲聊”和“不可丢弃的约束”。修复方向因此不是加大模型上下文长度,而是调整压缩策略——把带有关键约束的消息固定保留,优先裁剪体积大的工具返回结果。根因不在模型,而在工程策略,这就是 trace 回溯的价值。
5. 对症下药:三个高频病症的修复方案与验证
体检的意义在于指导修复。每个病症的修复手段不同,但统一原则是:先做最小改动验证,再全量回归,绝不一次性上多个改动。下面是我在项目里验证过有效的方案,你可以直接套用。
5.1 乱编修复:给模型装一个“刹车系统”
乱编的核心是模型在证据不足时强行补全。修复思路就是两条:要么让它有据可依,要么让它承认自己不知道。
第一刀是强制检索引用。在生成回答前,Agent 先执行知识库检索,并且把检索到的片段作为上下文注入,同时要求回答中引用对应的片段编号。这一步不是让模型"参考"资料,而是用结构化的输出约束(引用标记)迫使它只能在检索结果上组织语言。第二刀是设置置信度阈值,当相似度分数低于阈值时,模型不是强行编一条答案,而是进入“拒答模板”:比如“这个问题我这边没有查到明确政策,建议转人工确认”。这个设计在客服场景中至关重要,把模型从“永远要回答”的困境中解放出来。
跑完复测,乱编率从初检的 23% 降到了 4%。值得注意的是,修复后出现了一个新现象:模型开始“过度拒答”,连一些可以推理的常见问题也不愿意回答了。这就到了下一轮的调优,把阈值往下微调,再跑一轮,让比例收敛到 8% 左右的健康区间。你会有一种看医生调药量的既视感。
5.2 连锁修复:在关键节点加“检查闸门”
连锁错误的修复重点不是“让每一步更准”,而是在错误发生后能及时拦截。AI 的推理不是确定性代码,不能指望每一环都 100% 正确,你要做的是在关键转换点加“检查闸门”。
具体做法是:第一步,把大任务拆成多个子步骤,明确每个子步骤的输出契约。第二步,对子步骤的输出做规则校验。比如意图分类模块的输出,必须从预设的意图列表里取值,如果分类置信度低于 0.6,则不允许直接进入后续流程,必须改成反问用户“请问您是想办理退货还是查询状态?”;工具返回的值如果是空数组,不允许自动生成“没有符合条件的记录”这种断言,必须走一次数据再确认或转人工。第三步,任何中间环节一旦触发异常,就触发一条旁路兜底:直接交给人工或回到上一步重新询问,而不是带着不确定性往下跑。
修复后,病例 B 这类事件的复现率从 16.7% 降到了 3.3%。等价的表达是:100 次请求里只会有 3 次意图识别失败,且这 3 次都会在被用户察觉前被拦截回问。闸门机制的本质是“用一次反问的代价,避免一连串错误的成本”。
5.3 失忆修复:把关键信息从“对话流”挪到“记忆卡片”
失忆的修复方案要分层处理。第一层是工程兜底:调整上下文压缩策略,不再简单从最早消息开始截断,而是先把工具返回的长文本优先裁剪或摘要,保留用户消息中的关键实体与约束。第二层是信息结构重构:在运行时维护一个独立的“记忆卡片模块”,从每一条用户消息中抽取关键信息——地址、时间范围、禁止项、偏好——写入固定结构,并在每次工具调用前把卡片内容作为系统级上下文注入。
有了记忆卡片,即使模型窗口被压缩,关键约束也不会丢。原因很简单:用户消息是动态的、变化的,但记忆卡片是一个稳定的结构化摘要,系统提示词里永久挂着它,模型在生成时天然会更重视系统级指令里的内容。实测数据也支持这个判断:失忆类问题的复现率从 13.3% 降到 0。
5.4 修复后全量回归:防止治好一个病引出新病
每一项修复上线后,都必须跑全量 30 条基线用例,而不是只跑之前失败的那几条。原因非常现实:你为了防止模型乱编,让它“不确定就拒答”,但这样做可能直接伤害准确性维度,把一些简单问题也拒掉了。你为了防止连锁错误加了闸门,但闸门触发次数过多又会把效率维度拖垮,用户被反问了太多次。
所以我的建议是:每修复一类病,用同一套体检流程复测五次维度,把“修复前 VS 修复后”的雷达图叠加在一起对比。如果总分提升了 8 分以上,但某一个非目标维度掉了 2 分以上,就说明这个修复有副作用,需要微调参数后再跑一轮。这种“一次改一个,每次全量回测”的做法,虽然看起来慢,实际上是把试错成本前移到了测试阶段,而不是上线后由真实用户来买单。
6. 体检体系中几个容易踩的坑
方法论部分讲完了,最后分享几个我反复踩过的坑。这些东西不写在任何文档里,但没有它们,整套体检流程很容易从“工具”变成“形式主义”。
第一个坑是基线答案的“版本漂移”。业务规则是活的,客服政策可能每个月变一次。如果你的基线答案还是上个季度的,Agent 可能正确回答了最新规则,却因为和旧基线不一致被打零分。我的解决办法是给体检加一个“基线有效期”概念,每次跑全量前先核对最近一次规则变更,更新受影响用例的基线答案,并在报告中标记“基线更新日期”。
第二个坑是主观评分的“口径蔓延”。两位标注者各评各的,时间一长,对“扣 1 分”的感知会悄然改变。我开始以为靠培训就能解决,后来发现最有效的手段是每一条异常用例都附带“基线答案 + 规则片段”,让标注者的任务从“凭感觉打分”变成“对比材料找差异”。差异找到了,分数自然对齐了。
第三个坑是回放脚本和线上环境不一致。如果你只在固定的离线用例上跑,Agent 在真实任务中用的外部依赖(比如订单服务的返回值结构)可能完全不同。测试环境测出来 0 失忆,线上接入高并发订单版本后突然失忆率飙升。解决办法是在回放脚本里支持 mock 和新数据注入两种模式,至少每两周用生产环境脱敏日志里的真实用户请求,混入体检样本集中做一轮“漂移检测”。
第四个坑是只测单轮不测长程。很多 Agent 的单轮回答质量非常高,但一进入多轮连续对话就开始退化。体检样本集里必须包含一条“10 轮以上长对话链”用例,专门用来观察记忆衰退和上下文漂移。我自己的经验是:很多 Agent 在 5 轮以内表现优秀,超过 10 轮才开始露出失忆的马脚,所以至少要让部分用例跑够 15 轮,才能发现真实交互场景里的隐患。
整个五维体检体系用下来,最大的感受是:它把一个玄学问题变成了工程问题。过去你说“这个 Agent 感觉不太行”,别人不知道你在说什么;现在你说“准确性 3.3、连贯性 3.7、失忆率 13%”,所有人都知道该怎么动。最后再分享一个小技巧:体检脚本一定要沉淀到仓库里,和每次发版绑定,prompt 一改就跑一遍相关用例子集,而不是等用户投诉了再做亡羊补牢。Agent 这个领域变化很快,但“先体检、后上线、常回测”这个流程,短期看多花点时间,长期看省的是无数个在用户面前翻车的现场。