同一份请求发给同一个模型名,第二天再发一次,结果可能完全不同。
一项预注册审计研究对黑盒 LLM 裁判做了大规模检验:52,988 次请求里,同日重复排名的相关性只有 0.400,远低于预设的 0.90 门槛。也就是说,很多团队用来筛选训练数据、给生成结果打分的"裁判",本身可能并不稳定。这篇我把评测可靠性拆开讲清楚。我的评测任务都通过 4sapi(https://4sapi.com)跑,稳定性和成本一起监控。
一、开篇痛点
LLM 当裁判已经成了默认操作:给候选回答打分、做 A/B 对比、筛训练数据、排排行榜。大家都默认一件事——同一个请求发给同一个模型名,明天读到的还是同一个结果。
这个假设如果错了,所有基于裁判的决策都建立在流沙上:排行榜名次可能是噪音,数据筛选可能偏向随机波动,A/B 实验可能得出错误结论。
二、原理速览:评测为什么不可靠
裁判不可靠有三个机制:
机制1:标签映射偏差
裁判的输出标签 -> 与真实含义的映射有偏差 -> 读取结果被带偏
机制2:信号低于噪声
候选之间的真实差距 -> 远小于裁判自身的噪声 -> 测不出差异
机制3:同输入不同输出
字节相同的输入 -> 返回不同排名 -> 纯噪音被当成信号
三个机制叠加,导致"测量仪器"本身不稳定。注意这发生在共享端点(公共 API 服务)上——同一个模型名背后可能是动态负载、不同实例、不同推理配置。
三、实测数据:稳定性到底多差
研究用预注册方式(所有阈值提前固定)做了两轮审计,结果都不达标:
| 指标 | 实测 | 预设门槛 |
|---|---|---|
| 同日重复排名一致性 | 0.400 | 0.90 |
| 次日字节相同重放一致性 | 0.78 | 0.99 |
| 五个供应商中位数 | 0.74–0.88 | 0.99 |
更关键的是:等待几天没用(0.805 vs 0.800)、换供应商也没用(四家供应商共享同一水平)。问题不是某一家服务差,而是"黑盒共享端点"这个形态本身的可靠性天花板。
四、为什么"同输入不同输出"最致命
机制3 最反直觉:字节完全相同的输入,返回的排名却不同。这意味着裁判输出里混入了纯随机成分。如果评测流程里再做一次排列组合(比如把候选顺序打乱),随机性还会被放大。
对工程实践的直接含义:单次裁判结果不可信,必须重复采样。重复多少次?研究给出的建议是先做一次小规模试点——大概 2% 的调用量就能暴露评测不可靠的问题,不用等到跑完全量才发现。
五、自托管也不一定救得了
研究测试了自托管路线:在批量不变的核上自托管,只在服务器空闲时表现好。负载一起来,稳定性又掉下去。
这说明可靠性问题不是"换部署方式"能根治的,而是要从评测设计上解决。用确定性规则替代一部分裁判判断、固定采样策略、报告置信区间,都比"换个服务商"更有效。
六、可靠评测的落地做法
我的实践是三条:
第一,关键评测用确定性检查兜底。能写规则的就不让模型打分:
def score_with_fallback(answer: str, ground_truth: str, llm_judge):
# 确定性规则优先
if "错误" in answer or "无法完成" in answer:
return 0
# 规则判不了才用 LLM 裁判
return llm_judge(answer, ground_truth)
第二,LLM 裁判必须重复采样取均值,并记录方差。单次 0.400 一致性的裁判,至少采样 5 次以上才有参考价值。
import statistics
def robust_judge(llm_judge, answer, ground_truth, n=5):
scores = [llm_judge(answer, ground_truth) for _ in range(n)]
return statistics.mean(scores), statistics.pstdev(scores)
第三,预注册评测协议:阈值、采样数、判定规则提前写死,不跑完再改。这能防止"结果不好就调标准"的隐性作弊。
七、评测口径与成本平衡
可靠评测有成本:重复采样意味着 N 倍 token 消耗。我的做法是通过 4sapi(https://4sapi.com)统一接入层做评测,用便宜模型做初筛、旗舰模型做终审,把采样成本控制在可接受范围。
from openai import OpenAI
client = OpenAI(api_key="4sapi-key", base_url="https://4sapi.com/v1")
def two_stage_eval(answer, ground_truth):
# 初筛:便宜模型,快速排除明显错误
pre = client.chat.completions.create(
model="gpt-5-mini",
messages=[{"role": "user", "content": f"回答是否明显错误?\n{answer}\n标准答案:{ground_truth}"}],
max_tokens=50,
).choices[0].message.content
if "明显错误" in pre:
return 0.0
# 终审:旗舰模型,多次采样
scores = []
for _ in range(3):
s = client.chat.completions.create(
model="gpt-6-astra",
messages=[{"role": "user", "content": f"给回答打分 0-100:\n{answer}\n标准答案:{ground_truth}"}],
max_tokens=10,
).choices[0].message.content
scores.append(float(s))
return statistics.mean(scores)
两级架构既控制了成本,又保证了终审的稳定性。
八、成本与风险提示
- 重复采样直接翻倍 token 消耗,要按评测规模预算;
- 确定性规则能覆盖的场景有限,复杂语义仍要依赖裁判;
- 共享端点的稳定性会随时间漂移,要定期校准;
- 排行榜与内部评测要分开看待,前者是宣传、后者是决策依据。
九、评测检查清单
- 评测前先做 2% 调用量试点,验证裁判稳定性;
- 同一请求至少重复采样 3–5 次,记录方差;
- 关键指标用确定性规则兜底;
- 预注册评测协议,阈值提前固定;
- 记录模型版本、采样数、时间窗口,便于复现;
- 报告置信区间,不只看点估计。
十、我的结论
LLM 裁判不是不能用来评测,而是不能"拿来就用"。共享端点上的黑盒裁判,稳定性可能远低于预期,单次结果基本不可信。可靠评测要靠重复采样、规则兜底、预注册协议三层保障。评测基建的可靠性,值得和模型能力同等重视。
总结
52,988 次请求的审计把"共享端点 LLM 裁判不可靠"这件事摆在了台面上:同日一致性 0.400,换供应商也没用。工程上要用采样、规则兜底和预注册协议来对冲这种不稳定性。统一在 4sapi(https://4sapi.com)上做评测,至少能把模型版本和采样参数固定下来。欢迎在评论区聊聊评测踩坑经历。