opik-online-eval について
opik-online-eval は、Opik プロジェクトでオンライン評価ルールを稼働させるスキルです。単一の失敗要因に対して判定器または Python メトリクスを設定し、新しいトレースにスコアが付くか確認します。アプリケーションコードは変更しません。
主な機能
- 01trace、span、thread のスコープを設定
- 02判定器の入力をトレースのフィールドに対応付け
- 03サンプリング率とコスト上限を設定
- 04LLM 判定器または Python メトリクスを使用
- 05新しいトレースで採点を確認
活用シーン
- 01本番トレースの特定の失敗要因を採点
- 02機械的なメトリクスで JSON の妥当性を確認
- 03有効化後の評価ルールを監視
MCP 対応
このスキルは Opik のホスト型 MCP を使って、既存のオンライン評価ルールやスコア名を一覧できます。ルールは REST クライアントまたは API で作成し、このスキル自体は MCP サーバーを提供しません。
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ comet-ml/ opik-skills --skill opik-online-evalインストール後、Claude Code で/opik-online-evalを入力して読み込まれたか確認します。
詳細
オンライン評価 — 評価者を本番稼働させる
完了の定義: プロジェクトにオンライン評価ルールが存在し、有効になっており、少なくとも1件の新しいトレースを評価していることです。これは、作成呼び出しの戻り値ではなく、新しいトレースのフィードバックスコアを読み取って確認します。このルールでは1つの失敗モードを評価し、プロジェクトの処理量に見合うサンプリング率を設定し、コスト上限を設け、変数をトレースに実際に存在するフィールドに対応付けます。トラフィックがまだ届いていない場合の完了状態は「ルールは稼働中、未検証 — このフィルターを監視」です。ルールを作成できない場合は、最初に見つかった実際の障害要因で停止し、次の手順をちょうど1つ返します。
実行方針:1つのルールにつき1つの失敗モード、拡大する前にサンプリング、支出に上限を設け、実際のトレースで検証 — アプリケーションコードは変更しません。 このスキルが書き込むのは Opik のみです。
入力
エントリーポイントは /opik-online-eval <what to score>(「ハルシネーション」、「返金期間に関する回答」、「拒否」など)、/opik-evaluate で評価者の検証が終わった直後の /opik-online-eval(その評価者を本番稼働させる)、または /opik-online-eval <project> です。それ以外は推定してください。次の項目は任意の上書き設定として扱います。
- プロジェクト(デフォルト:設定済みのもの) · スコープ(デフォルト:trace。1回のモデル呼び出しには
span、会話全体にはthread) · サンプリング率(デフォルト:約1,000トレース/日未満なら1.0、それ以上なら0.1~0.2) · フィルター(デフォルト:なし。一般的な例:environmentまたはタグのフィルター) · 評価者モデル · コスト上限(デフォルト:設定する) · 変数の対応付け(デフォルト:input → input、output → output)。
推定できない実際の障害要因がある場合にのみ質問してください(「障害要因」を参照)。
有効化 — 対象となる作業はこれだけ
1. プロジェクト、評価者、スコープを特定する
Opik に接続できることを確認します(~/.opik.config または OPIK_API_KEY。どちらもない場合 → 障害要因)。トレースまたは名前からプロジェクト ID を特定します。評価者を次のように決定します。
/opik-evaluateですでに検証済みの評価者がある場合 → そのプロンプトと出力スキーマをそのまま再利用します。- 名前付きメトリクス(ハルシネーション、回答の関連性、モデレーション)→ その1つの失敗モードだけを判定する最小限のバイナリー評価者(
../opik-evaluate/references/write-judge-prompt.md)。 - 機械的なチェック(有効な JSON、免責事項の有無、レイテンシの予算)→ 評価者ではなく、Python メトリクスルールを使います。
デフォルトのスコープは trace です。チェック対象が1回の LLM/ツール呼び出しの場合は span、会話全体が必要な場合は thread にします(スレッドルールは、スレッドが非アクティブになるまで待機します。デフォルトは15分です)。
2. 変数を対応付ける前にトレースを確認する
最近の本番トレースを3件読み取り、input と output の実際の形状を確認します。実験の実行結果は、異なる入力形状で同じプロジェクトに保存されます(メタデータには test_suite_experiment_id が含まれます)。そのため、これらは除外してください。アプリのエントリーポイントで絞り込むのが確実です:client.search_traces(project_name=…, max_results=3, filter_string='name = "<entrypoint>"')。(OQL では metadata.* キーに対する is_empty は使えません。)変数には、ドット記法でネストしたキーを指定する通常のフィールドパスを使います(output.answer、input.messages)。{{ }} テンプレートは使いません。パスの指定ミスは、ルールが何も評価しないままになる最も一般的な原因です。
3. すでに動作しているルールを確認する
import opik
client = opik.Opik()
existing = client.rest_client.automation_rule_evaluators.find_evaluators(project_id="<project_id>")
同じ名前または同じ失敗モードのルールがすでにある場合は、2つ目を作成しないでください。exists と報告し、サンプリング率の調整または有効化を提案します。ホスト型 MCP が接続されている場合は、list('online_rule', project_id=…) と list('score_name', project_id=…) でも同じ内容を確認できます。各ルールの種類、有効フラグ、サンプリング率が表示されます。
4. ルールを作成する
高レベルの SDK ラッパーはありません。REST クライアントを使用してください。LLM-as-judge、トレーススコープ:
from opik.rest_api.types import (
AutomationRuleEvaluatorWrite_LlmAsJudge, LlmAsJudgeCodeWrite,
LlmAsJudgeModelParametersWrite, LlmAsJudgeMessageWrite, LlmAsJudgeOutputSchemaWrite,
)
rule = AutomationRuleEvaluatorWrite_LlmAsJudge(
action="evaluator", # required literal; the model rejects the payload without it
name="refund_window_correct", # becomes the feedback-score name on every scored trace — use underscores, not hyphens: OQL parses `feedback_scores.a-b` as an operator
project_ids=["<project_id>"],
sampling_rate=0.2, # fraction of SDK-logged traces scored
enabled=True,
filters=[], # e.g. [{"field": "tags", "operator": "contains", "value": "production"}]
code=LlmAsJudgeCodeWrite(
model=LlmAsJudgeModelParametersWrite(name="<judge model>", temperature=0.0),
messages=[LlmAsJudgeMessageWrite(role="USER", content="<the validated judge prompt using {{input}} and {{output}}>")],
variables={"input": "input", "output": "output"}, # field paths from step 2
schema_=[LlmAsJudgeOutputSchemaWrite(name="refund_window_correct", type="BOOLEAN",
description="True if the response states 5-7 business days")],
max_cost_usd=5.0, # per-rule spend cap — set it
),
)
created = client.rest_client.automation_rule_evaluators.create_automation_rule_evaluator(request=rule)
注意:Opik Cloud で独自のプロバイダーキーを使用しない場合、model.name="opik-free-model" を指定すると、ワークスペースに組み込まれた無料プロバイダーが使用されます。Python の属性は schema_(ワイヤー上の名前は schema)です。sampling_rate は本番トレースにのみ適用されます(実験トレースは常にすべてスコアリングされます)。trigger_scope のデフォルトは production です。スパンおよびスレッドのバリアント:AutomationRuleEvaluatorWrite_SpanLlmAsJudge、AutomationRuleEvaluatorWrite_TraceThreadLlmAsJudge。Python メトリック:AutomationRuleEvaluatorWrite_UserDefinedMetricPython。code={"metric": "<python source defining a BaseMetric>", "arguments": {"output": "output"}} を指定します。
Python 以外からスクリプトを実行する場合のエンドポイント:POST /v1/private/automations/evaluators/。本文は同じです。
5. 実際のトレースで検証する
import time
for _ in range(12): # ~2 min
scored = client.search_traces(project_name="<project>", max_results=1,
filter_string='feedback_scores.refund_window_correct is_not_empty')
if scored: break
time.sleep(10)
スコア名にすでにハイフンが含まれている場合(既存のルールなど)、キーを二重引用符で囲んでください。囲まないと、OQL パーサーがハイフンを演算子として解釈します:filter_string='feedback_scores."refund-window-correct" is_not_empty'。
スコアが付いたトレースがある → live。トレースがなく、プロジェクトにも対象期間内の新しいトレースがない → 監視するフィルターとともに live_unverified。トレースは届いているのにスコアがない → ルールのログ(get_evaluator_logs_by_id(id))を確認してください。変数パスのエラーやモデルの失敗がログに表示されます。修正して再検証してください。
6. 結果を報告する
ルール名/ID、スコープ、サンプリング率、コスト上限、スコア名、検証したトレースへのリンク、次のステップを 1 つ(出力を参照)報告します。自然な次のステップ:/opik-diagnose でこのスコア名の低スコアを検出できるようになりました。スコアしきい値に対するアラートを設定する。または、ジャッジを事前に検証していない場合は、「誰かがこの結果に基づいて行動する前に、20 件の人手ラベルで検証する(/opik-evaluate)」。
ブロッカー
最初に見つかったブロッカーで停止し、次のステップを必ず 1 つだけ返してください:
- "
opik configureを実行してから、/opik-online-evalを再実行してください。" - "どのプロジェクトのスコアを付けますか?
/opik-online-eval <what> <project>を渡してください。" - "トレースの
outputは{answer, sources}です。ジャッジはoutput.answerを読むべきですか?(別の指示がなければ、そのようにマッピングします。)" — マッピングが本当に曖昧な場合にのみ尋ねてください。 - "ルールで検出する失敗モードは何ですか? 1 つ指定してください(例:ハルシネーション、誤った返金期間、安全でないコンテンツ)。"
出力
ユーザー向け: 短い説明メッセージ。ルール(名前、スコープ、サンプリング率、上限)、スコア名、クリック可能な Opik UI の検証トレースリンク(未検証の場合は監視フィルター)、次のステップを 1 つ含めてください。JSON 形式にはしないでください。
内部用(合成/評価用)、次の形式を 1 つ使用します:
status:live|live_unverified|exists|blockedrule:id、name、type(llm_as_judge|user_defined_metric_python| スパン/スレッドのバリアント)、scope、sampling_rate、filters、max_cost_usd、enabledscore_namevariables:使用したフィールドパスのマッピングverification:trace_id、trace_url、value(liveの場合);watch_filter(未検証の場合)source:sdk|mcpnext_step:必ず 1 つ
不変条件:live には verification.trace_id が含まれます。作成されたすべてのルールには max_cost_usd と sampling_rate が設定されています。1 つのルールにつき失敗モードは 1 つです。exists の場合、何も作成されていません。blocked には next_step が必ず 1 つだけ含まれます。どの経路でもコードベースに変更は加えられません。
例
検証済みのジャッジを本番稼働させる。 /opik-evaluate で「返金期間を5~7営業日と回答する」を調整しました(TPR 0.95)。/opik-online-eval:プロジェクト support-bot、1日あたり約5k件のトレース → サンプリング 0.1、フィルター tags contains "production"、上限 $5、マッピング output → output.answer(トレースではネストされているため)。作成後、40秒でトレースに refund-window-correct = 1 が付与されました。→ live;次のステップ =「1時間平均が0.8を下回ったらアラートを出す」。
機械的なチェック。「本番環境の回答がすべて有効な JSON であることを確認する。」→ Python メトリックルール(output に対する IsJson)、サンプリング 1.0(低コスト)、ジャッジなし。→ live。
まだトラフィックがない。 営業時間中にのみトレースを受信するプロジェクトでルールを作成しました。→ live_unverified:「feedback_scores.<name> is_not_empty を監視するか、トレース付きのリクエストを1件送信してください」。
すでに存在する。 hallucination という名前のルールが、0.5で有効になっています。→ exists;次のステップ =「コストが懸念事項なら、サンプリングを0.1に下げてください」。
アンチパターン
高トラフィックのプロジェクトで、コストに触れずに sampling_rate: 1.0 のルールを設定すること;max_cost_usd を指定しないこと;変数に {{input}} 形式のテンプレート構文を使うこと(変数はフィールドパスです);包括的な「品質」ジャッジをルールにすること;機械的なチェックにジャッジを使うこと;同じ失敗モードに対して2つ目のルールを作ること;スコア付きトレースを確認せず、作成呼び出しだけで成功を宣言すること;検証していないジャッジを本番稼働させ、そのスコアを真実として扱うこと;アプリケーションコードを編集すること。
参考資料
本番環境とオブザーバビリティの詳細は、このスキルと同じ場所にインストールされている opik スキルにあります。このファイルを基準とするパスは、../opik/references/production.md(オンライン評価、変数マッピング、フィードバックスコア、アラート)、../opik/references/observability.md(トレース/スパン/スレッドのモデル)、../opik/references/evaluation-datasets.md(OQL フィルター、feedback_scores.<name> 演算子)です。ジャッジの設計については、../opik-evaluate/references/write-judge-prompt.md、../opik-evaluate/references/validate-evaluator.md を参照してください。ホスト環境でスキルの配置が異なる場合は、opik スキルの references/ ディレクトリを探してください。
opik スキルがインストールされていない場合は、レポートにその旨を記載し、記憶に頼らず https://www.comet.com/docs/opik/ を参照してください。