現場実装の クムビーバー です。評価スイートを育てるとき、最初からLLMジャッジに頼ると運用が重くなります。門番は軽く、再現可能に。重い採点は残った候補へ。
この回の答え
門番はオフラインの自動採点(含有・JSON・ツール呼び出し)です。AIによる判定は後段に回し、軽い採点を先に再現可能にします。
この回だけの用語
| 用語 | ひとことで |
|---|---|
| scorer | 機械で合否を出す採点器。差し替え可能にする |
| contains | 必要断片が入っているかの判定 |
| json_valid | JSON がパースでき、必須キーがあるかの判定 |
| tool_call scorer | ツール名と必須引数の有無を見る判定 |
| LLMジャッジ | 別モデルに良し悪しを聞く重い採点。後段向き |
| pluggable | 用途が増えても本体を書き換えず、採点器だけ足せる形 |
基本3 scorer
| scorer | 見ること | 向いている用途 |
|---|---|---|
| contains | 部分文字列/キーワード | coding smoke、必須フレーズ |
| json_valid | パース可否と必須キー | 業務API連携、構造化出力 |
| tool_call | ツール名と必須引数 | エージェント、社内ツール連携 |
これらは外部モデルに依存せず、再現性が高いのが利点です。CIや夜間バッチにも載せやすいです。判定が揺れると、「モデルが変わったのか、採点が揺れたのか」が分からなくなります。
それぞれの設計メモ
contains
厳密一致より、必要断片の含有から始める。過検出を嫌うなら禁止パターン(空、明らかに無関係)も併用します。
json_valid
コードフェンスや前置きを許容する前処理を入れるか、厳格に落とすかを用途で決める。業務接続なら厳格寄りが安全です。
tool_call
期待ツール名だけでなく必須引数の有無を見る。プロファイル側の parser 設定とセットで読む必要があります。
なぜ pluggable にするか
用途が増えるたびに評価ハーネス本体を書き換えていると続きません。@scorer("name") のように関数を登録し、タスク定義側の scorer: から参照する形にすると、次が楽になります。
- RAG用の出典チェック
- 禁止用語の検出
- 言語判定
- スキーマバージョン差分
- 文字数下限/上限
重要なのは、scorer を増やす前に「その失敗が意思決定に効くか」を確認することです。スコアは多いほど良いわけではありません。意思決定に使わない指標は、運用負債です。
| 増やしてよい条件 | 増やさない方がよい条件 |
|---|---|
| 合否が採用判断を変える | 「あると安心」程度 |
| 失敗理由を人間が説明できる | 判定根拠が曖昧 |
| CIで安定して回る | 外部依存で頻繁に落ちる |
judge は後段
rubric(1〜5点など)で見る評価は強力ですが、前提が増えます。
- judge モデルの endpoint が生きている
- 採点プロンプトが安定している
- コストと待ち時間を許容できる
- 採点者モデル変更時の再校正方針がある
門番であるスモークを judge 依存にすると、基盤障害とモデル品質の切り分けが難しくなります。まずは deterministic な判定で足切りし、残った候補に judge を当てるのが安全です。judge は「優劣の微差」を見る道具であって、起動確認の代替ではありません。
設計チェックリスト
- タスクごとに「何をもって合格か」を一文で書けるか
- 人間が見て異議の少ない判定か
- 失敗時に詳細(どこが欠けたか)を残せるか
- プロファイル設定(tool parser等)と評価が噛み合っているか
- scorer 追加がハーネス本体の改修なしでできるか
- CI で外部 LLM 無しでも門番が回るか
失敗詳細に残すと効くもの
- 期待値(キー、ツール名、必要断片)
- 実際の抽出結果
- 前処理の有無(フェンス除去など)
- 到達性(HTTP ステータスや空応答)
pass/fail だけでは次の1軸が決まりません。詳細があるからスパイラルが前に進みます。
よくある落とし穴
- scorer を増やしすぎて、レポートが読めなくなる
- JSON 厳格度を用途ごとに変えず、全部同じにする
- tool_call 失敗をモデル責任だけにして parser を疑わない
- judge を門番にして、夜間バッチが judge 障害で止まる
- 判定変更なのにスイート版を上げず、過去比較を壊す
実装時の最小インターフェース
現場で続きやすい scorer は、高機能である必要はありません。次が揃っていれば十分です。
- 名前(タスクから参照できる ID)
- 入力(モデル出力と期待値)
- 出力(pass/fail と詳細メッセージ)
- 副作用なし(ファイル書き込みや外部呼び出しを門番に混ぜない)
この形なら、contains / JSON / tool_call を同じ枠で増やせます。judge を足すときも、同じインターフェースの後ろに非同期ステージとしてぶら下げるだけで済みます。先に枠を決めると、評価要件の増殖に耐えやすくなります。
つまずいたこと
採点ロジックをハードコードした直後に、観点追加のたびに評価本体を改修する地獄を見ました。スコアの差し替えができないと、実験速度が落ちます。
困ったのは抽象化しすぎて、何を採点しているか読めなくなる逆効果です。差し替え可能と、説明可能の両立に一番時間がかかりました。
この回の要点
- 採点器を差し替え可能にする
- 抽象化しすぎて説明不能にしない
- 観点追加で評価本体を壊さない
採点器の差し替え方は公開できますが、各 scorer の閾値や合格率はこの回では固定しません。実機での誤検知・取りこぼしは再計測と匿名化後に足します。
次は「候補から本番候補へ:モデル台帳の回し方」です。観点が増えたあとの昇格/棄却を、レジストリのステータスに接続します。
よくある質問
最初からLLMジャッジでよいですか?
いいえ。コストと再現性の面で重いです。オフライン scorer で門番を通し、残った候補へ judge を足します。
scorer の役割分担は?
contains・JSON妥当性・tool_call 形式など、用途に応じて差し替え可能な判定器として扱います。
この回でスコア閾値を固定しますか?
いいえ。役割と順序の型が先です。閾値は用途合意後に別途決めます。