Chapter 04

LLM-as-Judge:让模型评估模型

生成式任务没有唯一标准答案,人工评分又太慢太贵。LLM-as-Judge 是当前最实用的中间解——但要避开它层出不穷的偏差陷阱。

为什么需要 LLM-as-Judge

想象你要评估一个客服回复的"语气是否友好"。没有精确匹配可用,BLEU 没意义,嵌入相似度区分不出微妙差别。三种选择:

方案准确度速度成本可扩展
人工评审★★★★★
训练专用分类器★★★★一次高后续低
LLM-as-Judge★★★★极好
字面/嵌入指标★★极快极好

Judge 的甜点区:需要"像人一样判断"又要规模化——语气、相关性、事实准确性、安全性这类主观维度。

Judge 的四种范式

① Pointwise — 单条打分

给一个回答打 1-5 分(或 0/1)。最常见。

JUDGE_POINTWISE = """你是一个严格的客服质量评审员。
给下面这条客服回复打分,考察其「专业程度」。

用户问题: {question}
客服回复: {answer}

评分标准(从 1 到 5):
5 — 完美专业,措辞得体,信息准确且完整
4 — 专业,有个别小瑕疵
3 — 合格,但缺少关键信息或有小的用词不当
2 — 不够专业,存在明显问题
1 — 不合格,错误或失礼

请先用 2 句话分析,然后输出 JSON:
{{"reasoning": "...", "score": 1-5}}"""

② Pairwise — A/B 哪个好

两两对比,只问"A 更好 / B 更好 / 平局"。在比较两个 prompt 或两个模型时特别有用。

JUDGE_PAIRWISE = """下面是两个不同的客服回复。判断哪个更好,或平手。

用户问题: {question}
回复 A: {answer_a}
回复 B: {answer_b}

从「准确性」「相关性」「语气」三方面综合判断。
返回 JSON: {{"reasoning": "...", "winner": "A" | "B" | "tie"}}"""
经验 Pairwise 通常比 Pointwise 更稳定——人类给绝对分也不擅长,但比较两样东西相对容易。A/B 迭代选型场景强烈推荐 pairwise。

③ Reference-based — 对照黄金答案

JUDGE_REF = """判断学生答案是否在语义上等价于参考答案。

问题: {question}
参考答案: {reference}
学生答案: {candidate}

忽略措辞差异,只看事实内容是否一致。
返回 JSON: {{"reasoning": "...", "correct": true|false}}"""

④ Rubric — 多维度打分

把一个任务拆成多个维度,每个维度独立打分。对发现"为什么不好"最有用。

JUDGE_RUBRIC = """从以下维度独立评分(每项 1-5):

1. relevance: 是否回答了用户实际问题
2. accuracy: 事实是否正确
3. completeness: 是否覆盖了必要信息
4. tone: 语气是否合适(专业/友好)
5. conciseness: 是否简明(无冗余)

用户问题: {question}
回复: {answer}

JSON 格式:
{{
  "relevance":     {{"score": 1-5, "reason": "..."}},
  "accuracy":      {{"score": 1-5, "reason": "..."}},
  "completeness":  {{"score": 1-5, "reason": "..."}},
  "tone":          {{"score": 1-5, "reason": "..."}},
  "conciseness":   {{"score": 1-5, "reason": "..."}}
}}"""

Judge 的常见偏差(Bias)

LLM Judge 不是客观的。有一系列系统性偏差已被学界大量研究:

位置偏好(Position Bias)
Pairwise 时,Judge 偏向第一个出现的选项(或偏向最后一个,因模型而异)。GPT-4 约有 5-10% 位置偏好。
长度偏好(Verbosity Bias)
长回答看起来"更认真",Judge 常给更长的答案打高分,即使信息密度更低。
自恋偏差(Self-enhancement)
Judge 模型偏向自己系列的输出——GPT-4 Judge 会给 GPT-4 答案打更高分。
权威偏差
答案中若出现"根据哈佛研究""数据显示"这类修饰,Judge 倾向给更高分,即使内容虚构。
格式偏好
带 Markdown 标题、项目符号的回答比纯文本得分高,不论内容。

位置偏好的修正

# 双位置评分 — 对每个 pair 跑两次,顺序互换
def judge_pair_debiased(q, a, b):
    r1 = judge_pairwise(q, a, b)  # A 在前
    r2 = judge_pairwise(q, b, a)  # B 在前

    # 一致才算数
    if r1 == "A" and r2 == "B": return "A_wins"
    if r1 == "B" and r2 == "A": return "B_wins"
    return "tie_or_inconsistent"  # 顺序变了结论就变 = Judge 在随机猜

长度偏好的缓解

自恋偏差的避免

Judge 必须和被评估模型异源。如果你在评估 GPT-4o,Judge 用 Claude 或 Gemini。

好的 Judge Prompt 的 7 条原则

  1. 角色明确:"你是一个严格的医疗文本审核员" > "请打分"
  2. 标准可操作:每个分数档给出具体锚点例子,不要只说"好/一般/差"
  3. 要求先推理再打分:Chain-of-thought 能显著提升 Judge 质量
  4. 结构化输出:JSON 严格模式,避免解析失败
  5. 使用 few-shot 例子:给 2-3 个已标注的 case 作为示范
  6. 维度独立:多维度 rubric 每维分开判,避免互相污染
  7. 校准引导:"我们标注的 baseline 平均分约 3.5",提示 Judge 不要全打 5

完整实现:一个生产级 Judge

from anthropic import Anthropic
import json

client = Anthropic()

JUDGE_TEMPLATE = """你是客服质量审核专家,严格、公正。

你将看到一个用户问题和一条客服回复,请从 3 个维度评分(1-5)。

评分锚点:
- 5 = 典范,可作为范例
- 4 = 良好,小瑕疵
- 3 = 合格,中等水平
- 2 = 不合格,明显问题
- 1 = 严重错误

## 参考例子

例 1 (accuracy=5):
问: 我的订单多久能到?
答: 您的订单已发货,预计 3-5 个工作日到达,物流单号:SF123456。

例 2 (accuracy=2):
问: 我的订单多久能到?
答: 一般来说很快的,您再等等吧。(缺少具体时间和物流信息)

---

请评估下面这条:

问题: {question}
回复: {answer}

## 输出

先用 2-3 句话说明你的核心判断,然后输出 JSON:

{{
  "reasoning": "...",
  "scores": {{
    "relevance":  {{"score": 1-5, "reason": "..."}},
    "accuracy":   {{"score": 1-5, "reason": "..."}},
    "tone":       {{"score": 1-5, "reason": "..."}}
  }}
}}"""

def judge(question: str, answer: str) -> dict:
    rsp = client.messages.create(
        model="claude-sonnet-4-6",  # Judge 用 Claude,被评估的是 GPT
        max_tokens=800,
        temperature=0,
        messages=[{"role": "user", "content": JUDGE_TEMPLATE.format(question=question, answer=answer)}],
    )
    txt = rsp.content[0].text
    # 粗略提取 JSON 块
    start, end = txt.find("{"), txt.rfind("}")
    return json.loads(txt[start:end+1])

Judge 校准:验证你的 Judge 真的可用

Judge 本身是模型,它可能系统性偏离人类判断。必须校准:

  1. 挑 50-100 条代表性样本
  2. 2-3 位人类独立打分,算 inter-annotator κ
  3. 用同样的 case 跑 Judge,算 Judge 与人的 κ
  4. 若 Judge-Human κ ≥ 0.6 且接近 Human-Human κ,Judge 可用
  5. 否则迭代 Judge prompt,直到达标
from sklearn.metrics import cohen_kappa_score

human_scores = [4, 3, 5, 2, 4, 3, 5, 4, 1, 3]
judge_scores = [4, 4, 5, 2, 4, 3, 4, 5, 2, 3]

κ = cohen_kappa_score(human_scores, judge_scores, weights="quadratic")
print(f"Judge κ = {κ:.2f}")
发表研究的共识 在大多数主观任务上,GPT-4 Judge 与人类专家的一致性(κ ≈ 0.6-0.7)已经接近人类专家之间的一致性(κ ≈ 0.65-0.8)。也就是说,一个精心调校的 Judge 在多数场景可以替代人类 80% 的工作。

成本控制

Judge 不是免费的。一次完整 eval 可能要几千次 Judge 调用。常见优化:

本章小结