- SKILL.md 双工作流(创建/迭代)+ 两道门(验料/通用化)+ 三档位 - 7 篇方法论 references + 3 个纯标准库脚本(scaffold/validate/trigger_eval) - 自身触发用例 16 条 + 先例研究/创建/迭代证据报告 - 方法论吸收自 qiaomu-meta-skill 与 luban-skill,取舍见 reports/prior-art.md
3.1 KiB
3.1 KiB
触发测试——让 description 在真实对话里可靠
触发是 skill 的生命线:触发不了,写得再好也是死代码。测试分两层,先冒烟后实测。
第一层:冒烟测试(脚本,秒级)
python3 scripts/trigger_eval.py <skill目录>
脚本做三件确定性的事:
- 解析 description,与用例文件里
positive_concepts声明的概念族词表合并; - 对每条测试原话做概念族匹配:命中负触发词直接判不触发;否则需命中全部
required_families(如 skill 实体族——"优化提示词"没有 skill 就不该触发)且总命中族数 ≥families_required(默认 2,防止单个词误伤);同时计算词面覆盖率作参考信息; - 输出
reports/trigger-eval.json(每条 case 的判定、命中族、覆盖率)。
它是词面信号检查,不是行为判断——作用是快速暴露"description 里根本没写用户会说的词"这类硬伤。没有配置概念族的用例文件会退化为纯覆盖率阈值模式。
第二层:真实对话实测(必做)
冒烟全绿不代表会触发。在新的对话轮里,把测试原话当真实请求发给模型,观察:
- 该触发的原话,skill 有没有被加载、有没有按正文执行;
- 不该触发的原话,有没有误伤。
每档至少测:
- 应触发 3–5 条:覆盖不同说法(口语/正式/中英混合)、不同入口(直接请求/丢来材料/求助式提问)。
- 不应触发 2–3 条:相邻请求("优化这段提示词"vs"优化这个 skill")、一次性任务。
- 边界 1–2 条:模糊但倾向触发的("这个流程每次都要重复讲一遍,烦死了")。
用例文件设计
evals/trigger_cases.json 的用例来自用户真的会说的话,不是设计师的语言。写用例时:
{
"negative_patterns": ["不要做成 skill", "只要总结", "翻译一下"],
"should_trigger": [
{"text": "帮我把每周的周报整理做成一个 skill", "family": "cn_workflow"},
{"text": "turn this checklist into a skill", "family": "en_workflow"}
],
"should_not_trigger": [
{"text": "把这篇文章翻译成英文", "family": "translate_only"}
],
"near_neighbor": [
{"text": "帮我优化这段提示词", "family": "prompt_not_skill"}
]
}
- 每条标注
family,回归时按族看退化。 - 用例随真实误触发/漏触发事件增长:每次现场翻车,把那句话原样收编成用例——这是触发资产的本金。
near_neighbor是最值钱的一族:它们定义了边界。
判定与修复
- 漏触发 → description 缺场景词或写得太被动 → 补触发短语,重跑。
- 误触发 → 缺负触发 → 在 description 加"不要用于……",重跑。
- 修 description 而不是加规则正文——触发问题永远先在触发信号上修。
- 改完 description 必须全量重跑用例,防止按下葫芦浮起瓢。
记录
rigorous 档把实测结果记进 reports/trigger-eval.json 的 live_turns 段:每条原话、期望、实际、结论。没做实测就标注「实测证据缺失」,不假装做过。