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で判定してください。
基準を満たす場合はYes、満たさない場合はNoとしてください。

1. 質問に答えるために必要な情報が出力に含まれているか
2. 出力中の固有名詞はすべて入力に含まれているか(固有名詞がなければYes)
3. 出力中の主張はすべて入力の内容から裏付けられるか

変えたのは2点ある。段階評価を2値にしたことと、1つの質問で1つのことだけを聞くようにしたことだ。

この形にして、落ちたときに確認すべき箇所を見つけやすくなった。「スコア3」だけでは修正点が分からないが、「項目2がNo」なら入力にない固有名詞が出ている、というように問題を追える。2値にしても基準が曖昧なままなら判定はブレるので、ラベルの変更と基準の具体化はセットで考える。

観点を分けるのも同じ理由だ。「正確で読みやすいか」のように複数の性質を1問に混ぜると、どちらを満たさなかったのかが判定ラベルから分からない。正確さと読みやすさを別々に聞けば、修正する箇所を絞れる。

対処2:判定理由を先に書かせる

2つ目は順序の問題だ。

# 変更前
判定: {Yes/No}
理由: {理由}

# 変更後(各項目について出力)
理由: {入力と出力の該当箇所を挙げた短い判定根拠}
判定: {Yes/No}

自分の運用では、判定を先に出させると、根拠と判定が食い違うケースがあった。順序を逆にして、根拠を先に書かせてから判定させると、この食い違いが減った。

ただし、理由が書かれていれば正しい判定だとは限らない。入力にない内容を根拠として挙げていないかも確認する。求めるのは、レビューで照合できる短い判定根拠だ。

理由を書かせるもう1つの利点は、判定が間違っていたときに原因を探す手がかりが残ることだ。判定基準の書き方と、根拠として挙げられた入力・出力を照合できる。理由なしのYes/Noだけより、プロンプトのどこを直すか検討しやすい。

対処3:判定基準に、合格例と不合格例を1つずつ置く

3つ目は、基準の書き方だ。言葉だけで基準を書くと、どうしても解釈の幅が残る。

3. 出力中の主張はすべて入力の内容から裏付けられるか

質問: 在庫状況を、入力に書かれた事実だけで一文で伝えてください。

Yesの例:
  入力「在庫は3件」→ 出力「在庫は3件あります」
Noの例:
  入力「在庫は3件」→ 出力「在庫は十分にあります」
    (「十分」は入力にない判断を足している)

ここで「十分」を落とす理由は、在庫3件という事実だけでは充足度を判断できないからだ。「在庫は4件」と書けば入力との矛盾だが、「在庫は十分」は入力から裏付けられない判断の追加に当たる。「矛盾していないか」だけを基準にすると、後者を落とす理由を説明できない。例と判定基準は、この違いが揃うように書く。

不合格例になぜ落ちるのかを添えるのが重要だった。理由を書くと、基準のどこに違反しているかを具体的に伝えられる。

自分の運用では、境界がはっきり分かる例を1組置くことで改善できた。必要な例の数はタスクによって変わる。まず1組で試し、別の入力でも意図した判定になるかを確認してから追加を考える。

判定プロンプト自体をどう検証するか

ここまでの3つは、判定プロンプトを良くする話だった。ただ、そのプロンプトが正しく判定できているかは別に確かめる必要がある。

やっているのは単純で、答えが分かっているケースを判定させる。意図的に壊した出力(入力にない固有名詞を混ぜたもの、結論を逆にしたもの)を用意して、判定プロンプトがそれを落とせるか見る。落とせなければ、判定プロンプトの側に問題がある。

この確認を省くと、「判定が全部Yesで通っている」状態が、品質が高いからなのか判定が甘いからなのか分からなくなる。評価の仕組みを入れたのに何も落ちないときは、まずこれを疑う。

これから同じ方法を試すなら、壊した出力に加えて、合格させたい出力も検証用に用意してほしい。プロンプト中の例をそのまま使うだけでなく、別の入力を人が判定し、その結果と照合する。不合格を見逃すケースと、合格を誤って落とすケースの両方を確認できる。

Langfuseの公式資料も、LLMによる評価を使う前に、ラベル付きの例や人による評価と照合する方法を案内している。自分が使うモデル・設定・プロンプトの版・評価データを記録し、同じ条件で比較できるようにすると、変更の効果を追いやすい。

まとめ

  • ルールベースで判定できるもの(フォーマット、禁止語、文字数)はコードで検査する
  • 5段階スコアをやめて、観点ごとのYes/Noに分ける。落ちたときに何が問題か分かる形にする
  • 1つの質問で1つのことだけ聞く。必要な情報の欠落や、根拠のない追加を区別する
  • 判定より先に短い根拠を書かせ、入力・出力と照合する。順序の効果は自分の評価データで確かめる
  • 判定基準には合格例と不合格例を1組ずつ、不合格の理由を添えて置く。例が基準と一致しているかも確認する
  • 判定プロンプト自体も、正解が分かる別の入力で検証する。合格・不合格の両方を人の判定と照合する

参考資料

関連記事

Xでフォローしよう

おすすめの記事