mcpField
S
skill-creator

skill-creator

github.com/bytedanceAgent 工作流84.6k2.3k 次安装1 天前更新
代码仓库

关于 skill-creator

skill-creator 帮助用户创建并迭代改进技能,涵盖明确目标与流程、撰写说明、测试和评估。既可用于开发新技能,也可用于完善现有草稿。

主要功能

  1. 01明确技能目标与工作流
  2. 02撰写技能说明
  3. 03创建测试提示词
  4. 04评估结果与指标
  5. 05根据反馈修改技能
  6. 06优化技能描述

适用场景

  1. 01将工作流整理为技能
  2. 02为技能草稿设计测试
  3. 03迭代提升技能质量
  4. 04改进技能的触发条件

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/bytedance/deer-flow --skill skill-creator

安装后在 Claude Code 中输入/skill-creator确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

LICENSE.txt
agents/
analyzer.md
comparator.md
grader.md
assets/
eval_review.html
eval-viewer/
generate_review.py
viewer.html
references/
output-patterns.md
schemas.md
workflows.md
scripts/
aggregate_benchmark.py
generate_report.py
improve_description.py
init_skill.py
package_skill.py
quick_validate.py
run_eval.py
run_loop.py
utils.py

详细介绍

Skill Creator

用于创建新技能并对其进行迭代改进的技能。

总体而言,创建技能的流程如下:

  • 确定技能要实现什么功能,以及大致如何实现
  • 编写技能草稿
  • 创建几个测试提示词,并使用 claude-with-access-to-the-skill 运行测试
  • 帮助用户从定性和定量两个方面评估结果
    • 在后台运行测试时,如果还没有定量评估,就起草一些;如果已有评估,可以直接使用,也可以根据需要修改。然后向用户说明这些评估(如果已有评估,则说明现有评估)
    • 使用 eval-viewer/generate_review.py 脚本展示结果,供用户查看,同时也让用户查看定量指标
  • 根据用户对结果的评估反馈重写技能;如果定量基准测试暴露出明显缺陷,也要据此改进
  • 重复上述过程,直到满意为止
  • 扩充测试集,并以更大规模再次测试

使用此技能时,你的任务是判断用户目前处于流程的哪个阶段,然后介入并帮助他们推进。例如,用户可能会说:“我想为 X 创建一个技能。”你可以帮他们明确需求、编写草稿和测试用例、确定评估方式、运行所有提示词,并反复迭代。

另一方面,用户也可能已经有了技能草稿。这时你可以直接进入评估和迭代环节。

当然,你应始终保持灵活。如果用户说“我不需要进行一堆评估,随便跟我聊聊就好”,那也可以照做。

技能完成后(不过流程顺序可以灵活调整),你还可以运行技能描述改进器来优化技能的触发方式。我们有一个单独的脚本专门用于此目的。

明白了吗?明白。


DeerFlow 环境(⚠️ 请先阅读)

如果你运行在 DeerFlow 沙盒 Agent 环境中(可以使用 skill_manage 工具),则必须遵守以下所有技能文件操作规则。这些规则优先于下文中的通用文件写入和打包说明。

为什么这很重要

在 DeerFlow 中,沙盒文件系统是隔离的。通过 write_file 写入的文件会存放在 /mnt/user-data/outputs/ 中,这是一个按会话线程划分的输出目录——新聊天无法访问其中的文件。必须通过专用的 skill_manage 工具持久化技能,使其存储在每位用户的技能目录中,并立即对今后的所有聊天可见。

所有技能文件操作均使用 skill_manage
操作skill_manage action示例
创建新技能action="create"skill_manage(action="create", name="my-skill", content="---\nname: my-skill\n---\n...")
替换整个 SKILL.mdaction="edit"skill_manage(action="edit", name="my-skill", content="updated SKILL.md")
部分编辑(查找并替换)action="patch"skill_manage(action="patch", name="my-skill", find="old text", replace="new text")
删除技能action="delete"skill_manage(action="delete", name="my-skill")
添加辅助文件action="write_file"skill_manage(action="write_file", name="my-skill", path="scripts/helper.py", content="...")
移除辅助文件action="remove_file"skill_manage(action="remove_file", name="my-skill", path="scripts/helper.py")
关键规则
  1. 绝不要使用沙盒 write_file 创建或修改技能文件(SKILL.md、scripts/、references/、assets/)。这些文件会写入 /mnt/user-data/outputs/,后续对话将无法访问。请始终使用 skill_manage。

  2. 跳过 package_skill.py 步骤。在 DeerFlow 中,skill_manage 会将技能保存到正确的每用户目录中。无需打包成 .skill,也无需手动安装。该技能会立即在所有新对话中可用。

  3. 跳过针对技能的 present_files 步骤。技能不是交付物,而是通过 skill_manage 保存并由技能系统自动加载。仅对非技能输出(评估报告、基准测试等)使用 present_files。

  4. 评估工作区文件可以保存在沙盒中。测试提示词、基准测试数据、评估查看器 HTML、评分结果等都不是技能文件——你可以像往常一样,使用沙盒 write_file 将它们写入 /mnt/user-data/outputs/ 或 /mnt/user-data/workspace/。

  5. 读取现有技能的 SKILL.md 时,请在沙盒中使用 read_file("/mnt/skills/custom/<name>/SKILL.md")(该路径映射到每用户技能目录)。

  6. 更新现有技能:使用 skill_manage(action="edit") 或 skill_manage(action="patch")。不要先复制到 /tmp/——skill_manage 会直接处理每用户存储。

在 DeerFlow 中的工作流

核心循环不变,但持久化方式有所不同:

  1. 收集意图 → 访谈 → 起草 SKILL.md 内容
  2. 调用 skill_manage(action="create", name=<name>, content=<SKILL.md>) 保存技能
  3. 运行测试用例(评估工作区文件使用沙盒 write_file)
  4. 评估结果并收集反馈
  5. 调用 skill_manage(action="edit") 或 skill_manage(action="patch") 改进技能
  6. 重复以上步骤,直到满意
  7. 完成——无需打包。 技能已保存,之后的所有对话都能使用。

与用户沟通

技能创建者可能会面对熟悉程度各不相同的用户,他们对编程术语的了解也大相径庭。如果你还没听说过(毕竟这股风潮才刚刚兴起),Claude 的强大能力正激励着水管工打开终端,也让父母和祖父母在 Google 上搜索“如何安装 npm”。另一方面,大多数用户可能都具备相当不错的计算机使用能力。

因此,请留意上下文线索,判断该如何措辞!通常来说,下面这些例子可以供你参考:

  • “评估”和“基准测试”属于介于专业与通俗之间的术语,但可以使用。
  • 使用“JSON”和“断言”时,最好先确认用户明确表现出对这些概念的了解,否则就要加以解释。

如果你不确定,可以简要解释术语;如果不确定用户是否能理解,也可以用简短的定义来说明。


创建技能

收集意图

首先了解用户的意图。当前对话中可能已经包含了用户想要固化成技能的工作流(例如,用户说“把这个做成一个技能”)。如果是这样,请先从对话记录中提取答案——包括使用过的工具、步骤顺序、用户提出的修正,以及观察到的输入和输出格式。用户可能需要补充缺失的信息,并应在进入下一步前确认。

  1. 这个技能应该让 Claude 能做什么?
  2. 在什么情况下应该触发这个技能?(用户会使用哪些措辞或上下文?)
  3. 预期的输出格式是什么?
  4. 是否应该设置测试用例来验证技能是否有效?对于输出可客观验证的技能(文件转换、数据提取、代码生成、固定工作流步骤),测试用例很有帮助。对于输出较主观的技能(写作风格、艺术创作),通常不需要测试用例。请根据技能类型提出合适的默认建议,但由用户决定。
访谈与调研

主动询问边缘情况、输入输出格式、示例文件、成功标准和依赖项。在这些问题理清之前,不要编写测试提示词。

检查可用的 MCP 服务。如果它们对调研有帮助(如搜索文档、查找类似的 Skill、查阅最佳实践),且有可用的子 Agent,则并行调用子 Agent 进行调研;否则直接在当前上下文中完成。提前准备好上下文,减少用户的负担。

编写 SKILL.md

根据用户访谈结果,填写以下组成部分:

  • name:Skill 标识符
  • description:触发时机及其功能。这是最主要的触发机制,需同时包含 Skill 的功能以及具体的使用场景。所有“何时使用”的信息都应放在这里,而不是正文中。注意:Claude 目前有“触发不足”的倾向,即在 Skill 本可派上用场时却不去使用。为了解决这个问题,请让 Skill 的 description 写得更“主动”一些。例如,与其写“如何构建一个用于展示 Anthropic 内部数据的简单快速仪表盘”,不如写“如何构建一个用于展示 Anthropic 内部数据的简单快速仪表盘。只要用户提到仪表盘、数据可视化、内部指标,或想展示任何类型的公司数据,即使没有明确要求‘仪表盘’,也务必使用此 Skill。”
  • compatibility:所需工具和依赖项(可选,很少需要)
  • Skill 的其余部分 :)
Skill 编写指南
Skill 的结构
skill-name/
├── SKILL.md (required)
│   ├── YAML frontmatter (name, description required)
│   └── Markdown instructions
└── Bundled Resources (optional)
    ├── scripts/    - Executable code for deterministic/repetitive tasks
    ├── references/ - Docs loaded into context as needed
    └── assets/     - Files used in output (templates, icons, fonts)
渐进式披露

Skill 采用三级加载机制:

  1. 元数据(name + description):始终在上下文中(约 100 词)
  2. SKILL.md 正文:Skill 触发时在上下文中(理想情况下少于 500 行)
  3. 附带资源:按需加载(数量不限,脚本可以直接执行而无需加载)

这些词数只是大致估计,如有需要可以适当写得更长。

关键模式:

  • 将 SKILL.md 控制在 500 行以内;如果接近该上限,请增加一层层级结构,并明确指出使用该 Skill 的模型接下来应前往何处。
  • 在 SKILL.md 中清晰引用参考文件,并说明何时应读取它们。
  • 对于较大的参考文件(超过 300 行),应包含目录。

领域组织:当一个 Skill 支持多个领域或框架时,按变体进行组织:

cloud-deploy/
├── SKILL.md (workflow + selection)
└── references/
    ├── aws.md
    ├── gcp.md
    └── azure.md

Claude 只读取相关的参考文件。

无意外原则

这一点不言自明:Skill 不得包含恶意软件、利用代码,或任何可能危及系统安全的内容。只要按描述,Skill 的内容就不应让用户感到意外。对于要求创建误导性 Skill,或旨在促成未授权访问、数据外泄或其他恶意活动的 Skill,不要配合。诸如“扮演某某角色”之类的内容是可以的。

编写模式

说明中优先使用祈使句。

定义输出格式:可以这样写:

## Report structure
ALWAYS use this exact template:
# [Title]
## Executive summary
## Key findings
## Recommendations

示例模式:加入示例很有用。可以按如下格式编写(但如果示例中包含“输入”和“输出”,你可能需要稍作调整):

## Commit message format
**Example 1:**
Input: Added user authentication with JWT tokens
Output: feat(auth): implement JWT-based authentication
写作风格

尽量解释事情为何重要,而不是大量使用生硬、陈旧的“必须”式表述。站在模型的视角思考,使 Skill 具有通用性,不要局限于某个特定示例。先写草稿,然后以旁观者的眼光重新审视,并加以改进。

测试用例

在编写 Skill 草稿之后,构思 2-3 个贴近真实情况的测试提示词,也就是真实用户可能会说的话。将它们分享给用户:[不必使用这段原文措辞] "以下是我想尝试的几个测试用例。这些看起来是否合适,还是你想再添加一些?" 然后运行它们。

将测试用例保存到 evals/evals.json。暂时不要编写断言,只保存提示词。你将在下一步、运行进行期间再起草断言。

{
  "skill_name": "example-skill",
  "evals": [
    {
      "id": 1,
      "prompt": "User's task prompt",
      "expected_output": "Description of expected result",
      "files": []
    }
  ]
}

完整的 schema 请参阅 references/schemas.md(其中包含 assertions 字段,你将在之后添加)。

运行和评估测试用例

本节是一个连续的流程,中途不要停止。请勿使用 /skill-test 或任何其他测试类 Skill。

将结果放在与 Skill 目录同级的 <skill-name>-workspace/ 中。在工作区内,按迭代组织结果(iteration-1/、iteration-2/ 等),每个迭代内,每个测试用例对应一个目录(eval-0/、eval-1/ 等)。不要预先创建所有目录,按需逐步创建即可。

步骤 1:在同一轮中启动所有运行(带 Skill 与基线)

对于每个测试用例,在同一轮中启动两个子 Agent:一个使用 Skill,一个不使用。这一点很重要:不要先启动带 Skill 的运行,之后再回头启动基线。应一次性全部启动,使它们大致同时完成。

带 Skill 的运行:

Execute this task:
- Skill path: <path-to-skill>
- Task: <eval prompt>
- Input files: <eval files if any, or "none">
- Save outputs to: <workspace>/iteration-<N>/eval-<ID>/with_skill/outputs/
- Outputs to save: <what the user cares about — e.g., "the .docx file", "the final CSV">

基线运行(提示词相同,但基线取决于上下文):

  • 创建新 Skill:完全不使用 Skill。提示词相同,不提供 Skill 路径,结果保存到 without_skill/outputs/。
  • 改进现有 Skill:使用旧版本。编辑前先为 Skill 创建快照(cp -r <skill-path> <workspace>/skill-snapshot/),然后让基线子 Agent 指向该快照。结果保存到 old_skill/outputs/。

为每个测试用例编写一个 eval_metadata.json(断言暂时可以为空)。为每个评估起一个能描述其测试内容的名称,而不只是 "eval-0",目录也使用该名称。如果本次迭代使用了新的或修改过的评估提示词,请为每个新的评估目录创建这些文件,不要假设它们会沿用上一次迭代的内容。

{
  "eval_id": 0,
  "eval_name": "descriptive-name-here",
  "prompt": "The user's task prompt",
  "assertions": []
}
步骤 2:在运行进行期间起草断言

不要只是等待运行结束,可以利用这段时间做有意义的工作。为每个测试用例起草量化断言,并向用户解释。如果 evals/evals.json 中已有断言,请审查它们并说明其检查内容。

好的断言应当可被客观验证,并且名称具有描述性,在基准测试查看器中清晰可读,使人扫一眼结果就能理解每条断言检查的内容。主观性较强的 Skill(如写作风格、设计质量)更适合定性评估,不要强行为需要人工判断的内容设置断言。

断言起草完成后,更新 eval_metadata.json 文件和 evals/evals.json。同时向用户说明他们在查看器中会看到什么,包括定性输出和定量基准结果。

步骤 3:运行完成时记录耗时数据

每当一个子 Agent 任务完成时,你会收到一条包含 total_tokens 和 duration_ms 的通知。请立即将这些数据保存到运行目录下的 timing.json 中:

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

这是获取该数据的唯一机会,它只通过任务通知传递,不会在其他地方持久保存。请在通知到达时逐条处理,而不要尝试批量处理。

第 4 步:评分、汇总并启动查看器

所有运行完成后:

  1. 为每次运行评分:启动一个评分子 Agent(或直接内联评分),让它读取 agents/grader.md,并根据输出结果逐条评估每个断言。将结果保存到每个运行目录下的 grading.json。grading.json 的 expectations 数组必须使用 text、passed 和 evidence 字段,不能使用 name、met、details 或其他变体,查看器依赖这些确切的字段名。对于可以通过程序检查的断言,请编写并运行脚本,而不是凭肉眼判断。脚本更快、更可靠,并且可以在后续迭代中复用。

  2. 汇总为基准测试结果:在 skill-creator 目录下运行汇总脚本:

    python -m scripts.aggregate_benchmark <workspace>/iteration-N --skill-name <name>
    

    该步骤会生成 benchmark.json 和 benchmark.md,其中包含每种配置的 pass_rate、耗时和 token 用量,以及均值 ± 标准差和差值。如果手动生成 benchmark.json,请参阅 references/schemas.md,其中有查看器所需的确切结构。 将每个 with_skill 版本排在对应的基线版本之前。

  3. 进行分析师复核:阅读基准测试数据,找出汇总统计可能掩盖的规律。请参阅 agents/analyzer.md 中的“分析基准测试结果”一节,了解需要关注的内容,例如:无论是否使用 skill 都始终通过的断言(无区分度)、方差较大的评测(可能不稳定),以及耗时与 token 之间的权衡。

  4. 启动查看器,同时呈现定性输出和定量数据:

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

    对于第 2 次及之后的迭代,还需传入 --previous-workspace <workspace>/iteration-<N-1>。

    Cowork / 无头环境: 如果 webbrowser.open() 不可用,或环境没有显示器,请使用 --static <output_path> 生成独立的 HTML 文件,而不是启动服务器。用户点击“Submit All Reviews”后,反馈会以 feedback.json 文件的形式下载。下载完成后,请将 feedback.json 复制到工作区目录中,供下一次迭代读取。

注意:请使用 generate_review.py 创建查看器,无需手动编写自定义 HTML。

  1. 告知用户,大致内容如下:“结果已在浏览器中打开。共有两个标签页:‘Outputs’可以逐个浏览测试用例并留下反馈,‘Benchmark’展示定量对比结果。完成后请回到这里告诉我。”
用户在查看器中看到的内容

“Outputs”标签页每次显示一个测试用例:

  • Prompt:给出的任务
  • Output:skill 生成的文件,尽可能内联渲染
  • Previous Output(第 2 次及之后的迭代):可折叠区域,显示上一次迭代的输出
  • Formal Grades(若已评分):可折叠区域,显示断言的通过/失败情况
  • Feedback:文本框,输入时自动保存
  • Previous Feedback(第 2 次及之后的迭代):上一次的评论,显示在文本框下方

“Benchmark”标签页展示统计摘要,包括每种配置的通过率、耗时和 token 用量,并附有按评测划分的明细和分析师观察结论。

可通过上一个/下一个按钮或方向键切换用例。完成后,用户点击“Submit All Reviews”,所有反馈将保存到 feedback.json。

第 5 步:读取反馈

当用户告知已完成审阅时,读取 feedback.json:

{
  "reviews": [
    {"run_id": "eval-0-with_skill", "feedback": "the chart is missing axis labels", "timestamp": "..."},
    {"run_id": "eval-1-with_skill", "feedback": "", "timestamp": "..."},
    {"run_id": "eval-2-with_skill", "feedback": "perfect, love this", "timestamp": "..."}
  ],
  "status": "complete"
}

反馈为空,表示用户认为结果可以接受。改进工作应聚焦于用户提出了具体意见的测试用例。

使用完查看器后,请关闭查看器服务器:

kill $VIEWER_PID 2>/dev/null

改进 skill

这是整个循环的核心。你已经运行了测试用例,用户也完成了审阅,现在需要根据反馈改进 skill。

如何思考改进
  1. 从反馈中归纳通用规律。 这里的大局是,我们要创建的 Skill 会被使用上百万次(也许真的会,甚至更多,谁知道呢),覆盖许多不同的提示词。你和用户之所以反复迭代少数几个示例,是为了加快进度。用户对这些示例了如指掌,评估新输出也很快。但如果你们共同开发的 Skill 只对这些示例有效,那它就毫无用处。与其做琐碎的过拟合式修改,或是令人压抑的强制性 MUST 规定,不如在遇到顽固问题时,尝试换一种比喻,或推荐不同的工作模式。尝试的成本不高,说不定就能找到很好的方案。

  2. 保持提示词精简。 删除那些没有发挥作用的内容。务必阅读转录记录,而不只是看最终输出。如果发现 Skill 让模型浪费大量时间做无效的事情,可以删除导致这些行为的部分,看看结果如何。

  3. 解释原因(why)。 请努力解释你让模型做每件事背后的原因。如今的大模型很聪明,具备良好的心智理论,在合适的运行框架下,能够超越机械式的指令,真正把事情做成。即使用户的反馈简短或带有挫败感,也要尝试真正理解任务,理解用户为什么这样写、究竟写了什么,然后把这种理解传达到指令中。如果你发现自己在写全大写的 ALWAYS 或 NEVER,或者使用非常僵化的结构,这就是一个黄色警示信号。如果可能,请换一种方式表述,并解释其中的理由,让模型明白你所要求的事情为什么重要。这是一种更人性化、更有力、更有效的做法。

  4. 寻找测试用例之间的重复工作。 阅读测试运行的转录记录,留意子 Agent 是否各自独立编写了相似的辅助脚本,或采用了同样的多步骤方法来完成某件事。如果三个测试用例中,子 Agent 都编写了 create_docx.py 或 build_chart.py,这就强烈表明 Skill 应当打包该脚本。将其编写一次,放入 scripts/ 目录,并告诉 Skill 使用它。这样以后每次调用都不必重复造轮子。

这项任务非常重要(我们要创造每年数十亿的经济价值!),你的思考时间不是瓶颈。请慢慢来,认真斟酌。我建议先写一份修订草稿,然后重新审视并加以改进。请尽力走进用户的内心,真正理解他们想要什么、需要什么。

迭代循环

完成 Skill 改进后:

  1. 将改进应用到 Skill 中
  2. 将所有测试用例重新运行到新的 iteration-<N+1>/ 目录中,包括基线运行。如果是创建新 Skill,基线始终为 without_skill(不使用 Skill),该基线在各次迭代中保持不变。如果是改进现有 Skill,则由你判断合适的基线:可以是用户最初提供的原始版本,也可以是上一次迭代的版本。
  3. 使用 --previous-workspace 指向上一次迭代目录,启动审阅器
  4. 等待用户审阅,并告诉你他们已完成
  5. 阅读新的反馈,再次改进,然后重复上述步骤

持续进行,直到:

  • 用户表示满意
  • 反馈全部为空(一切看起来都很好)
  • 你已无法取得实质性进展

进阶:盲比较

当你需要对同一 Skill 的两个版本进行更严格的比较时(例如用户问"新版本是否真的更好?"),可以使用盲比较系统。详细内容请阅读 agents/comparator.md 和 agents/analyzer.md。其基本思路是:在不告知来源的情况下,把两份输出交给一个独立的 Agent,由它判断质量,然后分析胜出方胜出的原因。

这一功能是可选的,需要子 Agent 支持,大多数用户并不需要。通常人工审阅循环已经足够。


描述优化

SKILL.md frontmatter 中的 description 字段是决定 Claude 是否调用该 Skill 的主要机制。在创建或改进 Skill 之后,应主动提出优化 description,以提高触发的准确性。

第一步:生成触发评估查询

创建 20 条评估查询,包括应触发和不应触发两类,并保存为 JSON:

[
  {"query": "the user prompt", "should_trigger": true},
  {"query": "another prompt", "should_trigger": false}
]

查询必须真实,是 Claude Code 或 Claude.ai 用户实际会输入的内容。不要使用抽象的请求,而应具体、细节充分,例如文件路径、用户工作或处境的个人背景、列名和取值、公司名称、URL 等,并带有一点背景信息。部分查询可以使用小写、缩写、拼写错误或口语化表达。查询长度应有所不同,并聚焦于边界情况,而不是制作界限分明的样例(用户会有机会确认这些查询)。

不好的示例:"Format this data"、"Extract text from PDF"、"Create a chart"

好的示例:"ok so my boss just sent me this xlsx file (its in my downloads, called something like 'Q4 sales final FINAL v2.xlsx') and she wants me to add a column that shows the profit margin as a percentage. The revenue is in column C and costs are in column D i think"

对于应触发的查询(8-10 条),应考虑覆盖面:同一意图的不同表述,有正式的也有随意的。应包括用户没有明确提及 Skill 或文件类型、但确实需要该 Skill 的情况;也应包括一些不常见的使用场景,以及本 Skill 与其他工具存在竞争、但本 Skill 应当胜出的情况。

对于不应触发的查询(8-10 条),最有价值的是"近似误判"查询,即与 Skill 共享关键词或概念,但实际需要其他工具的查询。可以考虑相邻领域、措辞模糊(朴素的关键词匹配会误触发但实际不应触发)的情况,以及查询涉及 Skill 所做的事情、但在某种场景下其他工具更合适的情况。

需要避免的关键问题是:不要让不应触发的查询显而易见地无关。例如,把"写一个斐波那契函数"作为 PDF Skill 的反例,过于简单,无法起到测试作用。反例应当确实具有迷惑性。

第二步:与用户共同审阅

使用 HTML 模板将评估集提交给用户审阅:

  1. 从 assets/eval_review.html 读取模板
  2. 替换占位符:
    • __EVAL_DATA_PLACEHOLDER__ → 评估条目的 JSON 数组(不加引号,因为它是 JS 变量赋值)
    • __SKILL_NAME_PLACEHOLDER__ → Skill 的名称
    • __SKILL_DESCRIPTION_PLACEHOLDER__ → Skill 当前的 description
  3. 写入临时文件(例如 /tmp/eval_review_<skill-name>.html),并打开:open /tmp/eval_review_<skill-name>.html
  4. 用户可以编辑查询、切换应触发状态、增删条目,然后点击"Export Eval Set"
  5. 文件会下载到 ~/Downloads/eval_set.json。如果存在多个版本(例如 eval_set (1).json),应检查 Downloads 文件夹中最新的版本

这一步很重要,评估查询质量不佳会导致 description 质量不佳。

步骤 3:运行优化循环

告诉用户:“这需要一些时间——我会在后台运行优化循环,并定期查看进度。”

将评估集保存到工作区,然后在后台运行:

python -m scripts.run_loop \
  --eval-set <path-to-trigger-eval.json> \
  --skill-path <path-to-skill> \
  --model <model-id-powering-this-session> \
  --max-iterations 5 \
  --verbose

使用系统提示词中的模型 ID(即为当前会话提供支持的模型),确保触发测试符合用户的实际体验。

运行期间,定期查看输出,向用户更新当前迭代次数和分数情况。

此流程会自动完成整个优化循环。它会将评估集拆分为 60% 的训练集和 40% 的留出测试集,评估当前描述(每个查询运行 3 次,以获得可靠的触发率),然后调用 Claude,根据失败的情况提出改进建议。它会在训练集和测试集上重新评估每个新描述,最多迭代 5 次。完成后,它会在浏览器中打开一份 HTML 报告,展示每次迭代的结果,并返回包含 best_description 的 JSON。该结果根据测试集分数而非训练集分数选出,以避免过拟合。

描述优化需要 PyYAML(软件包验证器也会用到)。名称和描述字段会作为 YAML 字符串解析,包括转义引号、注释和块标量。元数据无效时,评估器、优化器或描述改进命令会停止运行,并在 stderr 中输出 Error:,退出状态为 1。

技能触发机制的工作原理

了解触发机制有助于设计更好的评估查询。技能会以名称和描述的形式出现在 Claude 的 available_skills 列表中,Claude 会根据描述决定是否查阅技能。需要注意的是,Claude 只会在无法轻松自行处理任务时查阅技能——例如“读取此 PDF”这样的简单单步查询,即使描述完全匹配,也可能不会触发技能,因为 Claude 可以直接使用基本工具处理。描述匹配时,复杂、多步骤或专业化的查询通常能可靠地触发技能。

这意味着你的评估查询应当足够具体,让 Claude 确实能从查阅技能中受益。像“读取文件 X”这样的简单查询不是好的测试用例——无论描述质量如何,它们都不会触发技能。

步骤 4:应用结果

从 JSON 输出中获取 best_description,并更新技能的 SKILL.md 前置元数据。向用户展示修改前后的内容,并报告分数。


打包并呈现(仅当 present_files 工具可用时)

检查你是否可以使用 present_files 工具。如果无法使用,请跳过此步骤。如果可以使用,请打包技能,并向用户提供 .skill 文件:

python -m scripts.package_skill <path/to/skill-folder>

打包完成后,告知用户生成的 .skill 文件路径,以便其进行安装。


Claude.ai 专用说明

在 Claude.ai 中,核心工作流与之前相同(起草 → 测试 → 审阅 → 改进 → 重复),但由于 Claude.ai 没有子 Agent,部分操作机制会有所不同。以下是需要调整的内容:

运行测试用例:没有子 Agent 意味着无法并行执行。对于每个测试用例,先阅读该技能的 SKILL.md,然后按照其中的说明亲自完成测试提示。请逐个进行。这比使用独立子 Agent 的严谨性要低(你既编写了技能,又在运行它,因此拥有完整上下文),但它是一个有用的基本检查,而且人工审阅环节可以弥补这一不足。跳过基线运行,只需使用该技能按要求完成任务即可。

审阅结果:如果无法打开浏览器(例如 Claude.ai 的虚拟机没有显示器,或你在远程服务器上),请完全跳过浏览器审阅器。改为直接在对话中展示结果。对于每个测试用例,展示提示词和输出。如果输出是用户需要查看的文件(如 .docx 或 .xlsx),请将其保存到文件系统中,并告知用户文件位置,以便其下载和检查。通过对话征求反馈:"这个效果如何?有什么需要修改的吗?"

基准测试:跳过定量基准测试,因为它依赖基线对比,而在没有子 Agent 的情况下,基线对比没有意义。请重点收集用户的定性反馈。

迭代循环:与之前相同,即改进技能、重新运行测试用例、征求反馈,只是中间去掉了浏览器审阅器。如果你有文件系统,仍可将结果整理到迭代目录中。

描述优化:本节需要 claude CLI 工具(具体为 claude -p),该工具仅在 Claude Code 中可用。如果你在 Claude.ai 上,请跳过此部分。

盲测对比:需要子 Agent,请跳过。

打包:package_skill.py 脚本在任何具备 Python 和文件系统的环境中均可运行。在 Claude.ai 上,你可以运行它,用户随后即可下载生成的 .skill 文件。

更新现有技能:用户可能要求你更新已有技能,而非创建新技能。此时:

  • 保留原名称。 记下技能的目录名和 name frontmatter 字段,并保持不变。例如,若已安装的技能为 research-helper,则输出 research-helper.skill(而非 research-helper-v2)。
  • 编辑前复制到可写位置。 已安装的技能路径可能是只读的。请复制到 /tmp/skill-name/,在该副本中编辑,并从副本打包。
  • 如需手动打包,请先在 /tmp/ 中暂存,然后再复制到输出目录,直接写入可能因权限问题而失败。

Cowork 专用说明

如果你在 Cowork 中,需要了解的主要事项如下:

  • 你可以使用子 Agent,因此主要工作流(并行生成测试用例、运行基线、评分等)都可以正常进行。(但如果遇到严重的超时问题,可以改为串行运行测试提示词,而不是并行。)
  • 你没有浏览器或显示界面,因此生成评估查看器时,请使用 --static <output_path> 生成独立的 HTML 文件,而不是启动服务器。然后提供一个链接,供用户点击并在浏览器中打开该 HTML。
  • 由于某些原因,Cowork 环境似乎让 Claude 不太愿意在运行测试后生成评估查看器,因此在此再次强调:无论你是在 Cowork 还是 Claude Code 中,运行测试后都应始终生成评估查看器,让用户先查看示例,然后再自行修改 Skill 并尝试纠正。请使用 generate_review.py(不要自己编写临时 HTML 代码)。抱歉要重复强调,我要用全大写说明:在你自己评估输入之前,先生成评估查看器!你要尽快让用户看到这些内容!
  • 反馈的工作方式不同:由于没有运行中的服务器,查看器中的“Submit All Reviews”按钮会将 feedback.json 下载为文件。之后你可以从该文件读取反馈(可能需要先请求访问权限)。
  • 打包可以正常工作,package_skill.py 只需要 Python 和文件系统。
  • 描述优化(run_loop.py / run_eval.py)在 Cowork 中应可正常运行,因为它通过子进程调用 claude -p,而不是浏览器。但请先等 Skill 完全制作完成,并且用户认可其质量后再进行此步骤。
  • 更新现有 Skill:用户可能要求你更新已有的 Skill,而不是创建新的。请遵循上文 claude.ai 部分中的更新指南。

参考文件

agents/ 目录包含专用子 Agent 的说明。需要生成相应子 Agent 时再阅读这些文件。

  • agents/grader.md:如何根据输出评估断言
  • agents/comparator.md:如何对两个输出进行盲法 A/B 比较
  • agents/analyzer.md:如何分析一个版本胜过另一个版本的原因

references/ 目录包含其他文档:

  • references/schemas.md:evals.json、grading.json 等文件的 JSON 结构

再次重复核心循环,以示强调:

  • 明确 Skill 的用途
  • 起草或编辑 Skill
  • 在测试提示词上运行可访问该 Skill 的 Claude
  • 与用户一起评估输出:
    • 创建 benchmark.json,并运行 eval-viewer/generate_review.py,帮助用户进行审阅
    • 运行定量评估
  • 重复上述步骤,直到你和用户都满意
  • 打包最终 Skill 并交付给用户。

如果你有待办列表功能,请将这些步骤加入其中,以免遗漏。如果你在 Cowork 中,请务必在待办列表中加入“创建 evals JSON 并运行 eval-viewer/generate_review.py,以便用户审阅测试用例”这一项。

祝你好运!

评论

支持 Markdown