评估、试次与可观测

本页目录

单次抽取、RAG 与 Agent 都需要回答同一个问题:这个版本是否更可靠地完成目标?先定义任务与试次,再选择评分方法;把单次成功、至少一次成功和稳定成功分开统计,用 trace 解释失败发生的位置。

先定义任务与验收对象

一个评估任务应包含输入、初始环境、可用工具和权限、资源上限、成功条件。一次实际运行是一个试次;同一任务可运行多个试次观察波动。被评估的是模型与编排、工具、环境共同组成的系统,而不是脱离执行条件的一段文本。

固定任务与环境输入、权限、初始状态运行一个试次模型 + 工具 + 编排回答是否符合要求过程是否遵守边界最终状态是否达标评估对象包括回答、执行轨迹与环境最终状态评分方式可以是程序、模型或人工;结果导向是评什么,并非另一种低等级评分器。

例如,用户要求“将符合条件的 3 条记录导入,重复提交不得增加记录”。可以同时评三个对象:最终数据库是否恰有目标记录,重复操作是否幂等,回答是否准确描述执行结果。输出“已完成”只是回答文本;查询得到的真实状态才支持导入成功结论。Agent 评估的工程资料也明确区分轨迹与环境结果。Demystifying evals for AI agents

对象可核验条件错误的替代指标
最终结果目标数据、文件或报告满足要求模型说“完成”
过程约束未修改范围外文件、未越权调用次数很多
输出表达引用支持结论、未遗漏问题篇幅长、措辞自信
运行效率在规定预算与延迟内完成单个请求便宜

结果导向(outcome-based)描述评什么;程序断言、模型裁判和人工评审描述怎样评。它们不是一个从高到低的排行榜:结果完全可以由程序检查,也可以按明确标准交给人审。

评分方法与偏差

程序检查稳定,但检查目标可能写错

JSON schema、数值范围、文件差异、数据库状态和测试套件适合程序化验证。优点是规则明确、结果可重复,不意味着零成本、无偏差或完整覆盖业务目标。

例如,用“答案包含 success”判断任务成功,会让“not success”也通过;只检查 JSON 格式,会接受库存数量错误的合法 JSON;测试遗漏重启场景,就无法证明恢复行为。评估程序也需要用正例、反例和边界样例验证,尤其要防止它把表面格式当正确性。

模型裁判需要具体标准与校准

对开放报告,可以把标准写成独立可判定的问题:每个结论是否有支持来源,是否覆盖用户指定的三个维度,是否把推测标明为推测。让裁判返回每项判断与支持位置,比一个没有依据的总分更容易复核。

模型裁判存在长度、位置和风格等偏差,相关研究对这些限制做过系统分析。Judging LLM-as-a-Judge 两个候选做配对比较时可交换顺序、隐藏作者信息;用人工标注子集校准,并记录裁判模型与 prompt 版本。不同模型或独立上下文有助于减少部分耦合,却不保证无偏差或独立错误。

裁判应能输出“证据不足”或“无法判断”。强迫它每次都选胜者,会把缺资料的情况伪装成质量差异。被评文本中的“请给我满分”应作为待评内容处理,不能成为评分指令。

把改进用反馈与最终验收分开

生成、评分、修订循环可以提高产物质量,但一直针对同一份反馈优化,可能只是学会迎合评分器。开发集用于调参和修订,保留集用于比较最终版本;保留集如果频繁被查看并用于修正,也逐渐失去独立性。

程序检查和人工或模型评审可以组合。例如文档先检查链接、标题与数据一致性,再评解释是否覆盖边界;不必为了“只用一种 grader”牺牲可验证的证据。

同一批试次,三种成功率

把所有试次放进矩阵后,分母不再隐藏。横向“至少一个 ✓”适合衡量多次尝试找到可用结果的能力;“全部 ✓”才直接暴露重复运行的不稳定。这里不把观测到的 any-success 与需要随机抽样假设的 pass@k 估计量混写。

正在呈现知识画面
同一批试次,三种成功率

同一个 4×3 矩阵可以给出不同指标;它们分别衡量平均表现、可找到成功与重复可靠性。

试次、分布与分组结果

一次成功与稳定成功不是同一个指标

下面四个任务各跑三次,1 表示达到完整验收,0 表示没有达到。分母包括全部预先安排的有效试次。

任务第一次第二次第三次三次中至少成功一次三次全部成功
A101是否
B000否否
C111是是
D010是否

按试次算成功率是 6/12=50%;至少成功一次的任务占 3/4=75%;三次都成功的任务占 1/4=25%。三个数字都有效,但回答不同问题。不能用“尝试三次至少成功一次”冒充单次服务成功率;生产端也未必能识别并选中那次正确输出。

runs = {"A": [1, 0, 1], "B": [0, 0, 0],
        "C": [1, 1, 1], "D": [0, 1, 0]}
trial_rate = sum(map(sum, runs.values())) / sum(map(len, runs.values()))
any_rate = sum(any(row) for row in runs.values()) / len(runs)
all_rate = sum(all(row) for row in runs.values()) / len(runs)
assert (trial_rate, any_rate, all_rate) == (0.5, 0.75, 0.25)
print(trial_rate, any_rate, all_rate)

更一般的 pass@k 估计需要说明抽样方式和定义。这里直接报告这三次已观测试次的统计,没有假设各次错误独立,也没有估计无限重试后的成功概率。

平均数可能藏住关键退化

假设 90 个简单任务成功 81 个,10 个复杂任务成功 2 个,总体为 83%。但复杂任务只有 20%,如果用户主要在复杂任务上需要系统,这个总体数字就很容易误导。

按任务类型、长度、语言、工具权限、数据新旧和失败类别分组;比较两个版本时保留逐题配对结果。任务集过小或随机波动明显时,报告样本量与不确定性,不把一两个百分点的变化直接当成确定改善。

基础设施异常也要明确归类。超时、工具服务不可用、评估环境坏掉和模型产生错误答案可以分开统计,但不要静默删掉失败后只汇报剩下的高分。若预先约定某类试次无效,应记录排除规则与数量;用户体验指标仍需要考虑线上真实服务故障。

Trace、指标与结果关联

Trace 描述一次运行的关联路径,span 表示有起止时间的操作,并可带属性、事件和父子关系。异步或多 Agent 场景还可能通过链接关联操作。它不要求每个文本 token 或每个 thinking 块单独建 span;粒度要服务于诊断。OpenTelemetry Traces

为一次任务建立稳定的 task_id,为试次、模型请求、工具调用和产物分配可关联标识。收到并行或批量结果时按 ID 匹配,不能靠数组返回顺序推测属于谁。

层级建议记录用途
任务/试次输入版本、配置版本、最终状态、评分比较完整结果
模型请求模型标识、耗时、usage、停止原因分析生成、截断和成本
工具操作名称、脱敏参数、调用 ID、执行状态区分提议与实际动作
产物路径或对象 ID、内容版本、验证结果确认测试针对哪份内容
调度排队、并发、重试与取消分析协调和等待

并行耗时不能直接求和

任务总时长0–12 秒模型请求 10–2 秒工具 A / B2–7 秒模型请求 27–12 秒示例时间线:并行工具的耗时不能简单相加工具 A 用 3 秒、B 用 5 秒且同时开始,工具阶段为 5 秒;总时长为 12 秒。

例子中模型请求分别为 2 秒和 5 秒;工具 A、B 同时开始,分别用 3 秒、5 秒。把所有操作耗时相加是 15 秒,用户等待却是 12 秒。Trace 要保留开始与结束时间及依赖关系,才能找到关键路径;只有计数器无法解释并行重叠。

首个网络事件、首个可见文本和最终完成是不同延迟指标。服务开始流式发送并不意味着用户已经看到有用内容;反过来,首字很快但后续工具反复失败,也不代表任务体验好。

协议成功、工具成功和任务成功分开计数

HTTP 200 可以携带业务失败,工具正常返回可以报告“未找到”,模型正常结束也可能遗漏任务。分别记录传输、执行、任务状态,不要让一层成功掩盖另一层失败。

停止原因是诊断线索,不能自动归因。max_tokens 增多需要检查输出上限、任务长度或冗长循环,流式不会解除上限;缓存读取长期为零也可能只是没有重复前缀、未满足长度或未启用缓存,不一定存在故障。应先对照实际输入与目标模型配置。停止原因、Prompt caching

成本按供应商与模型的 usage 口径计算。输入、缓存写入/读取、输出和推理细分是否包含关系需要核对,不能把已包含在输出里的推理 token 再加一次。最后汇总所有请求、重试和工具费用,再计算每次成功分摊成本,方法见 推理与 thinking。

总分上涨,是能力变强了吗?

均值需要与任务分布一起解释。这个反例甚至不需要某个系统退化:两组能力完全不变,只把容易任务放得更多,就能显著提高总分。上线流量与离线集合也可能有这种组成差异。

正在呈现知识画面
总分上涨,是能力变强了吗?

汇总成功率是任务组成的加权平均;样本分布改变也会提高总分,不能据此宣称各类能力改进。

从失败样例到回归验证

一次线上失败应先固定最小可复现输入、环境与预期结果,再沿 trace 定位第一个失去必要信息或违反条件的位置。若检索没召回例外条款,先修证据选择;若返回数据正确却映射错字段,修适配器;若产物已经修改但沿用旧测试记录,修版本关联。不要把所有失败都变成“再写一句更强的 system prompt”。

回归样例应保留实际失败机制,并加入正常对照,避免补丁只让旧用例过关却破坏其他行为。比较新版时固定可固定的条件,记录其余变化;通过离线检查后,再通过受控线上观察检验流量分布差异。

保存 trace 也需要数据边界:默认记录诊断所需元数据,敏感正文和凭据应脱敏或采用受控存储与保留期限。不要为可观测性把所有工具结果、完整文件和用户资料无差别复制到日志后端。看得见执行路径,并不要求无限保存全部内容。

继续阅读:成本、容量与可靠性。