0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Claude CodeでLLMの出力品質を「別のLLMに審判させる」評価パイプラインを作った

0
Last updated at Posted at 2026-04-06

LLMを実務で使っていると、ベンチマークのスコアだけでは判断しにくいことがある。

  • プロンプトを変えたが、本当に品質は上がったのか
  • 安いモデルに切り替えたいが、この用途では十分なのか
  • ローカルモデルのJSON出力はどこまで信用できるのか

こういうときに欲しいのは、自分のテストケースを使って、同じ基準で比較できる仕組みだと思った。

そこで、別のLLMを審判役にして候補モデルの出力品質を評価するパイプラインを作った。
いわゆる LLM-as-a-Judge だが、実際に使いやすいように、評価の分離やバイアス対策を入れている。

GitHub:
https://github.com/archminor/llm-as-a-judge

全体像

テストケース(JSONL) + 設定(YAML)
        │
        ▼
  ┌─────────────┐
  │  Inference   │  候補モデルで推論実行
  │              │  (フォーマット・スキーマの自動検証を含む)
  └──────┬──────┘
         ▼
  ┌─────────────┐
  │    Judge     │  別のLLMが9メトリクスで評価
  │              │  (format / content / expression を分離)
  └──────┬──────┘
         ▼
  ┌─────────────┐
  │   Compare    │  集計・比較レポート生成
  │              │  (JSON + Markdown)
  └─────────────┘

セットアップして実行するだけなら、基本は3コマンドで動く。

uv sync
cp .env.example .env  # APIキーを設定
uv run llm-judge run-all

設計のポイント

3層分離Judge

評価をフォーマット・内容・表現の3層に分け、それぞれ独立したLLM呼び出しで実行する。

Layer メトリクス 狙い
Layer 1 format_compliance, harmlessness 形式と安全性
Layer 2 accuracy, faithfulness, completeness, relevance, reasoning, citation_quality 内容の品質
Layer 3 expression_quality 文章表現

1回のプロンプトで全部を評価させると、たとえばJSONが崩れている回答に対して内容まで引きずられたり、その逆が起きたりしやすい。
分けることで、どこに問題があるかを追いやすくした。

評価モード

モード 用途
pairwise 2モデルの出力をA/B比較する
absolute 1モデルの出力を独立にスコアリングする
hybrid 両方を実行する

バイアス対策

  • ブラインディング: 候補モデル名を隠し、提示順もランダム化
  • Think-before-score: 根拠を先に書かせ、そのあとスコアを出させる
  • 多数決集計: judge_repeats: 3 のように複数回評価して集計する

一貫性モード

inference_repeats >= 2 に設定すると、同じ入力に対する複数回の出力の安定性も評価できる。
単発では良く見えても、毎回かなり違う答えを返すモデルは運用で扱いづらいので、そこも見られるようにした。

設定ファイル

設定はYAML 1つでまとめるようにしている。

run_id: "eval-001"

dataset:
  testcases_path: "data/eval/testcases.jsonl"

candidates:
  - candidate_id: "gpt-oss-20b"
    vendor: "lmstudio"
    model_id: "gpt-oss-20b"
    endpoint: "http://localhost:1234/v1"
    generation_params:
      temperature: 0
      max_tokens: 1024

  - candidate_id: "gpt-5.4-mini"
    vendor: "openai"
    model_id: "gpt-5.4-mini"
    generation_params:
      temperature: 0
      max_completion_tokens: 1024

judges:
  - judge_id: "gpt-5.4-judge"
    vendor: "openai"
    model_id: "gpt-5.4"
    rubric_version: "v1"

protocol:
  evaluation_mode: "hybrid"
  blinding:
    enabled: true
    random_seed: 42
  repeats:
    judge_repeats: 3
  metrics:
    - format_compliance
    - harmlessness
    - accuracy
    - faithfulness
    - completeness
    - relevance
  aggregation:
    method: "majority_vote"   # mean | majority_vote | worst_case

候補モデルとJudgeモデルのベンダーは自由に組み合わせられる。
たとえば GPT 系をJudgeにしつつ、ローカルモデルとクラウドモデルを比較する、といった構成もそのまま書ける。

現時点では、OpenAI、Azure OpenAI、Gemini(ネイティブREST)、OpenAI互換エンドポイントに対応している。

テストケース

テストケースはJSONL形式で、チャット形式と自由形式の両方に対応している。

{"testcase_id": "tc-001", "task_type": "qa", "input": {"messages": [{"role": "user", "content": "What is the capital of France?"}]}}
{"testcase_id": "tc-002", "task_type": "summarization", "input": {"text": "..."}, "constraints": {"required_points": ["mention the fox"]}}

constraints で、必須ポイント・禁止ポイント・出力形式・引用ポリシーなども指定できる。
Judgeはそれらも踏まえて評価する。

ルーブリック

評価基準は Markdown ファイル(rubrics/v1.md)として分離している。

  • 9メトリクスの定義
  • 1 / 3 / 5 のスコア基準
  • 層の割り当て
  • バイアスガード
  • クリティカルイシュー時のスコアキャップ

評価基準のカスタマイズはルーブリック編集でできるようにし、コード変更は不要にした。

出力

比較結果は JSON と Markdown で出力される。

comparison-report.json には、たとえば次の情報が入る。

  • 勝率・敗率(pairwise)
  • メトリクスごとの平均スコア
  • 95%信頼区間
  • クリティカルイシュー件数
  • 一貫性スコア(一貫性モード時)

Markdownレポートも同時に生成されるので、共有やレビューに使いやすい。

以下はサンプル実行結果の Claude Code による可視化。

Evaluation Results — Sample Run

たとえば、あるタスクで高価なモデルAと安価なモデルBを比べた結果、内容面の差は小さいが format_compliance はBのほうが不安定、といった見え方ができる。
その場合、「通常用途はBで十分だが、厳密なJSON出力用途では追加検証が必要」といった判断がしやすくなる。

想定ユースケース

  • プロンプト改善の効果測定
  • モデル選定
  • 回帰テスト
  • ローカルモデルの品質検証

これは何ではないか

  • ベンチマークスイートではない
    テストケースは自分で用意する前提

  • 学習ツールではない
    モデルを訓練するものではなく、出力を評価するもの

  • エージェントフレームワークではない
    バッチ評価パイプラインとして作っている

技術スタック

  • Python >= 3.11
  • Pydantic, Typer, Rich, httpx, tenacity
  • パッケージマネージャ: uv

LLMの評価は、実際にやってみると「何をどう比べればよいか」が意外と難しい。
同じ条件で、ある程度再現可能に比較できる土台があるだけでも、モデル変更やプロンプト変更の判断はかなりしやすくなると思っている。

このパイプラインの実装と記事の執筆には Claude Code を使用した。

フィードバックや質問があればぜひ。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?