LLMの出力を別のLLMに評価させる、いわゆるLLM-as-a-judgeを評価の仕組みに組み込んでいる。評価を自動化する記事では全体の構成を書いたが、実際にやってみると判定プロンプトの書き方で結果が大きく変わる。今回はそこに絞って書く。
先に結論を書くと、判定がブレる原因はモデルの能力ではなく、こちらの聞き方にあった。効いた対処は3つで、いずれも「判定を曖昧にしない」方向の工夫だ。
そもそもLLMに判定させない範囲を先に決める
プロンプトの話に入る前に、前提を1つ置く。ルールベースで判定できるものはLLMに渡さない。
- フォーマットの崩れ、必須キーの欠落 → スキーマ検証
- 禁止語の混入、文字数の超過 → 文字列処理
- 意味的にずれていないか、トーンが適切か → LLM-as-a-judge
判定にLLMを使う以上、判定自体にブレが出るのは前提として受け入れるしかない。だからこそ、ブレなく判定できるものをLLMに渡すのは損になる。ここを分けずに全部を判定プロンプトへ押し込むと、ブレの原因がどこにあるのか切り分けられなくなる。
以下は、この切り分けをした上で残った「意味的な判定」の話になる。
対処1:5段階スコアをやめて、2値の観点に分ける
最初に書いた判定プロンプトは、こういう形だった。
以下の出力を1〜5で評価してください。
5: 非常に良い / 1: 非常に悪い
これが一番ブレた。同じ入力を複数回流すと3と4を行き来し、しかも何が変われば4が5になるのかが分からない。スコアの根拠が説明できないので、閾値を決めることもできない。
今は、観点ごとに分けてYes/Noで聞いている。
以下の出力について、各項目をYes/Noで判定してください。
1. 質問で聞かれていない情報を勝手に追加していないか
2. 入力に含まれていない固有名詞を出力していないか
3. 結論が入力の内容と矛盾していないか
変えたのは2点ある。段階評価を2値にしたことと、1つの質問で1つのことだけを聞くようにしたことだ。
2値にすると、判定が安定するだけでなく、落ちたときに何が問題なのかがそのまま分かる。「スコア3」からは何も読み取れないが、「項目2がNo」なら入力にない固有名詞が出ているということで、確認すべき箇所が特定できる。
観点を分けるのも同じ理由だ。「正確で読みやすいか」のように複数の性質を1問に混ぜると、モデルはどちらを重く見るかを勝手に決める。その配分がこちらから見えないので、結果を追えない。
対処2:判定理由を先に書かせる
2つ目は順序の問題だ。
# 悪い例
判定: {Yes/No}
理由: {理由}
# 良い例
理由: {なぜそう判定したか}
判定: {Yes/No}
判定を先に出させると、理由が後付けになる。先に「Yes」と書いてしまうと、その後の理由はYesを正当化する方向で書かれる。順序を逆にして、根拠を先に書かせてから判定させると、根拠と判定が食い違うケースが減った。
これは人間のレビューでも同じことが起きるので、特別な話ではない。ただ、LLMの場合は出力が前から順に決まっていく性質があるぶん、順序の影響が直接的に出る。
理由を書かせるもう1つの利点は、判定が間違っていたときに原因が分かることだ。理由を読むと、判定基準の書き方が曖昧だったのか、そもそも入力の解釈がずれていたのかが切り分けられる。理由なしのYes/Noだけだと、プロンプトを直す手がかりが残らない。
対処3:判定基準に、合格例と不合格例を1つずつ置く
3つ目は、基準の書き方だ。言葉だけで基準を書くと、どうしても解釈の幅が残る。
3. 結論が入力の内容と矛盾していないか
Yesの例:
入力「在庫は3件」→ 出力「在庫は3件あります」
Noの例:
入力「在庫は3件」→ 出力「在庫は十分にあります」
(「十分」は入力にない判断を足している)
不合格例になぜ落ちるのかを添えるのが重要だった。例だけを並べると、モデルはその例と表面的に似ているかどうかで判断しがちになる。理由を書いておくと、形の違う入力でも同じ趣旨で判定される。
例は1つずつで足りた。増やすほど良くなるかというとそうでもなく、多く置くと今度は「例に近いかどうか」の判断に寄っていく。境界がはっきり分かる例を1組選ぶ方が効いた。
判定プロンプト自体をどう検証するか
ここまでの3つは、判定プロンプトを良くする話だった。ただ、そのプロンプトが正しく判定できているかは別に確かめる必要がある。
やっているのは単純で、答えが分かっているケースを判定させる。意図的に壊した出力(入力にない固有名詞を混ぜたもの、結論を逆にしたもの)を用意して、判定プロンプトがそれを落とせるか見る。落とせなければ、判定プロンプトの側に問題がある。
この確認を省くと、「判定が全部Yesで通っている」状態が、品質が高いからなのか判定が甘いからなのか分からなくなる。評価の仕組みを入れたのに何も落ちないときは、まずこれを疑う。
まとめ
- ルールベースで判定できるもの(フォーマット、禁止語、文字数)はLLMに渡さない。ブレなく判定できるものを判定にLLMを使うのは損
- 5段階スコアをやめて、観点ごとのYes/Noに分ける。落ちたときに何が問題か分かる形にする
- 1つの質問で1つのことだけ聞く。複数の性質を混ぜると、モデルが勝手に配分を決める
- 判定より先に理由を書かせる。判定を先に出すと理由が後付けになる
- 判定基準には合格例と不合格例を1組ずつ、不合格の理由を添えて置く。例は増やしすぎない
- 判定プロンプト自体も、意図的に壊した出力で検証する。何も落ちないときは判定が甘い可能性を先に疑う