mcpField
O
opik-verify

opik-verify

github.com/comet-ml测试与质量855 次安装6 周前更新
代码仓库

关于 opik-verify

opik-verify 按声明的发布策略评估 Opik 基线与候选运行结果,供团队判断变更是否可以发布。它会报告判定、各项阈值与观测结果及失败案例,不修改应用代码,也不部署。

主要功能

  1. 01应用策略文件或文档默认值
  2. 02检查回归、安全性和通过率
  3. 03评估子组、延迟和成本指标
  4. 04报告证据量和评判器验证状态
  5. 05列出未通过标准及相关案例
  6. 06按请求记录判定结果

适用场景

  1. 01比较评估运行后为变更设置发布门槛
  2. 02发布前检查安全回归
  3. 03判断是否需要补充评估证据

MCP 相关

使用 Opik 托管 MCP 时,该技能可通过实验列表工具查找运行摘要;条目级比较使用 SDK。MCP 并非必需。

安装

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

$npx skills add https://github.com/comet-ml/opik-skills --skill opik-verify

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

详细介绍

Verify — 依据可读的策略决定发布还是暂缓

完成定义:根据基线与候选数据,按照一项已声明的策略计算出一个结论——ship、hold、needs_review 或 insufficient_evidence——并列出每项标准及其阈值、观测值和通过/失败情况,指出任何失败背后的案例,并提供比较视图链接。策略采用仓库中的 opik-release-policy.yaml 或文档所述的默认值,报告中须说明采用了哪一个。如果无法读取两次运行的数据,或二者不可比较,则在遇到第一个真正的阻碍时停止,并且只返回一个后续步骤。“我觉得不错”不算结论;没有列明标准的结论也不算。

操作方式:**机械地应用策略,展示计算过程,若评审器未经验证就拒绝发布,并且不更改任何应用代码。**此技能唯一可以写入的文件是策略文件,而且只有用户明确要求时才可以写入。它绝不部署。

输入

入口可以是紧接 /opik-compare(提供其基线和候选运行)之后的 /opik-verify、/opik-verify <suite>(该套件最近的两次运行),或 /opik-verify <baseline-id> <candidate-id>。推断其余信息;以下均为可选覆盖项:

  • policy(默认:仓库根目录或 .opik/ 下的 opik-release-policy.yaml,否则使用以下默认值)·要比较哪些实验(默认:如上所述)·--record(默认:关闭——将结论写入候选实验的配置)。

只有遇到真正无法推断的阻碍时才提问(参见阻碍)。

策略

所有键均为可选;缺少的键采用以下默认值。报告中说明采用了哪个来源。

# opik-release-policy.yaml — repo root or .opik/. Versioned with the code so the gate is reproducible.
min_items: 10                      # fewer scored items than this -> insufficient_evidence, never ship
max_regressions: 0                 # pass -> fail cases allowed (flaky items excluded when flaky_policy: exclude)
pass_rate: not_below_baseline      # or a number in 0..1; candidate pass rate must satisfy it
safety_tags: [safety]              # a regression on an item whose data.tags contains one of these -> hold, always
subgroup_key: null                 # a data key (e.g. "category"); no subgroup's pass rate may fall
latency_p90_max_increase: 0.25     # candidate p90 duration vs baseline (experiments expose p50/p90/p99)
cost_per_item_max_increase: 0.25   # candidate mean cost per item vs baseline, as a fraction
flaky_policy: exclude              # exclude | count — an item that flips between runs of the SAME code is flaky
judge_validated: false             # set true once the suite's judge has been checked against human labels

judge_validated: false 是人工审核门槛:在有人确认评审器的判断与人一致之前(参见 /opik-evaluate 的 validate-evaluator 参考),即使运行通过,也会得到 needs_review,而不是 ship。确认完成后,在文件中将其改为 true——这必须由人工编辑,绝不会由此技能自行设置。

激活 — 唯一在范围内的工作

1. 加载策略

先在仓库根目录查找 opik-release-policy.yaml,再查找 .opik/。解析文件;遇到未知键 → 阻碍(指出该键)。没有文件 → 使用默认值,并说明这一点。绝不使用文件或默认值中未列出的阈值。

2. 确定两次运行

如果刚运行过 /opik-compare,则采用其输出中的运行。否则:

import opik
client = opik.Opik()
runs = sorted(client.get_test_suite_experiments(name="<suite>", project_name="<project>"),
              key=lambda e: e.get_experiment_data().created_at)
baseline, candidate = runs[-2], runs[-1]     # or the two ids the user gave

跳过评审失败的运行(评审器没有凭据的运行不能作为候选——/opik-compare 会说明这种情况是如何发生的)。scoring_failed 不会保留在读取路径中;读取回来的信号是:每个条目均失败,且每条断言的 reason 都提到缺少凭据或 LLM 基础设施错误。说明跳过了哪次运行以及原因。连接了托管 MCP 时,list('experiment', name=…) 会显示每次运行的平均值和通过率,可用于选择;条目级别的读取仍通过 SDK 完成。

3. 逐条读取两次运行

一次实验中,每次运行每个数据项可能对应多个条目:当 runs_per_item: 3 时,一个数据集条目会出现三次,具有相同的 dataset_item_id 和不同的 trace_id。请分组处理——使用以 dataset_item_id 为键的字典会悄悄保留一次运行,丢失其余计数。

from collections import defaultdict
def by_item(exp):
    groups = defaultdict(list)
    for i in exp.get_items():
        groups[i.dataset_item_id].append(i)      # each: dataset_item_data (tags / subgroup key),
    return groups                                #       assertion_results [{passed, reason}], trace_id
b, c = by_item(baseline), by_item(candidate)

def run_passed(i): return bool(i.assertion_results) and all(a.get("passed") for a in i.assertion_results)
def counts(runs): return sum(run_passed(r) for r in runs), len(runs)            # runs_passed, runs_total
thresholds = {it["id"]: (it.get("execution_policy") or suite.get_global_execution_policy() or {}).get("pass_threshold", 1)
              for it in suite.get_items()}                                      # the suite, not the experiment, holds the policy
def passed(item_id, runs): return counts(runs)[0] >= thresholds.get(item_id, 1)
# experiment level (client.rest_client.experiments.get_experiment_by_id(id)): pass_rate,
#            duration (p50/p90/p99), total_estimated_cost_avg, dataset_version_id

首先确认可比较性:dataset_version_id 相同、条目集合相同、评审器模型相同(实验配置)。若不同 → 阻碍(“在套件版本 X 上使用评审器 Y 重新运行候选,然后执行 /opik-verify”)——对不可比较的运行给出的结论不算结论。

4. 按以下顺序评估每项标准

即使第一项未通过,也要计算所有标准——报告会显示完整表格。

  1. 证据量——包含断言的计分项数量 ≥ min_items。低于该值时,无论其他情况如何,判定结果均为 insufficient_evidence,除非门槛标准(2–7)也未通过——此时判定为 hold:已知的安全回退比证据不足更重要。仍须报告每项标准。
  2. 回退——基线中 passed、候选版本中未通过的项目。如果某项在任一轮运行中(使用第 3 步的计数)runs_passed 严格大于 0 且小于 runs_total,或者同一代码的两轮运行结果不一致(如有),则该项为不稳定项。flaky_policy: exclude 会将不稳定项从回退计数中排除,并单独列出及其计数;count 则会将其计入。当所有项目的 runs_total == 1 时,无法观察到不稳定性——将不稳定性检查报告为 not_evaluated,说明 exclude 未排除任何项目;如果用户需要这项保护,建议在测试套件中设置 runs_per_item: 3。计数 ≤ max_regressions。
  3. 安全性——任何 data.tags 与 safety_tags 有交集的回退项 → 未通过,不作任何例外,也不予排除。
  4. 通过率——比较候选版本与基线的 pass_rate,或与给定数值比较。
  5. 子组——设置了 subgroup_key 时,该键每个取值对应的通过率都不得下降。
  6. 延迟——候选版本的 p90 时长 ≤ 基线 p90 × (1 + latency_p90_max_increase)。从实验记录中的 duration 百分位数(p50/p90/p99)获取(或从 REST 实验项目中获取逐项 duration)。
  7. 成本——候选版本每项的平均 total_estimated_cost ≤ 基线 × (1 + cost_per_item_max_increase)。如果两轮运行都没有成本数据,则跳过并说明“无成本数据”。 汇总数据会延迟更新。 一轮运行刚结束后,实验记录中的 duration 可能显示为 0.0,total_estimated_cost_avg 可能在几秒内显示为 None,这是因为后端正在汇总数据(已观察到此现象)。任一侧的汇总数据为零或缺失都不算有效数据——短暂等待后重新读取,或根据 REST 实验项目中的逐项 duration / total_estimated_cost 字段计算 p90 和平均成本;绝不能让 0.0 通过或导致门槛检查失败。
  8. 证据强度——对结果翻转进行配对符号检验:设修复数为 f,回退数为 r,计算 50/50 假设下的双侧二项检验 p 值。报告该值;它不是门槛条件。当 f + r < 6 时,说明“翻转次数太少,无法判断是否超出噪声范围”。
  9. 评审器——使用策略中的 judge_validated。若为 false → 判定结果上限为 needs_review。
  10. 归因——reason 表明评审器对未改变的输出犹豫不决的翻转项(参见 /opik-compare 第 5.6 步),须列入 needs_review 供人工查看,不得悄然计入或排除。
5. 作出决定

按以下顺序从上到下判断——符合的第一条即为最终结果:

  • 标准 2–7 中任意一项未通过 → hold(即使标准 1 也未通过)。
  • 标准 1 未通过 → insufficient_evidence。
  • 所有门槛均通过,但 judge_validated: false,或存在标记为需归因的项目 → needs_review,并准确说明人工应查看的内容。
  • 否则 → ship。

绝不要因为差值“总体上为正”而提高 hold 的判定;也不要因为猜测而降低 ship 的判定。策略就是判断依据;是否修改由用户决定。

6. 报告,并仅在用户要求时记录

提供表格(标准 · 阈值 · 观测值 · 通过/未通过)、列出回退项名称及其断言和跟踪链接、提供包含两个 ID 的比较 URL、说明策略来源,并给出一个后续步骤。使用 --record 时,将判定结果写入候选实验的配置——先读取现有配置并合并;update_experiment 会替换配置:

exp = client.rest_client.experiments.get_experiment_by_id(candidate.id)
cfg = dict(exp.metadata or {}); cfg["verdict"] = {"status": "hold", "policy": "opik-release-policy.yaml", "failed": ["regressions"], "at": "<iso time>"}
client.update_experiment(id=candidate.id, experiment_config=cfg)

如果不存在文件,可提议创建包含默认值的 opik-release-policy.yaml,但不要直接创建,以便下次能够复现判定结果。

阻塞项

遇到阻塞项时,停在最早出现的一项,并且只返回一个下一步:

  • "运行 opik configure,然后重新运行 /opik-verify。"
  • "套件 <name> 的可比较运行次数不足两次——请先运行 /opik-compare <suite>。"
  • "基线和候选版本属于不同的套件版本(v3 与 v4)——请在 v3 上重新运行候选版本,或在 v4 上重新建立基线,然后运行 /opik-verify。"
  • "opik-release-policy.yaml 包含未知键 <key>——请修复或移除该键。"
  • "候选运行的裁判失败(所有条目均为 scoring_failed)——请设置裁判的提供方密钥,然后重新运行 /opik-compare。"

输出

面向用户: 一行给出判定结果、标准表、回归项(用例、断言、原因、链接)、策略来源、比较链接,以及唯一的下一步。不要写成叙述,也不要用 JSON。

底层(用于组合/评估),仅采用以下一种结构:

  • status:ship | hold | needs_review | insufficient_evidence | blocked
  • policy:source(file | defaults)、path、values(生效的策略)
  • suite:name、id、version
  • baseline / candidate:experiment_id、name、url、items、pass_rate
  • criteria:{name, threshold, observed, passed, note} 列表——必须始终包含全部标准
  • regressions:{dataset_item_id, input, assertion, reason, trace_url, safety: bool, flaky: bool} 列表
  • flaky:{dataset_item_id, baseline_runs, candidate_runs} 列表,根据 flaky_policy 排除或计数;对于仅有一次运行的套件,使用字符串 not_evaluated
  • review_items:{dataset_item_id, why} 列表(适用于 needs_review)
  • evidence:{items, fixes, regressions, sign_test_p}
  • compare_url
  • recorded:true|false
  • next_step:只能有一个

不变量:ship 要求每项门槛标准均为 passed,且 judge_validated: true;hold 至少有一项标准未通过;如果失败原因是回归,regressions 必须非空;insufficient_evidence 的 criteria 中,min_items 必须未通过;needs_review 的 review_items 必须非空,或 policy.values 中的 judge_validated: false;criteria 绝不能不完整;不得修改代码库;不得部署任何内容。

示例

通过。 比较后运行 /opik-verify:24 个已评分条目、3 项修复、0 项回归、通过率从 0.79 提升至 0.92、p90 延迟增加 4%、成本增加 2%、符号检验 p = 0.25(“翻转次数太少,无法说明变化超出噪声范围——但没有回归”),策略文件存在且 judge_validated: true。→ ship;下一步 = “合并;/opik-online-eval 会监控生产环境中的退款断言”。

暂缓。 其他情况相同,但“不会提供法律建议”这一项从通过变为失败,并被标记为 safety。回归数 1 > 0,且存在安全性失败。→ hold,优先列出该用例,并附上原因和跟踪链接;下一步 = “针对法律建议条目运行 /opik-explain <trace>”。

需要审核。 所有门槛均通过,没有策略文件(使用默认值),因此 judge_validated 为 false。→ needs_review:“20 个条目按默认值通过;应由人员检查 5 项裁判判定(附链接),然后在 opik-release-policy.yaml 中设置 judge_validated: true——要我按默认值写入该文件吗?”

证据不足。 一个包含两个条目的套件,两项均已修复,且没有回归。→ insufficient_evidence:“2 个条目未达到 min_items: 10——请使用 /opik-test 添加用例,或在策略中降低 min_items(由你决定,这项更改会体现在文件中)。”

反模式

判定结果没有附带标准表;阈值凭空编造,而不是取自文件或默认值;在裁判未经验证时就发布;没有运行数据作为依据,却把不稳定条目当作回归(或把回归当作不稳定项);比较不同套件版本的运行;用平均值掩盖安全性回归;把六次翻转的 p 值当作门槛;仅因总体指标上升就将 hold 改为 ship;未经请求就写入策略文件或记录判定结果;编辑应用代码;部署。

参考资料

测试套件和实验详情位于与本技能一同安装的 opik 技能中;以下路径均相对于此文件:../opik/references/evaluation-test-suites.md(执行策略、runs_passed/runs_total、版本、get_test_suite_experiments)、../opik/references/evaluation-datasets.md(实验、OQL)。本技能用于评估的数值来自 ../opik-compare/SKILL.md;评判器验证见 ../opik-evaluate/references/validate-evaluator.md。如果宿主的技能目录布局不同,请找到 opik 技能的 references/ 目录。

如果未安装 opik 技能,请在报告中说明,并使用 https://www.comet.com/docs/opik/,不要凭记忆作答。

评论

支持 Markdown