LLMを使ったアプリケーションでは、「回答が生成できたか」だけでなく、「その回答が本当に良いか」を継続的に確認する必要があります。しかし、毎回人手で評価するのは時間がかかり、評価者によって基準もばらつきます。
そこで試したのが、別のLLMに回答を採点させる「LLM-as-a-Judge」です。
結論から言うと、LLM-as-a-Judgeは、生成AIアプリの回帰テストやプロンプト比較にかなり便利です。ただし、評価用LLMの判断を完全に正解とみなすのではなく、評価基準を明示し、人手評価と組み合わせて使うことが重要です。
LLM-as-a-Judgeとは
LLM-as-a-Judgeで回答を生成・評価し、必要に応じて人手確認や回帰テストにつなげる流れは次の通りです。
LLM-as-a-Judgeは、LLMの出力を別のLLMに評価させる手法です。
例えば、ユーザーの質問、期待する回答、実際の回答を評価用プロンプトに渡し、次のような観点で採点します。
- 質問に正しく答えているか
- 期待する情報を含んでいるか
- 根拠のない内容を作っていないか
- 読みやすく簡潔か
- 指定した形式を守っているか
評価結果は、単純な合否でも構いませんし、1〜5点のスコアやJSON形式でも構いません。
実際に試す場合は、生成用と評価用でモデルやプロンプトを分けます。
ユーザー質問
↓
生成用LLM
↓
回答
↓
評価用LLM
↓
スコア・理由・改善点
まずは評価データを用意する
評価の精度は、評価データの品質に大きく左右されます。最初から大量のデータを用意する必要はありません。私はまず、代表的な質問を10〜30件ほど作り、期待する回答の条件を整理しました。
例えば、FAQボットなら次のようなデータです。
[
{
"question": "パスワードを忘れた場合はどうすればよいですか?",
"reference": "ログイン画面の「パスワードを忘れた方はこちら」から再設定してください。",
"answer": "ログイン画面でパスワード再設定を選択し、登録済みのメールアドレスを入力してください。"
}
]
ここで重要なのは、referenceを必ずしも模範解答の完全一致にしないことです。
実際の回答は、表現が違っていても意味が正しければ合格です。そのため、評価プロンプトでは「referenceと文字列が一致するか」ではなく、「必要な情報を満たしているか」を判定させます。
また、次のような失敗ケースも意識して含めました。
- 情報が一部不足している回答
- もっともらしい誤情報を含む回答
- 質問とは関係ない回答
- 指定したJSON形式を守っていない回答
評価用プロンプトを作る
評価用プロンプトでは、評価観点と採点基準を具体的に書きます。
JUDGE_PROMPT = """
あなたはLLMの回答品質を評価するレビュアーです。
以下の質問、期待回答、実際の回答を読み、客観的に評価してください。
評価基準:
1. 正確性: 事実関係や手順に誤りがないか
2. 網羅性: 質問への回答に必要な情報が含まれているか
3. 関連性: 質問と関係のない情報を含んでいないか
4. 明瞭性: 読者が理解しやすい文章か
各項目を1〜5点で採点してください。
判断に迷う場合は厳しめに評価し、理由を具体的に説明してください。
必ず次のJSON形式だけで返してください。
{
"accuracy": 1,
"completeness": 1,
"relevance": 1,
"clarity": 1,
"total": 1,
"reason": "評価理由",
"improvement": "改善案"
}
質問:
{question}
期待回答:
{reference}
実際の回答:
{answer}
"""
JSON形式を指定しておくと、後から集計しやすくなります。ただし、LLMが常に正しいJSONを返すとは限りません。実運用では、JSONのパースに失敗した場合の再試行やエラーログも用意しておくと安全です。
Pythonから評価を実行する
OpenAI互換APIを使う場合の最小構成は次のようになります。モデル名は利用する環境に合わせて変更してください。
python -m venv .venv
.venv\Scripts\activate
pip install openai
APIキーはソースコードに直接書かず、環境変数から読み込みます。
$env:OPENAI_API_KEY = "your-api-key"
評価処理の例です。
import json
import os
from openai import OpenAI
client = OpenAI(api_key=os.environ["OPENAI_API_KEY"])
def judge(item):
prompt = JUDGE_PROMPT.format(
question=item["question"],
reference=item["reference"],
answer=item["answer"],
)
response = client.chat.completions.create(
model="評価に使うモデル名",
temperature=0,
messages=[
{
"role": "system",
"content": "あなたは厳密な品質評価者です。"
},
{
"role": "user",
"content": prompt
}
]
)
text = response.choices[0].message.content
return json.loads(text)
item = {
"question": "パスワードを忘れた場合はどうすればよいですか?",
"reference": "ログイン画面からパスワードを再設定してください。",
"answer": "ログイン画面の再設定リンクを開き、メールアドレスを入力してください。"
}
result = judge(item)
print(json.dumps(result, ensure_ascii=False, indent=2))
私が試した範囲では、temperatureを低くすると評価のばらつきが減りました。ただし、同じ回答でも毎回まったく同じ判定になるとは限りません。特に、文章の自然さや十分性の評価は揺れやすい傾向があります。
スコアだけで判断しない
評価結果を平均点だけで見ると、問題を見落とします。
例えば、次の2つの回答が同じ合計点だったとします。
回答A: 正確だが、手順が一つ不足している
回答B: 説明は詳しいが、重要な部分に誤りがある
プロダクトによっては、回答Aは許容できても、回答Bは絶対に許容できないかもしれません。
そのため、私は合計点だけでなく、項目別スコアとreasonも保存するようにしました。特に正確性が一定点未満の場合は、他の点数に関係なく人手確認へ回す、といったルールを設定できます。
def needs_human_review(result):
if result["accuracy"] <= 2:
return True
if result["total"] <= 12:
return True
return False
また、評価用LLMが間違う可能性もあります。評価対象の回答に引っ張られたり、流暢な誤答を高く評価したりすることがあります。
対策として、次のような確認を行いました。
- 評価用LLMの判定を人手でサンプル確認する
- 明らかな正解・不正解のケースを評価データに含める
- 評価基準ごとに具体例をプロンプトへ追加する
- 複数の評価者や複数回の判定を比較する
- 高リスクな回答は自動合格にしない
プロンプト変更の回帰テストに使う
LLM-as-a-Judgeの便利な使い方が、プロンプト変更前後の比較です。
同じ評価データに対して、旧プロンプトと新プロンプトの回答を生成し、それぞれを評価します。
def average_score(results):
return sum(r["total"] for r in results) / len(results)
old_results = [judge(item) for item in old_answers]
new_results = [judge(item) for item in new_answers]
print("old:", average_score(old_results))
print("new:", average_score(new_results))
ただし、平均点が上がったからといって、必ず改善したとは限りません。特定のカテゴリだけ悪化している可能性があるため、質問をカテゴリ分けして確認します。
カテゴリ別に見る項目の例:
- FAQ
- トラブルシューティング
- 要約
- コード生成
- 禁止事項を含む質問
特に本番で多い質問や、失敗すると影響が大きい質問には重みを付ける方法もあります。
まとめ
LLM-as-a-Judgeを使うと、LLMの回答品質を一定の基準で繰り返し確認できます。特に、次の用途で効果を感じました。
- プロンプト変更の回帰テスト
- 生成結果の大量スクリーニング
- 回答品質の悪化検知
- 人手評価の補助
- モデルや設定の比較
一方で、評価用LLMも万能ではありません。評価基準を明示し、代表的なテストデータを用意し、人手によるスポットチェックを組み合わせる必要があります。
まずは10件程度の評価データと、正確性・網羅性・関連性・明瞭性の4項目から始めるのがおすすめです。評価結果を蓄積していくと、自分のLLMアプリでどの種類の失敗が多いのかも見えるようになります。