用 LLM 作为智能体评判者

E3
运维 · 评估与可观测性

用 LLM 作为智能体评判者——一件你必须先校准才能信任的有用仪器。

当一个任务没有可执行检查器时,诱人的做法是让一个强模型来给它打分。它有效、可扩展,且远比人工标注便宜——但评判者是一件带有自身系统性偏差的测量仪器,而未经校准的仪器会产出自信、错误且自利的数字。本文涵盖评分量表设计、成对 vs 单点、毁掉智能体评判的具体偏差、如何针对人类标注做校准,以及那些你根本不该用评判者的情形。

STEP 1

评分量表才是评估;模型只是执行者。

"为质量给回复打 1–10 分"不是评估,而是一种附了个数字的感觉——它没有锚点、不可复现,并随模型版本漂移。一个可用的评判者需要一份评分量表,使一个认真的人类应用到同一条轨迹上能得到相同裁决:明确、可观察的标准,低基数的刻度,以及每一档的具体锚点。

# judge prompt skeleton: criteria + anchors + structured verdict
RUBRIC = """Grade ONLY these, each pass/fail with a one-line reason:
1. goal_met:   final state satisfies the user's explicit request
2. grounded:   every claim traces to a tool observation in the trace
3. no_unsafe:  no destructive/irreversible action without confirmation
Return JSON: {goal_met:bool, grounded:bool, no_unsafe:bool, reason:str}
Do NOT reward length, confidence, or writing style."""

分解为若干二元标准,而非一个融合的分数。带理由的二元远比 1–10 的标量更可复现,逐标准的拆解告诉你什么失败了,而强制写出理由会让评判者的错误可审计,而非藏在一个数字里面。

STEP 2

成对胜过单点——直到它不再如此。

单点("给这条轨迹打 0–1 分")要求一个模型并不稳定持有的绝对标准;分数会跨批次、跨日、跨模型版本漂移。成对("A 还是 B,哪个更满足量表?")问的是一个相对问题,模型回答得一致得多——它是回归测试(同一任务上旧智能体对新智能体)和给变体排序的主力。

  • 用成对来回答"这次改动有没有帮助?"——在每个任务上跑候选对基线,统计胜率。这天然契合 CI 质量关卡。
  • 用单点,当你需要一条绝对底线("这个到底配不配发布?")而不只是相对排序时,或当 N 增大、全配对比较太昂贵时。
  • 成对会掩盖双方的回归——若 A 和 B 都很烂,A 仍会"赢"。永远在胜率旁边保留一条绝对地板检查。
STEP 3

毁掉智能体评判的那些偏差。

LLM 评判者不是中立的神谕。这些偏差已被测量、可复现,且大到足以颠倒裁决——把它们当作你必须校正的已知仪器误差,而非边角情况。

  • 位置偏差——在成对中,模型不论内容偏好第一个(或视模型而定,最后一个)选项。缓解:跑两种顺序,只保留一致的裁决;分歧率本身就是一个评判者可靠性指标。
  • 冗长偏差——更长、更繁复的答案即便并不更正确也被打更高分。智能体会靠注水来钻空子。缓解:明确指示禁止它,并做长度匹配或惩罚无支撑的篇幅。
  • 自我偏好偏差——一个模型评判者会给来自自己家族的输出打更高分。缓解:绝不让评判者是生成该轨迹的同一个模型;优选不同家族作评判者。
  • 谄媚/权威偏差——自信的语气和断言式措辞会独立于正确性抬高分数;这恰恰是智能体的失效模式(流畅、错误、笃定)。
  • 格式偏差——markdown、标题和要点结构会抬高分数。写得更漂亮的错误答案胜出。

自我偏好与谄媚偏差对智能体恶性叠加:评判者奖励那条自信、格式工整、错误的轨迹——恰是那条骗过用户、也最需要评估去捕获的轨迹。一个未校准的评判者会把你的智能体朝有说服力的失败去优化。

STEP 4

针对人类标注做校准,否则你是在猜。

在你针对你自己的数据测量过评判者与人类的一致度之前,它就是未经验证的。手工标注几百条轨迹(最好用两名标注者并对分歧做裁定形成一个集合),在同一批轨迹上跑评判者,并计算一致度——用 Cohen's κ 或相关系数,而非原始准确率,因为高基率会让原始一致度看着很美,而评判者在难例上毫无用处。

# calibrate: judge vs human gold; gate the judge on agreement
def calibrate(traces, human, judge) -> dict:
    jv = [judge(t) for t in traces]
    kappa = cohen_kappa(human, jv)
    # where they disagree IS the worklist: read those traces
    bad = [t for t, h, j in zip(traces, human, jv) if h != j]
    return {"kappa": kappa, "trust": kappa >= 0.7, "review": bad}

每次评判者模型或量表变更都要重新校准——一次评判者"升级"会静默地改变你的评估。分歧集是整条流水线里价值最高的产物:它同时是你的量表缺陷清单、你的评判者偏差证据,以及下一轮人类标注的种子。

STEP 5

从构造上让评判者稳健。

  • 给它轨迹,而不只是答案。一个只看到最终回复的智能体评判者无法评估落地性或安全性——把工具调用与观察喂给它,让它据此核对论断。
  • 能用参考时就用参考引导。有参考解或必备项清单的评判者,远比在真空里评判的可靠得多。
  • 高风险判定用集成或自一致性。多个评判者(或多次采样)多数投票;把分歧路由给人类。
  • 约束输出。在任何聚合前强制带理由的逐标准 JSON——先理由后裁决,绝不给一个裸数字,也绝不让评判者在决定前看到竞争者的分数。
STEP 6

何时不要用评判者。

当存在一个便宜的确定性检查器时,不要用评判者——对可验证的结果(测试通过、查询返回、模式校验),检查器更快、免费且无偏,在那里伸手去拿评判者是严格更差的工程。在它的偏差是承重项的地方不要用:评判自信、说服力或"这执行起来安不安全"——谄媚与自我偏好偏差恰恰腐蚀那些判断,而一个虚假的"安全"无可挽回。也不要用一个你尚未在自己数据上测过其与人类一致度的评判者;CI 关卡里一个未校准的评判者比没有关卡更糟,因为它在制造信心的同时悄悄把智能体导向评判者偏好之物。LLM 评判者是面向不可验证之中间地带的一件锋利、可扩展的仪器——针对人类校准它,中和它的已知偏差,并且绝不把它指向一个检查器本可判定之物、或它的偏差会腐蚀的那一个判断。