关于 opik-verify
opik-verify 按声明的发布策略评估 Opik 基线与候选运行结果,供团队判断变更是否可以发布。它会报告判定、各项阈值与观测结果及失败案例,不修改应用代码,也不部署。
主要功能
- 01应用策略文件或文档默认值
- 02检查回归、安全性和通过率
- 03评估子组、延迟和成本指标
- 04报告证据量和评判器验证状态
- 05列出未通过标准及相关案例
- 06按请求记录判定结果
适用场景
- 01比较评估运行后为变更设置发布门槛
- 02发布前检查安全回归
- 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. 按以下顺序评估每项标准
即使第一项未通过,也要计算所有标准——报告会显示完整表格。
- 证据量——包含断言的计分项数量 ≥
min_items。低于该值时,无论其他情况如何,判定结果均为insufficient_evidence,除非门槛标准(2–7)也未通过——此时判定为hold:已知的安全回退比证据不足更重要。仍须报告每项标准。 - 回退——基线中
passed、候选版本中未通过的项目。如果某项在任一轮运行中(使用第 3 步的计数)runs_passed严格大于 0 且小于runs_total,或者同一代码的两轮运行结果不一致(如有),则该项为不稳定项。flaky_policy: exclude会将不稳定项从回退计数中排除,并单独列出及其计数;count则会将其计入。当所有项目的runs_total == 1时,无法观察到不稳定性——将不稳定性检查报告为not_evaluated,说明exclude未排除任何项目;如果用户需要这项保护,建议在测试套件中设置runs_per_item: 3。计数 ≤max_regressions。 - 安全性——任何
data.tags与safety_tags有交集的回退项 → 未通过,不作任何例外,也不予排除。 - 通过率——比较候选版本与基线的
pass_rate,或与给定数值比较。 - 子组——设置了
subgroup_key时,该键每个取值对应的通过率都不得下降。 - 延迟——候选版本的 p90 时长 ≤ 基线 p90 × (1 +
latency_p90_max_increase)。从实验记录中的duration百分位数(p50/p90/p99)获取(或从 REST 实验项目中获取逐项duration)。 - 成本——候选版本每项的平均
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通过或导致门槛检查失败。 - 证据强度——对结果翻转进行配对符号检验:设修复数为
f,回退数为r,计算 50/50 假设下的双侧二项检验 p 值。报告该值;它不是门槛条件。当f + r < 6时,说明“翻转次数太少,无法判断是否超出噪声范围”。 - 评审器——使用策略中的
judge_validated。若为 false → 判定结果上限为needs_review。 - 归因——
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|blockedpolicy:source(file|defaults)、path、values(生效的策略)suite:name、id、versionbaseline/candidate:experiment_id、name、url、items、pass_ratecriteria:{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_evaluatedreview_items:{dataset_item_id, why}列表(适用于needs_review)evidence:{items, fixes, regressions, sign_test_p}compare_urlrecorded:true|falsenext_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/,不要凭记忆作答。