作者用同一套题对比5个模型时发现,评估用的评分模型本身存在偏差,导致结论不可信,揭示了基准测试的方法论风险。
我写了一个 pytest 测试套件,能同时用五个语言模型跑同一套题目——一个免费的本地 Llama,加上 GPT、DeepSeek 和两个 Claude 模型——然后从团队付费的三个维度来比较:每次查询成本、响应速度、回答质量。方案很简单,跑一遍,看分数,决定用哪个模型。
结果出来,表格清晰易读。但这是我不敢相信它的故事,以及我验证后发现的东西。我开始不相信的那个东西,不是任何一个被测的模型,而是我用来给它们打分的工具。
这也是这个系列里第一个真正花钱的项目。之前每一个都是本地运行、分文不花。这次每个调用都要付费,整个对比下来大概花了 21 美分。钱不多,但改变了我测试的方式,而且是以一种出乎意料的方式。
五个模型,同样的十道题,每题跑两次,每次调用都有测量。以下是跑出来的结果,按质量分排序(另一个模型给每个回答打分,衡量正确性和相关性,综合成 0-1 的分数,及格线 0.7):
model quality mean $/query mean latency out-tokens
deepseek-v4-pro 0.970 $0.000138 2713 ms 113
claude-haiku-4-5 0.967 $0.000537 1597 ms 104
gpt-5.6-luna 0.962 $0.000082 1323 ms 65
claude-sonnet-5 0.937 $0.002426 4093 ms 239
llama3.2 (local) 0.922 $0.000000 7859 ms 130
直接看,这个结果好像已经定论了。整个质量列集中在很窄的区间,0.92 到 0.97。最便宜最快的付费模型跟其他表现一致。最贵的那款 Sonnet,每次查询价格大概是其他模型的三十倍,分数却没有更高——它的回答只是更长(239 个 token 对比 GPT 的 65 个),花更多钱、耗时更久,质量分却没有更好。
所以简单的结论是:用这个小而便宜的模型,别用贵的那个。但我要谨慎一点,因为这种整洁的结果是我学会有理由去怀疑的。顶尖模型之间的差距很小,基于小差距做出的排名通常并不能说明它看起来说的那些东西。
所以在给任何模型排名之前,我给每个分数加了一个置信区间——也包括同一道题上每对模型之间的差异——来看这些差距是真的还是只是噪声。
每一对付费模型之间的区间都穿过了零。这意味着:在这组题目上,付费模型质量上打了个平手。它们之间的顺序是噪声。我可以量化这个噪声有多大——这次跑 GPT 排第三,而用同样配置的上一次跑 GPT 排第一。排名变了,但平局没变。
所以我不想说"模型 X 最好"。诚实的版本更收敛:付费模型在这里得分差不多,所以质量不是区分因素。如果非要选,那就看成本和速度,不是分数。这个结论比排行榜弱,但它在下一次跑的时候依然成立。
每个质量分数都来自一个裁判。而裁判是那个免费的本地 Llama——它同时也是被评分的五个模型之一。一个参赛者在给自己的组打分,而且还在给比它强得多的模型打分。整个基准测试的质量维度都依赖于此。
所以我把这个问题本身往上提了一级。它问的是"便宜模型还是贵的?"我把这个同样问题问到裁判身上。我用付费裁判重新给同样的 200 个保存回答打分。没有再调用任何模型——裁判只读取已经存在磁盘上的回答文本——所以重新评分的成本大概是三美分。
这一换,反复做了一件同样的事:
answer model cheap judge paid judge pass rate (cheap -> paid)
claude-haiku-4-5 0.969 1.000 40/40 -> 40/40
gpt-5.6-luna 0.966 1.000 39/40 -> 40/40
deepseek-v4-pro 0.957 1.000 40/40 -> 40/40
claude-sonnet-5 0.938 0.997 39/40 -> 40/40
llama3.2 (local) 0.936 0.919 39/40 -> 35/40 <- 唯一下降的
每个付费模型都往顶部上升了。只有 Llama 下降了。在便宜裁判手下它看起来稍微落后于其他模型(0.936,刚好低于 Sonnet)。在更好的裁判手下差距拉开了,它的通过率从 40 题中对 39 题降到了 35 题,而每个付费模型都保持在干净的 40/40。便宜裁判一直在掩盖一个更好的裁判揭示出来的真实差距。
然后我读了两个裁判给出不同意见的回答——这是唯一能真正学到东西的地方。那些不一致不是随机的。同一件事反复发生:便宜裁判对弱模型的错误回答太宽松了。
那些错误回答来自第二组、更难的一套题。简单的十道题分不出模型的高下——每个人都能过——所以我又写了十道带陷阱的题,是那种弱模型真的会翻车的题目。差距就是在那里显现的:
"唯一一个没有陆地海岸线的海是哪个?"(马尾藻海)。Llama 回答"地中海"——错了。便宜裁判给了它正确性 8/10 分,让它过了。付费裁判给了 0/10,让它没过。
"strawberry 里有多少个 r?"(三个)。Llama 回答"两个"。便宜裁判认为它部分正确,让它过了。付费裁判让它没过。
一个答错了海,一个答错了字母数,两个都被基准测试依赖的那个裁判放过了。这个发现才是我最在意的。便宜裁判不只是在整体上更宽松。它在基准测试最需要它严格的唯一一个地方——抓住弱模型的错误回答——上宽松了。如果我信任它的总分,我发出的会是一份把真实错误判为通过的分数表。
一旦我不再信任裁判,同样的问题在其他地方也出现了。我做了一个配对测试:给裁判看同一个题的两个回答,问哪个更好,然后再把两个回答顺序颠倒给它看。回答本身没有任何变化,只有顺序。一个看质量的裁判两次应该选同一个。如果它选了不同的,那它选的是位置,不是质量。
在简单题目上,便宜裁判在 45% 的配对中改变了它的赢家——将近一半——而唯一变化的只是顺序。付费裁判这个比例是 19%。当便宜裁判翻转时,45 次里有 42 次它选中了它先看到的那个回答。它没有在权衡回答,它是在奖励排在前面的位置。
你可以在它自己的推理过程中看到这件事。在"我们的太阳系有多少颗行星"这道题上,两个回答都说八颗并列了出来——其实是一样的回答。给它先看其中一个,它夸它提到了冥王星的重新分类。给它先看另一个——那个没提冥王星的——它夸它没有提起冥王星。同一道题,理由相反,但两次它都选了排在上面的那个。
它还偏心。给它自己所在的组评分时,它把自己的回答排在了五选第三,而单独看这些回答的分数,它们其实是最后一名。和那个海以及草莓的例子一样的教训:便宜裁判是个更差劲的工具,而基准测试的质量取决于给它打分的那个裁判。
这些数字背后有一道疤。早期的项目里我有一条规则:保留每一张收据,不要扔掉一个结论所依赖的原始输出。对于位置偏差的发现,我是手动做的——我把裁判的原话复制进了文章里作为证据。
后来我想把每句引文追溯到它出自哪一次调用。但第一次跑的时候只保存了裁判的判决,没有保存它的推理,所以要想再拿到措辞就得重新跑一遍。而重新跑就会得到新的回答——这些模型就是这样,同一个问题会返回不同的答案。所以我抄下来的那些话现在描述的已经是不存在的回答了。我的证据指向了空无一物。
规则本身没错,只是还不够。手工冻结的证据在它描述的东西移动的那一刻就会漂移。所以我改变了收据的工作方式:不再手工冻结任何东西。文章里的每一句引语和每一个数字都是由一个小生成器从报告读取的同一批保存回答中重建的,所以证据和报告来自同一个地方,不可能漂移。如果我无法从保存的回答中重建一张收据,那它就不是收据。
这也是我反复在说的一句话的诚实版本——这里的分数是一次跑出来的结果。重新跑会让它们移动,而正是这件事曾经让我的证据指向了空无一物。
这部分是我没有预料到的,这就是为什么这个项目感觉和前四个不同。
当每个调用都要花钱时,会有一种持续的拉力让人减少测试。只跑一遍而不是两遍。用免费的裁判而不是花钱用好的。再少问一道题就收工。整个对比花了大概 21 美分,而价格产生的那种本能是把成本往零压。
这种本能是反的,这次跑本身就证明了。唯一"多花了钱"的地方是每道题跑了两遍。按省钱逻辑,第二遍是浪费——同样的题再跑一次。但五个模型里有三个得了 19/20 而不是干净的满分,读了记录才发现原因:那些回答刚好卡在及格线上,两次跑之间跨过了它。第一次过,第二次没过,同一道题。一遍的话会把一个抛硬币的结果记录成一个事实。"浪费的"第二遍才是说出真相的那个。
所以钱没有让我测得更少。它让我有目的地测。每个调用都得证明自己的位置,这才是测试本来应该做的。普通的自动化隐藏了成本,所以没人会问某个测试值不值得跑。按次计费把这个选择摆到了你面前。省下那几美分少测一点可能让你选错模型,或者选到一个你无法信任的裁判,而这个选择会乘以你服务过的每一个请求。贪便宜才是贵的那个错误。
两点,都跟某个具体模型无关。
不要只看原始分数给模型排名。这里的分数相差零点零几分,这么小的差距通常只是运气——再跑一遍它就变了。所以在信任任何顺序之前,我先检查了每个分数在重新跑的时候会摆动多少,一旦算上那个摆动,付费模型的结果是一样的。这个检查把"模型 X 赢了"变成了更真实、更有用的"这些是平局,按成本决定。"
不要让你正在测试的东西同时成为给你测试打分的东西。整个基准测试的质量维度都经过了一个裁判——它同时也是被测的模型之一,而且不够格做这个工作——然后它放过了我最需要它抓住的那些回答。我之所以看到这些,是因为花了几个美分用另一种方式给回答打分,然后读了两种方式不一致的地方。那种阅读才是真正的工作。
保持规模真实:十道简单题加一套更难的,两遍跑,一个本地模型和四个付费模型。具体的分数是一次跑出来的结果——再跑一遍它们会变,有时变到足以重新排名。保持不变的是形态:付费模型打平,便宜裁判让弱模型看起来比实际更好,第二遍跑值回它的成本。这些会迁移过去。具体的数字不会,说出来也是工作的一部分。
Repo: github.com/sbezjak/llm-benchmark
这是五个 AI 系统测试项目的第五个也是最后一个,前四个分别是 eval harness、RAG 系统、red-team suite 和 agent tester。这个项目收尾了整个循环:用来给所有这些打分的裁判,才是你首先要检查的东西。
下一个不是项目。是关于这五个项目教给我如何在工作中与模型协作、而不只是测试它——而且我不只是把教训写下来,我还把它们放回项目上验证是否站得住。