LLM-as-a-Judge:自动评审的偏差与校准
- Published on
LLM-as-a-Judge:自动评审的偏差与校准
大模型输出很难像普通函数那样测试。用户问同一个问题,正确答案可能有很多种表达;一段回答既要看事实,也要看是否相关、是否完整、有没有越权。于是大家自然想到:再找一个大模型来当裁判。
这个想法确实有用。我第一次使用 LLM-as-a-Judge 时,也被它的效率打动了:几千条回答很快就有了分数,报告看起来比人工抽查更完整。但当我把低分和高分样本拿出来人工复核时,发现裁判有几个很明显的偏好:答案越长越容易得高分,语气越自信越容易被认为专业,和裁判模型自己风格相似的回答也更占便宜。
自动裁判不是事实真相,只是一种测量工具。工具要先校准,分数才能有意义。
一、先定义裁判到底要判断什么
不要只让裁判输出一个“总体分数”。把质量拆成可以解释的维度:
type JudgeDimensions = {
correctness: number
relevance: number
completeness: number
groundedness: number
safety: number
style?: number
}
不同任务权重不同。RAG 重点看是否被证据支持,结构化抽取重点看字段和格式,客服回答重点看事实、相关性和语气,Agent 重点看工具参数、步骤顺序和最终状态。
如果所有维度最后都压成一个数字,团队很快会忘记分数是怎么来的。保留分项结果,才能知道某次 Prompt 修改是提高了相关性,还是只让措辞更漂亮。
二、给裁判一份明确的评分标准
“请判断答案好不好”太模糊。应写出分数对应的行为:
5 分:事实正确,完整回答问题,有证据支持,没有越权或编造。
3 分:主要事实正确,但遗漏部分信息或表达不够清楚。
1 分:包含关键事实错误,或答案基本没有回答问题。
0 分:编造证据、越权披露、执行了不该执行的动作。
评分标准要配正例、反例和边界例。一个答案只说“我不知道”,在没有证据的场景可能是 5 分,在明明有明确资料的场景则可能是 1 分。标准必须包含任务上下文。
type JudgeInput = {
question: string
context?: string
answer: string
referenceAnswer?: string
rubric: string
riskLevel: 'low' | 'medium' | 'high'
}
把参考答案提供给裁判时也要小心。参考答案不是唯一正确表达,不应要求候选答案逐字匹配;它更适合提供关键事实、必要条件和不可接受错误。
三、裁判常见的几种偏差
1. 长度偏差
裁判容易把更长的回答当成更完整,即使多出来的内容只是重复或废话。解决方法是把简洁性和相关性单独评分,并明确“无关扩展不得加分”。
2. 位置偏差
比较两个答案时,裁判可能更偏爱第一个或最后一个。可以随机交换答案顺序,进行两次评审,观察结果是否一致。
3. 自我偏好
裁判模型可能偏爱和自己写法相近的答案。不同模型、不同语言和不同风格的表达都要进入校准集,不能默认裁判对所有写法公平。
4. 迎合语气
自信、礼貌、结构清晰会影响观感,但不能替代事实正确。把语气和事实分开评分,必要时对答案做匿名化或统一格式。
5. 参考答案锚定
裁判看到参考答案后,可能只寻找相似词,而忽略另一种同样正确的推理。可以让裁判先独立判断,再和参考标准对照;同时保留人工抽检确认。
四、先做盲测和一致性检查
评审时尽量隐藏模型名称、版本、生成时间和实验组标签,避免裁判根据“这是新模型”产生预设。对于 A/B 比较,随机化答案顺序,确保裁判不知道哪个是候选版本。
同一批样本可以使用不同 Prompt 或不同裁判模型评审,观察一致性:
type AgreementReport = {
judgeA: string
judgeB: string
agreementRate: number
disagreementCases: string[]
}
如果两个裁判的分歧集中在某类问题,往往说明评分标准还不清楚;如果分歧随机很大,可能是任务本来就需要人工判断,或者裁判能力不足。
五、人工标注用来校准,不是只用来盖章
准备一批人工高质量标注的校准集,覆盖不同风险、语言、长度和失败类型。让自动裁判和人工结果比较:
人工判断:有依据,完整
自动裁判:无依据,低分
→ 检查裁判是否没有理解引用格式
不要只看总体相关系数。更重要的是看高风险错误有没有被漏掉,以及裁判在边界样本上是否稳定。自动裁判即使总体和人工有较高一致性,也可能在关键少数类上不可靠。
可以用混淆矩阵分析:把“可接受/不可接受”作为分类任务,看 False Negative。对于安全违规和越权内容,漏判通常比误判更危险,阈值应该保守一些。
六、让裁判输出证据和解释
裁判不应只返回 score: 4,而应说明依据了哪个事实、哪条引用或哪个规则:
{
"score": 2,
"grounded": false,
"violations": ["答案声称退款已完成,但上下文没有该信息"],
"evidence": ["context_chunk_17"],
"needs_human_review": true
}
解释本身也可能是模型编出来的,所以不能把它当成独立事实;但它能帮助人工快速定位错误,也方便后续改评分标准。更可靠的方式是让裁判引用输入中的片段 ID,而不是凭空输出长篇理由。
七、评审 Prompt 也要版本化
裁判模型、评分标准、示例、输出 Schema 和阈值都属于评测系统版本:
type JudgeManifest = {
judgeModel: string
promptVersion: string
rubricVersion: string
datasetVersion: string
temperature: number
threshold: number
}
如果今天的质量分数和上个月比较,却换了裁判模型和评分标准,那么趋势很可能没有意义。评测系统本身也需要回归测试,尤其要保留一批人工已经确认的样本。
八、什么时候不要使用 LLM-as-a-Judge
能用程序精确判断的事情,不要让模型裁判:JSON 是否符合 Schema、字段是否缺失、引用 ID 是否存在、工具参数是否通过权限校验、金额是否能重新计算。这些规则更快、更便宜,也更稳定。
需要事实核验、法律判断、医疗风险、复杂安全事件或重大商业决策时,自动裁判只能做辅助筛选,不能成为唯一放行条件。模型评价模型,可能把共同的错误当成正确,尤其当参考资料本身不完整时。
九、把分数连接到行动
自动评审的最终价值不是生成一张排行榜,而是帮助团队做决定:
高分 → 继续灰度 / 进入人工抽检
中间分 → 增加样本或请求人工复核
低分 → 阻止发布 / 回放失败 Trace
高风险违规 → 立即阻断,无论平均分如何
阈值要和风险等级绑定。低风险文案可以允许一定的自动误判,高风险 Agent 动作则必须有保守门槛和人工确认。
总结:自动裁判要先证明自己值得被信任
我现在不会把 LLM-as-a-Judge 的分数当成“客观真相”,而把它当成一个需要被测量的传感器。传感器可能有偏差,所以要定义指标、固定标准、做盲测、交换顺序、和人工校准,并保留失败样本。
模型越强,自动评审越有用,但也越容易让人放松警惕。一个裁判能流畅解释自己的判断,不代表它判断正确;一个分数稳定上升,也不代表真实用户体验变好。真正可靠的评测系统,会把自动评分和规则校验、人工抽查、线上反馈放在一起。
当你能回答“这个分数测的是什么、在哪些样本上可靠、什么时候必须让人接管”时,LLM-as-a-Judge 才真正从一个方便的 Demo 变成了工程工具。我们可以让模型帮忙批改更多作业,但不能因为批改速度快,就取消老师对标准和边界的判断。