技能评估方法论
技能评估方法论
学习目标
读完本章后,你将能够:
- 设计有技能 vs 无技能的并行对比实验
- 理解 benchmark.json 的统计指标和解读方法
- 使用 eval-viewer 进行定性与定量分析
- 优化技能描述以提高触发准确率
- 避免评估中的常见陷阱(非判别性断言、高方差测试)
核心概念
为什么需要评估技能?
技能(SKILL.md)是指令性文本,引导 LLM 以特定方式执行任务。但指令的效果无法通过静态阅读判断——必须通过实际运行来验证。评估的核心问题:
- 技能是否有效? 有技能时的输出质量是否优于无技能?
- 技能哪里不足? 哪些测试用例表现差,具体差在哪里?
- 描述是否精准? 应该在哪些场景触发,不应该在哪些场景触发?
评估闭环
实验设计
并行对比架构
每个测试用例同时运行两个版本:
| 配置 | 说明 | 基线选择 |
|---|---|---|
| with_skill | 使用当前技能 | 当前迭代版本 |
| baseline | 对照版本 | 新技能用无技能,改进技能用旧版本 |
关键原则:两个版本必须在同一 turn 内并行启动,而非先跑完一个再跑另一个。这消除了时间偏差和上下文差异。
工作目录结构
workspace/├── iteration-1/│ ├── eval-0/│ │ ├── with_skill/outputs/│ │ ├── without_skill/outputs/│ │ ├── eval_metadata.json│ │ └── timing.json│ ├── eval-1/│ │ └── ...│ ├── benchmark.json│ └── benchmark.md├── iteration-2/│ └── ...└── skill-snapshot/ # 改进模式下的旧版本快照测试用例设计
测试用例应覆盖:
- 典型场景:用户最常见的 3-5 种请求
- 边界场景:边缘情况、异常输入
- 歧义场景:可能需要技能也可能不需要的请求
每个测试用例包含:
prompt:用户实际会说的话expected_output:期望结果的描述files:可选的输入文件expectations:可验证的断言列表
指标采集与统计
timing.json
每个子代理完成时立即采集:
{ "total_tokens": 84852, "duration_ms": 23332, "total_duration_seconds": 23.3}这是唯一的机会——通知中包含的 total_tokens 和 duration_ms 不会持久化到其他地方。
benchmark.json 统计
聚合多个运行结果后生成:
| 指标 | 含义 | 解读 |
|---|---|---|
| pass_rate | 断言通过率 | 技能质量的核心指标 |
| time_seconds | 执行时间 | 技能带来的延迟代价 |
| tokens | Token 消耗 | 技能带来的成本变化 |
| delta | 有技能 - 无技能 | 净收益/净代价 |
统计汇总包含 mean ± stddev,便于判断结果的稳定性和可复现性。
grading.json
Grader agent 对每个运行结果进行评估:
{ "expectations": [ {"text": "断言内容", "passed": true, "evidence": "证据"} ], "summary": {"passed": 6, "failed": 1, "total": 7, "pass_rate": 0.86}}可视化分析:eval-viewer
eval-viewer 是一个 HTML 交互式页面,提供双标签视图:
Outputs 标签
逐个查看每个测试用例的产出:
- 用户提示(Prompt)
- 有技能的输出 vs 无技能的输出(并排对比)
- 形式化等级(如果运行了 grading)
- 人工反馈文本框(自动保存)
Benchmark 标签
全局统计概览:
- 每个配置的平均 pass_rate、时间、Token
- Delta(有技能相比无技能的提升/代价)
- 分析师观察:非判别性断言、高方差测试、时间-质量权衡
描述优化循环
技能描述(description 字段)是主要的触发机制。优化目标:让技能在应该触发时触发,不应该触发时不触发。
优化流程
测试查询设计
Should-Trigger(8-10 条):
- 不同措辞的同一意图(正式 vs 口语化)
- 用户不直接提及技能名称但明显需要的场景
- 罕见用例和竞争场景(多个技能都可用时应该选这个)
Should-Not-Trigger(8-10 条):
- 邻近领域(共享关键词但需要不同技能)
- 模糊表述(简单关键词匹配会误触发)
- 避免过于明显的负例(对 docx 技能用”写一个斐波那契函数”太简单,没有测试价值)
关键发现:简单查询不会触发技能
Claude 只对自己无法轻易处理的任务咨询技能。简单的一步查询(如”读这个 PDF”)即使描述完全匹配,也不会触发技能——因为 Claude 认为可以直接处理。测试查询必须有足够的复杂性。
常见陷阱与对策
非判别性断言
问题:某些断言在两个配置下都 100% 通过(如”输出是 PDF 文件”),无法区分技能的实际价值。
对策:定期审查断言,移除双方都通过的断言,或增加更细粒度的检查。
高方差测试
问题:某些测试用例的通过率波动很大(如 50% ± 40%),可能是不稳定的模型行为或测试设计问题。
对策:增加运行次数(3+),检查测试是否依赖不稳定的外部数据。
描述过拟合
问题:描述在训练集上得分很高,但在测试集上得分很低。
对策:始终用测试集得分选择最优描述,而非训练集得分。
忽略基线
问题:只看有技能的绝对得分,不看与无技能的对比。
对策:始终运行基线对照。技能的价值 = 有技能得分 - 无技能得分。
参考来源
- Anthropic Skills 仓库:
skills/skill-creator/SKILL.md - JSON Schema 规范:
skills/skill-creator/references/schemas.md - agentskills.io 规范:https://agentskills.io/specification