Lesson CH09-L03
LLM-Judge
別LLMに採点させる評価パターンとその落とし穴。
- 読了目安
- 11 min
- Colab目安
- 17 min
- 合計
- 28 min
- 前提
- Pydantic Evals
関連: 公式ドキュメント
一行サマリ
LLMJudge(rubric='採点基準', model='gemini-3-flash-preview') を Dataset の Evaluator に追加すると、別 LLM が rubric (採点基準) に従って 0.0〜1.0 で採点 してくれる。自然文の翻訳品質・要約妥当性・トーン適合のような 決定的検証では捉えられない主観品質 を自動評価する標準パターン。ただし コスト・偏り・揺らぎ という固有の落とし穴がある。
ヒーロー: 「採点もまた LLM がやる」
Ch9-L02 のビルトイン Evaluator (IsInstance / EqualsExpected 等) は 決定的 な検証しかできません。「この翻訳は自然か」「この要約は元の意味を保っているか」「このメールは丁寧か」── こうした 主観品質 には 採点役の LLM (Judge) を別途立て、rubric (採点基準) を渡して数値化するパターンが定石です。
概念: 何を Judge に渡し、何を渡さないか
| 項目 | Judge への渡し方 |
|---|---|
評価対象 Agent の output | 常に渡る (採点対象) |
inputs (元の質問) | include_input=True で渡る |
expected_output | include_expected_output=True で渡る (デフォルトで渡るバージョンもある) |
rubric (採点基準) | Evaluator 構築時に文字列で指定 |
「答えと参考解答を見比べて」採点したいなら include_expected_output=True、「答えだけ見て自然さを評価」なら include_input=False, include_expected_output=False。Judge の 見えてる範囲を絞る ことが採点の安定性に直結します。
コード: 3 つのパターン
パターン 1: 最小例 — 翻訳の自然さを採点
from pydantic_ai import Agent
from pydantic_ai.models.google import GoogleModel
from pydantic_evals import Case, Dataset
from pydantic_evals.evaluators import IsInstance, LLMJudge
translator = Agent(
GoogleModel('gemini-3-flash-preview'),
instructions='与えられた英語を自然な日本語に訳してください。',
)
dataset = Dataset(
cases=[
Case(inputs='Hello, world!', expected_output='こんにちは、世界!'),
Case(inputs='I appreciate your help.', expected_output='ご協力に感謝します。'),
Case(inputs='See you tomorrow.', expected_output='また明日。'),
],
evaluators=[
IsInstance(type_name='str'),
LLMJudge(
rubric=(
'出力は与えられた英語の自然な日本語訳になっているか。'
'不自然な直訳や明らかな誤訳は減点。'
'0.0 (誤訳) 〜 1.0 (完璧) で採点してください。'
),
model='google-gla:gemini-3-flash-preview',
include_input=True,
),
],
)
def task(inputs: str) -> str:
return translator.run_sync(inputs).output
dataset.evaluate_sync(task).print(include_input=True, include_output=True)ポイント:
rubricは 採点基準を自然文で記述。具体的・短く・スコアレンジを明示model='google-gla:gemini-3-flash-preview'で Judge 自体のモデルを指定include_input=Trueで inputs (元の英文) も Judge に見せる
パターン 2: 「参考解答との一致度」を採点
from pydantic_evals import Case, Dataset
from pydantic_evals.evaluators import LLMJudge
dataset = Dataset(
cases=[
Case(
inputs='Pydantic AI とは?',
expected_output='型安全と DX に注力した Python のエージェントフレームワーク',
),
Case(
inputs='Logfire とは?',
expected_output='OpenTelemetry 準拠の可観測性プラットフォーム',
),
],
evaluators=[
LLMJudge(
rubric=(
'出力が expected_output の主要な情報をほぼ含んでいれば 1.0。'
'一部しか含まなければ 0.5。完全に違えば 0.0。'
),
model='google-gla:gemini-3-flash-preview',
include_input=True,
include_expected_output=True,
),
],
)「参考解答と意味的に一致しているか」を string match に頼らず Judge に任せる構成。同義語や言い換えにも対応できます。
パターン 3: 複数の Judge を組み合わせる (品質 + トーン)
from pydantic_evals import Dataset
from pydantic_evals.evaluators import LLMJudge
dataset = Dataset(
cases=cases, # 既存ケース
evaluators=[
LLMJudge(
rubric='出力は質問に正しく答えているか。0.0 (誤答) 〜 1.0 (完全正答)。',
model='google-gla:gemini-3-flash-preview',
include_input=True,
),
LLMJudge(
rubric='出力は社内ヘルプデスクとして丁寧で礼儀正しい日本語か。0.0 〜 1.0。',
model='google-gla:gemini-3-flash-preview',
),
],
)「正確さ」と「トーン」 を別 Judge で測ると、片方だけ劣化したケースを発見しやすくなります。
観察: Judge のコストと揺らぎ
- コスト: ケース 100 件 + Judge 2 個なら 200 回の追加 API 呼出。CI で毎回回すと積み重なります。夜間ジョブ + 主要 PR のみ が現実解
- 揺らぎ: 同じ output を 2 回採点すると ±0.1 程度の揺れが普通に起きる。スコアは個別値ではなく分布で見る
- 偏り: Judge 自身の好みが反映される (冗長な出力を高く評価する等)。rubric に「簡潔さも評価軸」と明示 すると緩和
- モデル一致リスク: 評価対象と同じモデルを Judge にすると 自己肯定バイアス。異なるモデル または 温度を下げた同モデル を選ぶ
まとめ
LLMJudge(rubric='採点基準', model='...')で 主観品質を自然文 rubric で採点include_input=True/include_expected_output=Trueで Judge の視野を制御- 複数 Judge (正確さ + トーン) を組み合わせるとケース診断が楽
- コスト・揺らぎ・偏り・自己肯定バイアスに注意 — 異なるモデル + 平均値判断 + 夜間ジョブ
- 決定的 Evaluator (毎 PR) + LLM-Judge (夜間 / リリース前) の 二段階運用
🎉 Ch9 完結 (Observability & Evals)
- ✅ L01 Logfire (可視化) / L02 Pydantic Evals (テスト) / L03 LLM-Judge (主観評価)
- ✅ 本番運用に必要な 観測 + 評価のフルセット が揃った
次の Ch10 Production からは、Durable Execution / UI Event Streams / A2A と、Agent を本番システムに組み込むための最後の 3 トピックを扱います。
Colab で実際に動かす
本レッスンの内容を Google Colab 上で実行できるノートブックを用意しています。下のボタンから自分のColab環境に開けます (要 Google アカウント / GOOGLE_API_KEY)。
notebooks/ch09/03-llm-judge.ipynb