首页 › tutorials › 给Skill造量化基准测试体系

Claude Code Skill 开发实战:用 eval 闭环给技能做量化基准测试

概述

本教程教你用官方 skill-creator 内置的 eval/benchmark 闭环,把"写完 SKILL.md 凭感觉发布"升级成"写测试用例 → 对比有无 Skill 的输出 → 量化 pass rate/耗时/token → 看 reviewer 回填反馈 → 迭代改进"。学完你将能为任意自定义 Skill 建立可回归、可量化、可比对的质量护栏。适合已会写基础 Skill、想给团队交付稳定技能的中高级开发者。

前置条件

为什么需要 eval 闭环:告别"hope and pray"

社区里有个普遍做法:写好 SKILL.md,随手测一句,发布,然后"向 LLM 之神祈祷它能在真实场景触发"。问题是——你根本不知道三件事:

  1. Skill 该触发时是否真的触发了?(欠触发是当前模型的通病)
  2. Skill 让输出变好了还是变差了?(没有对照组)
  3. 模型升级后这个 Skill 是否回归了?(无基准可比)

2026 年 3 月 3 日 Anthropic 升级了 skill-creator,正式给出工程化答案:给 Skill 写测试用例(evals)、同时跑 with-skill 和 baseline(无 Skill 或旧版 Skill)两组、用脚本量化对比、用浏览器 reviewer 收集人类反馈、迭代下一轮。这套机制本质上是为 Skill 做 TDD + A/B 测试 + 回归测试。

它特别适合输出客观可验证的 Skill:文件转换、数据抽取、代码生成、固定工作流(如 commit message、分支命名、PR 描述生成)。对于风格化、艺术化的 Skill(写作风格、设计审美),更适合定性评审,不要硬套断言。

核心机制:with-skill vs baseline 双轨并行

eval 闭环的精髓是对照实验。每个测试用例同时孵化两个子代理:

运行类型 新建 Skill 场景 改进已有 Skill 场景
with_skill 加载当前 Skill 加载改后版本
baseline 不加载任何 Skill 加载改前快照(cp -r 备份的 skill-snapshot/)

两组用完全相同的 prompt 和输入文件,结果分目录存放。这样你看到的"Skill 贡献值"= with_skill 与 baseline 的差值(delta)。没有 baseline,"效果好不好"就是一句空话。

关键纪律:所有运行必须在同一轮(same turn)一起孵化,不要先跑 with-skill 再回头补 baseline。一起启动,它们会差不多同时完成,不浪费等待时间。

工作流总览

flowchart TD
    A["1. 捕获意图<br/>访谈+研究"] --> B["2. 写 SKILL.md 草稿<br/>name/description/正文"]
    B --> C["3. 写 evals.json<br/>2-3 个真实测试 prompt"]
    C --> D["4. 同轮孵化双轨运行<br/>with_skill + baseline"]
    D --> E["5. 边跑边写 assertions<br/>客观可验证的断言"]
    E --> F["6. 捕获 timing.json<br/>tokens + duration"]
    D --> F
    F --> G["7. 打分 grading.json<br/>text/passed/evidence"]
    G --> H["8. aggregate_benchmark<br/>benchmark.json/md"]
    H --> I["9. 生成 reviewer<br/>Outputs + Benchmark 两页"]
    I --> J["10. 人类回填 feedback.json"]
    J --> K{"满意?"}
    K -- 否 --> L["11. 泛化改进<br/>去 overfit/删冗余"]
    L --> C
    K -- 是 --> M["12. description improver<br/>优化触发准确率"]
    M --> N["13. 扩大测试集<br/>更大规模再跑一轮"]
    N --> C

分步详解

第 1 步:写一个客观可验证的 Skill

实战案例我们做一个 branch-namer——根据改动描述生成规范化的 git 分支名(feat/auth-jwt-login 这种)。它输出固定格式,极易断言,非常适合演示 eval 闭环。

在你的 skills 目录下建结构:

branch-namer/
└── SKILL.md

SKILL.md 草稿:

---
name: branch-namer
description: Generate a conventional-style git branch name from a change description. Make sure to use this skill whenever the user is about to create a branch, mentions branch naming, starts new work, or asks "what should I call this branch", even if they don't explicitly say "branch name".
---

# Branch Namer

Turn a free-text change description into a branch name following the
`<type>/<short-kebab-slug>` convention.

## Rules
1. Pick a type from: feat, fix, docs, refactor, test, chore, perf.
2. Lowercase the slug, join words with hyphens, drop stopwords.
3. Keep total length under 40 characters.
4. Return ONLY the branch name, nothing else.

## Example
Input: "I'm adding JWT-based login"
Output: feat/auth-jwt-login

注意 description 里那句"Make sure to use this skill whenever..."——这是官方推荐的"略微 pushy"写法,对抗模型的欠触发倾向。这一句在你后面跑 eval 时会直接体现为触发率的提升。

第 2 步:写测试用例(先不写断言)

在 Skill 目录下建 evals/evals.json,只放 prompt,先不写 assertions(断言在运行进行中再起草,节省时间):

{
  "skill_name": "branch-namer",
  "evals": [
    {
      "id": 1,
      "prompt": "我要开始做用户登录功能,用 JWT",
      "expected_output": "形如 feat/auth-jwt-login 的分支名",
      "files": []
    },
    {
      "id": 2,
      "prompt": "修复用户列表分页的崩溃 bug",
      "expected_output": "形如 fix/user-list-pagination 的分支名",
      "files": []
    },
    {
      "id": 3,
      "prompt": "重命名一批变量,纯重构不改行为",
      "expected_output": "形如 refactor/rename-variables 的分支名",
      "files": []
    }
  ]
}

设计原则:prompt 要像真实用户会说的话,而不是测试人员腔。把这三条拿给用户确认:"这几条测试用例对吗,要不要加?"

第 3 步:同轮孵化双轨运行

在与 Skill 同级的位置建工作区 branch-namer-workspace/,按 iteration-N/eval-name/ 组织。不要预先建好所有目录,边跑边建。

对每个 eval,同一轮内孵化两个子代理。给子代理的指令模板:

执行此任务:
- Skill 路径: ./branch-namer
- 任务: <eval prompt>
- 输入文件: none
- 输出保存到: ./branch-namer-workspace/iteration-1/feat-auth-jwt-login/with_skill/outputs/
- 需保存的输出: 最终分支名字符串

baseline 子代理用相同 prompt,但不传 Skill 路径,输出存到 without_skill/outputs/。如果你是在改进已有 Skill,则先 cp -r branch-namer ../skill-snapshot/,把 baseline 指向快照,输出存到 old_skill/outputs/。

每个 eval 目录写一个 eval_metadata.json(用描述性名字而非 eval-0):

{
  "eval_id": 1,
  "eval_name": "feat-auth-jwt-login",
  "prompt": "我要开始做用户登录功能,用 JWT",
  "assertions": []
}

第 4 步:运行进行中,起草断言

不要干等运行结束。趁这段时间起草客观可验证、带描述性名字的断言。好断言读起来就像基准查看器里的体检项,扫一眼就懂。

填入 eval_metadata.json 和 evals.json:

{
  "eval_id": 1,
  "eval_name": "feat-auth-jwt-login",
  "prompt": "我要开始做用户登录功能,用 JWT",
  "assertions": [
    {
      "text": "输出是单个分支名,无多余解释文字"
    },
    {
      "text": "类型前缀属于 feat/fix/docs/refactor/test/chore/perf 之一"
    },
    {
      "text": "slug 全小写,词间用连字符连接"
    },
    {
      "text": "总长度小于 40 字符"
    }
  ]
}

第 5 步:捕获 timing(唯一时机)

每个子代理任务完成时,你会收到一个带 total_tokens 和 duration_ms 的通知。这是唯一捕获时机——通知不持久化。每到一个处理一个,写到运行目录的 timing.json:

{
  "total_tokens": 84852,
  "duration_ms": 23332,
  "total_duration_seconds": 23.3
}

第 6 步:打分

全部跑完后,孵化一个 grader 子代理(读 agents/grader.md),对每个运行评估每条断言。能用脚本判定的断言优先写脚本——正则匹配分支名格式、长度校验这类,脚本比"肉眼瞄"更快、更可靠、可复用。

结果写入每个运行目录的 grading.json。字段名必须是 text/passed/evidence(不是 name/met/details),查看器依赖这组精确字段名:

{
  "expectations": [
    {
      "text": "输出是单个分支名,无多余解释文字",
      "passed": true,
      "evidence": "输出为 feat/auth-jwt-login,无前后缀文字"
    },
    {
      "text": "类型前缀属于 ... 之一",
      "passed": true,
      "evidence": "feat 在允许列表内"
    }
  ]
}

第 7 步:聚合成基准

从 skill-creator 目录运行聚合脚本:

python -m scripts.aggregate_benchmark \
  ./branch-namer-workspace/iteration-1 \
  --skill-name branch-namer

产出 benchmark.json 和 benchmark.md,含每种配置(with_skill / without_skill)的 pass_rate、time、tokens,给出 mean ± stddev 和 delta(贡献值)。with_skill 版本要排在它对应 baseline 之前。

接着做一次分析师 pass(读 agents/analyzer.md):挖掘聚合统计掩盖的模式——比如某条断言加不加 Skill 都过(无区分度)、某个 eval 方差高(可能 flaky)、耗时与 token 的取舍。

第 8 步:启动 reviewer,收人类反馈

nohup python <skill-creator-path>/eval-viewer/generate_review.py \
  ./branch-namer-workspace/iteration-1 \
  --skill-name "branch-namer" \
  --benchmark ./branch-namer-workspace/iteration-1/benchmark.json \
  > /dev/null 2>&1 &
VIEWER_PID=$!

迭代 2+ 时加 --previous-workspace ./branch-namer-workspace/iteration-1,查看器会折叠展示上一轮输出做对比。无显示环境的协同/headless 场景用 --static output.html 生成独立 HTML,反馈以 feedback.json 下载。

查看器两个页签: - Outputs:逐个看测试用例,prompt / 输出 / 上一轮输出 / 形式化评分 / 反馈文本框,左右键翻页,点"Submit All Reviews"保存 - Benchmark:pass rate、耗时、token 的量化对比 + 每 eval 明细 + 分析师观察

用户看完回来告诉你后,读 feedback.json:

{
  "reviews": [
    {"run_id": "feat-auth-jwt-login-with_skill", "feedback": "", "timestamp": "..."},
    {"run_id": "refactor-rename-variables-with_skill",
     "feedback": "输出带了多余解释,破坏了规则1", "timestamp": "..."}
  ],
  "status": "complete"
}

空反馈 = 用户觉得没问题。把改进火力集中在有具体抱怨的用例上。用完关掉查看器:kill $VIEWER_PID 2>/dev/null。

改进心法:泛化而非过拟合

拿到反馈后,这是闭环的心脏。两条铁律:

1. 泛化。 这个 Skill 最终可能被使用百万次、横跨无数 prompt。你和用户反复迭代的只是几个样本,是因为样本快、用户熟。如果改进只对这几个样本有效,Skill 就废了。别塞零碎的 overfit 补丁,也别堆压迫性的"MUST"。遇到顽固问题,换个比喻、换种工作模式再试——试错成本很低,也许就撞上金子了。

2. 保持 prompt 精简。 删掉没在起作用的指令。读 transcript(对话记录),不只看最终输出——如果发现 Skill 让模型在某处浪费大量时间做无用功,就砍掉诱导这部分的那段指令,看会发生什么。

收尾:优化触发与扩大规模

Skill 满意后(顺序灵活),跑 description improver(官方提供独立脚本),专门优化 description 的触发准确率——解决"该触发没触发"和"不该触发乱触发"的问题。

最后扩大测试集,用更多样本更大规模再跑一轮,验证 Skill 的泛化性而非过拟合到最初几个用例上。

常见问题与排坑

问题 原因 解决
查看器报字段缺失 grading.json 用了 name/met 改回 text/passed/evidence
timing 数据丢失 没在通知到达时立即处理 每个通知单独处理,勿批量
Skill 总不触发 description 太保守 加"Make sure to use this skill whenever..."句式
某断言加不加 Skill 都过 无区分度 删掉或改成更有区分力的断言
benchmark delta 是负的 Skill 反而拖累输出 读 transcript 找让模型绕弯的指令并精简
无显示器环境打不开 webbrowser.open() 不可用 用 --static out.html 生成独立 HTML

训练营适用性评估

延伸阅读

参考来源

  1. skill-creator SKILL.md(官方源码) — 完整的 eval/benchmark 闭环流程、目录结构、schema 与迭代心法的权威定义
  2. Improving skill-creator: Test, measure, and refine Agent Skills(Anthropic 官方博客, 2026-03-03) — 该 eval/benchmark 能力正式发布的公告与设计动机
  3. Claude Code Skill Creator: How to Test and Benchmark Your Skills(nathanonn) — "hope and pray" 方法论痛点与实操视频/图文指南
  4. Skill Creator Complete Guide(smartscope.blog) — 2026 年 1 月的 Skill/Plugin 安装与市场机制综述

[!tip] 51学通信知识星球 星主:爱卫生(微信:gprshome201101)——公众号「51学通信」创办者,19 年通信行业运维与讲师经验,著有《GPRS网络信令实例详解》《EPC原理与实践》《5G核心网原理与实践》三本纸质书(各大电商平台有售)。 星球定位:深耕 5G 核心网、IMS、NFV/AI、云原生等 ICT 领域,主打运维岗位与信令分析。 当前规模:5200 篇主题 / 990 个回答,198 元/年。 加入福利:加入星球后请加爱卫生微信,拉您进知识星球年度陪伴与答疑群——不限量回复您的各种问题,另有群内分享。 AI 加持:51学通信知识星球已作为 skill 接入 WorkBuddy,使用 deepseek-4-flash 在海量星球帖子中精准找贴、找视频、找 FAQ 和案例,做总结、找文档和 PPT 等场景全覆盖。

51学通信知识星球海报-扫码加入