0Pricing
AI Prompt Engineering · レッスン

LLMによるLLM出力の評価

LLMによる評価が機能する理由と、人間による評価と比べた場合の弱点を学びます。

「LLMによるLLM出力の評価」はCoddyKit上の無料AI Prompt Engineeringレッスンです。 これはレッスン1/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはAI Prompt Engineering学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 AI Prompt Engineeringコースには全4レッスンが含まれています。

LLMを評価者として使う理由

BLEU、ROUGE、完全一致などの従来の評価指標は、構造化された出力には機能しますが、有用性、正確性、トーン、創造性といった微妙な品質の評価には不向きです。

人手による評価は細かなニュアンスを捉えられますが、時間と費用がかかります。LLM-as-judgeはその中間的な方法です。意味や文脈、主観的な品質を理解できる自動評価を、大規模かつ低コストで実現します。

LLM評価者が機能する理由

LLM評価者がうまく機能するのは、評価対象のモデルと同じ言語理解能力を共有しているためです。次のような点を評価できます。

  • 応答が、参照文との語彙的な類似性だけでなく、事実として正確か
  • 指定された目的に対して、応答が役に立つか
  • トーンが要件に合っているか
  • 要約が重要なポイントを捉えているか

これらは、単純な文字列照合の指標では測定できない品質です。

シンプルなLLM評価者

最も基本的なLLM評価者は、応答を数値スケールで評価し、簡潔な理由を添えるようモデルに依頼するものです。これは、より高度な評価者パターンの基礎となります。

import anthropic
import json

client = anthropic.Anthropic(api_key='sk-ant-...')

def simple_llm_judge(question, response, criterion):
    judge_prompt = (
        f'Rate the following response on {criterion} from 1 to 5.\n\n'
        f'Question: {question}\n'
        f'Response: {response}\n\n'
        f'Return JSON: {{"score": <1-5>, "reason": "<one sentence>"}}'
    )
    r = client.messages.create(
        model='claude-opus-4-5',
        max_tokens=100,
        messages=[{'role': 'user', 'content': judge_prompt}]
    )
    try:
        result = json.loads(r.content[0].text)
        return result['score'], result['reason']
    except Exception:
        return None, r.content[0].text

score, reason = simple_llm_judge(
    question='What is recursion in programming?',
    response='Recursion is when a function calls itself.',
    criterion='clarity and completeness'
)
print(f'Score: {score}/5 — {reason}')

LLM評価者が失敗する理由:位置バイアス

位置バイアス:2つの応答(AとB)を提示すると、LLM評価者は品質に関係なく、先に表示された方を好む傾向があります。単純な評価者プロンプトを使った場合、ペア比較の60~70%にこの影響が及ぶことが研究で示されています。

つまり、選択肢を提示する順番によって、評価者の判定が変わります。

import anthropic

client = anthropic.Anthropic(api_key='sk-ant-...')

def demonstrate_position_bias(question, response_a, response_b):
    def ask_judge(first, second, order):
        prompt = (
            f'Question: {question}\n\n'
            f'Response 1: {first}\n\n'
            f'Response 2: {second}\n\n'
            f'Which response is better? Reply with 1 or 2.'
        )
        r = client.messages.create(
            model='claude-opus-4-5',
            max_tokens=10,
            messages=[{'role': 'user', 'content': prompt}]
        )
        choice = r.content[0].text.strip()
        # Map back to original labels
        if order == 'AB':
            return 'A' if choice == '1' else 'B'
        else:  # BA
            return 'B' if choice == '1' else 'A'

    result_ab = ask_judge(response_a, response_b, 'AB')
    result_ba = ask_judge(response_b, response_a, 'BA')

    print(f'Order A-B: Judge picked {result_ab}')
    print(f'Order B-A: Judge picked {result_ba}')
    if result_ab != result_ba:
        print('Position bias detected: different results!')

    return result_ab, result_ba

LLM評価者が失敗する理由:冗長性バイアス

冗長性バイアス:LLM評価者は、簡潔な応答の方が客観的に優れている場合でも、長く詳細な応答を高く評価する傾向があります。50語で言えることを400語使って説明する応答が、簡潔なバージョンより高い評価を得ることもよくあります。

評価者に不要な長さを減点するよう明示的に指示することで、影響を抑えられます。

import anthropic

client = anthropic.Anthropic(api_key='sk-ant-...')

def length_aware_judge(question, response):
    judge_prompt = (
        f'Evaluate this response for quality. Be aware of verbosity bias: '
        f'do NOT score longer responses higher just because they are longer.\n\n'
        f'Question: {question}\n'
        f'Response: {response}\n\n'
        f'Evaluate on:\n'
        f'1. Accuracy (does it correctly answer the question?)\n'
        f'2. Conciseness (does it avoid unnecessary filler?)\n'
        f'3. Helpfulness (does it serve the user well?)\n\n'
        f'Penalize responses that add filler, repetition, or irrelevant information.\n'
        f'Score each 1-5 and provide an overall score. Return JSON.'
    )
    r = client.messages.create(
        model='claude-opus-4-5',
        max_tokens=200,
        messages=[{'role': 'user', 'content': judge_prompt}]
    )
    print(r.content[0].text)

LLM評価者が失敗する理由:自己選好

自己選好バイアス:Claudeが2つの応答を評価すると、Claudeらしい応答を好む傾向があります。GPT-4が評価すると、GPT-4らしい応答を好みます。これは、すべてのLLM評価者に影響する体系的なバイアスです。

対策として、異なる複数のモデルを評価者として使い、そのスコアを集約します。評価が分かれた場合は、境界的なケースとして人間によるレビューが必要であることを示します。

import anthropic
import openai

anthropic_client = anthropic.Anthropic(api_key='sk-ant-...')
openai_client = openai.OpenAI(api_key='sk-...')

def multi_model_judge(question, response):
    judge_prompt = (
        f'Rate this response 1-10 for overall quality.\n'
        f'Q: {question}\nA: {response}\n'
        f'Reply with only a number.'
    )

    # Judge 1: Claude
    r_claude = anthropic_client.messages.create(
        model='claude-opus-4-5',
        max_tokens=10,
        messages=[{'role': 'user', 'content': judge_prompt}]
    )
    score_claude = float(r_claude.content[0].text.strip())

    # Judge 2: GPT-4o
    r_gpt = openai_client.chat.completions.create(
        model='gpt-4o',
        max_tokens=10,
        messages=[{'role': 'user', 'content': judge_prompt}]
    )
    score_gpt = float(r_gpt.choices[0].message.content.strip())

    avg = (score_claude + score_gpt) / 2
    print(f'Claude judge: {score_claude}, GPT judge: {score_gpt}, Average: {avg}')
    if abs(score_claude - score_gpt) > 2:
        print('WARNING: High disagreement — consider human review')
    return avg

スコアのインフレーション

スコアのインフレーション:LLM評価者は、ほとんどの応答に高いスコア(5点満点で4~5点)を付ける傾向があります。その結果、スコアの分布が狭まり、良い応答と非常に優れた応答を区別しにくくなります。本来なら3/5程度の応答が、4~4.5/5と評価されることもあります。

対策として、評価基準を調整せざるを得ないルーブリックを使うか、絶対評価ではなく相対評価(ペア比較)を使います。

# Anti-inflation judge prompt with explicit score anchors
CALIBRATED_JUDGE_PROMPT = (
    'Rate this response 1-5 using these STRICT score definitions:\n'
    '1 = Completely wrong, harmful, or completely off-topic\n'
    '2 = Partially relevant but contains significant errors or omissions\n'
    '3 = Correct and addresses the question but lacks depth or precision\n'
    '4 = Correct, reasonably complete, and clearly expressed\n'
    '5 = Exceptional: correct, complete, insightful, and concise\n\n'
    'Only give 5 if the response is genuinely outstanding.\n'
    'Give 3 for any adequate-but-not-impressive response.\n\n'
    'Question: {question}\n'
    'Response: {response}\n\n'
    'Score (1-5) and one-sentence reason:'
)

# Compare to non-anchored prompt which tends to cluster at 4-5
print('Anchored rubrics force the judge to use the full scale')

LLM評価者が最もよく機能する場面

LLM評価者は、次のような場合に最も信頼できます。

  • 評価基準が明確で、十分に定義されている
  • 応答の品質差が大きい(明らかに良いものと明らかに悪いもの)
  • 評価対象の領域が評価者モデルの知識の範囲内にある
  • 人間の評価者同士でも意見が分かれる主観的な品質(トーン、有用性)を評価する

一方、最新の知識、高度に専門的な領域、専門知識がなければ検出できない微妙な事実誤認の評価では、信頼性が低くなります。

人間による評価が必要な場面

次のような場合は、人間を評価プロセスに関与させてください。

  • 専門領域(医療、法律、セキュリティ)における応答を評価する場合
  • LLM評価者の基準となる正解データを確立する場合
  • LLM評価者の誤りが現実の重大な結果につながる、高リスクな意思決定の場合
  • 評価者モデルに学習シグナルがほとんどない新規のタスク
  • 領域の専門知識が必要な、微妙な事実誤認を検出する場合
def triage_for_human_review(question, response, llm_score, confidence_threshold=0.7):
    """
    Route low-confidence or high-stakes evaluations to human review.
    """
    # Route to human if judge is uncertain
    if llm_score is None:
        return 'human_review', 'LLM judge failed to produce a score'

    # Route to human for borderline scores (near decision boundaries)
    if 2.5 <= llm_score <= 3.5:
        return 'human_review', f'Borderline score {llm_score} — needs human judgment'

    # Route to human for domain-specific high-risk content
    HIGH_RISK_KEYWORDS = ['medication', 'legal advice', 'financial advice', 'security']
    if any(kw in question.lower() for kw in HIGH_RISK_KEYWORDS):
        return 'human_review', 'High-risk domain — human verification required'

    # Else: LLM score is sufficient
    return 'auto_accept', f'Score {llm_score} — LLM judgment sufficient'

routing, reason = triage_for_human_review('What medication should I take?', 'Take aspirin.', 4.5)
print(f'{routing}: {reason}')

評価パイプラインを構築する

実用的なLLM-as-judgeのパイプラインは、応答を生成 → LLM評価者を実行 → 境界的なケースを人間に振り分け → スコアを集約 → 品質指標を報告、という流れです。監査証跡のために、すべてを記録してください。

import anthropic
import json

client = anthropic.Anthropic(api_key='sk-ant-...')

def evaluate_batch(examples, product_under_test, criteria):
    results = []
    for ex in examples:
        response = product_under_test(ex['question'])
        score, reason = simple_llm_judge(ex['question'], response, criteria)

        results.append({
            'question': ex['question'],
            'response': response,
            'score': score,
            'reason': reason,
            'needs_review': score is None or 2.5 <= (score or 0) <= 3.5
        })

    # Summarize
    valid_scores = [r['score'] for r in results if r['score'] is not None]
    avg_score = sum(valid_scores) / len(valid_scores) if valid_scores else 0
    review_count = sum(1 for r in results if r['needs_review'])

    print(f'Average score: {avg_score:.2f}/5')
    print(f'Cases needing review: {review_count}/{len(results)}')
    return results, avg_score

# results, avg = evaluate_batch(test_cases, my_product, 'helpfulness')

参照あり評価と参照なし評価

LLM評価者は、次の2つのモードで動作できます。

  • 参照あり評価:評価者が応答を既知の正解と比較します。正確性は高くなりますが、ラベル付きデータが必要です。
  • 参照なし評価:評価者が応答そのものの品質を評価します(一貫しているか、役に立つか、文章が適切かなど)。柔軟性は高くなりますが、事実の正確性については精度が低くなります。

正解データを用意できる場合は、参照あり評価を使ってください。要約、トーンの評価、創作文の品質など、自由度の高いタスクには参照なし評価を使います。

知識チェック:位置バイアス

LLM-as-judge評価における位置バイアスとは何で、どのような影響を引き起こしますか?

振り返り:LLM-as-Judge評価

LLM評価モデルは、ニュアンス、意味の正確性、主観的な品質など、従来の指標では測定できない要素を理解できます。一方で、位置バイアス(最初の選択肢を好む)、冗長性バイアス(長い回答を好む)、自己選好(自分と同じスタイルを好む)、スコアインフレーション(4~5/5に集中する)には弱い傾向があります。対策として、回答順をランダム化し、冗長性を抑制する明示的な指示を加え、各スコアレベルを定義したアンカー付きルーブリックを使用し、異なる複数のモデルを評価モデルとして使います。境界的なスコアや高リスク領域は人間の評価者に回してください。大規模運用にはLLM評価モデルを使い、キャリブレーションと重大な意思決定には人間を使います。

よくある質問

「LLMによるLLM出力の評価」レッスンは無料ですか?

はい。「LLMによるLLM出力の評価」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、AI Prompt Engineeringコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 AI Prompt Engineeringコースには全4レッスンが含まれています。

「LLMによるLLM出力の評価」で何を学びますか?

LLMによる評価が機能する理由と、人間による評価と比べた場合の弱点を学びます。 ブラウザで直接実行するハンズオンコードでAI Prompt Engineeringを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

AI Prompt Engineeringを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのAI Prompt Engineeringは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン1/4です。

「LLMによるLLM出力の評価」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このAI Prompt Engineeringレッスンでコードを書いて実行できますか?

はい。すべてのAI Prompt Engineeringレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. LLMによるLLM出力の評価
  2. ルーブリックベースの採点プロンプト
  3. 比較評価:A対B
  4. LLM評価者のキャリブレーションとバイアス
← AI Prompt Engineeringに戻る