コンテンツにスキップ

eval 設計 用語集+学習メモ — 評価系を「作る側」になる

LLM 出力の品質を定量化する評価系を設計するための写経メモ+用語集。 決定論チェッカー → golden dataset → LLM-as-a-Judge → judge のバイアス実測 → ハイブリッド合成 → 回帰ゲート、を ex01〜06 で一周する。 ロードマップ本体は ../../agent-design/STUDY_NOTES.md(STEP 3〜5)、サンプルの並びは README.md を参照。


全体像

ファイル間の関係と学ぶ順序

# ファイル 学ぶ概念 LLM この回の「背骨の一言」
01 ex01_deterministic_checks.py 決定論チェッカー(JSON / schema / regex / 長さ / 禁止語)を (passed, reason) に統一 形式は決定論で測る
02 ex02_golden_dataset.py golden dataset 設計(代表性・難易度混在・エッジ・タグ)+正規化・EM・文字 F1・層別集計 評価の質はデータ設計で決まる
03 ex03_llm_as_judge.py ルーブリック採点(観点別 1〜5)。reason→score の judge 版 CoT、JSON 固定+temperature=0 意味は judge で測る
04 ex04_judge_bias.py position bias を swap consistency で、verbosity bias を同内容・長さ違いペアで実測 judge を信じる前に judge を測る
05 ex05_hybrid_pipeline.py 決定論ゲート → judge の 2 段構え。「決定論で落とせるものに LLM を使わない」コスト設計 安いゲートで先に落とす
06 ex06_regression_gate.py baseline vs candidate のケース単位勝敗。デグレ検知で exit 1(CI ゲート) 平均でなく win/loss を見る

ex01(形式の検証器)と ex03(意味の採点器)が二本柱で、ex05 がそれを直列合成、ex06 が ex02 のデータセット+スコアラを使って変更前後を比較する、という依存になっている。ex01 → ex02 → ex03 → ex04 → ex05 → ex06 の順に読むと、部品が出てきた順に合成されていく。

評価フロー(決定論 / golden / judge / ハイブリッド / 回帰ゲート)

flowchart TD
    OUT["LLM 出力 1 件"] --> KIND{"検証したいのは<br/>形式か 意味か"}

    KIND -->|"形式(JSON・型・書式・長さ・禁止語)"| DET["決定論チェッカー<br/>ex01: check_json / check_schema /<br/>check_pattern / check_length / check_forbidden"]
    DET --> DETR{"passed?"}
    DETR -->|"No"| FAIL["fail(理由つき)<br/>= judge を呼ばずに確定(無料)"]
    DETR -->|"Yes"| JUDGE

    KIND -->|"意味(正確性・完全性・忠実性)"| JUDGE["LLM-as-a-Judge<br/>ex03: ルーブリックで観点別 1〜5<br/>reason → score の順で JSON 出力"]
    JUDGE --> BIAS["judge の健全性チェック<br/>ex04: swap consistency / 長さ違いペア"]
    JUDGE --> PASS["pass / fail(score 閾値で判定)"]

    subgraph DATA["評価対象の供給源"]
      GOLD["golden dataset<br/>ex02: (input, expected, tags)<br/>正規化 → EM / 文字 F1 → 層別集計"]
    end
    GOLD -.->|"既知の正解があるタスク"| KIND

    DET -.->|"前段ゲートとして合成"| HYB["ハイブリッド評価<br/>ex05: 決定論ゲート → judge"]
    JUDGE -.->|"後段として合成"| HYB

    GOLD --> GATE["回帰ゲート<br/>ex06: baseline vs candidate を同一データで<br/>ケース単位 win/loss → デグレなら exit 1"]
    GATE --> CI{"losses あり?"}
    CI -->|"Yes"| RED["CI を赤く(マージ不可)"]
    CI -->|"No"| GREEN["PASS"]

要するに 「形式 = 決定論(ex01)/意味 = judge(ex03)/正解付きの量産検証 = golden(ex02)」 の3部品があり、ex05 が縦に合成(コスト設計)、ex06 が横に比較(回帰検知)する構図。


サンプル別の要点

ex01 — 決定論チェッカー(LLM ゼロ呼び出しで白黒つく検査を先に全部やる)

中心概念: 決定論チェッカー(deterministic checker)。「機械的に passed/failed が一意に決まる」検査のこと。速い・無料・100% 再現可能の3拍子がそろう。LLM 出力でも「JSON としてパースできるか」「必須キーがあるか」「日付書式を含むか」「長さ制限内か」「禁止語が混じってないか」は決定論で測れる。逆に「内容が正しいか・役に立つか」は決定論では測れず、ex03 の judge の仕事になる。この線引きが eval 設計の出発点。

設計上の肝は、全チェッカーを (passed: bool, reason: str) のタプルに戻り値を統一していること(17〜18 行目の CheckResult = tuple[bool, str])。戻り値の形をそろえると、ex05 で複数チェッカーを直列のゲートとして並べられる(合成可能になる)。

# ex01_deterministic_checks.py
CheckResult = tuple[bool, str]            # ① 戻り値の型を統一 → 合成可能にする土台

def check_json(output: str) -> CheckResult:   # ② パースできるか(最頻出の事故を先に潰す)
    try:
        json.loads(output)
        return True, "valid JSON"
    except json.JSONDecodeError as e:
        return False, f"JSON parse error: {e}"

def check_schema(output: str, required: dict[str, type]) -> CheckResult:  # ③ キー有無+型
    ...
    if not isinstance(data[key], expected_type):
        return False, f"key {key} is {type(data[key]).__name__}, want {expected_type.__name__}"
やってること なぜそうする
CheckResult = tuple[bool, str](18) 戻り値の型を (合否, 理由) に固定 reason まで返すと、落ちた時に「何が」「どう」ダメかが集計できる。bool だけ返すと原因が消える
check_json(23-28) まずパース可否だけ見る 「```json フェンス混入」「前置きトーク混入」が JSON タスクの最頻出事故。意味検証の前にここで弾く
check_schema(33-43) 必須キー+型を確認 パースできても amount が文字列「千二百」だと後段が壊れる。本格運用は pydantic / jsonschema に置換する最小版
実行部(68-84) 「正常・フェンス混入・型違い」3 サンプルを全チェッカーにかける 1 出力 × 複数観点のマトリクスを作ると、どの観点で落ちたかが一目で分かる

末尾の「ここまで LLM ゼロ呼び出し・実行 0.01 秒」がこの回の主張。無料で落とせるものに金のかかる LLM judge を使うな

ex02 — golden dataset 設計(評価の土台になる正解付き入力集合)

中心概念: golden dataset(input, expected, tags) のレコード集合で、eval の品質はモデルでもプロンプトでもなくまずこのデータ設計で決まる。4 つの設計原則がコードに埋め込まれている(25〜33 行目)。

  • 代表性: 本番で来る入力の分布を映す(きれいな例だけ集めない)
  • 難易度の混在: 必ず解けるべき easy と、改善を検知する hard を両方入れる
  • エッジケース: g04 のように「答えが本文にない」ケースを入れ、「わからない」と言えるか(= 幻覚チェック)を測る
  • タグ: 集計を「全体 1 個の数字」でなく層別で見られるようにする

スコアラは2段構え。EM(Exact Match)= 正規化後の完全一致(厳しいが解釈の余地ゼロ)と、文字 F1 = 部分一致の度合い(EM=0 でも「惜しい」を拾う)。

# ex02_golden_dataset.py
def normalize(text: str) -> str:                       # ② 揺れを吸収(日本語 eval の生命線)
    text = text.strip().lower()
    return re.sub(r"[\s。、.,「」『』\"']", "", text)

def exact_match(pred: str, expected: str) -> bool:     # ③ EM = 正規化後の完全一致
    return normalize(pred) == normalize(expected)

def char_f1(pred: str, expected: str) -> float:        # ④ 文字集合の precision/recall の調和平均
    p, e = set(normalize(pred)), set(normalize(expected))
    precision = len(p & e) / len(p)
    recall = len(p & e) / len(e)
    return 2 * precision * recall / (precision + recall)
やってること なぜそうする
GOLDEN(25-33) easy / hard / edge をタグ付きで保持 「実務では JSONL で管理し、本番の失敗事例が出るたび 1 行足す」= データセットは育てるもの
normalize(40-42) 全角半角・大文字小文字・記号を除去 正規化が甘いと、内容は合っているのに記号差で EM が落ち、スコアが信用できなくなる
char_f1(51-59) 文字集合の積集合から precision・recall を出し調和平均 EM は 0/1 で粗い。部分一致を連続値で拾えると改善の方向が見える
タグ別集計(91-96) タグごとに EM 率を出す 「全体 75%」より「edge だけ 0%」の方が次の行動につながる。集計は必ず層別で

temperature=0(69 行目)も要点。eval では出力のばらつきを消すのが基本。

ex03 — LLM-as-a-Judge(決定論で測れない意味の品質をルーブリックで採点させる)

中心概念: LLM-as-a-Judge とルーブリック。要約・説明文のように正解が一意でないタスクは EM/F1 が使えない。そこで採点者役の LLM に点を付けさせる。鍵は ルーブリック(rubric)= 採点基準の明文化。「良い回答か?」と丸投げせず、観点(accuracy / completeness / conciseness)ごとに 1〜5 の各点の意味まで書く(24〜38 行目)。ここが曖昧だと judge のスコアは「雰囲気の数値化」にしかならない。

もう一つの肝が reason → score の順で出させる judge 版 CoT(34 行目の指示)。先に理由を言語化させてからスコアを決めさせると、採点の一貫性が上がる(思考の外部化)。出力は response_format={"type": "json_object"} で JSON 固定、temperature=0 でばらつきを抑える(52-53 行目)。

# ex03_llm_as_judge.py
RUBRIC = """...
必ず次の JSON だけを返してください(reason を先に書いてから score を決めること):
{"accuracy": {"reason": "...", "score": 1-5}, ...}"""   # ① 観点・尺度・各点の意味を明文化

def judge(question, reference, answer) -> dict:
    response = client.chat.completions.create(
        model=JUDGE_MODEL,
        messages=[{"role": "system", "content": RUBRIC},
                  {"role": "user", "content": f"質問: ...\n参照情報: ...\n採点対象の回答: ..."}],
        temperature=0,                                   # ② ばらつきを消す
        response_format={"type": "json_object"},         # ③ 構造化を強制
    )
    return json.loads(response.choices[0].message.content)

実行部では「良い回答 / 捏造を含む不正確な回答 / 冗長な回答」の 3 つを採点させ、不正確な回答の accuracy・冗長な回答の conciseness がちゃんと下がるかを見る(83-84 行目)。これは「judge 自体の動作確認」= judge の eval の入り口でもある。下がらないならルーブリックの文言を直す。

ex04 — judge のバイアスを実測する(position bias と verbosity bias)

中心概念: judge のバイアス。LLM-as-a-Judge は採点者自身に系統的な癖を持つ。

  • position bias(位置バイアス): ペア比較で「先に提示された方(A の席)」を選びがち。対策が swap consistency: 同じペアを (a,b)(b,a) の両順序で聞き、判定が一致した時だけ採用。順序で反転したら、それは中身でなく位置で勝った産物。
  • verbosity bias(冗長性バイアス): 同じ内容なら長い方を高く採点しがち。対策はルーブリックに簡潔性を明記、または長さを揃えて比較。
# ex04_judge_bias.py
def swap_test(question, ans1, ans2) -> dict:
    first  = pairwise_judge(question, ans1, ans2)   # ① ans1 を A の席に置く
    second = pairwise_judge(question, ans2, ans1)   # ② ans1 を B の席に置く(順序を入れ替え)
    winner_run1 = "ans1" if first  == "A" else "ans2"
    winner_run2 = "ans1" if second == "B" else "ans2"  # ③ B 視点に読み替え
    return {
        "consistent": winner_run1 == winner_run2,      # ④ 両順序で同じ勝者なら信頼できる
        "verdict": winner_run1 if winner_run1 == winner_run2 else "tie(順序依存)",
    }
やってること なぜそうする
first / second(48-49) 同じペアを順序だけ替えて 2 回聞く 1 回だけだと「位置で勝った」のか「中身で勝った」のか区別できない
winner_run2(50) 2 回目は ans1 が B の席なので、"B" を ans1 勝ちに読み替え 席ではなく「どの回答が勝ったか」に正規化しないと一致判定できない
consistent(52) 両順序で同じ勝者か 不一致なら position bias の影響下 → tie 扱いにして判定を捨てる

実行部の設計が巧い。互角ペアでだけ position bias が表に出る(71-72 行目)。実力差が大きいペアでは中身の差が位置の癖に勝つので、バイアスは隠れる。だから「ほぼ互角」のペアでテストする。末尾に実務の定石3つ(両順序で聞く / judge と被採点モデルを分ける = self-preference 対策 / 人手ラベル 20〜30 件と一致率を測ってから本採用)が並ぶ。

ex05 — ハイブリッド評価パイプライン(決定論ゲート → LLM judge の 2 段構え)

中心概念: ハイブリッド評価とゲート方式。ex01 のチェッカーと ex03 の judge を直列合成する。原則は 「決定論で落とせるものに LLM を使わない」。形式不備は無料・ミリ秒で即落とし、合格したものだけを高価・低速な judge に回す。

# ex05_hybrid_pipeline.py
def evaluate(source: str, output: str) -> dict:
    for gate in (check_json_schema, check_date_format):   # ① 決定論ゲートを直列に
        passed, reason = gate(output)
        if not passed:
            # 決定論で落ちた = judge 呼び出しなし(コスト 0 で不合格確定)
            return {"verdict": "fail", "stage": gate.__name__, "reason": reason, "judged": False}  # ②
    result = judge_summary(source, json.loads(output)["summary"])  # ③ 通過分だけ judge へ
    verdict = "pass" if result["score"] >= 4 else "fail"
    return {"verdict": verdict, "stage": "judge", "reason": result["reason"], "judged": True}
やってること なぜそうする
for gate in (...)(65) チェッカーを直列に並べ、1 つでも落ちたら即 return ex01 で (passed, reason) に統一したから、こうやって並べられる
"judged": False(69) 「この件は judge を呼んでいない」を記録 後で「何件 judge を呼んだか」= コストを集計できる
"stage": gate.__name__(69) どの段で落ちたかを残す 層別集計で「形式不備が多い/意味不備が多い」= 直すべき場所が見える

実行部では形式不備 2 件+意味不備 1 件+正常 1 件を流し、judge が呼ばれるのは後ろの 2 件だけ(4 件中 2 件 = コスト半減)。前段で 8 割落とせれば eval 全体のコストとレイテンシが 1/5 になる、という設計思想。eval のコストもレイテンシも設計対象。

ex06 — 回帰ゲート(プロンプト変更の前後をスコア差分で比較し、デグレなら落とす)

中心概念: 回帰ゲート(regression gate)。eval の最終形は「変更のたびに自動で回り、デグレを検知したら CI を赤くする」回帰スイート。ex02 の golden dataset+スコアラを使い、プロンプト 2 案(baseline = 現行版 / candidate = 変更案)を同一データで比較して勝敗を判定する。

# ex06_regression_gate.py
PROMPTS = {
    "baseline":  "...本文に答えがなければ「わからない」と答えてください。",
    "candidate": "質問に単語または短いフレーズで答えてください。",   # ① 「わからない」指示を削除(デグレを仕込む)
}

base = run_suite(PROMPTS["baseline"])    # ② 各案を golden 全件に回し id→正誤 の辞書に
cand = run_suite(PROMPTS["candidate"])

wins   = [i for i in base if cand[i] and not base[i]]   # ③ candidate で直ったケース
losses = [i for i in base if base[i] and not cand[i]]   #    candidate で壊れたケース

if losses or (cand_em - base_em) < DEGRADE_THRESHOLD:    # ④ 1 ケースでも壊れたら CI を赤く
    print("❌ REGRESSION: candidate はデグレを含む。マージ不可")
    sys.exit(1)
やってること なぜそうする
PROMPTS(34-37) candidate からわざと制約を 1 つ削る edge ケース g04(「わからない」と答えるべき)が壊れる様子を再現する仕込み
wins / losses(73-74) ケース単位で「直った/壊れた」を抽出 平均 EM が同じでも win/loss の中身が違えば別物。壊れたケース id まで出すから直せる
if losses ... sys.exit(1)(86-88) 壊れたケースがあれば終了コード 1 「平均は同じだから OK」を機械的に禁止。exit 1 が CI(GitHub Actions 等)を赤くするフック

DEGRADE_THRESHOLD = 0.0(39 行目)は「ベースラインを 1 ケースでも下回ったら fail」の厳格運用。本格運用ではこの構造を promptfoo / inspect-ai に載せ替える。


用語集(最重要)

1. 一番混同する2語: 決定論チェッカー と LLM-as-a-Judge

eval の背骨。形式は決定論で、意味は judge で測る、という役割分担。

決定論チェッカー LLM-as-a-Judge
測るもの 形式(パースできるか・型・書式・長さ・禁止語) 意味(正確か・役立つか・忠実か)
判定 機械的に一意(再現 100%) LLM が採点(バイアスあり・ばらつきあり)
コスト / 速度 無料 / ミリ秒 数円 / 数秒
具体例 ex01 の check_json / check_schema / check_pattern ex03 の judge(ルーブリック採点)
使う API json.loads / re.search / isinstance chat.completions.create(response_format={"type":"json_object"})

判定基準(1文): その品質が「機械的に白黒つくか」で決める。つくなら決定論、つかない(人によって採点が割れる類)なら judge。ex05 はこの2つを直列に並べて両取りする。

よくある誤解: 「judge があれば決定論は要らない」→ 逆。無料で落とせる形式不備に judge を使うのは金とレイテンシの無駄(ex05 の主題)。決定論を前段ゲートにして judge の呼び出し数を減らすのが定石。

2. judge のバイアス2語: position bias と verbosity bias

どちらも judge の系統的な癖。混同しやすいので対比で。

position bias verbosity bias
癖の中身 ペア比較で先に出た方(A の席)を選びがち 長い方を高く採点しがち
出やすい条件 品質が互角のペア(実力差があると隠れる) 同内容で長さだけ違うペア
対策 swap consistency: 両順序で聞き、一致時だけ採用 ルーブリックに簡潔性の観点を明記 / 長さを揃える
具体例 ex04 の swap_test(互角ペアで検査) ex04 の short vs long(水増し)ペア

ほかに self-preference(judge が自分のモデルの生成文を好む)がある。対策は judge のモデルと被採点モデルを分けること。

3. golden dataset と 本番ログ(評価データの2系統)

golden dataset 本番ログ(production trace)
正解 expected がある(採点が自動化できる) 正解なし(オンライン judge かサンプリング人手)
いつ回すか 変更前(オフライン)。CI で回帰検知 運用中(オンライン)。実トラフィックの監視
具体例 ex02 / ex06 の GOLDEN ../langfuse_basics/ の本番トレースへの score
本メモの範囲 ★ここ(ex02・ex06) langfuse_basics ex05 のスコアと接続

育て方: 本番ログで見つけた失敗事例を golden に 1 行足す(ex02 末尾)。データセットは固定の試験問題ではなく、失敗のたびに育てるもの

4. 評価指標: EM / 文字 F1 / precision / recall

指標 定義 性質 具体例
EM(Exact Match) 正規化後に完全一致なら 1 / それ以外 0 厳しい・解釈の余地ゼロ・粗い(0/1) ex02 exact_match, ex06
precision 予測した文字のうち正解にも在った割合 = |p∩e|/|p| 「無駄を出してないか」 ex02 char_f1 の途中計算
recall 正解の文字のうち予測で拾えた割合 = |p∩e|/|e| 「取りこぼしてないか」 ex02 char_f1 の途中計算
文字 F1 precision と recall の調和平均 EM=0 でも「惜しい」を連続値で拾う ex02 char_f1

EM か F1 か: 短答抽出(「ClickHouse」など答えが定まる)は EM。言い換えや部分一致を拾いたい(自由記述寄り)なら F1。ただし自由記述の「意味の正しさ」自体は F1 でも測りきれず judge へ(ex03)。 ※この回の F1 は文字単位。一般の QA で出る token-level F1(単語単位)とは粒度が違う点に注意。

5. pointwise judge と pairwise judge(judge の2方式)

pointwise(点数式) pairwise(ペア比較式)
何を出すか 1 回答に絶対スコア(1〜5) 2 回答のどちらが良いか(A/B)
出てくる回 ex03(ルーブリック採点) ex04(pairwise_judge
バイアス verbosity 等 position bias が出る(→ swap 必須)
向く用途 単体の品質を数値化 2 案の優劣を決めたい(A/B 比較)

6. 回帰ゲート と オフライン評価(運用での位置づけ)

オフライン評価 回帰ゲート
やること golden を回して現状のスコアを知る baseline と candidate を比べデグレを検知
判断 絶対値(「EM 80%」) 差分(「前の版を下回ったか」)
出力 スコア表・層別集計 win/loss + exit code(CI を赤/緑に)
具体例 ex02 ex06

平均は罠: 平均 EM が同じでも「直った 2 件・壊れた 2 件」なら中身は別物。回帰ゲートは平均でなくケース単位の win/lossを見て、壊れた id まで出す(ex06)。

7. テスト と eval(最も根本の対比)

テスト eval
期待 毎回 100% pass pass で測る(LLM は非決定的)
失敗 1 件の意味 バグ 分布の 1 サンプル
運用 落ちたらマージ不可 閾値・ベースライン比較で判断(ex06)

決定論チェッカー(ex01)だけは「テスト」に近い(一意に白黒つく)。judge(ex03)が入った瞬間に「eval」の世界(率と分布)になる。

8. クイック早見表(困りごと → 見る/使うもの)

困りごと 見る/使うもの
出力が JSON / 型 / 書式どおりか確かめたい 決定論チェッカー(ex01 check_json / check_schema / check_pattern
要約・説明文の「中身の良さ」を点数化したい LLM-as-a-Judge + ルーブリック(ex03)
judge のスコアを信じてよいか不安 swap consistency で position bias を実測(ex04)
judge が長い回答ばかり高評価する verbosity bias。ルーブリックに簡潔性を明記(ex04)
eval のコスト・レイテンシを下げたい 決定論ゲート → judge のハイブリッド(ex05)
プロンプト変更で性能が落ちてないか 回帰ゲート。baseline vs candidate で win/loss(ex06)
「全体は良いのに特定ケースが弱い」を見つけたい タグ別の層別集計(ex02)
短答が正解と一致しているか自動採点したい 正規化 + EM(ex02 exact_match
EM=0 でも「惜しい」を拾いたい 文字 F1(ex02 char_f1
本番トレースを judge で採点したい(オンライン) ../langfuse_basics/ ex05 の score と接続

学んだこと(要点)

  • 形式は決定論、意味は judge。この役割分担が eval 設計の背骨。決定論で白黒つくものに LLM を使うのは無駄(ex01 ⇔ ex03 ⇔ ex05)。
  • チェッカーの戻り値を (passed, reason) に統一しておくと、後で直列ゲートとして合成できる(ex01 の設計が ex05 で効いてくる)。reason まで返すと落ちた原因が集計できる。
  • eval の品質はデータ設計で決まる。代表性・難易度混在・エッジケース・タグの4原則を golden に埋め込む。集計は必ず層別で見る(「全体 75%」より「edge だけ 0%」が行動につながる)。
  • judge を信じる前に judge を測る。position bias は swap consistency で、verbosity bias は同内容・長さ違いペアで実測できる。互角ペアでだけバイアスが表に出る点が巧い。
  • judge は reason → score の順(judge 版 CoT)、JSON 固定、temperature=0、ルーブリック明文化、の4点セットでばらつきと曖昧さを抑える。
  • 回帰ゲートは平均でなく win/loss。平均が同じでも壊れたケースがあれば別物。exit 1 で CI に繋ぐ。
  • テストと eval は別物。テストは 100% pass・失敗=バグ、eval は pass 率・失敗=分布の1サンプル。

拡張アイデア

  1. golden dataset を JSONL ファイル化: ex02 の GOLDEN をハードコードから golden.jsonl に出し、ex02 と ex06 で共有読み込みにする。本番の失敗事例を追記する運用(データセットを育てる)を実体験する。
  2. judge と人手ラベルの一致率を測る: 20〜30 件に人手で good/bad を付け、ex03 の judge スコアとの一致率(Cohen's κ など)を出す。「judge を本採用してよいか」をデータで判断する ex04 末尾の定石を実装する。
  3. ルーブリックなし版との比較: ex03 を「良い回答ですか? 1〜5 で」と丸投げする版に書き換え、ルーブリックあり版とスコアの説明力・一貫性を比較する。ルーブリックの効果を定量化。
  4. ハイブリッドのコスト計測を実数化: ex05 に judge 1 回あたりのトークン数・概算コストを記録し、「前段ゲートで N% 落とすとコストが何分の一になるか」を実測のグラフにする。
  5. promptfoo / inspect-ai への載せ替え: ex06 の自前回帰スイートを promptfoo の YAML、または inspect-ai の Task で書き直し、GitHub Actions の PR で自動実行する(STEP 5 の到達点)。
  6. pairwise の Bradley–Terry でランキング化: ex04 の pairwise 比較を 3 案以上に拡張し、勝敗行列から Bradley–Terry / Elo で総合ランキングを出す。多案比較を pointwise でなく pairwise で回す設計を学ぶ。

記事参照

  • 連載との対応: Software Design 第28回(GEPA + LLM-as-a-Judge)。判定器としての LLM を最適化に組み込む回の前提知識。
  • ロードマップ: ../../agent-design/STUDY_NOTES.md(STEP 3〜5)
  • オンライン評価(本番トレースへの judge): ../langfuse_basics/ の ex05 スコアと接続する
  • サンプルの並び・観察ポイント: README.md

作成: 2026-06-12 / 最終更新: 2026-06-12