mcpField
I
improve-skill-quality

improve-skill-quality

github.com/dotnetAgent 工作流5.8k2.7k 次安装1 天前更新
代码仓库

关于 improve-skill-quality

improve-skill-quality 是用于诊断技能评测表现不佳或结论不确定的技能,强调先查明原因再修改内容。它区分 fixture、harness、可靠性、统计效力、评测设计、激活和内容问题,并指导针对性修复与复验。

主要功能

  1. 01按证据分类评测失败原因
  2. 02区分隔离组与插件组的激活情况
  3. 03检查 fixture、harness 和可靠性问题
  4. 04评估统计效力与评测设计
  5. 05指导内容调整及重新验证

适用场景

  1. 01处理回归或提升不足的评测结果
  2. 02排查评测无结果、超时或输出为空
  3. 03调查技能未激活或成本增加

安装

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

$npx skills add https://github.com/dotnet/skills --skill improve-skill-quality

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

附带文件references/eval-triage.mdreferences/writing-for-baseline-delta.md

详细介绍

提升技能质量

将失败或缺乏说服力的评估转化为有针对性的修复。本仓库中最常见的错误,是根据评估结论重写技能文案,而真正的问题其实出在评估、测试夹具或测试框架上。先分类,再修复。

适用场景

  • 评估结论为回归、效力不足或“没有可信的提升”。
  • 技能在独立组中表现更好,但在插件组中没有,或报告称“未激活”。
  • /evaluate 报告“评估已运行,但没有生成结果”。
  • 技能得分不错,但成本过高(token 数、轮数、耗时、插件菜单预算)。
  • 决定是否加强或弃用长期表现不佳的技能。

不适用场景

  • 从头创建新技能——使用 create-skill。
  • 从头创建新的 eval.yaml——使用 create-skill-test。
  • 修改测试框架本身(eng/skill-validator、eng/vally-adapter、evaluation*.yml)。

输入

输入必需说明
结论证据是/evaluate 的 PR 评论,或运行产物中的 results.json
失败试验记录内容修复时必需基线与启用技能后的输出,以及评审给出的理由
刺激项投票 W/T/L 和重复运行 W/T/L是区分跨任务证据与可靠性
各组的激活状态是独立组和插件组中的激活失败并不相同

工作流

第 1 步:先获取证据,再形成假设

阅读 InvestigatingResults.md,了解如何下载产物并读取 results.json。针对每个失败的刺激项,提取:

  • 权威的刺激项投票 W/T/L,以及单独的重复运行 W/T/L
  • 独立组和插件组中的激活状态,分别记录
  • 评审对每个失败试验给出的原文理由
  • 是否有试验出错、超时或产生空输出

在能够引用失败试验及评审给出的理由之前,不要修改技能内容。对于其他原因类别,证据则有所不同:测试框架故障要根据作业日志和规格诊断,效力问题要根据试验记录诊断——这两种情况都没有可供引用的失败试验,执意要求提供此类记录,正是导致人们错误地重写文案的原因。

第 2 步:对失败进行分类

按顺序检查下表,遇到第一个符合的行时就停止。各行按症状被误判为技能内容问题的频率排序——夹具问题排在第一,因为夹具故障也会表现为设置或可靠性故障,从而被错误归入这些类别。

症状实际原因类别转到
测试夹具无法构建、未被 git 跟踪、因错误原因而失败,或自相矛盾测试夹具第 4 步
没有 results.json、报告“没有生成结果”,或规格从未加载测试框架 / 规格加载第 3 步
试验出错、超时或返回空输出可靠性第 3 步
轨迹未匹配、试验出错或摘要不一致——结论报告为无法判定可靠性(不是效力问题)第 3 步
记录为正向(例如 16W/8T/1L)、比较结果明确,但结论仍未通过统计效力第 5 步
启用技能组按设计就与基线组相同评估设计第 6 步
已激活,但质量表现不佳,评审指出了具体缺陷技能内容第 7 步
在独立组中已激活,在插件组中未激活激活 / 路由第 8 步
在两个组中都未激活Frontmatter 描述第 8 步
获胜,但成本远高于基线范围与成本第 7 步

只有比较结果明确,结论才是经过测量的结果:adapt.mjs 要求没有出错的试验、没有未匹配的轨迹,并且摘要一致,之后才会报告通过或回归。将记录判定为效力问题之前,请先确认这一点。

步骤 3:排除测试框架和可靠性问题

完整目录请参阅 references/eval-triage.md。常见问题如下:

  • 仓库门禁会拒绝已弃用的顶层 config: 别名,而 Vally 会拒绝同时声明 config: 和 defaults: 的规范。请将该别名替换为一个 defaults: 块。
  • 试验出错不一定是 fixture 问题——从判定结果看,评判端的身份验证和 session.idle 故障完全相同,需要修复测试框架,而不是固定 SDK 版本。
  • 在建议性问题上设置 expect_tools: [bash] 会强制执行还原或构建,并使回答超时,却不会提升质量。
  • 真正的代码生成刺激大约需要 360s;超时会导致输出为空,从而无法通过任何评分器,并掩盖真正的质量信号。
  • 轨迹不匹配、试验出错或摘要不一致,都会使比较变为无法得出结论:其余匹配试验存在偏差,因此该记录不是经测量得出的无效结果,也不应被解读为统计效能或内容问题。
  • 通用 YAML 解析器并非生产环境加载器。如果 Vally 拒绝某项技能评估,或原生 SDK 测试通道拒绝 Agent 评估中的可执行场景字段,应先归类为测试框架/规范加载问题,再更改内容。原生 Agent 解析器会忽略黄金参考,因此应使用 check_eval_quality.py 和确定性的黄金工作区重放,单独验证这些参考。
  • 单个工作进程通过,或本地超时时间延长后通过,都不能作为正常执行的证据。请使用仓库的正常并发数和声明的套件预算复现;若仍失败,则属于可靠性缺陷。
步骤 4:修改技能前先验证 fixture

运行 python eng/eval-quality/check_eval_quality.py——它会拦截 22 类可能导致此处实际结果受损的缺陷。然后手动确认:

  • 每个 fixture 的行为都符合其刺激的假设——预期正常的 fixture 能成功构建;预期有问题的 fixture 会因刺激所针对的确切原因而失败,且不存在其他原因;
  • 每个引用的 fixture 都已纳入 Git 索引(git ls-files),而不只是存在于磁盘上——.gitignore 曾悄然忽略已提交的覆盖率 fixture;
  • fixture 不会在两个地方陈述同一事实,却给出互相矛盾的内容——Cobertura 报告中的声明 line-rate、摘要总数和 <line> 元素不一致,就是典型案例——或者两个分支确实读取了不同的事实。
  • 每项保留或范围断言都覆盖完整的范围内文件集,而不只是一个代表性文件。
  • 黄金轨迹和补丁都能通过确定性评分器,并且现实的错误变更会被负责保护该行为的评分器判为失败。
步骤 5:确认评估是否有可能通过

门禁有两项彼此独立的标准,混淆二者是最常见的误诊原因:

  1. 不同刺激数量 ≥ 5。 少于此数量时,判定结果会报告为 underpowered——既不算通过,也不算回归。
  2. 符号检验必须在不一致(非平局)刺激投票上达到 p ≤ 0.05。 平局不会被悄然丢弃;它们会减少不一致投票的数量。
不一致刺激投票数通过的记录p
≤ 4无论技能多好,都没有≥ 0.0625
5–7仅零负向票(5W/0L)0.031
8可容忍一次负向票(7W/1L)0.035

因此,恰有 5 个刺激时,一次平局就会导致失败——不一致投票只剩 4 个。6 个刺激时,可以容忍一次平局(5W/1T/0L);7 个刺激时,最多可以容忍两次(5W/2T/0L)。负向票则不行。

因此,正向记录却未通过判定,说明是统计效能问题,而不是内容问题。请通过增加具有区分度的刺激来解决。提高 runs 只会测量同一任务的可靠性,无法达到最低要求。

步骤 6:检查两组是否存在差异

将技能与自身进行比较的评测,测量的是评判器噪声:

  • 休眠保护(expect_activation: false)不得同时设置 constraints.reject_skills。 这样会让启用技能的一组不含任何技能,因此激活契约无法检测到劫持。 架构版本 4 会保留相同组比较以供诊断,但不会将其用于偏好推断;意外的单独激活仍会导致评测不通过。
  • 设置了 disable-model-invocation: true 的技能不会出现在面向模型的启用技能组中,因此无论评判器检查的是激活情况还是回答内容,其直接评测比较的都是两组相同的内容。应通过使用者的结果来覆盖它;例如,filter-syntax 由 run-tests 和 mtp-hot-reload 覆盖。
  • 如果评判器的 config 缺少必需的键,就不会执行任何约束,因此刺激项实际包含的断言比表面上少一个。
步骤 7:根据落败的试验修复技能内容

现在才修改技能。应用 references/writing-for-baseline-delta.md 中的模式;以下做法最常让结果从落败转为获胜:

  • 将模型已经掌握的参考性说明替换为模型原本会判断错误的决策要点。
  • 添加停止条件,避免强大的技能过度应用;但不要矫枉过正,让回答比基线更狭窄。
  • 根据输入规模调整输出结构;对于包含 8 个测试的套件,仪表板不如直接回答。
  • 要求如实报告验证结果;恢复失败后却声称“Build succeeded”会直接导致落败。
  • 通过编译或探测来验证关键 API 声明,而不是阅读源代码。
  • 对于成本回退,将罕见或昂贵的路径放在 references/ 读取之后,并让编排规模与用户需求相匹配。
步骤 8:修复激活问题

激活失败属于 frontmatter 和路由问题,而非正文问题。参见 references/eval-triage.md。概要如下:

失败情况修复方法
所有组都未激活在 description 中使用用户自己的措辞:症状、错误代码、产物名称和引用的请求
另一个同级技能在提示词中胜出在 description 中声明这些确切的歧义措辞,并为两个同级技能添加相应的排除项
模型完全不使用技能直接作答在描述中强调问题的重要性,精简插件菜单,并通过插件组验证
边界排除了真实场景对照每条评测提示词和真实工作流阶段,重新检查每个“不要用于”条款
描述达到 1,024 个字符上限删除重复说明的正文内容,而不是触发短语;同时检查插件菜单预算
步骤 9:重新验证
dotnet run --project eng/skill-validator/src/SkillValidator.csproj -- check --plugin ./plugins/<plugin>
python eng/eval-quality/check_eval_quality.py
./eng/run-skill-evals.sh <plugin> <skill>

使用生产路径,在正常的工作器并发下,并采用声明的 defaults.timeout: 技能评测使用 Vally,Agent 评测使用 skill-validator evaluate。对于 Agent 评测,请另外运行 check_eval_quality.py,将每个 golden 补丁应用到其物化的 fixture,并针对 golden 结果运行适用的确定性文件、输出和命令评判器。不要将仅串行运行的通过结果或临时增加的预算作为完成依据。对于广泛的路由或行为变更,请分别收集 GPT 系列和 Claude 系列的结果。不要将不同模型系列的结果合并为额外的刺激项投票。

然后,在 PR 评审中提交 /evaluate(Files changed → Review changes),以请求官方运行,并将运行绑定到已评审的提交。在根据结果判定回归之前,请确认技能载荷确实发生了变化——对字节完全相同的内容重新运行,结果可能会从 7W/2T/2L 变为 4W/5T/2L。

验证

  • 对于内容修复,PR 描述中引用了一次失败的试验以及评审者给出的理由。
  • 在编辑任何内容之前,已对失败进行分类。
  • check_eval_quality.py 和 skill-validator check 均通过。
  • 生产环境中的技能或 Agent 运行器接受该可执行规范。
  • 黄金参考通过独立检查器和确定性重放。
  • 评估在正常并发条件和声明的时间预算内完成。
  • 已证明黄金验收和变异拒绝。
  • 不同刺激的数量达到目标效果和观察到的平局率所需的统计功效门槛。
  • 已分别报告独立激活和插件激活。
  • 大范围更改提供了 GPT 系列和 Claude 系列的独立证据。
  • PR 正文记录了根本原因、修复和验证结果,以便复用经验。

常见陷阱

陷阱解决方案
因统计功效不足的判定而重写技能说明统计功效不足意味着不同刺激太少;应添加有区分度的刺激
使用已弃用的顶层 config: 别名将其改为 defaults: 并保留其设置;仓库门禁会拒绝该别名
增加 runs 数量来达到刺激数量下限重复运行衡量的是单项任务的可靠性;应添加刺激
将出错的试验视为夹具不确定性首先查看 stderr;评审端的身份验证失败需要修复测试框架
修复一个“错误”答案,而实际上是夹具使答案变得错误归咎于回复之前,先检查夹具是否自洽
强化一个无人使用且没有任何通过项的技能评估信号弱且遥测数据有限,是合理的退役依据
修复后不重新运行便合并确认调用的负载中包含该修复;评审噪声确实存在

参考资料

评论

支持 Markdown