所属阶段:第五阶段「进阶能力」(第 23-27 课) 前置条件:第 25 课(持续学习) 本课收获:设计并运行一次 Eval,理解 pass@k 指标体系
一、本课概述
上一课你学到了如何让 AI "学习"。但学习的效果如何衡量?一个 Agent 配置调整后,是变好了还是变差了?
传统软件有单元测试来验证功能正确性。AI Agent 需要的不是单元测试,而是 Eval(评估):
- EDD 循环 --- Eval 驱动开发的完整流程
- pass@k 指标 --- 理解 AI 行为的概率性质
- Eval 类型 --- Checkpoint-based、Continuous、Agent-vs-Agent
- benchmark Skill --- 性能基准与回归检测
- verification-loop Skill --- 验证闭环
Eval 是连接"AI 能力"和"工程可靠性"的桥梁。
二、为什么需要 Eval
2.1 传统测试 vs AI Eval
| 维度 | 传统单元测试 | AI Eval |
|---|---|---|
| 确定性 | 相同输入 → 相同输出 | 相同输入 → 可能不同输出 |
| 通过标准 | 全部通过 = 正确 | 通过率达标 = 可靠 |
| 重复次数 | 运行 1 次即可 | 需要多次运行取统计 |
| 评判方式 | 精确匹配 | 语义评判(可能需要另一个 LLM) |
| 失败原因 | Bug | 可能是 Prompt、模型、上下文、温度... |
2.2 AI 行为的概率性
一个关键认知:AI Agent 的行为是概率性的,不是确定性的。
同一个 Prompt + 同一个 Agent + 同一个模型,运行 10 次可能得到 7 次正确、2 次部分正确、1 次错误。
这意味着:
- 你不能只运行一次就下结论
- "通过率"比"通过/不通过"更有意义
- 你需要 pass@k 这样的统计指标
三、EDD 循环
Eval 驱动开发(Eval-Driven Development,EDD)是一个迭代循环:
java
┌──────────────────────────────────────────┐
│ EDD 循环 │
│ │
│ 1. 定义评估标准 │
│ │ 什么算"通过"?什么算"失败"? │
│ ↓ │
│ 2. 运行 Eval │
│ │ 多次运行,收集结果 │
│ ↓ │
│ 3. 分析 pass@k │
│ │ 计算通过率,识别薄弱环节 │
│ ↓ │
│ 4. 调整配置 │
│ │ 修改 Prompt / Skill / Agent / 模型 │
│ ↓ │
│ 5. 重新运行 Eval │
│ │ 验证改进效果 │
│ ↓ │
│ 6. 达标? │
│ │ │
│ ├── 否 → 回到步骤 4 │
│ └── 是 → 部署 │
│ │
└──────────────────────────────────────────┘
3.1 定义评估标准
评估标准应该是具体的、可衡量的:
markdown
## Eval: Code Reviewer Agent
### 测试用例 1:检测未处理的空指针
- 输入:包含空指针解引用的 Java 代码
- 期望:Agent 识别出空指针风险并给出修复建议
- Pass 条件:输出中包含 "null check" 或 "NullPointerException"
### 测试用例 2:检测 SQL 注入
- 输入:包含字符串拼接 SQL 的 Python 代码
- 期望:Agent 识别出 SQL 注入风险
- Pass 条件:输出中包含 "parameterized" 或 "SQL injection"
### 测试用例 3:不误报安全代码
- 输入:已经使用参数化查询的代码
- 期望:Agent 不报告 SQL 注入
- Pass 条件:输出中不包含 "SQL injection"
3.2 好的评估标准特征
| 特征 | 说明 | 反例 |
|---|---|---|
| 具体 | 明确的 pass/fail 条件 | "代码质量应该好" |
| 可自动判断 | 可以用程序检查 | 需要人工阅读评判 |
| 独立 | 测试用例之间不互相依赖 | "测试 2 依赖测试 1 的输出" |
| 覆盖正反面 | 既测能力也测不误报 | 只测能检测出问题 |
四、pass@k 指标体系
4.1 三种 pass@k 指标
| 指标 | 定义 | 衡量什么 | 严格程度 |
|---|---|---|---|
| pass@1 | 单次运行通过率 | 可靠性 | 中等 |
| pass@5 | 5 次中至少 1 次通过 | 极限能力 | 宽松 |
| pass^k | k 次全部通过 | 一致性 | 最严格 |
4.2 直观理解
假设一个 Agent 运行 10 次,结果如下:
yaml
运行 1: ✅ 通过
运行 2: ✅ 通过
运行 3: ❌ 失败
运行 4: ✅ 通过
运行 5: ✅ 通过
运行 6: ❌ 失败
运行 7: ✅ 通过
运行 8: ✅ 通过
运行 9: ✅ 通过
运行 10: ❌ 失败
| 指标 | 计算 | 结果 |
|---|---|---|
| pass@1 | 7/10 | 70% --- 单次运行有 70% 概率成功 |
| pass@5 | 至少 1 次通过的概率 | 99.8% --- 跑 5 次几乎肯定能成功 |
| pass^5 | 全部 5 次通过的概率 | 16.8% --- 连续 5 次都成功很难 |
4.3 选择哪个指标
| 场景 | 推荐指标 | 原因 |
|---|---|---|
| 代码审查(可以人工兜底) | pass@1 ≥ 80% | 大部分时候对就行 |
| 安全扫描(不能漏报) | pass@5 ≥ 99% | 运行多次,确保不遗漏 |
| 自主部署(无人监督) | pass^3 ≥ 95% | 必须极其一致 |
| 探索性任务(找方案) | pass@5 ≥ 60% | 只要有一次找到就好 |
五、Eval 类型
5.1 Checkpoint-based Eval
在开发流程的关键节点运行评估:
markdown
代码变更 → Eval(代码审查 Agent 能否检测已知问题?)
↓
配置修改 → Eval(修改后的 Agent 表现是否不低于之前?)
↓
模型升级 → Eval(新模型下 Agent 表现是否不低于之前?)
用途:验证配置变更不会导致退化。
5.2 Continuous Eval
持续运行的评估,类似于持续集成:
css
每天自动运行一组 Eval 用例
↓
收集 pass@k 趋势数据
↓
发现退化时自动告警
用途:监控 Agent 行为的长期趋势。
5.3 Agent-vs-Agent Eval
用一个 Agent 评估另一个 Agent 的输出:
markdown
被评估 Agent:生成代码审查报告
↓
评估 Agent(Evaluator):判断报告是否正确
↓
对比人类标注的标准答案
↓
计算 Evaluator 的一致性
ECC 提供了 agent-eval Skill 来支持这种模式。
注意:Agent-vs-Agent 评估本身也有不确定性。评估 Agent 可能误判。所以需要用人类标注的"黄金答案"来校准评估 Agent。
六、benchmark Skill
ECC 的 benchmark Skill 提供了性能基准和回归检测能力:
6.1 核心功能
| 功能 | 说明 |
|---|---|
| 基准建立 | 在已知良好状态下运行 Eval,记录基线 |
| 回归检测 | 变更后重新运行,对比基线 |
| 趋势分析 | 多次运行结果的趋势图 |
| 阈值告警 | pass@k 低于阈值时告警 |
6.2 使用示例
markdown
## 建立基准
1. 确保当前 Agent 配置是"已知良好"的状态
2. 运行 benchmark Skill 建立基线
3. 记录 pass@1、pass@5 值
## 检测回归
1. 修改 Agent 配置(Prompt、模型、Skill 等)
2. 使用相同的 Eval 用例重新运行
3. 对比新结果与基线
4. 如果 pass@k 下降超过 5%,调查原因
七、verification-loop Skill
verification-loop Skill 提供了一个自动化的验证闭环:
markdown
执行任务
↓
自动验证结果(测试、Lint、类型检查、安全扫描)
↓
├── 全部通过 → 完成
└── 有失败 → 自动修复 → 重新验证(最多 N 轮)
7.1 与 Eval 的关系
| 维度 | verification-loop | Eval |
|---|---|---|
| 时机 | 开发过程中(实时) | 开发完成后(事后) |
| 目标 | 确保当前任务正确 | 衡量 Agent 整体能力 |
| 频率 | 每次任务 | 定期或变更后 |
| 反馈 | 自动修复 | 指导配置调整 |
两者是互补的:verification-loop 保证单次任务质量,Eval 保证 Agent 长期可靠性。
八、设计 Eval 的最佳实践
8.1 Eval 设计清单
| # | 要点 | 说明 |
|---|---|---|
| 1 | 覆盖正面和负面 | 既测"能检测出"也测"不误报" |
| 2 | 用例数量 ≥ 10 | 少于 10 个统计意义不足 |
| 3 | 明确 pass/fail 条件 | 可以用字符串匹配或语义判断 |
| 4 | 运行次数 ≥ 5 | 取统计平均,不依赖单次结果 |
| 5 | 设定基线 | 知道"现在有多好"才能判断"变好还是变差" |
| 6 | 固定随机种子 | 如果可能,减少不确定性来源 |
| 7 | 记录环境 | 模型版本、温度、Prompt 版本 |
8.2 Eval 结果分析模板
markdown
## Eval Report: [Agent Name] - [Date]
### 环境
- Model: claude-sonnet-4-6
- Temperature: 0
- Prompt version: v2.3
- Eval cases: 15
- Runs per case: 5
### 结果
| 指标 | 值 | 基线 | 变化 |
|------|----|------|------|
| pass@1 | 82% | 78% | +4% ✅ |
| pass@5 | 98% | 96% | +2% ✅ |
| pass^3 | 65% | 60% | +5% ✅ |
### 薄弱环节
- 用例 #7(复杂嵌套代码):pass@1 仅 40%
- 用例 #12(多文件变更):pass@1 仅 60%
### 下一步
- 针对用例 #7 增加 Skill 指导
- 针对用例 #12 考虑拆分为子任务
九、本课练习
练习 1:设计 3 个 Eval 用例(20 分钟)
这是本课最重要的练习。
为一个你使用的 Agent(如 code-reviewer)设计 3 个评估用例。每个用例包括:
| 字段 | 内容 |
|---|---|
| 测试名称 | 描述性名称 |
| 输入 | 提供给 Agent 的代码或问题 |
| 期望行为 | Agent 应该做什么 |
| Pass 条件 | 具体的通过标准 |
| Fail 条件 | 什么情况算失败 |
练习 2:理解 pass@k(10 分钟)
一个 Agent 运行 20 次,有 14 次通过。计算:
- pass@1 = ?
- 如果 pass@5 的目标是 ≥ 99%,这个 Agent 达标了吗?
- 如果 pass^3 的目标是 ≥ 50%,这个 Agent 达标了吗?
(提示:pass@5 = 1 - (失败率)^5 = 1 - 0.3^5;pass^3 = (通过率)^3 = 0.7^3)
练习 3:EDD 循环实践(15 分钟)
选择一个简单的任务(如"让 Claude 把 JSON 转换为 YAML"),执行一个简化的 EDD 循环:
- 定义 pass 条件(输出是合法的 YAML)
- 运行 3 次
- 记录 pass@1
- 如果不理想,调整 Prompt 后再运行 3 次
- 对比前后结果
练习 4(选做):Agent-vs-Agent
思考:如果让一个 Agent 来判断另一个 Agent 的代码审查质量,你会怎么设计评估 Prompt?评估 Agent 自身的准确性怎么衡量?
十、本课小结
| 你应该记住的 | 内容 |
|---|---|
| EDD 循环 | 定义标准 → 运行 Eval → 分析 pass@k → 调整 → 重跑 → 达标 → 部署 |
| pass@1 | 单次通过率,衡量日常可靠性 |
| pass@5 | 至少 1 次通过,衡量极限能力 |
| pass^k | 全部通过,最严格的一致性要求 |
| Eval 类型 | Checkpoint(变更验证)、Continuous(长期监控)、Agent-vs-Agent |
十一、下节预告
第 27 课:Agent 工程与 LLM 成本优化
Eval 告诉你 Agent 有多好,但"好"不能不计成本。下节课学习 Agent Harness 的构建原理(Action Space、Observation 格式化、Reward Signal),以及如何用 cost-aware-llm-pipeline Skill 按复杂度路由模型、追踪预算、优化成本。
预习建议 :浏览 skills/agent-harness-construction/SKILL.md 和 skills/cost-aware-llm-pipeline/SKILL.md。