# 触发测试——让 description 在真实对话里可靠 触发是 skill 的生命线:触发不了,写得再好也是死代码。测试分两层,先冒烟后实测。 ## 第一层:冒烟测试(脚本,秒级) ```bash python3 scripts/trigger_eval.py ``` 脚本做三件确定性的事: 1. 解析 description,与用例文件里 `positive_concepts` 声明的**概念族词表**合并; 2. 对每条测试原话做概念族匹配:命中负触发词直接判不触发;否则需命中全部 `required_families`(如 skill 实体族——"优化提示词"没有 skill 就不该触发)且总命中族数 ≥ `families_required`(默认 2,防止单个词误伤);同时计算词面覆盖率作参考信息; 3. 输出 `reports/trigger-eval.json`(每条 case 的判定、命中族、覆盖率)。 它是**词面信号检查**,不是行为判断——作用是快速暴露"description 里根本没写用户会说的词"这类硬伤。没有配置概念族的用例文件会退化为纯覆盖率阈值模式。 ## 第二层:真实对话实测(必做) 冒烟全绿不代表会触发。在**新的对话轮**里,把测试原话当真实请求发给模型,观察: - 该触发的原话,skill 有没有被加载、有没有按正文执行; - 不该触发的原话,有没有误伤。 每档至少测: - **应触发** 3–5 条:覆盖不同说法(口语/正式/中英混合)、不同入口(直接请求/丢来材料/求助式提问)。 - **不应触发** 2–3 条:相邻请求("优化这段提示词"vs"优化这个 skill")、一次性任务。 - **边界** 1–2 条:模糊但倾向触发的("这个流程每次都要重复讲一遍,烦死了")。 ## 用例文件设计 `evals/trigger_cases.json` 的用例来自**用户真的会说的话**,不是设计师的语言。写用例时: ```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` 段:每条原话、期望、实际、结论。没做实测就标注「实测证据缺失」,不假装做过。