| name | skill-creator-cn |
| description | 创建新技能、修改和改进现有技能,以及衡量技能表现。当用户想要从头创建技能、编辑或优化现有技能、运行评估测试技能、通过方差分析对技能进行基准测试,或优化技能描述以提高触发准确性时使用。注意:这是一个中文版技能创建器,所有交互和产出均为中文。 |
| version | 1.0.0 |
| author | Hermes Agent (adapted from skill-creator) |
| license | MIT |
| metadata | {"hermes":{"tags":["skill-creation","evaluation","iteration","benchmarking","optimization"],"related_skills":["writing-plans","test-driven-development","subagent-driven-development"]}} |
技能创建器 (Skill Creator 中文版)
一个用于创建新技能并迭代改进的技能。
高层次上,创建技能的过程如下:
- 确定你希望技能做什么以及大致如何实现
- 撰写技能草稿
- 创建几个测试提示词(prompt),让拥有该技能的 Claude 运行它们
- 帮助用户定性和定量地评估结果
- 在运行进行的同时,如果没有定量评估则草拟一些;如果有则直接使用或根据需求修改。然后向用户解释这些评估
- 使用
eval-viewer/generate_review.py 脚本向用户展示结果,同时让他们查看定量指标
- 根据用户对结果的评估反馈来重写技能(同时也要注意定量基准中暴露出的明显缺陷)
- 重复上述步骤直到满意为止
- 扩展测试集,在更大规模上再次尝试
你使用此技能时的任务是:判断用户处于这个过程中的哪个阶段,然后介入并帮助他们推进。例如,用户可能会说"我想为 X 做一个技能"。你可以帮他们明确需求、写草稿、写测试用例、确定评估方式、运行所有提示词、然后重复迭代。
另一方面,也许用户已经有了一份技能草稿。这时你可以直接进入评估/迭代环节。
当然,你应当始终保持灵活——如果用户说"我不需要跑一堆评估,我们直接凭感觉来",你也可以照做。
技能完成之后(但同样,顺序是灵活的),你还可以运行描述优化脚本,来优化技能的触发准确性。
明白了吗?很好。
与用户沟通
技能创建器的使用者可能来自各种技术背景。有些人可能对编程术语很熟悉,有些人可能是第一次接触终端。请注意根据上下文线索调整你的沟通方式!默认情况下:
- "评估"和"基准测试"是可接受的词汇
- 对于"JSON"和"断言"这类术语,需要确认用户明白它们的含义后再使用
- 如果不确定,可以简单解释一下相关术语
这不会影响你们——你们通常是在和开发者或至少是有技术背景的用户打交道。但养成好习惯总是没错的。
创建技能
捕获意图
首先理解用户的意图。当前对话可能已经包含了用户想要封装成技能的工作流程(例如,用户说"把这个变成技能")。如果是这样,先从对话历史中提取答案——使用的工具、步骤顺序、用户的纠正、观察到的输入/输出格式。用户可能需要补充空缺内容,并且在进入下一步前应当确认。
- 这个技能应该让 Claude 能够做什么?
- 这个技能应该在什么情况下触发?(用户说什么话/在什么上下文中)
- 预期的输出格式是什么?
- 我们是否应该设置测试用例来验证技能是否正常工作?具有可客观验证输出的技能(文件转换、数据提取、代码生成、固定工作流步骤)适合有测试用例。具有主观输出的技能(写作风格、艺术)通常不需要。根据技能类型建议合适的默认方案,但让用户决定。
面谈与研究
主动询问关于边缘情况、输入/输出格式、示例文件、成功标准和依赖项的问题。在把这些问题弄清楚之前,先不要写测试提示词。
检查可用的工具——如果对研究有用(搜索文档、寻找类似技能、查找最佳实践),可以通过子代理并行研究,否则直接进行研究。做好准备以减少用户的负担。
编写 SKILL.md
根据用户面谈的结果,填写以下组成部分:
- name:技能标识符
- description:何时触发、做什么。这是主要的触发机制——既要包含技能做什么,也要包含何时使用它的具体上下文。所有"何时使用"的信息都放在这里,而不是正文中。注意:目前 Claude 有"欠触发"的趋势——在应该使用技能时不去使用。为了对抗这一点,请让技能描述稍微"强势"一些。例如,不要只写"如何构建一个简单的仪表盘",而是写"如何构建一个简单的仪表盘来展示内部数据。当你听到用户提到仪表盘、数据可视化、内部指标,或者用户想展示任何类型的公司数据时,务必使用此技能——即使他们没有明确提到'仪表盘'。"
- compatibility:所需的工具、依赖项(可选,很少需要)
- 技能的其余部分 :)
技能编写指南
技能的文件结构
skill-name/
├── SKILL.md(必需)
│ ├── YAML 前置元数据(name、description 为必需)
│ └── Markdown 指令
└── 捆绑资源(可选)
├── scripts/ - 用于确定性/重复性任务的可执行代码
├── references/ - 按需加载到上下文中的文档
└── assets/ - 输出中使用的文件(模板、图标、字体)
渐进式信息揭示
技能使用三级加载系统:
- 元数据(name + description)——始终在上下文中(约100词)
- SKILL.md 正文——触发技能时始终在上下文中(最好控制在500行以内)
- 捆绑资源——按需使用(不限量,脚本可以执行而无需加载)
这些字数仅供参考,如果需要可以延长。
关键模式:
- 保持 SKILL.md 在 500 行以内;如果接近此限制,增加一层层次结构,并明确指示使用该技能的模型下一步应该去哪里跟进
- 从 SKILL.md 中清晰地引用文件,并说明何时需要读取它们
- 对于大型参考文件(超过 300 行),包含目录
领域组织:当技能支持多个领域/框架时,按变体组织:
cloud-deploy/
├── SKILL.md(工作流 + 选择逻辑)
└── references/
├── aws.md
├── gcp.md
└── azure.md
Claude 只读取相关的参考文件。
无意外原则
技能不能包含恶意软件、漏洞利用代码或任何可能危及系统安全的内容。技能的内容不应当在被描述后让用户感到意外。不要协助创建具有误导性的技能,或旨在实现未授权访问、数据窃取或其他恶意活动的技能。角色扮演类的技能是可以的。
编写模式
在指令中优先使用祈使句。
定义输出格式 - 可以这样做:
## 报告结构
始终使用以下模板:
# [标题]
## 执行摘要
## 主要发现
## 建议
示例模式 - 包含示例是有帮助的。可以这样格式化(但如果"输入"和"输出"在示例中,你可能需要稍作调整):
## 提交信息格式
**示例 1:**
输入:使用 JWT 令牌添加用户认证
输出:feat(auth): implement JWT-based authentication
写作风格
尽量向模型解释为什么某些事情很重要,而不是用严厉的"必须"。运用心智理论,尽量让技能具有通用性,不要过于狭窄地针对特定示例。先写一份草稿,然后以全新的眼光审视并改进它。
测试用例
写好技能草稿后,提出 2-3 个真实的测试提示词——真实用户会说的那种。分享给用户:"这里有几个我想试试的测试用例。这些看起来对吗?还是你想添加更多?"然后运行它们。
将测试用例保存到 evals/evals.json。暂时不要写断言——只写提示词。你将在下一步——运行进行中的时候——起草断言。
{
"skill_name": "example-skill",
"evals": [
{
"id": 1,
"prompt": "用户的任务提示词",
"expected_output": "预期结果的描述",
"files": []
}
]
}
完整的 schema(包括 assertions 字段)请参考 references/schemas.md。
运行和评估测试用例
本节是一个连续的流程——不要中途停止。不要使用 /skill-test 或其他测试技能。
将结果放在 <skill-name>-workspace/ 中,作为技能目录的同级目录。在工作区内,按迭代组织结果(iteration-1/、iteration-2/ 等),在每个迭代中,每个测试用例对应一个目录(eval-0/、eval-1/ 等)。不要一次性创建所有目录——按需创建。
第一步:在同一轮中启动所有运行(带技能 + 基线)
对于每个测试用例,在同一轮中启动两个子代理——一个有技能,一个没有。这一点很重要:不要先启动带技能的运行然后回头做基线。一次性启动所有任务,这样它们会在大致相同的时间完成。
带技能运行:
执行此任务:
- 技能路径:<path-to-skill>
- 任务:<评估提示词>
- 输入文件:<评估文件(如果有),否则为"无">
- 保存输出到:<workspace>/iteration-<N>/eval-<ID>/with_skill/outputs/
- 需要保存的输出:<用户关心的内容——例如"docx 文件"、"最终的 CSV">
基线运行(相同的提示词,但基线取决于上下文):
- 创建新技能时:不使用任何技能。相同的提示词,不指定技能路径,保存到
without_skill/outputs/。
- 改进现有技能时:旧版本。编辑前,将技能快照保存(
cp -r <skill-path> <workspace>/skill-snapshot/),然后将基线子代理指向快照。保存到 old_skill/outputs/。
为每个测试用例编写一个 eval_metadata.json(断言可以为空)。根据测试内容给每个评估起一个描述性的名称——而不仅仅是"eval-0"。目录名也使用这个名称。如果本次迭代使用了新的或修改过的评估提示词,请为每个新评估目录创建这些文件——不要假设它们会从之前的迭代继承。
{
"eval_id": 0,
"eval_name": "描述性名称",
"prompt": "用户的任务提示词",
"assertions": []
}
第二步:在运行进行的同时,起草断言
不要干等运行结束——你可以利用这段时间高效工作。为每个测试用例起草定量断言,并向用户解释它们。如果断言已存在于 evals/evals.json 中,请审查它们并解释每一条的检查内容。
好的断言是可客观验证的,并且有描述性名称——它们应该在基准查看器中清晰可读,让瞥一眼结果的人立刻明白每条断言在检查什么。主观技能(写作风格、设计质量)更适合定性评估——不要把断言强加到需要人类判断的事情上。
更新 eval_metadata.json 文件和 evals/evals.json,加入起草好的断言。同时向用户解释他们在查看器中会看到什么——包括定性的输出和定量的基准数据。
第三步:当运行完成时,捕获计时数据
当每个子代理任务完成时,你会收到包含 total_tokens 和 duration_ms 的通知。立即将此数据保存到运行目录下的 timing.json 中:
{
"total_tokens": 84852,
"duration_ms": 23332,
"total_duration_seconds": 23.3
}
这是捕获此数据的唯一机会——它通过任务通知传入,不会被持久化到其他地方。每条通知到达时立即处理,而不是尝试批量处理。
第四步:评分、聚合和启动查看器
当所有运行完成后:
-
对每次运行进行评分——启动一个评分子代理(或直接评分),读取 agents/grader.md 并评估每条断言。将结果保存到每个运行目录的 grading.json 中。grading.json 的 expectations 数组必须使用 text、passed 和 evidence 字段(而不是 name/met/details 等其他变体)——查看器依赖这些确切的字段名。对于可以通过编程方式检查的断言,编写并运行脚本而不是人工目测——脚本更快、更可靠,并且可以在多次迭代中复用。
-
聚合为基准——从技能创建器目录运行聚合脚本:
python -m scripts.aggregate_benchmark <workspace>/iteration-N --skill-name <name>
这会生成 benchmark.json 和 benchmark.md,包含每种配置的通过率、时间和 token 数,以及均值 ± 标准差和差值。
-
进行分析——阅读基准数据,挖掘聚合统计可能隐藏的模式。查看 agents/analyzer.md("分析基准结果"部分),了解需要关注的内容——比如总是通过的断言(无区分度)、高方差评估(可能不稳定)以及时间/token 的权衡。
-
启动查看器,同时展示定性的输出和定量的数据:
python eval-viewer/generate_review.py \
<workspace>/iteration-N \
--skill-name "my-skill" \
--benchmark <workspace>/iteration-N/benchmark.json \
> /dev/null 2>&1 &
VIEWER_PID=$!
对于第二次及以后的迭代,额外传入 --previous-workspace <workspace>/iteration-<N-1>。
无头/远程环境:如果 webbrowser.open() 不可用或环境没有显示器,使用 --static <output_path> 生成独立 HTML 文件而非启动服务器。当用户点击"提交所有反馈"时,反馈会作为 feedback.json 文件下载。
- 告诉用户:"我已经在浏览器中打开了结果。有两个标签页——'输出'让你可以逐个点击并留下反馈,'基准'显示定量对比。完成后回到这里告诉我。"
用户在查看器中看到的内容
"输出"标签页每次显示一个测试用例:
- 提示词:给定的任务
- 输出:技能生成的文件,尽可能内联渲染
- 之前的输出(第二次及以上迭代):折叠区域,显示上一次迭代的输出
- 正式评分(如果运行了评分):折叠区域,显示断言通过/失败
- 反馈:文本框,输入时自动保存
- 之前的反馈(第二次及以上迭代):他们上次的评论,显示在文本框下方
"基准"标签页显示统计汇总:每种配置的通过率、计时和 token 使用情况,以及每个评估的详细分解和分析师观察。
使用上一个/下一个按钮或箭头键导航。完成后,点击"提交所有反馈"将所有反馈保存到 feedback.json。
第五步:读取反馈
当用户告诉你他们已经完成时,读取 feedback.json:
{
"reviews": [
{"run_id": "eval-0-with_skill", "feedback": "图表缺少轴标签", "timestamp": "..."},
{"run_id": "eval-1-with_skill", "feedback": "", "timestamp": "..."},
{"run_id": "eval-2-with_skill", "feedback": "完美,非常喜欢", "timestamp": "..."}
],
"status": "complete"
}
空反馈意味着用户认为没问题。将改进集中在用户有具体抱怨的测试用例上。
完成后杀掉查看器服务器:
kill $VIEWER_PID 2>/dev/null
改进技能
这是迭代循环的核心。你已经运行了测试用例,用户已经审查了结果,现在你需要根据他们的反馈来改进技能。
如何思考改进
-
从反馈中归纳。 大图景是:我们正在尝试创建可以被使用一百万次(甚至更多)的技能,覆盖许多不同的提示词。在这里,你和用户反复迭代少数几个例子,因为这样推进更快。用户对这些例子了如指掌,能快速评估新输出。但如果你和用户共同开发的技能只对这些例子有效,那就没用了。与其做零碎的过度拟合修改,或施加压迫性的"必须",不如尝试使用不同的隐喻或推荐不同的工作模式。尝试的成本很低,也许你会找到更好的方案。
-
保持提示词简洁。 删除那些没有贡献的内容。确保阅读对话记录,而不仅仅是最终输出——如果技能让模型浪费大量时间做无产出的事情,试着删除导致这种情况的技能部分,看看会发生什么。
-
解释为什么。 努力解释你要求模型做每一件事的为什么。今天的 LLM 非常聪明。它们有良好的心智理论,在合理的框架下可以超越机械的指令,真正把事情做成。即使用户的反馈简短或带有挫败感,尝试真正理解任务,理解用户写下的内容背后的原因,然后将这种理解传达给指令。如果你发现自己写了全大写的"ALWAYS"或"NEVER",或者使用了超级僵化的结构,这是一个黄旗——如果可能,重新构建并解释原因,让模型理解你要求的事情为什么重要。这是一种更人性化、更有力、更有效的方法。
-
留意测试用例之间的重复工作。 阅读测试运行的对话记录,注意多个子代理是否独立编写了类似的辅助脚本,或者采取了相同的多步骤方法。如果 3 个测试用例都导致子代理写了 create_docx.py 或 build_chart.py,这是一个强烈的信号,表明技能应该打包这个脚本。编写一次,放入 scripts/,告诉技能使用它。这样每次调用都无需重新发明轮子。
这项任务非常重要(我们正在尝试创造巨大的经济价值!),你的思考时间不是瓶颈——花点时间真正深思熟虑。我建议先写一份修改草稿,然后重新审视并改进。尽最大努力进入用户的头脑中,理解他们真正想要和需要什么。
迭代循环
改进技能后:
- 将改进应用到技能中
- 将所有测试用例重新运行到一个新的
iteration-<N+1>/ 目录中,包括基线运行。如果你在创建新技能,基线始终是 without_skill(无技能)——这在各迭代中保持不变。如果你在改进现有技能,用你的判断决定什么是合适的基线:用户最初带来的原版,还是上一次迭代。
- 使用
--previous-workspace 指向上一次迭代来启动查看器
- 等待用户审查并告诉你他们已完成
- 读取新的反馈,再次改进,重复
持续进行直到:
- 用户说他们满意了
- 所有反馈都是空的(一切都看起来不错)
- 你不再取得有意义的进展
高级:盲测对比
对于想要在技能的两个版本之间进行更严格比较的情况(例如,用户问"新版本真的更好吗?"),有一个盲测对比系统。读取 agents/comparator.md 和 agents/analyzer.md 了解详情。基本思路是:将两个输出交给一个独立代理,不告诉它哪个是哪个,让它评判质量。然后分析胜出者为什么胜出。
这是可选的,需要子代理,大多数用户不需要。人工审查循环通常就足够了。
描述优化
SKILL.md 前置元数据中的 description 字段是决定 Claude 是否调用技能的主要机制。创建或改进技能后,主动提议优化描述以提高触发准确性。
第一步:生成触发评估查询
创建 20 个评估查询——混合应触发和不应触发的场景。保存为 JSON:
[
{"query": "用户的提示词", "should_trigger": true},
{"query": "另一个提示词", "should_trigger": false}
]
查询必须是真实的,是 Claude Code 或 Claude.ai 用户会实际输入的内容。不要使用抽象的请求,而应该是具体且有一定细节的请求。例如,文件路径、关于用户工作或情况的个人背景、列名和值、公司名称、URL。一些简短的背景故事。有些可能是小写的,或包含缩写、拼写错误或口语化表达。混合使用不同长度,重点关注边缘情况。
应触发的查询(8-10 个),考虑覆盖率。你需要不同措辞的同一意图——有些正式,有些随意。包括用户没有明确说出技能名称但明显需要它的情况。加入一些不常见的用例,以及这个技能与另一个技能竞争但应该胜出的情况。
不应触发的查询(8-10 个),最有价值的是"近失"情况——与技能共享关键词或概念但实际上需要不同技能的查询。考虑相邻领域、模糊措辞(关键词匹配会触发但实际上不应该)、以及查询涉及技能能做但在上下文中其他工具更合适的情况。
要避免的关键点是:不要让不应触发的查询明显不相关。"写一个斐波那契函数"作为 PDF 技能的负测试太容易了——它测试不了什么。负例应该是真正有迷惑性的。
第二步:与用户一起审查
使用 HTML 模板向用户展示评估集以供审查:
- 从
assets/eval_review.html 读取模板
- 替换占位符:
__EVAL_DATA_PLACEHOLDER__ → JSON 格式的评估项数组(不要加引号)
__SKILL_NAME_PLACEHOLDER__ → 技能名称
__SKILL_DESCRIPTION_PLACEHOLDER__ → 技能的当前描述
- 写入临时文件(如
/tmp/eval_review_<skill-name>.html)并打开
- 用户可以编辑查询、切换应触发状态、添加/删除条目,然后点击"导出评估集"
- 文件会下载到
~/Downloads/eval_set.json
这一步很重要——糟糕的评估查询会导致糟糕的描述。
第三步:运行优化循环
告诉用户:"这需要一些时间——我会在后台运行优化循环并定期检查进度。"
将评估集保存到工作区,然后在后台运行:
python -m scripts.run_loop \
--eval-set <path-to-trigger-eval.json> \
--skill-path <path-to-skill> \
--model <当前会话使用的模型 ID> \
--max-iterations 5 \
--verbose
使用你系统提示中的模型 ID(当前会话使用的那个),这样触发测试与用户实际体验一致。
在运行期间,定期检查输出,向用户更新当前迭代和分数情况。
这会自动处理完整的优化循环。它将评估集分成 60% 训练集和 40% 留出测试集,评估当前描述(每个查询运行 3 次以获得可靠的触发率),然后调用 AI 根据失败情况提出改进建议。它在训练集和测试集上重新评估每个新描述,最多迭代 5 次。完成后,会在浏览器中打开一个 HTML 报告,显示每次迭代的结果,并返回 JSON 格式的 best_description——根据测试集分数而不是训练集分数选择,以避免过拟合。
技能触发的工作原理
了解触发机制有助于设计更好的评估查询。技能出现在可用技能列表中,包含名称和描述,Claude 根据描述决定是否查阅技能。需要知道的是,Claude 只为它不能轻易独立处理的任务查阅技能——简单的一步查询(如"读取这个 PDF")可能不会触发技能,即使描述完美匹配,因为 Claude 可以直接用基本工具处理。复杂、多步或专业化的查询会在描述匹配时可靠地触发技能。
这意味着你的评估查询应该足够充实,让 Claude 能从中受益。简单的查询(如"读取文件 X")是糟糕的测试用例——无论描述质量如何,它们都不会触发技能。
第四步:应用结果
从 JSON 输出中取 best_description 并更新技能的 SKILL.md 前置元数据。向用户展示前后对比并报告分数。
打包和交付
检查你是否有访问打包工具的权限。如果有,打包技能并向用户展示技能文件路径。
python -m scripts.package_skill <path/to/skill-folder>
打包后,将生成的技能文件路径告知用户,以便他们安装。
更新现有技能
用户可能要求你更新现有技能,而非创建新技能。此时:
- 保留原始名称。 注意技能目录名和
name 前置字段——保持不变。例如,如果已安装的技能是 research-helper,输出 research-helper.skill(而不是 research-helper-v2)。
- 复制到可写位置后再编辑。 已安装的技能路径可能是只读的。复制到
/tmp/skill-name/,在那里编辑,并从副本打包。
- 如果手动打包,先在
/tmp/ 中准备,然后复制到输出目录——直接写入可能因权限而失败。
参考文件
agents/ 目录包含专门子代理的指令。当你需要启动相关子代理时读取它们。
agents/grader.md —— 如何评估断言与输出
agents/comparator.md —— 如何进行盲测 A/B 对比
agents/analyzer.md —— 如何分析一个版本为什么胜过另一个
references/ 目录有更多文档:
references/schemas.md —— evals.json、grading.json 等的 JSON 结构
再次强调核心循环:
- 确定技能是关于什么的
- 起草或编辑技能
- 让拥有该技能的 Claude 在测试提示词上运行
- 与用户一起评估输出:
- 创建 benchmark.json 并运行
eval-viewer/generate_review.py 帮助用户审查
- 运行定量评估
- 重复直到你和用户都满意
- 打包最终技能并交付给用户
请在任务清单中添加步骤,确保你不会忘记。确保将"创建 evals JSON 并运行 eval-viewer/generate_review.py 让用户审查测试用例"放入任务清单中。
祝你好运!