已发布资料基础官方资料 + 个人实践
·14 分钟AI Agent 工程进阶
文章/AI 与智能体

Agent Evals:用 Task、Trial 与 Grader 证明版本真的变好

AI Agent 工程进阶第 2 篇:在同一个 Agent Reliability Lab 中建立 20 个任务、重复 Trial、五类确定性 Grader、失败台账和发布门禁,用实际代码比较 baseline-v1 与 candidate-v2,而不是凭感觉判断新版本更聪明。

文章目录
  1. 一分钟概览
  2. 1. 为什么普通单元测试还不够
  3. 2. 先把六个词分清
  4. 3. 评什么:Outcome 优先,Trace 用来解释
  5. 4. 从系统契约长出第一版任务集
  6. 5. Grader 不是越智能越好
  7. 6. 公平比较:一次只改一个主要变量
  8. 7. 运行 Lab:从 Task 到报告
  9. 8. 结果:60% 到 95%,但结论要收窄
  10. 9. 最有价值的一次失败,来自 Eval 自己
  11. Bug 1:来源 Grader 拿不到章节名
  12. Bug 2:禁用词误伤否定句
  13. 10. 为什么要重复 Trial
  14. 11. 把发布条件写成代码
  15. 12. 什么时候引入 Model Grader
  16. 13. 如何映射到现有工具
  17. 14. 把自己的 Agent 接入 Harness
  18. 15. 45 分钟跟做练习
  19. 第 0-10 分钟:写 5 个真实 Task
  20. 第 10-20 分钟:为每个 Task 写成功标准
  21. 第 20-30 分钟:先写确定性 Grader
  22. 第 30-40 分钟:重复运行并读失败记录
  23. 第 40-45 分钟:写第一条发布门禁
  24. 16. 收藏清单
  25. 17. 这篇真正建立了什么
  26. 参考资料
阅读提要

AI Agent 工程进阶第 2 篇:在同一个 Agent Reliability Lab 中建立 20 个任务、重复 Trial、五类确定性 Grader、失败台账和发布门禁,用实际代码比较 baseline-v1 与 candidate-v2,而不是凭感觉判断新版本更聪明。

#Agent#Agent Engineering#Evals#Grader#测试

这是《AI Agent 工程进阶:从 Demo 到可靠系统》的第 2 篇。

上一篇先定义了系统契约,并用一个确定性检索脚本建立非 Agent 基线。它能回答 4 个手册问题,也能拒答 1 个资料外问题。但只要准备修改检索、Context、模型、Prompt 或工具,一个更难的问题就会出现:

版本 B 看起来比版本 A 更聪明,怎样证明它真的更好,而且没有在别处退步?

“我试了几个问题,回答挺好”无法回答这件事。单次成功可能是运气;总分上升可能掩盖安全回归;最终文字正确,也不代表工具调用、真实状态和成本正确。

这篇继续使用同一个公开工程 Agent Reliability Lab,把评测真正写进代码。读完可以带走:

text
20 个版本化 Task
  × 每题 3 次 Trial
  × 5 类确定性 Grader
  + baseline / candidate 对照报告
  + 失败 Trial 台账
  + 可阻止发布的 release gate
项目说明
内容类型AI Agent 工程教程与可复现实验
适合读者已有 Agent Demo,希望比较 Prompt、模型、Context 或 Harness 版本的开发者
阅读时间速读约 12 分钟,完整阅读约 18-24 分钟
跟做时间45-60 分钟
实验环境Python 3.10+,零第三方依赖,不需要 API Key
代码检查点ce601a1
可带走产物Task Schema、Eval Harness、Grader、对照报告、失败台账、发布门禁
资料核对日期2026-07-28

时效与范围

本文用本地、厂商中立的最小实现讲清评测结构,不把教程绑定到某一个 Dashboard。OpenAI 当前的 Agent Evals 指南建议在调试阶段先读 Trace,明确成功标准后再转向 Dataset 与可重复 Eval Run;同时,Evaluation best practices页面已经标注旧 Evals 平台的弃用时间表。实际接入托管产品前,应重新核对当时的官方入口。

本文的 20 个任务只是一组教程任务,足以演示工程结构,不构成生产样本量或统计显著性证明。

一分钟概览

如果只保存这篇文章的结论,可以记住下面八句:

  1. Task 是有输入和成功标准的测试;Trial 是对 Task 的一次完整尝试。
  2. 同一个 Task 要重复运行,因为 Agent 的输出、工具选择和路径可能变化。
  3. 先验证 Outcome,再看 Trace;“说已完成”不等于真实世界已经完成。
  4. 能用代码判断的结果,优先使用确定性 Grader;开放质量再用模型评分。
  5. Capability Eval 寻找能力上限,Regression Eval 保护已经会做的事情。
  6. 数据集必须同时包含“应该做”和“不应该做”,否则系统会学会一味触发。
  7. 总分上升不能抵消安全回归、错误行动或跨 Trial 波动。
  8. 失败时先审查 Task、Grader 和环境是否公平,再修改 Agent。

图 1:Agent Eval 的六个组成部分图 1:Agent Eval 的六个组成部分

图 1:一个 Eval 不是“Prompt + 分数”。Task、Trial、Trace、Outcome、Grader 与汇总报告共同构成证据链。移动端可打开原始 SVG查看。

1. 为什么普通单元测试还不够

传统函数通常可以写成:

text
固定输入 -> 确定输出

Agent 更像:

text
输入 + 环境 + 上下文
  -> 多轮模型决策
  -> 工具调用
  -> 状态变化
  -> 最终回复

这里至少多出四类不确定性:

  • 同样输入可能选择不同工具;
  • 前一步的小偏差会传递到后续步骤;
  • 外部工具、网络和状态可能发生变化;
  • 最终回复可以正确描述一件根本没有发生的事。

例如,一个预订 Agent 最后说“机票已经订好”,真正应该检查的是数据库里是否存在符合约束的订单。一个代码 Agent 说“测试通过”,真正应该检查的是退出码、测试报告和工作区 diff。

所以,单元测试没有失效。相反,它应该成为 Agent Eval 中最可靠的一类 Grader。变化在于:我们还要测试环境、行为路径、真实终态、重复运行和系统级约束。

2. 先把六个词分清

Anthropic 的 Agent Evals 工程文章给出了一组很实用的定义。结合本项目,可以整理成下面这张表:

概念本文定义Lab 中的对应物
Task一次测试的问题、环境和成功标准datasets/eval-tasks.jsonl 中的一行
Trial某个系统对一个 Task 的一次完整尝试task_id + system_id + trial_index
Grader检查某一维表现的评分逻辑statusrequired_termssource
Trace / Transcript一次 Trial 的过程记录检索、阈值门、回答或拒答步骤
OutcomeTrial 结束后真实世界的状态本篇先用回答状态与来源模拟,后续会接文件和工具状态
Eval Harness执行、隔离、记录、评分和汇总的基础设施agent_lab/evals.pyeval_reporting.py

其中最容易混淆的是 Task 和 Trial。

假设任务是:

text
Task: 资料不足时,知识库 Agent 应明确拒答。

运行三次,就会产生三个 Trial。它们可能分别是:

text
Trial 1: 拒答
Trial 2: 猜了一个答案
Trial 3: 拒答

这不是“一个任务得了 66.7 分”那么简单。对内部制度、安全操作或生产写入而言,第二次误答本身就可能让版本不能发布。

3. 评什么:Outcome 优先,Trace 用来解释

我会把 Agent 的评测对象分为五层:

要回答的问题例子
最终结果输出是否满足任务回答覆盖了要求的信息
真实终态外部世界是否真的改变数据库订单存在、文件内容正确
行为边界是否执行了禁止动作未联网、未泄露密钥、写入前有批准
过程质量工具和路径是否合理选对工具、参数正确、没有无限循环
运行代价是否能在预算内完成延迟、Token、工具次数、人工接管率

优先级不是“Trace 越细越好”,而是:

text
先确认 Outcome
  -> 再确认关键边界
  -> 最后用 Trace 解释为什么成功或失败

这也避免另一种常见误区:把“严格按我设想的步骤走”当成正确。Agent 可能找到一条同样安全、甚至更短的有效路径。除非顺序本身属于合规要求,否则不要把每个中间动作都写死。

本篇 Lab 检查 retrieve -> threshold_gate -> answer/abstain,是因为这是当前最小系统的结构契约。等系统拥有更多有效路径后,Trace Grader 也要从“固定顺序”升级为“必要事件和禁止事件”。

本篇的 Outcome 仍是代理指标

这个只读 Lab 没有真的修改外部世界,因此 statusanswersource 只能证明“程序返回了什么”,不能证明数据库、文件、订单或工单已经处于正确状态。评测写入型 Agent 时,至少要在运行前后读取真实环境,把数据库行、文件 diff、API 回读结果或审批记录作为 Outcome;最终回复只能作为另一项输出质量检查。

4. 从系统契约长出第一版任务集

任务不应该从网上抄一组“常见问题”,而应该从四个地方来:

  1. 产品合同里明确承诺的行为;
  2. 开发时每次手工检查的案例;
  3. 生产日志、工单与用户投诉中的真实失败;
  4. 高风险边界和容易被绕过的反例。

Anthropic 建议早期可以从 20-50 个来自真实失败或手工检查的简单任务起步,而不是等待几百条“完美数据”。OpenAI 的评测最佳实践同样强调任务特定、持续扩充,并反对只凭感觉判断。

本篇先写 20 个 Task,分成两组:

Suite数量目的
regression8保护基线已经会做的直接问题和拒答边界
capability12测试缩写、同义表达和更困难的边界问题

当前 Lab 没有生产用户流量,因此这 20 条主要从系统契约、手工检查和边界反例派生。它们能验证教程代码,却不能代表真实请求分布。上线后的正确动作是把脱敏后的失败、工单和人工接管案例持续补入数据集,而不是继续批量生成看起来丰富的同义句。

一个 Task 的真实结构如下:

json
{
  "id": "cap-003",
  "suite": "capability",
  "risk": "safety",
  "question": "处理 PII 时,权限、日志和 secret 有什么要求?",
  "expected_status": "answered",
  "required_terms": ["最小权限", "脱敏", "密钥"],
  "forbidden_terms": ["可以进入普通日志"],
  "expected_source": "敏感数据",
  "expected_trace_steps": ["retrieve", "threshold_gate", "answer"]
}

这里有三个设计点。

第一,成功标准和输入放在同一条版本化记录中,避免 Grader 暗中检查 Task 没有声明的东西。

第二,同时测试应该回答与应该拒答的问题。只测“能不能答”,最容易优化出一个什么都敢答的系统。

第三,risk 不直接增加分数,而是让发布门禁可以声明:“安全任务的回归不能被其他任务的改善抵消。”

5. Grader 不是越智能越好

常见 Grader 可以分成三类:

类型适合检查优点局限
Code Grader状态、Schema、测试、工具参数、数据库、文件快、便宜、可复现容易对有效变体过于严格
Model Grader语义完整性、Groundedness、交流质量、开放任务能处理多解与自然语言有成本和波动,需要校准
Human ReviewGold Set、争议样本、业务判断、模型评分校准最接近真实责任判断慢且昂贵

Inspect 也采用 Dataset、Solver、Scorer 的可组合结构,并同时提供文本匹配、模型评分和自定义 Scorer。不同框架名字略有区别,工程问题是相同的:应该用哪一把尺测哪一种结果?

图 2:Agent Grader 的选择顺序图 2:Agent Grader 的选择顺序

图 2:优先用代码检查真实终态和硬约束;开放质量再引入模型评分,并用人工样本持续校准。移动端可打开原始 SVG查看。

本篇故意只用确定性 Grader:

text
status           是否回答或正确拒答
required_terms   是否覆盖任务要求
forbidden_terms  是否出现明确违规表述
source           是否来自预期手册章节
trace            是否经过必要步骤

这不是因为关键词匹配足够强,而是因为它便于先验证 Eval Harness 自己。评分基础设施还没跑通时就加 LLM Judge,会同时引入被测系统和评分系统两份不确定性。

6. 公平比较:一次只改一个主要变量

这次比较两个零模型、零 API Key 的系统:

text
baseline-v1
  确定性中文 bigram 检索 + 固定阈值

candidate-v2
  baseline-v1 + 查询别名归一化

候选版只增加一项能力:把真实提问里的表达映射到手册用词,例如:

python
QUERY_ALIASES = {
    "429": "持续限流",
    "上线": "发布",
    "人审": "人工批准",
    "PII": "敏感数据",
    "access token": "密钥",
    "知识不够": "资料不足",
}

两边保持相同:

  • 同一个知识手册;
  • 同一组 20 个 Task;
  • 同一个 0.28 检索阈值;
  • 同样的 Grader;
  • 每题同样运行 3 次;
  • 相同的报告与发布门禁。

这样,改善才能合理归因于查询归一化。若同时换模型、Prompt、Chunk、阈值和 Grader,即使分数提高,也很难知道哪一项有用。

7. 运行 Lab:从 Task 到报告

进入代码检查点:

bash
git clone https://github.com/RalfNick/ai-agent-learn.git
cd ai-agent-learn
git checkout ce601a1
cd phase-7-agent-engineering/agent-reliability-lab

运行评测:

bash
python run_lab.py eval

再运行 Harness 自己的测试:

bash
python -m unittest discover -s tests -v

在该代码检查点应看到 Ran 14 testsOK。这 14 个测试覆盖任务加载、版本对照、失败报告和发布门禁等路径;如果测试失败,应先修 Eval Harness,再解释 Agent 分数。

默认执行:

text
20 Task
  × 2 System
  × 3 Trial
  = 120 条 Trial 记录

CLI 会原样输出嵌套 JSON,并在 reports/local/ 写入四个文件。为便于阅读,下面是从真实 JSON 提取的关键结果,不是终端原样排版:

text
baseline task pass rate:  60%
candidate task pass rate: 95%
improvements:              7
regressions:               0
gate_passed:               true
process exit code:         0
文件用途
comparison.json给 CI 或其他程序读取的汇总
comparison.md给人看的版本对照与 Gate
failures.md每个失败 Trial 的评分器与状态
trials.jsonl120 次尝试的完整结构化记录

本地目录默认被 Git 忽略,避免每次运行的机器延迟污染工作区。仓库中的 reports/保留代码检查点对应的参考证据。

8. 结果:60% 到 95%,但结论要收窄

这次固定实验得到:

指标baseline-v1candidate-v2
Trial 通过率60%95%
严格 Task 通过率60%95%
未知问题正确拒答率100%100%
未知问题误答率0%0%
输出稳定率100%100%
通过全部 Trial 的 Task12 / 2019 / 20

所谓“严格 Task 通过”是:

text
同一个 Task 的 3 次 Trial 必须全部通过

它在直觉上接近一致性导向的 pass^k,但本文只汇报观察到的三次结果,不把 20 个教程任务包装成统计概率估计。

本文报告中的三个列表按下面的确定性规则生成:

text
improvement = baseline 严格 Task 失败,candidate 严格 Task 通过
regression  = baseline 严格 Task 通过,candidate 严格 Task 失败
unstable    = 同一 Task 的多次 Trial 出现不同 status、answer 或 source

因此,improvement 不是“某个评分略有上升”,而是候选版把一个三次均通过的严格 Task 从失败变成通过;unstable 也不等于措辞有任何微小变化都危险,它只是当前 Lab 采用的保守指纹。生产项目应根据任务语义决定哪些字段必须稳定。

图 3:Agent Reliability Lab 的版本对照结果图 3:Agent Reliability Lab 的版本对照结果

图 3:候选版改善了 7 个同义表达任务,没有破坏原有任务或拒答边界;cap-008 仍然失败,因此 95% 不能写成“已经可靠”。移动端可打开原始 SVG查看。

这组数据支持的结论是:

在当前 20 个任务、固定手册和固定阈值下,查询别名归一化相对基线带来了 7 个可复现改善,未观察到回归。

它不支持:

text
candidate-v2 已经适合生产
candidate-v2 对所有内部问答更好
95% 就代表用户有 95% 概率满意
换成任意模型也会得到相同提升

剩下的 cap-008 是“知识不够时,应该给提问者什么下一步?”。归一化后得分仍低于阈值,三个 Trial 都拒答。它没有被总分藏起来,而是明确进入下一轮改进列表。

9. 最有价值的一次失败,来自 Eval 自己

第一版 Eval Harness 跑出来时,两个系统都只有 40%,看起来很差。检查失败 Trial 后,我发现不是系统突然退化,而是评测写错了。

Bug 1:来源 Grader 拿不到章节名

知识解析器把 Markdown 标题和正文按空行拆开了。检索答案正确,但 source=None,于是来源 Grader 全部判错。

修复方式不是删掉来源 Grader,而是让 Eval Harness 按二级标题解析完整章节。

Bug 2:禁用词误伤否定句

最初我把 无限重试 设为禁用词,但手册的正确答案是:

text
不得无限重试

简单子串匹配仍会命中“无限重试”,把安全答案判成违规。后来任务改为检查更完整的危险表述:

text
可以无限重试

这件事说明两个问题:

  1. Code Grader 很稳定,但稳定地写错仍然是错;
  2. 失败报告不能只给一个红色分数,必须保留输入、输出、来源和每个 Grader 的理由。

Anthropic 的文章也强调:失败应该让人觉得公平。若任务含糊、环境不稳定或 Grader 拒绝有效解,就应先修评测。Eval 不是裁判席上的真理,它也是需要测试和维护的软件。

10. 为什么要重复 Trial

当前两个正式系统是确定性的,所以三次输出完全一致。重复运行仍然有价值,因为它先固定了 Harness 接口:未来接入模型或外部工具时,不必重写 Task、Grader 和报告。

为了验证门禁确实能抓住波动,Lab 还提供一个明确标注的故障模拟器:

bash
python run_lab.py eval --candidate flaky-simulator --output reports/flaky-demo

这一行可直接在 PowerShell、Bash 和常见终端中运行。它故意让部分 capability 任务在偶数 Trial 拒答。结果是:

指标baseline-v1flaky-simulator
Trial 通过率60%83.3%
严格 Task 通过率60%60%
输出稳定率100%65%
不稳定 Task07

只看 83.3%,会觉得候选版明显变好;但它没有新增一个“三次都可靠通过”的任务,反而让 7 个任务的结果随运行变化。

图 4:平均分上升也可能被发布门禁拒绝图 4:平均分上升也可能被发布门禁拒绝

图 4:总分不能抵消一致性问题。故障模拟命令按预期退出 1,可直接作为本地或 CI 门禁。移动端可打开原始 SVG查看。

对于“多试几次,只要一次成功就行”的探索工具,可以关注 pass@k;对于用户每次都期待可靠结果的服务,更需要关注一致性。具体选哪种,不由排行榜决定,而由产品失败成本决定。

11. 把发布条件写成代码

本篇的发布门禁不是单一分数:

python
gate_checks = {
    "candidate_not_worse_overall":
        candidate.trial_pass_rate >= baseline.trial_pass_rate,
    "at_least_one_measured_improvement":
        bool(improvements),
    "no_task_regressions":
        not regressions,
    "no_safety_regressions":
        not safety_regressions,
    "no_false_answer_increase":
        candidate.false_answer_rate <= baseline.false_answer_rate,
    "candidate_trials_are_stable":
        not unstable_candidate_tasks,
}

它表达了一个重要工程判断:

某些指标可以权衡,某些边界不能被平均分抵消。

真实项目还可以加入:

  • 工具参数错误不能增加;
  • 未经批准的写操作必须为 0;
  • p95 延迟不得超过预算;
  • 单任务成本不得超过上限;
  • 人工接管率不能无解释地上升;
  • 高风险 Slice 必须全部通过;
  • Model Grader 与人工 Gold Set 的一致率达到门槛。

门禁通过也不是“自动全量发布”。它只表示候选版本获得进入灰度、人工验收或下一阶段验证的资格。

12. 什么时候引入 Model Grader

关键词和规则适合本篇的结构验证,但遇到下面任务就会很快不够:

  • 研究报告是否有关键遗漏;
  • 回答是否真正被来源支持;
  • 代码改动是否过度设计;
  • 对话是否既解决问题又保持合适语气;
  • 两个都正确的答案,哪一个更清楚。

这时可以引入 Model Grader,但建议遵守五条规则:

  1. 一个 Rubric 只评一个清晰维度;
  2. 尽量做分类、打分或 Pairwise,而不是开放式点评;
  3. 提供 Unknown,证据不足时不要强迫评分;
  4. 用领域专家标注的 Gold Set 校准;
  5. 定期抽查 Grader 与人工判断分歧最大的样本。

OpenAI 的评测最佳实践建议把自动指标与人工判断结合;Anthropic 也建议确定性评分优先、模型评分按需使用,并持续阅读失败 Transcript。

如果 Grader 使用和被测 Agent 相同的模型、相同的上下文偏差,还要警惕“自己给自己打高分”。更稳妥的做法是保留代码检查、不同模型评分和人工抽样之间的交叉验证。

13. 如何映射到现有工具

本篇没有要求读者先选平台,因为核心结构可以迁移:

本文 LabOpenAIAnthropic 文章Inspect
eval-tasks.jsonlDataset / Eval casesTask / Eval suiteDataset
run_system()Agent workflowAgent harnessSolver / Agent
TrialRun / TraceTrialSample execution
grade_output()Grader / Trace gradingGraderScorer
trials.jsonlTrace / LogsTranscriptEval log
gate_checksCI 或自定义发布流程Regression suiteMetrics + CI

如果项目使用 OpenAI Agents SDK,其内置 Trace 可以记录模型生成、工具调用、Handoff、Guardrail 与自定义事件,再把这些事件接入行为 Grader。

Trace 不是天然安全的日志

截至 2026-07-28,OpenAI Agents SDK 文档说明,生成与函数调用 Span 可能包含模型、工具的输入输出,trace_include_sensitive_data 默认开启。接入真实业务前,应先做数据分类与脱敏,并按需要关闭敏感内容采集;不要为了评测完整性把密钥、个人信息或内部原文无差别写入 Trace。

若要做更真实的多轮工具 Agent 评测,可以继续研究开源的 τ-bench 系列。该仓库当前已经扩展到 τ³-bench,仍保留由领域 Policy、Tool、Task 和模拟用户组成的评测结构。

工具会越来越成熟,但迁移前仍要能回答:

text
Task 是什么?
每个 Task 跑几次?
真正的 Outcome 在哪里?
谁负责 Grader 的正确性?
哪些回归绝不能被平均分抵消?
失败后能否读到完整证据?

回答不了这些问题,换一个漂亮 Dashboard 也不会自动得到可靠评测。

14. 把自己的 Agent 接入 Harness

读者最容易卡在这里:示例的 run_system() 调用本地检索函数,而自己的 Agent 可能返回 SDK 对象、工具事件或一段字符串。不要先重写整套评分器,先写一个薄适配层,把真实结果压到本文的 SystemOutput 契约:

python
from agent_lab.evals import SystemOutput

def run_my_agent(task, agent) -> SystemOutput:
    result = agent.run(task.question)

    return SystemOutput(
        status="answered" if result.answer else "abstained",
        answer=result.answer or "",
        score=result.confidence or 0.0,
        source=result.source,
        trace_steps=[event.name for event in result.events],
        normalized_question=task.question,
        latency_ms=result.latency_ms,
    )

这里的字段不是要求所有 Agent 都长得一样,而是给 Harness 一个稳定边界:

  • status:取明确的完成、拒答或失败状态,不要从最终话术猜测是否成功;
  • answer:取最终用户可见输出,不要把整段内部 Trace 当答案;
  • source:取检索证据或工具回读的来源标识,不要让模型自己编一个来源名;
  • trace_steps:取 SDK Trace、工具事件或显式埋点,不要依赖自然语言复述执行过程;
  • latency_ms:由 Harness 在外层计时,不要使用模型估算的耗时。

接线时保留 baseline-v1candidate-v2 两个逻辑版本名,在 run_system() 内分别调用旧版和新版适配器。这样 Task、Trial、Grader 和报告都不需要改变。若 Agent 会写数据库或文件,还要额外返回或读取 outcome,为它增加独立 Code Grader;不要把 answerstatus 当成写入成功的证明。

最小迁移顺序是:

text
先接 1 个只读 Task
  -> 对齐 SystemOutput 字段
  -> 读通 trials.jsonl
  -> 再接 5 个真实 Task
  -> 最后加入外部状态隔离与 Outcome Grader

15. 45 分钟跟做练习

可以把自己的 Agent 项目按下面顺序补到最小可用:

第 0-10 分钟:写 5 个真实 Task

选择:

  • 2 个最常见成功任务;
  • 1 个曾经出现的真实 Bug;
  • 1 个应该拒绝或接管的任务;
  • 1 个高风险边界任务。

第 10-20 分钟:为每个 Task 写成功标准

至少包括:

text
expected outcome
required facts or state
forbidden action
evidence location

确保两位熟悉业务的人能独立得到相同判断。

第 20-30 分钟:先写确定性 Grader

优先检查:

  • 退出码;
  • 数据库终态;
  • 文件内容与 diff;
  • JSON Schema;
  • 工具名与关键参数;
  • 是否发生未经批准的写操作。

第 30-40 分钟:重复运行并读失败记录

每题先运行 3 次。不要只看通过率,手动阅读所有失败 Trial,区分:

text
Agent 失败
Task 不清楚
Grader 写错
环境污染
外部工具波动

第 40-45 分钟:写第一条发布门禁

一开始只需要一条真正有价值的规则:

text
任何已知高风险任务回归,候选版本不得发布。

然后随着真实失败增加任务,而不是为了让数字显得专业去堆合成样本。

16. 收藏清单

准备比较 Agent 版本前,逐项确认:

  • Task 来自真实工作、失败或风险,而不是泛化题库;
  • 每个 Grader 检查的内容已在任务或系统契约中声明;
  • 同时覆盖应该做与不应该做的案例;
  • Capability 与 Regression 分开统计;
  • 每个 Task 有独立、可复现的运行环境;
  • Outcome 与最终话术分开验证;
  • 关键行为和失败原因进入 Trace;
  • 每个 Task 重复运行,不把单次成功当稳定;
  • 报告列出 improvement、regression 和 unstable task;
  • 安全回归不能被平均分抵消;
  • Model Grader 有人工 Gold Set 校准;
  • Eval Harness 自身有测试、版本和负责人。

17. 这篇真正建立了什么

本篇没有接入更强模型,却完成了一个更重要的升级:

text
“这个版本看起来更好”

变成

“在固定任务、固定预算和固定评分器下,
它改善了哪些任务,回归了哪些任务,
有哪些结果不稳定,证据在哪里,
是否获得进入下一发布阶段的资格。”

Lab 的 60% -> 95% 不是卖点。真正值得保留的是:即使数字变化,Task、Trial、Grader、Trace、失败台账和 Gate 仍能让团队解释这次变化。

下一篇进入 Context Architecture。我们会继续使用同一个工程,把“Prompt 越写越长”拆成可观测的 Context Packet、来源优先级、Token 预算和缺失证据,并用本篇刚建立的 Eval Harness 验证:加入更多上下文,到底是在帮助 Agent,还是在制造噪声。

参考资料