はじめに
LLMの出力品質をどう評価するか、というのは実運用でLLMを使う上で避けて通れないテーマです。人手評価はコストが高くスケールしない一方、BLEU/ROUGEのような表層一致指標では意味的な妥当性を捉えられません。この間を埋める手法として最近急速に注目されているのが LLM-as-Judge(LLMにLLMの出力を採点させる手法)です。
本記事では、LLM-as-Judge専用にファインチューニングされたオープンソースモデル Prometheus を実際にローカル環境(Intel Arc GPU)で動かし、「この審判は本当に信頼できるのか?」という視点で簡易的な検証を行った過程をまとめます。
システム構成
- 推論環境: ローカルPC (Intel Arc GPU)
-
評価対象モデル:
prometheus-eval/prometheus-7b-v2.0 - 実行バックエンド: OpenVINO (optimum-intelでIRに変換)
- Python環境: venv
LLM-as-Judgeとは何か
人間による評価と、ルールベースの表層一致指標との中間を埋める手法として登場した背景があります。LLM自身に「採点者」の役割を与え、生成結果の品質・妥当性を評価させます。
Prometheusとは
PrometheusはGPT-4のような汎用LLMを審判に使う代わりに、評価タスクに特化してファインチューニングされたオープンソースモデルです。入力には以下の4要素を必ず含みます。
- instruction: 評価対象への指示
- response: 評価したい実際の出力
- reference answer: 満点(5点)となる模範解答
- score rubric: 何を評価基準にするかの定義(1〜5点それぞれの基準)
reference answerを与えることで、評価用LM自身が問題を解く必要がなくなり、評価だけに集中できるという設計思想です。実際、公式論文でもreference answerを外すと人間評価との相関が明確に下がることが報告されています。
Prometheus 2 (prometheus-7b-v2.0)は絶対評価(pointwise)と相対評価(pairwise)の両方を1モデルでサポートしており、プロンプトのシステムメッセージや入力フォーマットを変えるだけでモードを切り替えられます。
環境構築
なぜvLLMではなくOpenVINOなのか
今回はIntel Arc GPU環境だったため、prometheus-evalパッケージの標準的なvLLMバックエンドは使いませんでした。vLLMのXPU(Intel GPU)対応はまだ発展途上で、Docker前提の限定的な環境構築が必要になるためです。
代わりに、Hugging Face公式のoptimum-intelを使い、モデルの重みを直接OpenVINO IR形式に変換する方法を採用しました。
venvの作成
python3 -m venv prometheus-ov-env
source prometheus-ov-env/bin/activate
pip install --upgrade pip
事前にOS側でIntel GPUドライバ(compute-runtime/level-zero)がセットアップ済みであることが前提です。
パッケージのインストール
pip install -r requirements.txt
requirements.txtの中身:
optimum[openvino]
nncf
transformers
numpy
モデルの変換
optimum-cli export openvino \
--model prometheus-eval/prometheus-7b-v2.0 \
--weight-format int4 \
./prometheus-7b-v2.0-ov
検証目的なので今回は4bit量子化にしています。
Prometheusの信頼性を検証する
ここからが本題です。今回はこの審判がどれだけ信頼できるのか以下の2点を検証します。
- 自己一貫性(Test-Retest Reliability): 同じ入力を複数回(temperature>0で)採点させ、スコアがどれだけブレるか
- 順序性(Score Separation): 明らかに質の異なるbad/goodの回答で、ちゃんと点数に差がつくか
外部の評価用データセット(Feedback-Collectionやoasst1など)を使う案も検討しましたが、二値化の閾値設定や汚染リスク、reference answerの自作といった前提が多く積み上がってしまうため、今回はシンプルさを優先し、自作の少数サンプル + 自己一貫性テストという構成に落ち着きました。
検証スクリプト
"""
Prometheus (LLM-as-Judge) の信頼性を、最小構成で検証するスクリプト
1. 同じ入力を複数回採点させて、スコアのブレ(標準偏差)を見る → 自己一貫性
2. bad/good の回答で、ちゃんと点数に差がつくかを見る → 順序性
"""
import re
import numpy as np
from optimum.intel import OVModelForCausalLM
from transformers import AutoTokenizer
MODEL_DIR = "./prometheus-7b-v2.0-ov"
model = OVModelForCausalLM.from_pretrained(MODEL_DIR, device="GPU")
tokenizer = AutoTokenizer.from_pretrained(MODEL_DIR)
PROMPT = """###Task Description:
An instruction, a response to evaluate, a reference answer, and a score rubric are given.
1. Write detailed feedback strictly based on the rubric.
2. After the feedback, write an integer score between 1 and 5.
3. Output format: "Feedback: (feedback) [RESULT] (score)"
###Instruction:
{instruction}
###Response to evaluate:
{response}
###Reference Answer (Score 5):
{reference}
###Score Rubrics:
{rubric}
###Feedback:"""
INSTRUCTION = "地球温暖化の主な原因を説明してください。"
REFERENCE = "地球温暖化の主な原因は、化石燃料の燃焼によるCO2などの温室効果ガスの増加です。"
RUBRIC = "回答が科学的に正確で、事実に基づいているか (1〜5点)"
RESPONSES = {
"bad": "地球温暖化は主に太陽の活動によるもので、人間活動とは無関係です。",
"good": "地球温暖化の主な原因は、化石燃料の燃焼によるCO2などの温室効果ガスの増加です。",
}
N_RUNS = 5 # 同じ入力を何回繰り返し採点させるか
def extract_score(text: str):
match = re.search(r"\[RESULT\]\s*\(?(\d)\)?", text)
return int(match.group(1)) if match else None
def evaluate(response: str) -> list[dict]:
results = []
prompt = PROMPT.format(
instruction=INSTRUCTION, response=response, reference=REFERENCE, rubric=RUBRIC
)
inputs = tokenizer(prompt, return_tensors="pt")
for _ in range(N_RUNS):
outputs = model.generate(**inputs, max_new_tokens=512, do_sample=True, temperature=0.7)
result = tokenizer.decode(outputs[0][inputs["input_ids"].shape[1]:], skip_special_tokens=True)
score = extract_score(result)
results.append({"score": score, "feedback": result}) # 文章(CoT)も一緒に残す
return results
if __name__ == "__main__":
for label, response in RESPONSES.items():
results = evaluate(response)
scores = [r["score"] for r in results if r["score"] is not None]
print(f"[{label}] mean={np.mean(scores):.2f} std={np.std(scores):.2f}")
print(f" 1回目のFeedback例:\n {results[0]['feedback']}\n")
実行結果
[bad] mean=1.00 std=0.00
1回目のフィードバック:
The response is incorrect because it fails to mention the role of human activities in causing
global warming. While the sun's activity is a significant factor, it is not the only one, and
its role is actually less significant than that of human activities in the context of global
warming. The response overlooks the role of CO2 emissions and other human-induced factors that
contribute to the greenhouse effect, which is the main cause of global warming. The claim that
human activities and solar activity are unrelated is misleading and not supported by scientific
consensus. Therefore, the response does not accurately represent the main causes of global
warming, as required by the instruction. So the overall score is 1.
[RESULT] 1
[good] mean=5.00 std=0.00
1回目のフィードバック:
The response accurately describes the main cause of Earth's warming, which is the burning of
fossil fuels leading to the increase in CO2, thereby explaining the greenhouse effect. The
answer is succinct and directly addresses the question. It is scientifically accurate and
adheres to established facts about global warming. The response does not deviate from the
topic and maintains a clear focus on the primary cause of Earth's warming. Therefore, it meets
the criteria of the score rubric for a score of 5.
[RESULT] 5
見るべきポイントは2つです。
-
badの平均点 <goodの平均点になっているか → 順序性が保たれているかの確認 - 標準偏差が小さいか → 同じ入力に対して安定した採点をしているか(自己一貫性)。標準偏差が大きい場合、そのサンプルは「Prometheusにとって判断に迷う事例」だった可能性があります
数値(スコア)だけでなく、フィードバック文も確認すると、単に点数を出しているだけでなく、「なぜその点数なのか」を rubric に沿って具体的に言語化できていることが分かります。badの例では、太陽活動と人間活動の重要度の違いや、CO2排出への言及漏れを的確に指摘しています。goodの例では、簡潔さと科学的正確性の両方を評価根拠として挙げています。この「理由付けの妥当性」も、スコアの数値と同じくらい信頼性評価の材料になります。
今回の結果では、bad/goodともに5回中5回とも全く同じスコア(標準偏差0.00)となり、かつ1点と5点というスコア範囲の両端まではっきり分離されました。少なくとも「明らかに質の異なる回答を、ブレなく極端な点数で区別できるか」という最低ラインについては、Prometheusはこの1サンプルにおいて安定した判定を示したと言えます。
ただし、この結果はあくまで「明らかにbad」「明らかにgood」という、判定が容易な両極端のペアで確認したものです。実運用で課題になってくるのは、両者の中間にあるような回答(例えば一部だけ不正確、説明はやや不十分だが大筋は合っている、といったケース)です。中間的な回答でも同じように標準偏差0.00を維持できるか、逆にそこでブレが出るのかは、パターンを追加して検証する価値がある部分です。
まとめ
- LLM-as-Judgeは人手評価とルールベース評価の間を埋める手法だが、"審判自体の信頼性"をどう検証するかが重要
- Prometheusはrubric + reference answerを用いた汎用評価用LMで、pointwise/pairwiseの両方に対応する
- Intel Arc GPU環境ではvLLMよりも
optimum-intelによるOpenVINO IR変換の方が安定して動かせた - 外部データセットに頼らず、自己一貫性と順序性という2つの軸だけでも、審判としての最低限の信頼性は確認できる
- 今回の検証(明らかにbad/goodな1サンプル)では標準偏差0.00、1点/5点への完全分離という安定した結果が得られたが、これは判定の難易度が低いケースであり、中間的な質の回答での挙動は別途確認が必要
今後は、mediocreのような中間パターンを増やしての境界事例の検証、rubricの書き方による評価結果の変化、専用の安全性判定モデル(Llama Guardなど)との役割分担についても検証を広げていきたいと思います。