Agentic RAG 的评测台:从跑分页到可诊断、可回归的系统

8 阅读12分钟

30 秒判断:当 Agent 能跑、用例和金标准也有了,下一步不是做一个更漂亮的通过率页面,而是建立一条闭环:固定现场 → 批量执行 → 判定 → 诊断 → 与基线比较 → 回归。真正难的不是“跑 10 次算 9 次通过”,而是分清哪次运行生成了什么、使用哪套规则判定、失败为什么发生,以及新结果是否真的比旧基线好。

核心结论:评测台由两层不可变事实组成:ExecutionRun 记录系统实际跑出了什么;EvaluationRevision 记录用哪套规则把它判成了什么。重跑和重判都不能改写历史。

适合谁读:已经有用例集,却仍靠手工表格看结果的人;模型、提示词或工具一改就不知道有没有退化的人;正在被 LLM-as-Judge 的抖动、缺失样本和“平均通过率”困扰的人。

系列位置:本文属于《文档学习问答 Agent 系列》。上一篇是《从 HTML 到可检索、可复现的快照》;本篇解决“怎样系统性地证明这套系统有没有变好”,下一篇从需求与质量属性推导技术选型。

结构速览:§0 评测台不是跑分页;§1 评测、诊断、回归三层职责;§2 第一版为什么端到端优先;§3 执行与判定为什么必须拆开;§4 一次运行怎样开始与封存;§5 N/K、pending 与红线;§6 判定解析;§7 诊断留痕;§8 报告与基线;§9 数据与安全边界;§10 一页速查。

证据标记:📎 既有设计=沿用前文已经确定的判定口径;🤔 推断=由质量属性与可复现要求推出。首版尚未完成整套评测台实现,因此不宣称“评测体系已被验证”。

先交代几个名词

  • ExecutionRun:一次固定现场下的批量执行,只记录系统实际跑出了什么。
  • Attempt:一条用例的一次运行;每条 attempt 从全新会话开始。
  • EvaluationRevision:针对某个 ExecutionRun,使用特定 checker、judge 和聚合规则算出的不可变判定快照。
  • Judgment:对一条判定项的一次结论,可来自程序、LLM 或人工。
  • Baseline:人工接受、用于后续比较的一组“执行+判定”结果。
  • pending:当前证据不足以做 pass/fail 判定,不能偷偷算成任何一边。
  • trace_status:执行现场是否完整,取值为 complete/partial/missing。

0. 评测台不是跑分页

只有“通过率”会制造一种很大的错觉:

上一版 82%
这一版 84%
所以新版本更好

但这条结论至少要经过四道检查:

  1. 两次用例集是同一版吗?
  2. collection 快照和运行策略一致吗?
  3. 有没有缺失 attempt、pending 或红线被平均?
  4. 翻转来自 Agent 生成,还是判官自己变了?

只要有一个答案不成立,82% → 84% 就可能只是换了比较对象。

因此评测台真正的产物不是一张总分表,而是:

  • 每次运行固定了哪些版本;
  • 每条回答对应哪份 trace 和证据;
  • 每个判定项为什么通过;
  • 失败落在哪一层;
  • 与人确认的当前基线相比哪些用例翻转了。

1. 评测、诊断、回归分别回答什么

能力回答的问题不负责什么
评测这次结果是否满足金标准?红线、延迟、成本是多少?不靠印象解释根因
诊断为什么没过?问题在入库、检索、循环、提示词、模型、引用还是判官?不篡改原始 pass/fail
回归和冻结基线相比,哪些结果、红线或成本发生变化?不把单次抖动当能力变化

三者共享 ID 和现场,但必须是不同产物。

如果把诊断意见直接写回判定记录,系统就无法回答“原始判定是什么”;如果每次重判都覆盖旧分数,又无法解释昨天和今天为什么不同。


2. 第一版为什么端到端优先

最容易失控的做法,是第一版同时建三套评测台:

  • 入库侧评测;
  • 检索工具评测;
  • 完整 Agent 评测。

每套都有自己的用例、指标和 UI。最终会发现,三个局部都“有数据”,但没有人能回答用户真实问题是否变好。

所以,评测台首版把评测对象定为端到端 Agent:

用户问题
  → Agent 规划
  → 工具调用
  → 文档检索/读取
  → 证据判断
  → 最终回答

这里的“完整”指评测覆盖从用户问题到最终回答的整条链路,不是指先开发 Agent,也不是要求一次评测解释所有内部组件。

入库与检索工具只补必要的确定性检查,并在端到端失败后用于组件级诊断。它们服务解释,不各自扩张成一个完整评测产品。

这不是否认组件评测。🤔 推断:当端到端结果已经告诉你“某类问题持续失败”,再把 trace 中对应组件抽出来做更细实验,成本更低、目标也更明确。


3. 执行与判定为什么必须拆开

最自然的数据模型往往长这样:

EvalRun
├─ attempts
├─ judgments
└─ reports

它隐含了一个假设:一次评测结果可以永久作为最终事实,判定规则也不会再变。但真正的问题不在这里的“补跑”,而是——判官本身也是需要持续调校的系统组件。

同一个回答,可能在判官 v1 下通过、在修过提示词或边界的 v2 下不通过;也可能因为人工复核而改变结论。此时如果覆盖旧 Judgment,系统就无法区分:

  • Agent 真的退化了;
  • 判官口径变了;
  • 判官自己误判了;
  • 人工最终采用了哪一条结论。

这才是执行与判定必须拆开的主因。

发生的事正确落点原因
未封存时基础设施失败、补跑 attempt同一 ExecutionRun 追加替代 attempt这是执行调度,不是重判
判官升级后重判旧回答新建 EvaluationRevision复用原回答,但使用新 judge 版本
人工推翻或确认某条判定新 Judgment + 新 binding/EvaluationRevision保留原判定,同时明确当前生效结论
聚合或报告规则变化新 EvaluationRevision/报告投影事实不变,计算方式变了

所以,“补跑”本身并不会强制拆层;判官调校、人工复核和判定规则演化才会。所有结果都覆盖到同一个可变 EvalRun 上,失去的不是一条 attempt,而是判定变化的原因。

因此拆成两层:

ExecutionRun
└─ Attempt[]

EvaluationRevision
├─ judge / checker / aggregation versions
├─ Judgment[]
├─ effective_judgment_bindings[]
├─ case aggregates
└─ report projection

首版可以不做完整的“判官校准工作台”,但数据模型必须允许重判。否则不是把功能延后,而是把未来判官升级的路提前堵死。

3.1 重跑和重判是两件事

  • 重跑:重新执行 Agent,产生新的 attempt。
  • 重判:不重跑 Agent,只对同一批回答使用新 checker/judge。

重跑创建新的执行成果;重判创建新的 EvaluationRevision。两者都不修改旧记录。

3.2 用例、金标准和判定项也要不可变

一次 ExecutionRun 应引用:

  • EvalSuiteRevision
  • EvalCaseRevision[]
  • CriterionRevision[]
  • 精确模型标识与参数
  • collection 快照
  • prompt、Agent 图、工具契约与预算策略

而不是引用“当前最新版用例”。

否则今天改一句金标准,昨天的失败会突然变成另一种解释。


4. 一次运行怎样开始与封存

4.1 启动前先做现场预检

预检至少检查:

  • suite/case/criterion revision 是否存在;
  • collection 快照是否可读;
  • 目标文档、section/block 是否都存在;
  • checker、judge、聚合规则版本是否可解析;
  • 模型配置、预算和并发策略是否合法;
  • 评测数据根与正常产品数据是否隔离。

任何一项失败都返回 invalid_plan,不要跑到一半才发现某条用例引用了不存在的文档。

4.2 每次 attempt 都是新会话

同一用例重复 N 次,不是把上一次回答留在 history 里再问一遍。每次 attempt 都从全新 Agent 会话开始,只携带:

  • 本条用例输入;
  • 固定 collection 快照;
  • 固定模型和 Agent 配置;
  • 允许的运行策略。

否则 N 次结果不再独立,测到的是“对话累积效果”,不是同配置稳定性。

4.3 可追加,随后封存

ExecutionRun 在未封存时,允许因基础设施失败追加替代 attempt。

达到有效 N 次,或用户主动结束后执行 run 被封存:

  • 输入不可改;
  • 执行配置不可改;
  • attempt 集合不可再追加;
  • 后续判定只读这份现场。

如果要继续一个已封存但残缺的运行,创建带 resume_of 关系的新 run,不把新结果混进旧历史。


5. N/K、pending 与红线

沿用金标准篇和需求定义中的口径:

  • 默认 N=10、K=9;
  • N/K 属于用例 revision,不在实际跑完后按结果修改;
  • 每条用例至少 K 次满足金标准,才判用例通过;
  • 任何一次红线违规,该用例直接失败。

但实际运行会遇到三类“不是简单 fail”的情况:

情况计数口径
基础设施失败保留 attempt;不计入有效 N;可在预算内补跑
回答已生成,但判官 pending计入 N;不算通过
进程崩溃、结果未知标记 abandoned/outcome_unknown;不自动重发

为什么崩溃不能自动重发?云端可能已经处理并计费。系统应先检查或显式创建替代 attempt,并留下替代关系。


6. 判定解析:保留投票,也保留“当前谁生效”

同一条 attempt + criterion 可能先后出现:

程序 checker
→ LLM judge
→ 人工复核

不能让“最后写入覆盖”,因为数据库写入时序不等于判定权威。

更合理的是:

  • 所有 Judgment 全部保留;
  • EvaluationRevision 显式记录当前生效的 judgment ID;
  • 人工裁决通过替换 binding 生效;
  • 原始结论仍保留 R 的三态和 X 的三态;
  • 聚合规则单独版本化。

语义判定首版每个 attempt、每个 criterion 只跑一次。失败或 pending 时可以人工复核,但不能声称“判官抖动已经被系统测量”。没有重复判定,就没有判定侧抖动数据。


7. 诊断:自动归因只给建议,人确认才算结论

诊断不是再让模型写一段“失败原因”。它要沿证据回指现场。

典型失败层包括:

失败层常见证据
基础设施超时、限流、5xx、连接失败
入库/collection失败文档、block 对账、partial 快照
检索排名、召回块、范围、空结果原因
Agent 循环轮次、工具选择、停止原因、预算
提示词/协议实际渲染提示词、Action/Observation
模型原始回答、模型版本、参数
引用block 存在性、归属与支持关系
判官输入、版本、人工复核

自动系统生成 DiagnosisSuggestion;人工确认后才形成 DiagnosisConclusion。没有完整 trace 时,只能标记“证据不足”,不能给确定性根因。


8. 报告与基线

8.1 报告是可重建投影

事实源是 ExecutionRun、Attempt、Judgment、聚合规则、诊断结论和人工复核记录。

报告可以从这些对象重新计算。换一种展示、重判或补人工结论时,不应改写历史报告正文;生成新的 revision。

8.2 基线必须人工设置

这里的“人工”限定的是确认动作,不是判定生产者:基线是一次已封存的 ExecutionRun 加上一份完整的 EvaluationRevision,可以由程序 checker、LLM judge 和人工复核共同产生;最后由人确认“这次结果可以代表当前基准”。

只有同时满足以下条件的组合才能设为基线:

  • ExecutionRun 已封存;
  • 所有必跑用例达到有效 N;
  • 判定完成;
  • 没有 pending;
  • 没有基础设施缺口。

每个互不重叠的评测范围只保留一个当前基线,历史基线可留档。

8.3 不是所有 run 都能直接比

比较前至少对齐:

  • suite/case revision;
  • collection 快照;
  • 运行策略;
  • 聚合规则。

模型、prompt、Agent 图或工具版本可以作为被比较变量,但不能连同现场一起变化。不满足条件就标“跨场比较”。


9. 数据与运行边界

首版评测台是开发工具,不是用户产品页面:

  • 独立本地服务与独立数据根;
  • 只监听 127.0.0.1;
  • 不做 CLI、局域网或远程访问;
  • 数据库存放 suite、case、criterion、execution、evaluation 与 baseline;
  • 评测 trace 独立保存;
  • 产品 trace 与评测记录通过 ID 关联,不复制正文;
  • 失败、pending 和基线关联项保留完整 trace;
  • 普通通过项只保留摘要。

评测元数据也必须隔离:

  • 金标准、目标文档、干扰文档和预期引用,不能进入 Agent 提示词;
  • JudgeInput 使用白名单投影,不能看到历史判定、通过率、基线和自动诊断;
  • 自动归因不能进入正式统计。

10. 一页速查

闭环:固定现场 → 执行 → 封存 → 判定 → 诊断 → 基线比较。

两层事实:ExecutionRun 记录“跑出了什么”;EvaluationRevision 记录“按哪套规则判成了什么”。

默认运行:N=10、K=9;任何一次红线违规都直接失败。

有效样本:基础设施失败不算有效 N;pending 计入 N 但不通过;崩溃未知不自动重发。

诊断:自动建议,人工结论;trace 不完整时只报证据不足。

基线:只接受已封存、完整执行、完整判定的组合;跨场必须显式标记。

一句话:评测台的价值不是给出一个分数,而是让每次分数变化都能回到现场、规则和版本。


上一篇:《从 HTML 到可检索、可复现的快照》

下一篇预告:《文档问答 Agent 技术选型:从部署约束推到 Tauri、Vue、Python 与 LangGraph》

完整设计记录:0059 评测台设计(HTML 源文件)


前置阅读:

  1. 《Agent 开发为什么要测试驱动升级版》
  2. 《需求定义四步》
  3. 《金标准:什么算对、怎么判》
  4. 《由检索需求反推存储》
  5. 《Agentic RAG 检索侧功能设计》
  6. 《Agentic RAG 能检索还不够:从质量属性反推错误、预算、Trace 与版本管理》
  7. 《从 HTML 到可检索、可复现的快照》