# LLM判定器の再採点実験

記事 `web/content/blog/ja/llm-judge-reference-context-biases.md` の実験素材です。論文のデータではなく、この記事のために作った合成ケースを使っています。

## 何をしたか

4領域（ホテル予約・注文キャンセル・社員のアクセス権付与・請求書の支払い済み化）×8＝**32ケース**。各ケースは「依頼」「検索ツールの返り値（12件のエントリ）」「関数定義」「提案された呼び出し（引数1つ）」でできています。

同じ候補値を、判定器に見せる情報だけ変えて採点しました。

| 軸 | 値 |
|---|---|
| 根拠の位置 (placement) | `visible`：正解のエントリが2番目で、先頭1,000文字に入る／`buried`：正解が最後で、1,000文字の外／`buried_notice`：buriedに「ここから先は省略」の一文を足す |
| 参照 (ref) | `none`／`ref_correct`：正しい値を期待値とする／`ref_wrong`：誤った値を期待値とする |
| 候補 (cand) | `correct`：正しい値／`wrong`：先頭エントリ（見える誤った値）／`wrong_hidden`：切れた側にある別の誤った値（`buried*`のみ） |

`ref_wrong`の参照は、候補が`wrong`か`wrong_hidden`なら**候補と同じ値**を、`correct`なら先頭エントリの値を指します。参照の文面は、値以外すべて同じです。

判定は ACCEPT／REJECT／UNSURE の3択。1行目がこの3語のどれか1語だけのものを判定として数え、それ以外は FORMAT として別に数えます。

## ファイル

- `gen_cases.py`：ケースを決定的に生成して `cases.json` を書く
- `run_judge.py`：`claude -p` で採点して `results_<model>.jsonl` に追記する（再開可能）
- `analyze.py`：条件ごとの ACCEPT／REJECT／UNSURE／FORMAT を数える
- `make_fig1.py`／`make_fig2.py`：記事の図を作る（`make_fig2.py` は結果を読む）
- `results_haiku.jsonl`／`results_sonnet.jsonl`／`results_opus.jsonl`：判定器の生の出力

## 実行

```bash
mkdir -p /tmp/llmj/run               # CLAUDE.mdなどが無い空のフォルダ
python3 gen_cases.py
python3 run_judge.py haiku 6         # 第2引数は並列数。sonnet・opusも同様
python3 analyze.py haiku sonnet opus
```

`claude -p` は `--tools ""`・`--setting-sources ""`・`--strict-mcp-config`・`--system-prompt`（判定器の役割）で、道具・設定・既定のシステムプロンプトを外して呼んでいます。生成設定（temperature等）は指定していません。1条件につき1回の採点です。

`modelUsage` には、判定とは別にClaude Code側の補助呼び出しとして `claude-haiku-5-5` が小さく（1回あたり入力約1,200・出力十数トークン）記録されることがあります。判定の出力は指定したモデルのものです。

## 限界

- 合成32ケース・日本語・1つのテンプレート・1つのrubric。実際の業務ログでの率ではありません。
- 条件ごとに1回の採点で、同じ条件を繰り返したときの揺れは測っていません。
- 論文（arXiv 2610.18497）の再現ではありません。論文の判定器は「Yes」確率を返すモデルで、この実験は文章で判定するClaudeです。
