一次翻车能证明模型犯过错,却不能独自证明它比以前更容易犯错。

“这个模型是不是又降智了?”一只脚悬在踏板外面的鹈鹕,一辆车架拧成麻花的自行车,再配上一张上周画得相当漂亮的截图,就足以让人产生这个疑问。

自然史插图:一只鹈鹕骑在自行车上,一只脚没有踩住踏板。

这种怀疑不该被一句“模型有随机性”打发掉。用户付了钱,原本能完成的任务现在做不好,当然值得追问。但反过来,两张截图也不足以说明模型被换了、思考预算被砍了,或者某个渠道一定“掺了水”。前段时间,我反复跑了几十次鹈鹕测试。这个题目有意思的地方,在于它把很多错误直接画了出来:代码能运行,不代表自行车结构正确;鸟和车都画全了,也不代表脚真的踩在踏板上。相比一段看似流畅、却可能藏着逻辑漏洞的回答,这些空间关系更容易被肉眼发现。但跑得越多,越会意识到另一件事:我们常常在用一张作品,评价一整套服务。这篇文章不想替任何模型开脱,也不想教人凭几个特征抓“假模型”。我更关心的是:当我们怀疑模型变差时,怎样把这种感觉变成可以复查的证据?

说明:下文所有 A、B 渠道及其测试数字均为教学示例,不对应任何真实服务,也不是 Folkbench 的实测排名。

一、先分清楚:你说的“变笨”,究竟是哪件事?

“降智”这个词方便,却把几个不同的问题揉到了一起。最直接的一层是:这一次,答案确实错了。鹈鹕多长了腿,脚没有踩住踏板,自行车的轮子和车架分了家。这些都是具体、可检查的失败。一个样本就足以证明“这种错误发生过”,甚至足以推翻“它绝不会犯这种错误”的承诺。第二层是:在相同或足够接近的条件下,这个服务更容易失败了。这就不能只看错误是否存在,还得看它出现的频率。过去多数时候能完成,现在多数时候做不好,才是我们日常所说的“体验变差”中最值得测量的部分。第三层则是:造成变化的原因,是模型本身或服务端配置发生了某种改变。

这已经进入原因判断。同样的坏结果,可以对应不同解释:请求参数不同、上下文不同、输出被截断,或者底层模型与推理配置真的变了。只看到结果,通常还不能把这些解释唯一地区分开。因此,“这次错了”“这家服务更不可靠”“这家偷偷换了模型”,需要的证据强度并不相同。承认这个区别,不是在抬高用户投诉的门槛。恰恰相反,把问题定位清楚,才能避免服务商用“随机性”解释所有故障,也避免评测者用“偷换模型”解释所有差异。

二、你看到的是一张作品,还是一组输出的分布?

在使用随机采样的生成设置下,同一输入可以产生不同输出。即使使用某些控制复现性的手段,也不应直接把“尽量一致”理解成“绝对一致”。例如,OpenAI 的一份历史技术说明明确写过:相同 seed、参数和后端指纹下,输出仍不保证完全相同。这说明复现性有边界,不代表今天所有模型都支持相同参数。1 对鹈鹕测试来说,我们真正想知道的,往往不是“它能不能偶尔画出一张好图”,而是“在指定条件下,再交给它一次任务,有多大机会得到合格结果”。用一个简化例子就能看出单张截图的问题。假设某个服务的真实单次合格率是 80%,且每次生成相互独立、测试期间状态不变。那么连续测试 20 次,至少出现一次失败的概率是: 1 − 0.8²⁰ ≈ 98.85% 也就是说,一个多数时候能做好的服务,在 20 次测试里留下翻车素材,几乎是必然的。

反过来,假设另一个服务的真实单次合格率只有 40%。同样在独立、稳定的前提下,跑 20 次,至少得到一次合格结果的概率是: 1 − 0.6²⁰ ≈ 99.996% 它也几乎肯定能交出一张可以拿去展示的作品。这两行计算不是在说所有真实调用都独立,也不是说真实合格率恰好就是这些数字。它们只是揭示一个选择问题:只展示最好的一次,很容易高估可靠性;只展示最差的一次,也很容易夸大退化程度。因此,同一服务完全可能同时出现在“满血实锤”和“降智实锤”的帖子里。截图都是真的,推断却未必成立。

这里还有一个容易被忽略的区别:一次生成就成功,和生成十次再挑出一次成功,不是同一种能力指标。后者包含额外的调用、等待和挑选成本。若比较两种工作流,就应让双方拥有相同的尝试预算,而不是拿 A 的第一次,去对比 B 的精选集。

三、跑到 20 次,差异就自动有统计意义了吗?

不会。20 次可以是一笔合理的试验预算,但不是统计学上的通行证。还是看那个直观的例子:A 渠道跑了 20 次,16 次合格;B 渠道跑了 20 次,8 次合格。双方使用同一道固定题目、相同评分标准,样本全部保留。

渠道合格次数 / 总次数样本合格率合格率的 95% Wilson 置信区间
A16 / 2080%58.4%–91.9%
B8 / 2040%21.9%–61.3%
示意图:A 在 20 次里合格 16 次,B 在 20 次里合格 8 次。

区间依据二项比例的 Wilson 方法计算,用来表达对合格率估计的不确定性,不是画面质量的分数范围。2 首先可以确定,样本中的差异是 40 个百分点。其次也要看到,两边只有 20 次,估计仍然不够精细:不能把 80% 和 40% 当成已经测准、永远不变的真实能力。若进一步假定各次调用独立、每个渠道在窗口内的合格概率稳定,且这是事先确定的一次比较,对上面的“合格/不合格”计数做双侧 Fisher 精确检验,得到 p ≈ 0.0225。按预先采用的 5% 显著性水平,这组示例支持“两者在该条件下的合格率存在差异”。3

但这个数字不是“B 有 97.75% 的概率掺水”,也不是“A 有 97.75% 的概率永远更好”。p 值描述的是:在无差异假设及相应检验条件下,出现如此极端或更极端数据的概率,而不是某种幕后原因的概率。3 也不要靠上表两个区间是否重叠来代替差异检验;它们分别估计两个合格率,检验的对象却是两者之间的差异。比记住一种检验方法更重要的,是记住三个边界。差距大小和样本量要一起看。 16 比 8,与 16 比 15,不该得到同样强度的结论。需要多少样本,取决于你希望识别多小的差距,以及愿意承担多大的误判风险。没有一个适用于所有任务的“至少跑几次”。

没有测出显著差异,不等于证明两者一样。 数据也可能只是太少、太不稳定,尚不足以下结论。要证明差异小到可以忽略,需要事先定义“多小算可以忽略”,而不是把一个不显著的结果当成等效证明。统计上有差异,也不等于实际值得换服务。 对用户而言,还要考虑失败的代价、调用价格、延迟和返工成本。一个可靠的差异,仍然可能小到不影响选择。统计在这里的作用,不是生产一个看起来专业的 p 值,而是阻止我们把证据说得比它本身更强。

四、Baseline 不是一句“Prompt 一样”,而是一份实验契约

很多对照测试的问题,并不出在样本不够,而是样本从一开始就不可比。同样输入“画一只骑自行车的鹈鹕”,一边是在全新会话里调用 API,另一边是在已经聊了几十轮、还启用了工具的聊天窗口里生成;一边允许较长输出,另一边中途达到长度上限。这样的结果,即使重复一百次,也不能直接归结为模型能力差异。 OLMES 评测标准的研究指出,提示格式、上下文示例和任务表述等评测选择,会改变测得的表现;可复现比较需要把这些设置明确记录下来。它研究的具体任务不等同于鹈鹕 SVG,但对实验配置的提醒同样值得借鉴。4 我的建议是,把 baseline 理解为一份“这次究竟在测什么”的契约。

比较对象要具体到服务、分组或路由,以及可获得的模型版本。只有一个会随时间变化的模型别名,就记录别名;不知道底层快照,就写未知。不要把接口返回的型号字符串,当成底层身份已经得到独立验证。输入要尽量保存完整:不仅是最后一句 Prompt,还包括你能够控制和观察到的系统提示、历史上下文、附件与工具设置。可见条件一致,不代表不可见条件也已经被证明一致。生成配置要记录思考强度、输出上限以及接口实际支持的采样参数。不支持的字段写“不支持”,无法确认是否生效的字段写“未知”,不要悄悄当成一致。不同模型里的同名“high”也不应默认代表相同算力预算。

评测环境则包括渲染方式和评分标准。同一份 SVG 要在相同视口与渲染环境下检查;动画题要按约定的观察窗口检查,不能一边看完整动作,另一边只挑一帧。如果题目没有要求动画,也不应因为输出是静态图而扣分。最后,重试规则必须写在测试之前。首次失败后能不能重试、重试几次、是否给反馈,都属于测试条件,而不是临场发挥。固定这些东西,并不是为了制造一个脱离现实的“实验室模型”。你完全可以比较两个聊天产品的默认体验,但结论就应该是“两个产品在默认设置下的交付差异”,而不是“我已经隔离出了底层模型权重的优劣”。控制不了的条件可以保留为未知;不能把未知写成已控制。

五、把测试安排好,往往比单纯多跑几次更重要

不要让渠道和时间绑在一起

上午连续跑完 A,深夜再连续跑完 B,会把“渠道差异”和“时间差异”混在一起。即使确实观察到差距,你也很难判断它在多大程度上依赖那个时间窗口。对于一个轻量的横向对照,我会在预先规定的窗口内,让 A、B 交错接受请求,并随机安排顺序。并发量也尽量一致,不要让一方逐个生成,另一方承受一批突发请求。进一步可以把窗口划成几个小批次,每批都有 A 和 B。这样除了总体结果,还能检查差异是否只集中在某个批次。随机顺序有助于降低时间混杂,但不会自动消除共用后端、短时故障等可能带来的相关性。

纵向的“是否比上周差”则不同:时间本来就是要研究的变量,不可能固定成同一时刻。此时应尽量保留相同的核心题、配置和评分标准,并在每个观察窗口一起重跑参照服务,而不是永远拿今天的结果对比上周最好的一张。看纵向结果时,绝对合格率和相对差值都要保留。如果被测服务和参照服务同时下降,相对差值可能不变;但这不代表用户体验没有下降。参照也不是永远正确、永远稳定的真值。

不要一边看结果,一边决定什么时候收工

“先跑五次,A 赢了就发帖;A 没赢就继续,直到出现显著差异。”这种方法看似增加了样本,实际改变了统计规则。用普通固定样本检验反复查看数据、根据结果决定停止,会破坏原本的误报控制;需要持续观察的测试,应采用专门的序贯方法。5 普通人不必从序贯统计学开始。最容易执行的办法,是预先写下本轮跑多少次、用哪个主要指标、做哪些主要比较,然后保留全部结果。先试几次确认接口和评分流程没有问题,当然可以。但这些属于试运行。流程修改完成后,再单独开始正式测试,不要把调题阶段的结果和正式结果混在一起。同理,一口气试几十道题,最后只公布最有利的一道;或者看见总分不占优,就改用某个分项宣布胜利,也不是同一个事先约定好的比较。

不要把同一道题刷一百遍,当成做过一百道题

重复生成能帮助我们了解“这道题上有多可靠”,却不能自动扩大结论的适用范围。鹈鹕画得再稳定,也不直接代表代码调试、长文分析和复杂指令遵循同样可靠。对一类任务做推断时,题目之间的差异和同一题多次生成的差异,是两种不同的不确定性。相关评测研究专门区分了重复采样、题目层面的比较以及成组相关样本的处理。6 因此,我会先用同一条探针观察重复性,再加入少量与实际用途相关的固定任务。两边都回答同一组题,先计算逐题表现和逐题差值,再做汇总,而不是只扔出一个总分。如果对多题结果做正式统计,就要保留同题和同批次的对应关系。不能简单把“10 道题,每题 10 次”当成“100 道彼此独立的题”,套用前面单题示例的计算。

还有一个小陷阱:固定 seed 适合排查复现问题,但把同一 seed 下几乎不变的输出复制二十次,不能当成对随机输出分布的二十次独立观察。测稳定性时,应预先约定采样策略;支持 seed 的接口可使用预先生成的多个 seed,不支持的就记录这一限制。题库怎样长期更新,是另一个需要单独展开的问题。至少在这一轮对照里,别一边换题,一边把新旧分数连成“模型进步曲线”。

六、超时、截断和画错,不能混成一锅

还有一种很常见的统计失真:只给“成功返回的作品”打分,把超时和报错的请求直接删掉。这样得到的分数,回答的是“拿到完整输出之后,它有多大机会合格”,而不是用户更在乎的“发出一次请求,能不能拿到合格结果”。假设预先安排了 20 次请求,其中 4 次超时;剩下 16 次返回完整作品,8 次合格。那么完整作品中的合格率是 50%,但按这 20 次请求计算的首次交付成功率只有 40%。只公布前者,会漏掉那四次没有交付的体验。因此,我会同时保留三类结果:技术层面的交付失败、完整返回但任务不合格,以及完整返回且任务合格。超时、接口错误、流式中断、达到长度上限等问题,再分别记录原因。

但“分开记录”不意味着给服务故障免责。对选服务的人而言,超时和画错都会消耗时间;只是在追查原因时,它们不应该全部被描述成“模型智力下降”。本地网络或测试脚本故障也要单列,是否排除应有事先约定的规则,不能看到哪边输了才临时删样本。这里我更倾向于把首次请求得到合格结果的比例设为主要指标,把完整输出中的内容合格率、技术失败率、耗时和成本放在旁边辅助解释。完整输出的内容合格率也不是完全无偏的“纯能力分数”:如果复杂请求更容易超时,留下来的作品可能本来就更容易。它能帮助定位问题,但不能替代完整请求层面的结果。至于“修一次后能不能成功”,可以另开一项测试,给双方相同的修复机会。不要给一边耐心纠错五轮,另一边一错就判死刑。

七、一场普通人也能执行的最小对照

不必为了测试一只鹈鹕,先造一个评测平台。下面是一份起步方案。它适合排查某条固定探针上的明显差异,不是保证检出小幅退化的样本量设计。

项目本轮约定
问题A、B 两个服务在这条固定题目上,首次交付合格结果的比例是否不同?
输入与配置保存完整可见请求;统一可控制参数;记录无法确认的差异
样本每边预先安排 20 次正式请求;试运行不混入正式样本
时间与顺序在预定窗口内分成 4 批,每批 A、B 各 5 次;批内随机交错,保持相同并发规则
重试正式首答测试不追加重试;需要评估修复能力时另开实验
评分开跑前定好合格标准;渲染后隐藏渠道名称、打乱顺序,再评分
输出保存全部原始结果、每次状态、评分依据,以及逐批和总体统计
示意图:4 个批次里,A 和 B 各 5 次,顺序交错。

鹈鹕题的合格标准不妨先朴素一些:文件能否在约定环境中正常渲染,主体与自行车是否完整到可辨认,关键结构是否明显错误,脚与踏板等题目要求的接触关系是否成立。美观可以另记,但不能用精致的配色抵消结构错误。如果有人对边界样本拿不准,就先标记为争议,按预定的复核规则处理,而不是看见渠道名字后才决定放不放行。小规模测试可以先人工盲评;规模扩大之后,再讨论自动评分与裁判校准。那是下一层问题,不必在第一轮就全部解决。记录时,把“每轮一份”的配置与“每次调用一行”的日志分开,会轻松很多。每轮配置保存原始请求模板、参数、题目版本、评分规则版本、时间窗口、超时与重试约定。每次调用则至少记录下面这些字段:

run_id,block_id,service,service_group,requested_model,returned_model,started_at,request_hash,status,finish_reason,latency_ms,qualified,failure_reason,artifact_path

时间使用带时区的格式。原始响应、提取出的 SVG 和渲染图通过 artifact_path 关联;接口暴露的 token 用量、后端指纹等信息也可以附加保存,没有提供就记为空或未知。request_hash 用来检查请求是否一致,但不能替代原始请求本身。保存与分享日志时,要移除 API 密钥,并对私人上下文或其他敏感内容做脱敏。公开验证需要的是实验条件,不是把账户凭据一起交出去。统计时,先看总体差值和逐批结果。前文的二项区间与 Fisher 检验,只适用于其独立性、稳定性等假设大致成立的情况;若结果明显受批次影响,或之后扩展为多题重复测试,就应采用匹配设计的分析,而不是机械复用单题公式。

如果初步差异值得追查,再在新的预定窗口复测,并加入与你实际用途有关的任务。第一轮数据是异常线索;独立的新一轮验证,才有助于判断它是不是持续存在。

八、发现差异之后,结论该怎么写?

还是以前面的教学数字为例,一份克制但有用的结论可以这样写:

在本轮固定题目、相同可见配置和预定时间窗口下,A、B 各测试 20 次,首次交付合格结果分别为 16 次和 8 次,样本合格率相差 40 个百分点。在独立采样等假设下,双侧 Fisher 精确检验的 p 值约为 0.0225,支持本轮条件下存在差异。该结果尚需在其他窗口和相关任务上验证,不能单独识别底层模型或服务端配置变化的具体原因。

它没有“满血实锤”那么刺激,却把别人复查所需的关键条件交代了出来。如果跨时段、跨相关任务的后续测试仍然得到一致方向的结果,我们就有更充分的理由说:这个服务在这些用途上不如参照可靠,或者相较历史基线确实退步了。但从“交付表现下降”跳到“偷偷换成了某个小模型”,仍然多走了一步。要确认具体机制,还需要能区分不同解释的独立证据,例如可核验的路由或配置记录;不能只靠输出风格猜型号。这也不意味着用户必须等到原因查明才有资格换服务。选择服务需要的是它是否满足你的要求;指控具体原因,需要的是关于那个原因的证据。 两件事可以分开。

九、真正要省下的,是“把问题证明清楚”的成本

手动测试最耗人的地方,往往不是点下运行按钮,而是后面的重复劳动:文件存在哪里,参数有没有变,这张图是第几次生成,是否重试过,截图和原始响应还能不能对应上。少了这些记录,当时再确信的“它真的变笨了”,过一周也可能只剩几张无法复查的截图。如果只是想先了解不同服务的表现,没有必要人人从零开始重复整理。可以先去 Folkbench 查看公开榜单及报告入口,确认你关心的模型、服务分组和指标是否已有结果。其公开页面强调在同一模型下比较不同服务,榜单也提示:某一行分组的数据,不代表这家站所有分组的表现。7

不过,现成榜单的意义应该是减少搜集和整理成本,而不是让人放弃核对条件。包括 Folkbench 在内,任何榜单都值得继续追问:什么时候测的,测了什么,样本有多少,失败有没有保留,结论适用于什么范围。没有公开的信息,就仍然是未知。回到最初的问题:“模型降智”到底有多少是真的,有多少是单次抽样的错觉?在没有共同定义、完整样本和可比条件之前,给出一个总比例,只会制造新的玄学。我们能做得更好的,是把每一次具体怀疑,逐步变成可检查的判断。看到翻车,先保留原始结果;怀疑退步,开始做对照;发现差异,再追查原因。别让这几个步骤在一张截图里被同时完成。一张截图可以提出一个好问题。要回答它,还得有一场像样的实验。

注释与参考资料

  1. OpenAI,How to make your completions outputs consistent with the new seed parameter,历史 Cookbook 示例,页面已标记归档。该说明将固定 seed 描述为尽力实现确定性,而非保证;本文只引用其复现性边界,不将其中旧型号和参数支持范围当作当前产品说明。原文↩
  2. NIST/SEMATECH,e-Handbook of Statistical Methods,第 7.2.4.1 节 Confidence intervals 中的 Wilson 比例区间方法。本文对 16/20、8/20 使用双侧 95% Wilson 区间,结果为作者按公式计算,四舍五入至百分数一位小数。这里的置信水平描述区间构造方法的长期覆盖性质,Wilson 方法为近似方法。原文↩
  3. SciPy 官方文档,scipy.stats.fisher_exact。本文以列联表 [[16, 4], [8, 12]],使用 alternative="two-sided" 计算,得到 p = 0.0224774273717544。这是示例数据的计算结果,不是论文或平台报告中的实测结果。该示例针对独立的二项结果比较;配对、多题聚类、时间相关或多重比较情形,需要按相应设计处理。原文↩
  4. Yuling Gu 等,OLMES: A Standard for Language Model Evaluations,Findings of NAACL 2025。论文讨论提示格式、上下文示例选择、任务表述等评测细节与可复现比较。原文↩
  5. Ramesh Johari、Leo Pekelis、David J. Walsh,Always Valid Inference: Bringing Sequential Analysis to A/B Testing,arXiv:1512.04922,2019 年修订版。论文讨论持续查看结果并据此决定样本量的问题,以及相应的序贯推断方法。原文↩
  6. Evan Miller,Adding Error Bars to Evals: A Statistical Approach to Language Model Evaluations,2024。有关题目层面的不确定性、重复采样、配对比较与聚类样本,参见第 2、3、4 节;样本量规划参见第 5 节。原文↩
  7. Folkbench 公开首页及榜单页面,查阅日期:2026 年 10 月 5 日。本文仅据公开页面说明其入口、比较范围和分组提示,不对具体榜单数据作独立背书,也不表示其已经实现本文提出的全部实验流程。首页;榜单↩