ふくふくHukuhuku Inc.
EP.10RAG 10分公開: 2026-05-10

評価の自動化:LLMを評価者に使う罠

「LLM as a Judge」は便利だが、罠もある。回答の自動採点を本番運用に組み込む際の注意点と、Position/冗長性/Self bias の対策。

#Eval#LLM as Judge
CO📔 Google Colab で開く(上から順にセルを実行)
シェア

が回答を採点するLLM as a Judge は、人間評価のスケール化として広く使われています。1000 件の回答を人間が評価するには 50 時間、LLM なら 30 分・$5。ただし、そのまま使うと数字が偏る罠があります。本記事では 3 大罠とその回避策、本番運用での組み込み方を共有します。

なぜ LLM as a Judge を使うのか

  • 人間評価のスケール限界:1000 件 / 月の回答評価は人間では現実的でない
  • A/B テストの即時フィードバック:プロンプト変更の効果を 30 分で測定
  • 回帰テスト:プロンプト改修後に既存テストケースが落ちていないか
  • 継続的モニタリング:本番回答のサンプリング評価を毎日

ありがちな 3 大 bias

Bias ① Position bias(位置バイアス)

先に提示された回答を高く評価しがち。A/B 比較で「A が左、B が右」と提示すると、内容が同じでも A が選ばれる確率が 55〜60%。

対策

順番をランダムにする + A/B 入れ替えて 2 回評価して平均。実装上は `random.shuffle([a, b])` を毎回呼ぶ、または同じ評価を逆順でもう 1 回実行。

Bias ② 冗長性 bias(長い方が丁寧)

長い回答を「丁寧で詳しい」と評価しがち。情報量が同じでも、冗長な回答が高得点に。 では「答えだけ短く」と「説明込みで長く」を比較したとき、長い方が勝つ傾向。

対策

評価プロンプトに「簡潔さも評価軸に入れる」と明示。または文字数を測って明らかな冗長は減点。「同じ答えなら短い方が良い」というルールを Judge に教える。

Bias ③ Self bias(自己評価バイアス)

同じ LLM で生成・評価すると自己採点が甘い が生成した回答を Claude で評価 → 高得点が出やすい。

対策

生成と評価で違うモデルを使う。生成 = Claude、評価 = GPT-4o(またはその逆)。コストは増えるが、より客観的なスコアが得られる。

それでも使うべき理由

罠はあるが、人間評価との相関は 0.7〜0.85 程度あり、十分実用的。bias を理解した上で補正すれば、人間評価の代替として機能します。

Eval 手法の比較
手法コスト/件1000 件の所要再現性信頼度
人間評価$2〜1020〜50 時間△(評価者次第)★★★
LLM as Judge$0.005〜0.0230 分○(プロンプト固定)★★(補正必要)
自動指標(BLEU/Rouge)ほぼ 0数秒★(意味は問えない)

本番運用での組み込み方

  1. 1評価データセット作成:50〜200 件、人間評価済みのゴールデンセット
  2. 2Judge プロンプト設計:bias 対策込みの評価指示。最初に人間評価との相関を確認
  3. 3回帰テスト化:プロンプト変更前後でゴールデンセットを再評価、回帰検出
  4. 4本番サンプリング:日次 100 件をランダムサンプリングして Judge 評価、トレンド監視
  5. 5異常時の人間レビュー:スコア急落 → アラート → 人間が確認

Judge プロンプトの実例

ふくふくが使っている Judge prompt(抜粋)
Markdown
あなたは厳格な評価者です。質問と回答を以下の 4 軸で 1〜5 点で評価してください。
【評価軸】- 正確性: 回答の事実が文脈と矛盾しないか(最重要)- 完全性: 質問のすべての要素に答えているか- 簡潔性: 過不足なく、冗長でないか(同じ情報量なら短い方が高得点)- 引用: 根拠となる文書が示されているか
【評価のルール】- 順番に bias されないこと(A と B のどちらが先でも公平に)- 長さで判断しないこと(短くても情報が揃っていれば満点)- 自分が書いた回答かどうかは関係ない(公平に評価)
【出力フォーマット】(JSON){  "accuracy": <1-5>,  "completeness": <1-5>,  "conciseness": <1-5>,  "citation": <1-5>,  "overall": <1-5>,  "reasoning": "<200字以内で評価理由>"}

Python での Judge 実装

Anthropic api で Judge を呼ぶ
Python
import jsonimport randomfrom anthropic import Anthropic
client = Anthropic()
JUDGE_PROMPT = """あなたは厳格な評価者です。質問と回答を以下の 4 軸で 1〜5 点で評価してください。
【評価軸】- 正確性: 回答の事実が文脈と矛盾しないか- 完全性: 質問のすべての要素に答えているか- 簡潔性: 過不足なく、冗長でないか- 引用: 根拠となる文書が示されているか
【評価のルール】- 順番に bias されないこと- 長さで判断しないこと(短くても情報が揃っていれば満点)
【出力フォーマット】(JSON){"accuracy": int, "completeness": int, "conciseness": int, "citation": int, "overall": int, "reasoning": "<200字以内>"}"""
def judge(question: str, answer: str, model: str = "claude-sonnet-4-6") -> dict:    response = client.messages.create(        model=model,        max_tokens=500,        system=JUDGE_PROMPT,        messages=[{"role": "user", "content": f"質問: {question}\n\n回答: {answer}"}],    )    return json.loads(response.content[0].text)
# 使用例score = judge("有給は何日まで?", "規程で年間20日が上限です([doc-hr-009])")print(score)# → {"accuracy": 5, "completeness": 4, "conciseness": 5, "citation": 5, "overall": 5, ...}
Position bias 対策(A/B 順序ランダム化)
Python
import randomfrom typing import Tuple
def judge_pairwise(question: str, answer_a: str, answer_b: str, n_trials: int = 2) -> Tuple[str, float]:    """A/B を順序ランダム化して 2 回評価、勝率を返す"""    wins_a = 0    for _ in range(n_trials):        # 順序をランダム化        if random.random() < 0.5:            first, second = ("A", answer_a), ("B", answer_b)        else:            first, second = ("B", answer_b), ("A", answer_a)
        prompt = f"質問: {question}\n\n回答 1: {first[1]}\n\n回答 2: {second[1]}\n\nどちらが優れているか、'1' or '2' のみで答えてください。"        result = client.messages.create(            model="claude-sonnet-4-6",            max_tokens=10,            messages=[{"role": "user", "content": prompt}],        )        winner_idx = result.content[0].text.strip()        # ランダム化を解除        if winner_idx == "1":            actual_winner = first[0]        else:            actual_winner = second[0]        if actual_winner == "A":            wins_a += 1
    win_rate_a = wins_a / n_trials    return ("A" if win_rate_a > 0.5 else "B"), win_rate_a
ゴールデンセットでの相関確認
Python
import pandas as pdfrom scipy.stats import pearsonr
# 人間評価済みのゴールデンセットgolden = pd.read_csv("eval/golden_human_rated.csv")  # query, answer, human_score
# Judge で再評価golden["judge_score"] = golden.apply(    lambda row: judge(row["query"], row["answer"])["overall"],    axis=1)
# 相関を確認corr, p = pearsonr(golden["human_score"], golden["judge_score"])print(f"Pearson 相関: {corr:.3f} (p={p:.4f})")# 0.7〜0.85 が実用的、0.6 未満なら Judge プロンプトを見直す

ふくふくの進め方

RAG の精度を継続的に測りたい」というご相談には、ゴールデンセット作成(人間評価 100 件)→ Judge プロンプト設計 → 相関 0.8 確認 → への組み込みを 1 ヶ月で構築。プロンプト変更時の自動回帰検出まで含めた評価基盤になります。

次回予告

EP.11 はガードレール:危険な質問を弾く設計。本番投入時の必須要素。「 漏洩」「機密情報質問」「悪意あるプロンプトインジェクション」の防御。

シェア

この記事の感想を教えてください

あなたの 1 クリックで、本当にこの記事は更新されます。「もっと詳しく」「続編希望」が一定数集まった記事は、 ふくふくが 実際に内容を拡充したり続編記事を公開 します。 送信したリアクションはお使いのブラウザに記録され、再カウントされません。

シリーズの外も探す:

まずは、現状を聞かせてください。

要件が固まっていなくて大丈夫です。現状診断と方針提案までを無料でお手伝いします。

無料相談フォームへ hello [at] hukuhuku [dot] co [dot] jp