笃行
首页
个人 & 心法
互联网/硬件后台
游戏基础架构
UE 引擎
游戏业务
AI / 大模型
数据结构与算法
机器学习数学
通用基础
GitHub
首页
个人 & 心法
互联网/硬件后台
游戏基础架构
UE 引擎
游戏业务
AI / 大模型
数据结构与算法
机器学习数学
通用基础
GitHub
  • AI / 大模型

    • AI / 大模型
    • 大模型核心原理
    • 推理与微调优化
    • RAG 检索增强生成
    • RAG 上下文剪枝实战(Listwise Pruning 复现)
    • RAG 数据清理
    • RAG 存量数据清理
    • Agent 开发
    • Agent 运行时深水区
    • Multi-Agent 协作
    • Agent 评测与线上运营
    • AI 与游戏研发周期
    • 互动影游与长视频创作 Agent
    • LLM 应用安全
    • LLM 评测方法论
    • LLM 成本与延迟
    • 微调策略
    • AI 研发工程化

Agent 评测与线上运营:离线全绿,线上照坏

四格矩阵 · Golden Set 与指标口径 · 轨迹级 judge · span 树归因 · 影子与灰度

🧠 一句话记忆锚点

评测按「离线/在线 × 单步/全轨迹」四格排布,冲突时以在线全轨迹为准(它离用户最近)。成功率的分母比分子难——超时与熔断样本必须显式归类,部分成功要拆成关键步达成率。轨迹 judge 的死穴是正确路径不唯一,所以判关键步而不是比参考轨迹。可观测埋点看 span 树:任务→轮→模型/工具,最小属性集里"终止原因"最值钱。上线走回放→影子→灰度三级,回滚看人工接管率而不是成功率。失败归因四分类:模型决策 / 工具执行 / 上下文缺失 / 护栏误拦。

名词速查

首次阅读可跳过本表,直接看「场景问题」,遇到生词再回查。

本篇是评测里「Agent 多步轨迹」子域的名词归属页。总论(基准污染、judge 偏差、Cohen's kappa)归 评测方法论,本表只收轨迹特有的词。

一句话说清本篇解决什么:单次问答只要判"答对没有",多步轨迹要判"这一路走得对不对"——而正确的路往往不止一条。类比过来就是:从断言返回值,升级到审计整条调用链。

名词后台类比在系统里干什么类比失效边界
四格评测矩阵监控的「离线压测 / 线上拨测 × 单接口 / 全链路」四格按「离线/在线 × 单步/全轨迹」排布评测手段,冲突时以在线全轨迹为准(它离用户最近)压测与拨测结果通常互相印证;这四格经常互相矛盾(离线单步全绿、线上全轨迹却失败率高),因为单步正确不代表串起来正确。矩阵的价值是提醒你"别只看一格",而不是给出统一分数
成功率分母SLI 的统计口径——分母里算不算超时、算不算主动降级的请求Agent 成功率里比分子更难的部分:超时、预算熔断、护栏拦截、人工接管的样本各自归到哪里常规 SLI 的口径一旦定下就稳定适用;Agent 的"失败"种类多且性质不同——被护栏拦住其实是系统正常工作,算失败会低估实际质量;不算又会掩盖护栏误拦。所以必须显式分类统计而不是压成一个数,任何单一的成功率数字都不可比
部分成功(Partial Success)批处理里的部分成功——100 条里成了 87 条,不是二值结果多步任务常常只完成一部分,需要拆成"关键步达成率"而非只判最终成败批处理的成功条数是精确可数的;这里"哪几步算关键"是人为定义的,定义变了指标就变了。且步骤之间有依赖,第 3 步失败导致后续全跳过,不能简单按"完成步数/总步数"算比例
轨迹级 judge审计整条调用链而非单个响应——看流程走得对不对让模型评判整条执行轨迹的合理性,而不只看最终答案链路审计有标准流程图可比对,偏离即异常;Agent 的正确路径不唯一——先查日志再查配置、还是反过来,可能都对。所以不能拿参考轨迹逐步比对,只能判关键步是否达成,这是本篇与单步评测最本质的分野
span 树分布式追踪的调用链树(trace → span)——你在 Jaeger 里看的那个把一次任务的执行结构化为树:任务 → 轮次 → 模型调用/工具调用,用于定位"是哪一步坏的"语义和结构几乎一致,这是本表最贴近后台原物的概念。差别在最值钱的属性不同:常规 span 看耗时与错误码,Agent span 最关键的属性是"终止原因"(正常完成/轮数耗尽/预算耗尽/无进展中止)——没有这个字段,你分不清"跑完了"和"被掐掉了"。属性命名建议对齐 gen_ai.* 语义约定,清单见 AI 研发工程化
步级归因(Step Attribution)故障根因定位——从链路里找出第一个出错的环节把失败归到具体某一步,并分类为:模型决策错 / 工具执行错 / 上下文缺失 / 护栏误拦链路里的错误有明确的错误码与堆栈可定位;这里第一个"错"的步骤往往不报错——模型决策错误表现为一次格式完全合法的工具调用,只是选错了工具。所以归因不能靠扫错误日志,必须靠轨迹重读与关键步断言
失败四分类故障分类(代码缺陷 / 依赖故障 / 配置缺失 / 限流误伤)把失败归入四类以指向不同的修复动作:改 prompt / 修工具 / 补检索 / 调护栏常规故障分类边界清晰,一个故障通常只属于一类;这四类经常同时成立且互为因果——上下文缺失导致模型决策失误,你既可以补检索也可以改 prompt。分类的价值是收敛修复方向,不是精确定责
回放(Replay)流量录制回放——用历史真实请求跑新版本上线三级的第一级:拿历史轨迹重跑,看关键步达成率是否退化常规回放能精确重放(同样输入同样依赖);Agent 回放无法重现当时的外部世界——工具依赖的数据已经变了,同一个查询现在返回不同结果,所以"失败"可能只是环境变了。需要把工具返回值一起录制回放(mock 化)才有可比性
影子(Shadow)双跑不生效——新版本吃真实流量但结果不返回用户上线三级的第二级:真实流量并行验证,无用户风险常规影子只消耗算力;Agent 影子会真实调用工具——如果工具有副作用(发消息、改数据、扣款),影子跑一遍就出事了。必须先把副作用工具替换成 mock,这一步做不到就不能上影子
灰度(Canary)按比例放量的金丝雀发布上线三级的第三级:小比例真实用户,观察后逐步放量常规灰度的回滚判据是错误率与延迟,秒级可见;Agent 的质量退化往往要等到用户抱怨或人工接管率上升才显现(延迟到小时级)。所以观察窗必须比常规灰度长,不能按"跑了 10 分钟没报错"就放量
人工接管率(Human Takeover Rate)自动化流程转人工的比例——最诚实的那个健康指标灰度与回滚的首要判据:用户或运营多久要接手一次。比成功率更早、更真实地反映退化常规转人工率主要反映流程覆盖度;这里它是质量的代理指标——但它有滞后性(用户忍一会儿才求人)和场景偏差(不同业务的容忍度天差地别)。所以要看它的相对变化趋势,不能设一个跨业务的绝对阈值

本篇引用的其他上下文名词

名词在本篇里的角色完整解释去哪读
基准污染 / LLM-as-judge / 位置偏差 / 长度偏差 / Cohen's kappa / Golden Set / 人类在环通用评测方法论总论,本篇不重复展开评测方法论 · 名词速查
rubric 打分 / 一致性断言 / 人评抽样无 golden answer 的创作类评测,归创作篇创作 Agent · 名词速查
调度状态机 / 四条终止线 / 预算熔断 / 护栏被观测的那套运行时机制("终止原因"字段的来源)Agent 运行时深水区 · 名词速查
gen_ai.* 语义约定 / span 属性清单span 命名对齐的标准,属性清单归工程化篇AI 研发工程化 · 名词速查
MAS 特有失效 / 级联幻觉多 Agent 轨迹归因时要区分的失效类型Multi-Agent 协作 · 名词速查

场景问题

一个客服 Agent 上线前,Golden Set 200 条跑到 94% 成功率,红队测了三轮没越权,团队签字发布。上线第四天,客服组反馈「机器人答得挺好但用户投诉暴涨」。

拉数据才看清:Agent 的回答质量确实没问题,但它有 11% 的会话在第 3~4 轮后触发了工具超时,然后礼貌地道歉并结束会话——离线评测里这类样本被判定为"未完成,不计入分母",于是 94% 是在 89% 的样本上算出来的。真实的用户视角成功率是 83%。

指标没错,口径错了。而离线评测的四格里,这个 Agent 只被测过一格。

阅读边界

本篇只讲 Agent 多步轨迹特有的评测与运营问题。通用 LLM 评测方法论——指标分类、基准选择与污染、LLM-as-judge 的可靠性总论与偏差校正、人类在环与标注一致性——是 评测方法论 的地盘,本篇不重复展开,只在轨迹场景下补它的特有变化。护栏与预算的实现见 Agent 运行时深水区;本篇讲这些护栏怎么被量化验证。

另有一类任务本篇不覆盖:无 golden answer 的创作类任务(剧本、视频不存在唯一正确版本,评测的数学基础从分类问题变成打分排序问题)。rubric 的分档设计、可自动化的一致性断言、按风险分层的人评抽样,归 互动影游与长视频创作 Agent。本篇的成功率口径与 Golden Set 方法论以「任务有可判定的正确结果」为前提。

实现方案

一、主骨架:离线/在线 × 单步/全轨迹 四格

Agent 评测容易乱,是因为「Golden Set / 红队 / 回放 / 影子流量」这四个词不在同一个维度上。摊到两个正交维度上就清楚了:

单步(一次决策 / 一次工具调用)全轨迹(一个完整任务)
离线① 决策单测:固定上下文快照,断言模型该选哪个工具、参数是否合法。跑得快、能进 CI② Golden Set 回归:200~500 条任务跑完整轨迹,看成功率/步数/成本/p95 延迟
在线③ 实时护栏与步级监控:每步的 Schema 校验失败率、工具错误率、护栏拦截率、单步延迟④ 影子 / 灰度 / 真实轨迹分析:与旧版并跑对比,看真实完成率与人工接管率

四格各自的必要性在于它们拦的东西不重叠:

  • 只有 ① 会漏掉「每步都对、组合起来跑偏」;
  • 只有 ② 会漏掉开篇那种「分母口径掩盖的问题」,因为 Golden Set 的任务分布不等于真实分布;
  • 只有 ③ 会漏掉「护栏没拦但结果就是错」;
  • 只有 ④ 则完全没有发布闸门,等于拿用户当测试集。

维度冲突时以哪个为准

这是四格模型必须给出的裁决规则,否则每次数据打架都要吵一轮:

离线指标与在线指标背离时,以在线全轨迹(第 ④ 格)为准,且必须回头修离线。 理由是 ④ 离用户最近,而离线与在线背离本身就是一个 bug 信号——它说明 Golden Set 的分布或口径与真实场景脱节。修法不是调整对 ④ 的解读,而是把背离的真实样本回捞进 Golden Set,让 ② 下次能拦住。

单步与全轨迹背离时(每步都对但任务失败),以全轨迹为准。 单步全绿而轨迹失败,通常意味着问题在步与步之间:上下文丢失、观察被误读、或规划层面的错误。这类问题不该靠加严单步断言解决。

二、Golden Set 与指标:分母比分子难

打个比方:Golden Set 就是你的回归测试集——典型用例、边界用例、每次线上事故的最小复现,跑一遍看通过率。而"分母比分子难"这件事你也遇过:统计接口成功率时,超时算不算失败、5xx 和 4xx 要不要分开、被限流拒掉的算不算一次请求——口径不同,同一份日志能算出差好几倍的成功率。类比失效边界:回归测试的通过判定是断言相等,非黑即白;Agent 的一次运行可能"跑完了、格式合法、但答得不对",也可能"答对了但绕了 30 步"。所以这里的判定必须先归类终止方式再谈对错,且要看指标结构而非单一数字——只看成功率会奖励"多试几次凑对"。

样本怎么构造

三类样本,配比经验值 典型 60% / 边界 25% / 已知失败 15%:

  • 典型:真实分布里最高频的任务形态。来源应当是线上轨迹回捞而不是人工想象——人工构造的"典型"通常过于干净。
  • 边界:参数极值、空结果、多义指令、超长输入、工具不可用。
  • 已知失败:每次线上事故的最小复现样本。这一类只增不减,是 Golden Set 里最值钱的部分。

回捞流程:从线上按分层抽样(按任务类型 × 结果状态),失败与慢轨迹要过采样。抽出来的轨迹需要人工确认「正确结果应该是什么」才能进 Golden Set——这一步无法省。

成功的可判定定义

「成功率」这个词在 Agent 上有歧义,必须拆开声明:

断言类型判定对象适用
终态断言最终答案/世界状态是否符合预期有唯一正确结果的任务(查询类、计算类)
过程断言是否调用了必需的工具、是否避开了禁止操作有合规要求的任务(必须查过库才能答)
关键步达成若干关键里程碑各自是否达成长任务、部分成功有意义的场景

部分成功怎么计分:不要用 0/1。定义 k 个关键步,得分 = 达成数 / k,同时单独报「完全成功率」(k/k)。开篇的客服案例如果早就这么报,「答得好但会话中断」会立刻显形为「关键步达成 0.75、完全成功率 0.83」。

核心指标族与分母陷阱

六个指标,缺一个都会有盲区:

  1. 任务成功率(按上面的定义,分完全/部分两档报)
  2. 平均步数(同时看 p95——长尾步数暴涨是跑偏的先行信号)
  3. 平均 token 与费用(分模型报,路由到小模型的部分单价不同)
  4. p95 端到端延迟(不是平均值,用户体感在长尾)
  5. 工具调用失败率(分工具报,能直接定位坏工具)
  6. 人工接管率(有 human-in-the-loop 时最重要的一个,见下文回滚判据)

分母陷阱——这是开篇事故的直接根因:

# ✗ 错:超时/熔断样本被悄悄踢出分母,成功率虚高
success_rate = n_success / (n_total - n_timeout - n_aborted)

# ✓ 对:所有样本进分母,异常单独归类并显式报出
@dataclass
class EvalReport:
    total: int
    success_full: int        # k/k 关键步全达成
    success_partial: int     # 0 < 达成 < k
    failed: int             # 跑完了但结果错
    aborted_budget: int     # 预算/轮数熔断
    aborted_tool: int       # 工具不可恢复错误
    timeout: int

    @property
    def success_rate(self) -> float:
        return self.success_full / self.total      # 分母永远是 total

    def assert_accounted(self) -> None:
        # 每个样本必须落进且只落进一个桶,防止口径漂移
        assert (self.success_full + self.success_partial + self.failed
                + self.aborted_budget + self.aborted_tool + self.timeout) == self.total

assert_accounted 这一行是防口径漂移的关键:每个样本必须落进且只落进一个桶。加了新的中止原因却忘了加桶,断言会立刻炸,而不是静默地把样本从分母里蒸发掉。

打分一条轨迹的骨架

def score_trace(trace: Trace, case: GoldenCase) -> TraceScore:
    # ① 先归类终止方式 —— 决定这条样本进哪个桶,必须最先做
    if trace.status == "timeout":
        return TraceScore(bucket="timeout", steps=len(trace.turns), cost=trace.cost)
    if trace.status == "aborted":
        bucket = "aborted_budget" if trace.abort_reason in BUDGET_REASONS else "aborted_tool"
        return TraceScore(bucket=bucket, steps=len(trace.turns), cost=trace.cost)

    # ② 关键步达成:按里程碑而非参考轨迹比对(路径不唯一)
    hit = [m for m in case.milestones if m.reached(trace)]
    ratio = len(hit) / len(case.milestones)

    # ③ 过程约束:必需工具调过没有、禁止操作碰过没有
    violations = [c for c in case.constraints if not c.holds(trace)]

    # ④ 终态断言(若该 case 有唯一正确答案)
    terminal_ok = case.assert_terminal(trace.answer) if case.has_terminal else True

    bucket = ("success_full" if ratio == 1.0 and terminal_ok and not violations
              else "success_partial" if ratio > 0 and not violations
              else "failed")
    return TraceScore(
        bucket=bucket, milestone_ratio=ratio, violations=violations,
        steps=len(trace.turns), cost=trace.cost,
        latency_p95_step=percentile([t.duration for t in trace.turns], 95),
        tool_failures={t.name: t.failures for t in trace.tool_calls},
        first_divergence=find_first_divergence(trace, case),   # 步级归因锚点
    )

注意 ① 的位置——先归类终止方式再谈对错。反过来写(先判对错、再看是否超时)就会写出上面那个错误的分母。

过拟合 Golden Set 的表现与防范

表现:Golden Set 成功率持续爬升到 97%+,但线上完成率不动或下降。原因通常是 prompt 被反复调到「刚好能过这 200 条」。

三条防范:

  • holdout 集:留 20% 从不用于调优,只在发布前跑一次。两者差距 >5pp 就是过拟合信号。
  • 定期轮换:每季度用新回捞的线上样本替换 30% 的典型样本。
  • 看指标结构而非单一数字:成功率涨但平均步数也涨,往往是「靠多试几次凑对」而非真的变强。

这一节记住三句话

  1. 分母比分子难。先归类终止方式(正常终止 / 超时 / 熔断 / 崩溃)再谈对错——反过来写"先判对错再看是否超时"就会算出一个虚高的成功率。
  2. Golden Set 的样本要从线上回捞,不能人工想象——人工构造的"典型"过于干净。三类配比约 60% 典型 / 25% 边界 / 15% 已知失败,而已知失败那一类只增不减,是最值钱的部分。
  3. 过拟合的信号是"Golden Set 涨、线上不动"。三条防范:20% holdout 只在发布前跑(差距 >5pp 即报警)、每季度轮换 30% 典型样本、看指标结构——成功率涨而平均步数也涨,是靠多试几次凑对。

三、轨迹级 judge:正确路径不唯一

评测方法论 讲了 LLM-as-judge 的通用可靠性问题。轨迹场景多出一个更硬的困难:

同一个任务有多条合法路径。 查一个玩家的异常,先看日志再看指标、还是先看指标再看日志,都对。所以「与参考轨迹比对相似度」这个思路从根上不成立——它会把一条更聪明的短路径判为偏离。

替代方案是判关键步而非判路径:

判分粒度成本归因能力适用
终态判分最低(1 次 judge 调用)无(只知道错了)有唯一答案、轨迹短
关键步判分中(k 次断言,多为规则而非 judge)强(知道哪个里程碑没达成)默认选择
逐步判分高(每轮 1 次 judge 调用)最强只在排查特定坏 case 时开

「关键步判分」之所以是默认——里程碑通常能写成规则断言("调用过 query_player_log 且返回非空"),根本不需要 judge,既省钱又没有 judge 偏差。judge 只用在无法规则化的地方("回答是否体现了对用户情绪的回应")。

步级归因:找到 first_divergence——第一个偏离所有合法路径的步骤。实现上不必穷举合法路径,用一个弱得多的判据就够:从哪一步开始,后续再也没有新里程碑达成。那一步通常就是跑偏点。

judge 偏差在长轨迹上的放大:

  • 位置偏好:judge 对轨迹开头和结尾的步骤给分明显不同于中间步骤——和「迷失在中间」同源。校正手段是分段判分(把长轨迹切成若干段分别判)而不是整条喂进去。
  • 长度偏好:judge 倾向给更长、更"努力"的轨迹更高分,即使结果一样。校正手段是把步数从 judge 的输入里剥离——judge 只看关键步是否达成,步数作为独立指标单独报。

什么时候必须退回人工:新任务类型上线的第一批样本(还没有可靠的里程碑定义时)、judge 与规则断言结论冲突的样本、以及所有进「已知失败」类的事故样本。judge 是用来扩大人工标注的覆盖面,不是替代它。

四、轨迹级可观测:span 树与最小属性集

一次 Agent 任务的 span 树形态是固定的三层:

最小属性集——少一个就有排查不了的场景:

层属性少了它排查不了
tasktask_id、总耗时、终止原因、总 token、总费用「为什么停了」——终止原因是全表最值钱的一个字段
turn轮次序号、本轮状态、上下文 token 数上下文膨胀曲线、压缩是否按预期触发
llm模型名、input/output token、是否命中 prompt 缓存、耗时成本归因、缓存失效
tool工具名、危险级别、参数指纹、耗时、错误码、返回是否被截断打转检测复盘、坏工具定位

gen_ai.* 语义约定的定位:属性名不必自己发明——OpenTelemetry 的 GenAI 语义约定已经给了 span 操作类型与属性名的完整清单(含 agent / tool / MCP span),详见 AI 研发工程化 · OpenTelemetry GenAI 语义约定,本页不重复罗列。这里只说它对 Agent 评测的意义:对齐它,换 APM 后端时不用重埋点;但它仍在 Development 阶段、属性名改过一次,所以务实做法是在自己代码里过一层常量映射,约定变更只改一处。

采样策略:全采样在 Agent 场景比普通 API 贵得多——一次任务几十个 span,每个 llm span 还想带上 prompt 摘要。分层采样:

  • 失败与中止轨迹:100% 采样(这是排查的主要材料)
  • p95 以上慢轨迹:100%
  • 成功轨迹:1~5% 抽样(用来看常态分布)
  • 成本超阈值的轨迹:100%

从 span 树反推「这次为什么失败」

固定的四步排查路径:

  1. 看 task span 的终止原因 —— 直接分流到四类归因之一。
  2. 若是 aborted/无进展:看 tool span 的参数指纹序列,找重复段,确认是否指纹计算漏剔了 nonce。
  3. 若是 failed(跑完但错):找 first_divergence 那一轮,读该轮的 llm span 输入——通常是上下文里少了某个事实,或工具返回被截断截掉了关键部分(这就是 tool span 要记「是否被截断」的原因)。
  4. 若是 timeout:看各 tool span 耗时分布,区分「某个工具慢」与「轮数太多累加慢」——两者修法完全不同。

打个比方:span 树像快递的物流轨迹——包裹(任务)每经一个网点(轮次)留一条记录,每条记录里有揽收人(模型调用)和运输方式(工具调用)。收不到货时你不是重寄一遍,而是顺着轨迹找最后一个正常节点。类比在哪失效:物流轨迹上每个节点的「正常」是客观的(签收了就是签收了),而 Agent 的每一步都可能看起来正常但语义上已经跑偏——模型成功调用了工具、拿到了结果、给出了下一步,每个 span 都是绿的,但它查的是错的那张表。所以 span 树只能定位「在哪一步开始偏」,不能自动告诉你「偏了」——后者仍要靠里程碑断言。

五、从离线到线上:回放 → 影子 → 灰度

离线回放

录制真实轨迹,换 prompt / 换模型后重放,对比结果。回放的不可复现来源有四个,每个都要显式固定:

不可复现来源固定手段
模型采样随机性temperature=0 + 固定 seed(注意:仍不保证跨版本一致)
工具返回随时间变化回放时用录制的工具返回而非真实调用(工具打桩)
并行工具回填顺序按发起顺序回填(见 运行时)
时间/随机数进 prompt冻结时钟,nonce 走可注入的 provider

工具打桩有个边界:换了 prompt 后模型可能调用录制里没有的工具。这时回放只能停在这里并标记「轨迹分叉」——分叉率本身是个有用的指标(分叉率高说明改动影响面大)。

影子流量

真实请求同时打给新旧两版,只有旧版的结果对用户生效。要点两条:

  • 副作用必须隔离:影子版的所有 L1/L2 工具(见 运行时的危险分级)必须走打桩或只读副本,否则一次影子跑就会产生两笔真实扣款。这是影子流量最容易出事的地方。
  • 成本要预先算:影子等于双倍模型成本。通常只对 5~10% 流量开影子,且优先覆盖高价值/高风险任务类型。

灰度与回滚判据

按流量比例(1% → 5% → 20% → 100%)或按用户分层(内部员工 → 低价值场景 → 全量)推进。

回滚看什么指标——这里有个反直觉的结论:不要只看成功率。成功率是滞后指标,且被口径影响。优先级更高的三个:

  1. 人工接管率(有 HITL 时的首选)——它对质量下降最敏感,且不受分母口径影响。
  2. 护栏拦截率突增——说明新版在尝试它不该做的事。
  3. p95 步数 / 成本漂移——说明它在靠多试凑答案,是质量下降的先行指标。

阈值设成相对旧版的偏移而非绝对值(人工接管率相对基线上升 >30% 即回滚),因为绝对值随任务分布波动。

六、线上失败归因四分类

每个失败必须落进且只落进一类,否则修复责任无法分派:

归因典型信号修法归属
模型决策错工具调用都成功、上下文里信息齐全,但选了错的工具或误读了结果Prompt / few-shot / 换模型;补进 Golden Set「已知失败」
工具执行错tool span 有错误码或超时;同一工具失败率异常修工具本身(分页、超时、错误消息可读性)
上下文缺失first_divergence 那轮的 llm span 输入里缺关键事实;或工具返回被截断截掉了关键段记忆层(压缩水位、pin、截断策略)→ 运行时
护栏误拦护栏拦截日志 + 用户本意合法调护栏阈值或分级,见下文代价不对称

护栏误拦 vs 放过的代价不对称如何定阈值:

两类错误的代价通常差几个数量级——放过一次 L2 不可逆操作(误删生产数据、错误扣款)的代价,可能是误拦一百次的一百倍以上。所以:

  • 对 L2 不可逆动作:阈值调到宁可多拦(高召回、低精确),误拦的代价只是一次人工确认。
  • 对 L0 只读动作:阈值调到宁可少拦,误拦会让 Agent 完全无法工作。
  • 判据是「误拦的补救成本」:能被一次人工点击补救的,就往严;补救需要走工单流程的,就要权衡。

这也解释了为什么护栏拦截率突增要当回滚信号——它可能意味着新版正在批量触碰不该碰的东西。

为什么这么做

为什么四格里 ② 是发布闸门而不是 ①

单步决策单测跑得快、能进 CI,看起来是最理想的闸门。但它有个结构性局限:它验证的是「给定这个上下文,模型该做什么」,而 Agent 的失败大多来自上下文本身是错的。上下文快照是人工准备的,天然干净;真实运行时的上下文经过了压缩、截断、召回,可能已经缺了关键事实。

所以 ① 的定位是快速回归(改 prompt 后 30 秒内知道有没有明显破坏),② 才是闸门。两者是漏斗关系,不是替代关系。

为什么人工接管率比成功率更适合做回滚判据

三个理由:

  1. 不受分母口径影响——它是「人接手的会话数 / 总会话数」,没有"该不该计入分母"的争议。
  2. 对质量下降更敏感——用户或客服在体感变差时会更早接手,早于自动判定的失败。
  3. 它直接对应人力成本——业务方能理解「接管率涨 30% 意味着客服要多招人」,比「成功率跌 2pp」更容易达成回滚共识。

局限:没有 HITL 的全自动场景用不了这个指标,此时退回「护栏拦截率 + 成本漂移」组合。

为什么里程碑断言优于 judge

成本与偏差两头都赢:里程碑多数能写成规则(调过某工具、返回非空、终态含某字段),零 judge 调用、零 judge 偏差、可重复。judge 的位置应该是规则写不出来的那部分(语气、是否体现共情、解释是否充分),而这部分通常只占判据的一小半。

一个常见的反模式是「整条轨迹丢给 judge,让它给 1-10 分」——这个分数既不可归因(不知道扣分在哪)又不稳定(同一轨迹两次判分能差 2 分)。

为什么别的选择不行

「用 RAGAS 那套指标评 Agent」

RAGAS 的 faithfulness / context precision-recall 是单轮检索质量的度量(详见 RAG),它假设了「一次检索 → 一次生成」。Agent 的问题是多步的:第 3 轮检索质量很好但第 5 轮基于它做了错误推论,RAGAS 全绿而任务失败。

它能用在 Agent 的某一个检索步骤上(作为里程碑断言的一部分),但不能作为轨迹的评价体系。

「只做在线 A/B,不要离线评测」

在线 A/B 的统计功效需要样本量。一个日活不高的内部 Agent,要检测 2pp 的成功率差异可能需要跑两周——而这两周里坏版本一直在影响用户。更要紧的是 A/B 无法覆盖低频高危场景(一个月出现两次的删除操作),这类只能靠 Golden Set 的「已知失败」类样本守。

「让 judge 对比新旧两条轨迹,选更好的那条」

成对比较(pairwise)确实比绝对打分稳定,但在轨迹上有两个坑:位置偏好(judge 系统性偏好放在前面或后面的那条,必须做位置交换取平均)和无法归因(知道 B 比 A 好,但不知道好在哪一步,改不动)。

它适合做发布前的最终 sanity check,不适合作为日常回归的主指标。

三种上线推进方式的对照

方式成本能发现的问题盲区
离线回放低(无真实流量)prompt/模型改动的直接影响、分叉率工具打桩后的真实工具行为、真实分布
影子流量高(双倍模型成本 + 副作用隔离复杂度)真实分布下的成本/延迟/分叉用户反馈(结果不生效,拿不到接管率)
灰度中全部(含用户反馈与接管率)已经在影响真实用户,需要快速回滚能力

三者是递进的:回放筛掉明显退化 → 影子验证成本与稳定性 → 灰度收真实反馈。跳过任一级都会把该级的盲区留到下一级去暴露,代价递增。

沉淀结论

面试常见问题清单

评测框架

  • Q:Agent 评测怎么组织? A:按「离线/在线 × 单步/全轨迹」四格——决策单测(快、进 CI)/ Golden Set 回归(发布闸门)/ 步级监控 / 影子灰度。四格拦的东西不重叠。
  • Q:离线和在线指标背离时听谁的? A:以在线全轨迹为准(离用户最近),但必须把背离样本回捞进 Golden Set 修离线——背离本身就是「离线分布或口径脱节」的 bug 信号。

指标口径

  • Q:Agent 的成功率怎么定义才不骗人? A:分母永远是全样本;超时/预算熔断/工具中止各自单独归桶并显式报出;部分成功按关键步达成比例计,同时单报完全成功率。加一个「所有桶之和 == total」的断言防口径漂移。
  • Q:怎么发现 Golden Set 被过拟合了? A:holdout 集与主集差距 >5pp;或成功率涨但平均步数也涨(靠多试凑对)。防范靠 holdout + 每季度轮换 30% 典型样本。

轨迹 judge

  • Q:为什么不能拿参考轨迹比相似度? A:同一任务有多条合法路径(先查日志还是先查指标都对),比相似度会把更聪明的短路径判成偏离。改判关键步里程碑。
  • Q:judge 在长轨迹上有哪些偏差? A:位置偏好(对首尾步骤给分不同于中间,与"迷失在中间"同源,靠分段判分校正)、长度偏好(偏好更"努力"的轨迹,靠把步数从 judge 输入剥离、单独报指标校正)。

可观测与运营

  • Q:Agent 的 span 树怎么埋?最值钱的字段是什么? A:三层——task → turn → llm/tool span。最值钱的是 task span 的终止原因,它直接把排查分流到四类归因。tool span 要记「返回是否被截断」,否则查不出上下文缺失。
  • Q:影子流量最容易出什么事故? A:副作用没隔离——影子版的写操作打到真实系统,一次影子跑产生两笔扣款。所有 L1/L2 工具必须打桩或走只读副本。
  • Q:灰度回滚该看什么指标? A:不要只看成功率(滞后且受口径影响)。优先看人工接管率(最敏感、无口径争议、直接对应人力成本)、护栏拦截率突增、p95 步数/成本漂移。阈值设成相对基线的偏移而非绝对值。

心法总结

Agent 评测的难点不在算指标,在于定口径和分归因。 一个没写清「超时算不算失败」的成功率,比没有成功率更危险——它给了团队一个签字发布的理由。

本域延伸

  • 枢纽结论与四种评测手段的定位:Agent 开发
  • 被评测的那些护栏、预算、幂等怎么实现:Agent 运行时深水区
  • 通用 LLM 评测方法论(基准污染、judge 可靠性总论、标注一致性):评测方法论
  • 无 golden answer 的创作类任务评测(rubric 分档、一致性断言、风险分层抽样):互动影游与长视频创作 Agent
  • 多 Agent 的跨 trace 归因与冲突裁决:Multi-Agent 系统
  • 单步检索质量的度量(RAGAS)与它的适用边界:RAG
  • token 计价与延迟拆解,成本漂移的口径:成本与延迟
  • 红队与对抗测试:LLM 应用安全

记忆口诀

  • 四格矩阵:离线/在线 × 单步/全轨迹 —— 决策单测 / Golden Set / 步级监控 / 影子灰度
  • 裁决规则:背离时听在线全轨迹,然后回捞样本修离线
  • 样本三类:典型 60(线上回捞)/ 边界 25 / 已知失败 15(只增不减)
  • 分母铁律:分母永远是 total,异常单独归桶 + 桶和断言
  • 判分三粒度:终态(省)/ 关键步(默认) / 逐步(排查才开)
  • judge 两偏差:位置偏好(分段判分)/ 长度偏好(剥离步数)
  • span 三层:task → turn → llm+tool;最值钱字段 = 终止原因
  • 采样分层:失败与慢 100%,成功 1~5%
  • 上线三级:回放 → 影子(副作用必隔离)→ 灰度
  • 回滚首选:人工接管率(不是成功率),阈值用相对基线偏移
  • 归因四分类:模型决策 / 工具执行 / 上下文缺失 / 护栏误拦

内容来源

综合整理:OpenTelemetry GenAI 语义约定(gen_ai.*,Development 阶段)、LangSmith / 主流 Agent 可观测方案的 span 模型、AI 巡检与客服 Agent 自研落地经验(2026-08)。

文中配比与阈值(60/25/15 样本配比、5pp 过拟合信号、接管率相对上升 30% 回滚)为经验值,需按自身任务分布与业务代价结构重新标定。gen_ai.* 约定仍在演进,属性名请以官方最新版本为准。

自测:合上资料能说清楚吗?

  1. Agent 评测的四格矩阵是哪两个维度?为什么不能只留 Golden Set 这一格?
参考答案

两维是 离线/在线 × 单步/全轨迹,四格 = 决策单测 / Golden Set 回归 / 步级监控 / 影子灰度。不能只留 Golden Set:它拦不住「护栏没拦但结果就是错」(要靠③步级监控),也拦不住「Golden Set 分布不等于真实分布」导致的口径盲区(要靠④在线轨迹分析);而缺了①决策单测就没有 30 秒级的快速回归。四格拦的东西不重叠。

  1. 「成功率 94%」这个数字可能怎么骗人?正确的口径怎么定?
参考答案

骗法:把超时 / 预算熔断 / 工具中止的样本从分母里剔除(n_success / (n_total - n_timeout - n_aborted)),于是 94% 是在 89% 的样本上算的,真实用户视角只有 83%。正确口径:分母永远是 total;异常各自单独归桶(timeout / aborted_budget / aborted_tool)并显式报出;部分成功按关键步达成比例计分,同时单报完全成功率。加一条「所有桶之和 == total」的断言,防止新增中止原因时样本静默蒸发。

  1. 为什么轨迹评测不能用「与参考轨迹比相似度」?替代方案是什么?
参考答案

因为同一任务的合法路径不唯一——先查日志再查指标、还是反过来,都对。比相似度会把一条更聪明的短路径判为偏离。替代:判关键步里程碑(默认粒度),且里程碑多数能写成规则断言(调过某工具、返回非空、终态含某字段),零 judge 调用、零偏差、可重复;judge 只用在规则写不出来的部分(语气、共情)。步级归因用 first_divergence——从哪一步起后续再无新里程碑达成。

  1. 对比 影子流量 与 灰度发布:成本、能发现的问题、各自盲区?影子最容易出什么事故?
参考答案

影子:成本高(双倍模型费 + 副作用隔离复杂度),能发现真实分布下的成本/延迟/分叉,盲区是拿不到用户反馈与接管率(结果不生效)。灰度:成本中,能发现全部问题含用户反馈,盲区是已在影响真实用户、需要快速回滚能力。影子最容易出的事故:副作用没隔离——影子版的 L1/L2 写操作打到真实系统,一次影子跑产生两笔真实扣款。所有写操作必须打桩或走只读副本。

  1. 灰度回滚为什么不该只看成功率?该看什么?阈值怎么设?
参考答案

成功率是滞后指标且受分母口径影响。优先看:① 人工接管率(对质量下降最敏感、无口径争议、直接对应人力成本,业务方容易达成回滚共识);② 护栏拦截率突增(说明新版在批量触碰不该碰的);③ p95 步数/成本漂移(靠多试凑答案,是质量下降的先行指标)。阈值设成相对旧版基线的偏移(如接管率相对上升 >30%)而非绝对值,因为绝对值随任务分布波动。全自动无 HITL 场景用不了接管率,退回「护栏拦截率 + 成本漂移」组合。

  1. 线上失败的四类归因分别是什么?各自的典型信号与修法归属?
参考答案

① 模型决策错:工具都成功、上下文齐全但选错工具/误读结果 → 改 Prompt/few-shot/换模型,并补进 Golden Set 已知失败类。② 工具执行错:tool span 有错误码或超时、某工具失败率异常 → 修工具本身。③ 上下文缺失:first_divergence 那轮的 llm span 输入缺关键事实,或工具返回被截断截掉关键段 → 修记忆层(压缩水位/pin/截断策略)。④ 护栏误拦:拦截日志 + 用户本意合法 → 按「误拦补救成本」调阈值,L2 不可逆动作宁可多拦、L0 只读宁可少拦。每个失败必须落进且只落进一类,否则修复责任无法分派。

最近更新: 2026/9/10 11:38
Prev
Multi-Agent 协作
Next
AI 与游戏研发周期