跳到正文

BadCase 与质量运营 ​

一句话:BadCase 不是 Bug,而是“这次会话没有达到预期”的样本;它的价值不在数量,而在能否从一条会话下钻到具体一步、归因到一类原因、再变成一条回归用例。没有这条闭环,BadCase 库只是情绪回收站。

适用:2026 年企业 Agent 质量运营。检测信号与阈值需按业务基线校准,文中比例只作示例。

为什么需要 ​

Agent 上线后,传统监控只能告诉你“服务没挂”,不能告诉你“答得不对”:用户很少主动点差评,不满意通常表现为追问、转人工或直接离开;模型、提示词、知识库、工具任一变更都可能让某类问题退化,却没有报错;评测集只覆盖已知问题,新失败模式只能从真实会话里发现。零散反馈又无法判断是个例还是系统性问题,所以需要把弱信号收敛成可排序、可定位、可验证的工单。

核心机制 ​

一、先定义“表现不佳” ​

BadCase 的判定维度要和业务目标对齐,不能只看“回答像不像”:

维度典型表现可观测信号
效率来回很多轮才解决、响应过慢轮次数、首响/完成时延
成本一次会话 token 异常高token 超基线、重复调用同一工具
质量答错、编造、工具失败工具错误码、引用缺失、人工标注
体验用户明显不满负面词、异常标点、连续重复提问
业务没完成转化/办理流程中断、转人工、目标未达成

同一句话在不同业务里含义不同:“转人工”在售后可能是失败,在金融合规里可能是正确兜底。判定规则必须带业务上下文,不能全平台一套阈值。

二、多信号检测:用组合换准确率 ​

单一信号误报极高,生产上通常组合使用:

信号抓什么主要误报
负面词/情绪用户明确不满用户转述别人的抱怨、引用政策原文
异常标点/短句困惑、打断、不耐烦正常口语、输入法问题
转人工任务未完成业务规定必须转人工
重复提问没听懂或答案没用用户补充信息时的正常复述
工具失败/超时执行链断了上游系统偶发抖动
循环/重复调用Agent 原地打转合法的重试与轮询
token/时延超基线成本或性能异常复杂任务本来就贵
引用缺失答案无依据闲聊类问题不需要引用
用户放弃会话突然结束用户已得到答案
显式差评明确反馈稀疏,且受按钮位置影响
业务目标未达成转化/办理失败用户本来就没这个意图

工程上不是“命中一个就报警”,而是打分 + 阈值 + 抽样复核:每个信号给权重,累计超过阈值进入候选池;候选池按比例抽样人工确认,用确认结果反过来校准权重。只做规则不做复核,两周后就会因为误报太多被运营弃用。

三、漏斗:从全量会话到可修问题 ​

漏斗每层都要保留转化率:候选→确认的准确率、确认→归因的完成率、修复→验证的通过率。只有最后一层是结果,前三层暴露的是检测系统本身好不好用。

四、Trace 下钻:从“答错了”到“哪一步错了” ​

一条会话的记录至少要能还原五层:

text
session → turn → step → tool call → raw request/response

下钻时按固定顺序排除:

  1. 输入:用户问题是否被截断、改写错、带错上下文;
  2. 检索:该召回的文档有没有召回,排序是否把正确文档压下去;
  3. 工具:参数对不对、返回码是什么、超时还是业务失败;
  4. 模型:在给定上下文下,这个输出是否合理;
  5. 编排:是否走错分支、循环、提前结束。

归因类别建议固定为:模型能力、提示词/上下文、工具/schema、知识与数据、编排逻辑、环境/依赖。固定分类的好处是能按周聚合——“本周 60% 的 BadCase 是工具 schema 描述不清”,这比一百条个案更有行动价值。

五、闭环:一条 BadCase 要变成一条回归用例 ​

修复动作分三类,对应不同的验证方式:

修复类型例子验证
提示词/上下文补边界条件、改工具描述离线评测集 + 灰度对比
工具/数据修 schema、补知识、加校验单测 + 端到端回放
编排/代码改分支、加终止条件回归测试 + 线上观察

每条确认的 BadCase 至少产出一条可重复执行的用例(输入、上下文、期望行为、判定方式),进入回归集。修复上线前跑全量回归,上线后观察同类信号是否下降;只改 Prompt 不建用例,下一次改 Prompt 很可能把它改回来。

六、排序:先修什么 ​

用 频次 × 严重度 × 可修复性 排序,而不是按发现时间:

  • 频次:同类问题簇的会话数,不是单条 BadCase 的数量;
  • 严重度:是否涉及资金、合规、人身安全,是否导致用户流失;
  • 可修复性:改提示词能解决,还是要改上游系统;后者先登记,不要占满迭代。

高频低危的问题适合批量修;低频高危的问题必须单独立项。只按频次排,会永远在修“话术不礼貌”,修不到“金额算错”。

实战场景 ​

场景一:答错率升了三天,靠客户投诉才发现 ​

现象:某模型供应商对线上模型做了不通知的小版本更新,“开票流程”类问题开始给出无依据的回答。直到第 72 小时,一个大客户提交工单投诉,团队才确认这条线已经退化。回溯数据:这三天该问题簇新增会话约 1,100 条,命中“引用缺失”与“重复提问”的比例是基线的 2.6 倍,转人工率从 8% 涨到 14%(示例比例,经验值,需校准)。

排查过程:确认退化后按固定顺序做分层定位——数据变了、检索变了、prompt 变了、模型换了,还是流量结构变了?先取候选池里“开票流程”簇的时间分布,把劣化起点定在 T0;T0 前后没有发布记录,排除提示词与编排;Trace 里检索结果字段正常、该召回的文档都在,排除知识与数据;比对 session 上的模型版本字段,T0 正是供应商切小版本的时刻;问题簇的会话占比与历史同期一致,排除流量结构变化。

对症做法:单条会话打分(SUM(weight) >= 3 进候选池)抓不到“缓慢劣化”,必须给漏斗加一层簇级趋势监控:

指标阈值(经验值,需校准)owner动作
问题簇同类信号量 / 7 日同期基线≥ 2 倍且样本 ≥ 30质量运营当日插入人工抽样复核,确认后按簇派单
转人工率、解决率(用户侧指标)偏离同期基线 > 5 个百分点业务 owner关联候选池聚类,判断是个例还是系统性
候选→确认准确率周环比跌破 60%质量运营校准信号权重,禁止用调高阈值“止血”

复盘要点:检测系统不能只盯“单条会话是否进候选池”,还要盯“簇的进池速率”;把阈值调高会让报表变好但质量不变,所以用户侧指标必须和检测指标同时上周报——这是把“防止指标游戏”落到值班表上的做法。

场景二:同一类问题三个月后换个说法复发 ​

现象:某月确认了 23 条“退款流程-第二步-材料清单”簇的 BadCase,归因 tool_schema,工程师修好 tool.check_refund_eligibility 的描述后逐条关闭工单,但每条记录的 regression_case 字段为空。三个月后一轮提示词/上下文重构上线,“拆封了还能退吗”这类换壳表述再次命中同一步骤,两周内该簇候选从 61 条积压到 149 条,退款场景转人工率从 9% 升到 17%(示例比例,经验值,需校准)。发布门禁没有拦住,因为回归集里根本没有这条用例。

排查过程:Trace 下钻到 tool.check_refund_eligibility,与三个月前的记录对比:失败步骤、归因类别完全一致,只有用户措辞不同。修复类型上,上次改工具描述属于工具/数据,这次改提示词属于提示词/上下文——正是“只改 Prompt 不建用例,下一次改 Prompt 很可能把它改回来”。

对症做法:每条确认的 BadCase 在关闭工单前必须产出一条可重复执行的用例,四要素直接从 Trace 生成,不靠人手写描述:

text
输入      ← Trace 的 raw request(用户原话)
上下文    ← 故障时刻的检索结果与会话状态快照
期望行为  ← 人工复核确认的正确行为(调用哪个工具、引用哪个章节)
判定方式  ← 规则断言:引用字段非空、工具返回码为 0,禁止“人工看个像不像”

用例按“场景 + 失败步骤 + 归因”挂回问题簇;发布门禁只认一条规则:回归集中存在未通过的同类用例,不允许发布。

复盘要点:漏斗的“修复→验证通过率”要按周公示;只修不沉淀的 BadCase,结论留在某个工程师的脑子里,人一走或提示词一改,同类问题必然复发。

场景三:归因口径不清,工单在三个团队间踢皮球 ​

现象:一轮知识库重建丢了部分旧文档的生效时间字段,“有效期”类问题开始答错。算法说是数据问题,数据组说是模型没用好上下文,模型组说是提示词没写约束。三方各改了一版提示词,没有一版命中真正原因,这批工单在 3 个队列间平均流转 5 天才回到数据组,期间同类 BadCase 积压 87 条(示例数字,经验值,需校准)。

排查过程:抽 10 条 Trace 按固定顺序验证:检索层发现正确文档根本没被召回——问题在数据,后面三层轮不到被审。争执的根源是各团队凭立场倒推原因,没有人按同一条 Trace 顺序走一遍。

对症做法:把归因分类做成可判定的决策表,判定顺序就是 Trace 下钻顺序,前一层不干净不允许归到后一层:

序判定条件(Trace 证据)归因owner处置与验证
1该召回文档未召回,或召回后字段缺失知识与数据数据组补知识、重建索引;单测 + 端到端回放
2工具参数不合 schema,或返回码为业务失败工具/schema工具 owner 团队修 schema、加校验;单测 + 端到端回放
3同参数重放必现上游超时/错误码环境/依赖SRE登记上游工单;走熔断与降级
4文档已召回且进入上下文,回答仍未引用提示词/上下文prompt owner补边界条件;离线评测集 + 灰度对比
5上下文完整、给定输入下输出仍不合理模型能力算法换模型或加兜底;单独立项,不用改提示词糊弄
6走错分支、循环或提前结束编排逻辑平台改代码、加终止条件;回归测试 + 线上观察

模型自动归因只能填候选值,最终以人工确认为准;归因结果按周聚合,“本周 60% 是工具 schema 描述不清”这类结论一出现,责任归属不再靠嗓门。

复盘要点:归因完成率是漏斗中间层的健康指标,卡在三方流转上的工单要在周会单独点名;一张人人可查的决策表,比十次协调会便宜。

最小上手 ​

sql
SELECT session_id, SUM(weight) AS score, MAX(created_at) AS last_seen
FROM session_signals
WHERE created_at >= NOW() - INTERVAL '7 days'
GROUP BY session_id
HAVING SUM(weight) >= 3
ORDER BY score DESC LIMIT 200;
json
{
  "badcase_id": "bc-2026-1012", "session_id": "s-8842",
  "cluster": "退款流程-第二步-材料清单", "signals": ["tool_error", "repeat_question"],
  "trace_step": "tool.check_refund_eligibility", "root_cause": "tool_schema",
  "severity": "high", "regression_case": "case-2210",
  "owner": "refund-team", "status": "fixed_pending_verify"
}

跑两周,看三件事:候选准确率、归因完成率、修复后同类信号是否下降。三项都能量化,再谈平台化。

生产动作 ​

  • 准确率优先于召回率:候选池宁可少而准,运营才愿意用;召回不足可以靠周度抽样补,误报过多会直接摧毁信任。
  • 聚合到问题簇再派单:按“场景 + 失败步骤 + 归因”聚类,一条工单修一类问题;逐条派单会让工程师陷入个案。
  • Trace 字段标准化:模型、提示词版本、检索结果、工具参数与返回、耗时、token 必须可关联;缺一项就无法归因。
  • 隐私与权限:BadCase 含真实会话,查看、导出、标注都要按租户与角色鉴权;进入评测集前脱敏。
  • 防止指标游戏:只考核“BadCase 数量下降”,团队会把阈值调高;要同时看抽样准确率与用户侧指标(转人工率、解决率)。
  • 和发布门禁打通:回归集里同类用例不通过,不允许发布;否则修复只是碰运气。

边界 ​

  • BadCase 不是 Bug 系统:它管“预期未达成”,Bug 系统管“确定的功能错误”;两者可以互相引用,但不能合并,否则优先级会被技术故障淹没。
  • 信号只是代理指标:负面词不等于答错,转人工不等于失败;任何自动判定都要保留人工复核通道。
  • 不要用单条案例驱动改模型:一条案例可能是个例;先聚类看频次,再决定改提示词、改工具还是改流程。
  • 模型自动归因只能辅助:模型可以读 Trace 给候选原因,但不能替代人工确认;错误归因会让修复方向整体跑偏。
  • 小团队不必建平台:一张信号表 + 每周人工抽样 + 回归用例文件,就能跑通闭环;先证明运营愿意用,再投入系统。

讲清楚 ​

BadCase 是“会话未达预期”的样本,不是 Bug。判定要按效率、成本、质量、体验、业务五个维度,结合业务上下文;检测靠多信号打分而不是单条规则,并且必须抽样复核来校准准确率。

它的核心是一条漏斗:全量会话 → 候选 → 去重聚合 → 人工确认 → Trace 下钻 → 归因 → 修复 → 回归验证。Trace 要能还原 session/turn/step/tool 五层,归因分类要固定,才能按周聚合出“哪一类问题最值得修”。每条确认的案例都要变成可重复执行的回归用例,否则修复会被下一次改动推翻。排序用频次 × 严重度 × 可修复性,指标要同时看候选准确率和用户侧结果,防止把阈值调高当成质量提升。

适用:2026 年企业 Agent 质量运营 | 初稿 2026-10

把 AI 工程讲到既懂也会用