mcpField
V
validate-evaluator

validate-evaluator

github.com/ai-evals-courseテスト・品質1.6k1.1k 回インストール5 週間前に更新
リポジトリ

validate-evaluator について

validate-evaluatorは、LLM judgeを人間の判定に照らして調整するSkillです。データ分割、TPR・TNRによる反復評価、本番データの合格率補正と信頼区間の算出を案内します。

主な機能

  1. 01訓練・開発・テストデータの分割
  2. 02TPRとTNRの測定
  3. 03不一致に基づくjudgeプロンプトの改善
  4. 04合格率の補正と信頼区間の推定

活用シーン

  1. 01二値判定のLLM judgeを人間のラベルで検証
  2. 02開発データの結果に基づく評価プロンプトの調整
  3. 03本番トレースの真の合格率の推定

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/ai-evals-course/evals-skills --skill validate-evaluator

インストール後、Claude Code で/validate-evaluatorを入力して読み込まれたか確認します。

同梱ファイルagents/openai.yaml

詳細

評価器の検証

LLM ジャッジを人間の判断に照らして調整します。

概要

  1. 人間がラベル付けしたデータを、トレーニング(10~20%)、開発(40~45%)、テスト(40~45%)に分割します
  2. 開発セットでジャッジを実行し、TPR/TNR を測定します
  3. 開発セットで TPR と TNR が 90%を超えるまで、ジャッジを反復調整します
  4. 最終的な TPR/TNR を測定するため、保留していたテストセットで一度だけ実行します
  5. 本番データにバイアス補正式を適用します

前提条件

  • 構築済みの LLM ジャッジプロンプト(write-judge-prompt で作成)
  • 人間がラベル付けしたデータ:失敗モードごとに Pass/Fail の二値ラベルを付けたトレースが約 100 件
    • Pass 約 50 件、Fail 約 50 件を目指します(実際の分布に偏りがあっても、バランスを取ります)
    • ラベルは外部委託のアノテーターではなく、ドメインの専門家が付ける必要があります
  • ラベル付けしたデータから選んだ、候補となる少数ショットの例

主な手順

ステップ 1:データを分割する

人間がラベル付けしたデータを、互いに重複しない 3 つのセットに分割します。

分割サイズ目的ルール
トレーニング10~20%(約 10~20 件)ジャッジプロンプト用の少数ショット例のソース明確な Pass と Fail のケースのみを使用します。プロンプトに直接含めます。
開発40~45%(約 40~45 件)評価器を反復的に改善するプロンプトには決して含めません。繰り返し評価に使用します。
テスト40~45%(約 40~45 件)最終的な偏りのない精度測定開発中は見ないでください。最後に一度だけ使用します。

目標:開発セットとテストセットの合計で、各クラス(Pass と Fail)を 30~50 件確保します。実際の発生率に偏りがあっても、バランスの取れた分割を使用してください。TNR を確実に測定するには、十分な数の Fail 例が必要です。

from sklearn.model_selection import train_test_split

# First split: separate test set
train_dev, test = train_test_split(
    labeled_data, test_size=0.4, stratify=labeled_data['label'], random_state=42
)
# Second split: separate training examples from dev set
train, dev = train_test_split(
    train_dev, test_size=0.75, stratify=train_dev['label'], random_state=42
)
# Result: ~15% train, ~45% dev, ~40% test
ステップ 2:開発セットで評価器を実行する

開発セットのすべての例に対してジャッジを実行します。予測結果を人間のラベルと比較します。

ステップ 3:TPR と TNR を測定する

TPR(真陽性率): 人間が Pass と判定したとき、ジャッジも Pass と判定する割合です。

TPR = (judge says Pass AND human says Pass) / (human says Pass)

TNR(真陰性率): 人間が Fail と判定したとき、ジャッジも Fail と判定する割合です。

TNR = (judge says Fail AND human says Fail) / (human says Fail)
from sklearn.metrics import confusion_matrix

tn, fp, fn, tp = confusion_matrix(human_labels, evaluator_labels,
                                   labels=['Fail', 'Pass']).ravel()
tpr = tp / (tp + fn)
tnr = tn / (tn + fp)

Precision/Recall や単純な正解率ではなく、TPR/TNR を使用してください。この 2 つの指標は、バイアス補正式に直接対応しています。Cohen の Kappa は、2 人の人間のアノテーター間の一致度を測定する場合にのみ使用し、ジャッジと正解ラベルの比較には使用しないでください。

ステップ 4:不一致を調べる

ジャッジの判定が人間のラベルと異なるケースをすべて確認します。

不一致の種類ジャッジ人間修正方法
誤った Pass 判定PassFailジャッジの判定が甘すぎます。Fail の定義を強化するか、エッジケースの例を追加します。
誤った Fail 判定FailPassジャッジの判定が厳しすぎます。Pass の定義を明確にするか、例を調整します。

不一致ごとに、次の対応が必要か判断します。

  • ジャッジプロンプトの表現を明確にする
  • トレーニングセットの少数ショット例を入れ替える、または追加する
  • エッジケースに対する明示的なルールを追加する
  • 基準を、より具体的なサブチェックに分割する
ステップ 5:反復する

ジャッジプロンプトを改善し、開発セットで再実行します。TPR と TNR が安定するまで繰り返します。

停止基準:

  • 目標: TPR > 90%、かつ TNR > 90%
  • 最低許容値: TPR > 80%、かつ TNR > 80%

調整が行き詰まった場合:

問題解決策
TPR と TNR の両方が低いより高性能な LLM をジャッジに使用します
一方の指標が低く、もう一方は許容範囲内低い指標に関連する不一致を重点的に調べます
両方の指標が目標未満で頭打ちになる基準をより小さく、より基本的なチェックに分解します
特定の入力タイプで一貫して誤判定するトレーニングセットから対象を絞った少数ショット例を追加します
ラベル自体に一貫性がないように見える人間のラベルを再確認します。評価基準の改善が必要な場合があります
ステップ 6:テストセットで最終測定する

保留していたテストセットに対して、ジャッジをちょうど一度だけ実行します。最終的な TPR と TNR を記録します。

テストセットの結果を見た後は反復調整しないでください。必要に応じて、新しい開発データを用意してステップ 4 に戻ります。

ステップ 7(任意):真の成功率を推定する(Rogan-Gladen 補正)

ラベル付けされていない本番データに対する生の判定スコアには偏りがあります。正確な集計合格率が必要な場合は、既知の判定誤りを補正してください。

theta_hat = (p_obs + TNR - 1) / (TPR + TNR - 1)

ここで:

  • p_obs = 判定者が Pass とスコア付けした、ラベルなしトレースの割合
  • TPR、TNR = テストセットで測定した値
  • theta_hat = 真の成功率の補正済み推定値

[0, 1] の範囲に収めてください。TPR + TNR - 1 が 0 に近い場合は無効です(判定者の性能がランダムと同程度です)。

例:

  • 判定者の TPR = 0.92、TNR = 0.88
  • 本番トレース 500 件:400 件が Pass とスコア付けされた場合、p_obs = 0.80
  • theta_hat = (0.80 + 0.88 - 1) / (0.92 + 0.88 - 1) = 0.68 / 0.80 = 0.85
  • 真の成功率は約 85% であり、生の値である 80% ではありません
ステップ 8:信頼区間

ブートストラップ信頼区間を計算します。点推定だけでは不十分です。

import numpy as np

def bootstrap_ci(human_labels, eval_labels, p_obs, n_bootstrap=2000):
    """Bootstrap 95% CI for corrected success rate."""
    n = len(human_labels)
    estimates = []
    for _ in range(n_bootstrap):
        idx = np.random.choice(n, size=n, replace=True)
        h = np.array(human_labels)[idx]
        e = np.array(eval_labels)[idx]

        tp = ((h == 'Pass') & (e == 'Pass')).sum()
        fn = ((h == 'Pass') & (e == 'Fail')).sum()
        tn = ((h == 'Fail') & (e == 'Fail')).sum()
        fp = ((h == 'Fail') & (e == 'Pass')).sum()

        tpr_b = tp / (tp + fn) if (tp + fn) > 0 else 0
        tnr_b = tn / (tn + fp) if (tn + fp) > 0 else 0
        denom = tpr_b + tnr_b - 1

        if abs(denom) < 1e-6:
            continue
        theta = (p_obs + tnr_b - 1) / denom
        estimates.append(np.clip(theta, 0, 1))

    return np.percentile(estimates, 2.5), np.percentile(estimates, 97.5)

lower, upper = bootstrap_ci(test_human, test_eval, p_obs=0.80)
print(f"95% CI: [{lower:.2f}, {upper:.2f}]")

または judgy(pip install judgy)を使用します。

from judgy import estimate_success_rate

# judgy expects 0/1 integer labels (1 = Pass, 0 = Fail)
test_labels = [1 if l == 'Pass' else 0 for l in test_human_labels]
test_preds = [1 if l == 'Pass' else 0 for l in test_eval_labels]
unlabeled_preds = [1 if l == 'Pass' else 0 for l in prod_eval_labels]

theta_hat, lower, upper = estimate_success_rate(
    test_labels, test_preds, unlabeled_preds
)
print(f"Corrected rate: {theta_hat:.2f}")
print(f"95% CI: [{lower:.2f}, {upper:.2f}]")

実践ガイダンス

  • LLM 判定者では、モデルの正確なバージョンを固定してください(<model>-<YYYY-MM-DD> のような日付付きスナップショット ID を使用し、変動するエイリアスは使いません)。プロバイダーは予告なくモデルを更新するため、気付かないうちに挙動が変わることがあります。
  • 判定プロンプトを変更した場合、モデルを切り替えた場合、または本番の信頼区間が予想外に広がった場合は、再検証してください。
  • ラベル付きの例を約 100 件使用します(Pass 50 件、Fail 50 件)。60 件未満では信頼区間が広くなります。
  • ラベル付けには、信頼できるドメインエキスパート 1 名に依頼するのが最も効率的です。それが難しい場合は、2 名のアノテーターにトレース 20~50 件を個別にラベル付けしてもらい、先に不一致を解決してください。
  • TPR の改善は、TNR の改善よりも信頼区間を狭めます。 補正では (TPR + TNR - 1) で割るため、TPR が低いと分母が小さくなり、推定誤差が増幅されて信頼区間が広くなります。

アンチパターン

  • 検証せずに判定者が「問題なく機能する」と思い込むこと。 判定者は失敗を一貫して見逃したり、合格したトレースを誤って不合格と判定したりする可能性があります。
  • 生の正解率や一致率を使うこと。 TPR と TNR を使用してください。クラスに偏りがある場合、生の正解率は誤解を招きます。
  • 開発用/テスト用の例を few-shot 例として使うこと。 これはデータリークです。
  • 開発セットの性能を最終的な正解率として報告すること。 開発セットの数値は楽観的です。偏りのない推定値が得られるのはテストセットです。
  • 偏り補正なしで判定者の生のスコアを使うこと。 集計合格率を報告する場合は、Rogan-Gladen の式を適用してください(ステップ 7)。
  • 信頼区間を示さずに点推定だけを示すこと。 補正後の合格率が 85% でも、テストセットが小さければ 78~92% になる可能性があります。関係者が数値をどの程度信頼できるか把握できるよう、範囲を報告してください。

コメント