跳到主要内容

采样漂移:当 Temperature 和 Top-P 变成团队内部的“口头传说”

· 阅读需 10 分钟
Tian Pan
Software Engineer

打开任何上线超过一年的 AI 功能的生产环境配置,你会发现一个考古挖掘现场。temperature: 0.7 是因为有人想让演示看起来不那么机械。top_p: 0.85 是因为一个客户抱怨输出太普通。frequency_penalty: 0.4 是因为 2024 年有那么糟糕的一周,一个现在已经退役的模型一直在重复自己。这些决定都没有记录。它们都没有针对当前的基座模型进行重新测试。它们在每一次请求、每一次评估、每一次 A/B 测试中运行,塑造着自原始工单关闭以来再也没有人会有意识选择的行为。

这就是采样漂移(Sampling Drift)。它是由于权宜之计而进行的采样器微调的缓慢积累,这些微调最初的理由已经消失,而其效果却在不断叠加。你配置中的数值并不是经过“调优”的——它们是过去事故的化石记录,被缩放到了你当前的流量规模。

它之所以不可见,是结构性原因造成的。你运行的每一次评估都是针对当前的采样配置进行评分的,所以头条数据看起来总是没问题。当 Temperature 值比基座模型落后两个版本时,不会触发报警。也没有日历邀请会提醒你“在本季度重新网格化采样参数”。这种衰减是无声的,直到有人运行了一个干净的实验,发现一个质量提升、Token 减少,或者两者兼而有之的机会,就摆在眼前,且不需要任何工程成本。

你配置中的化石记录

为了观察采样漂移是如何形成的,看看一个数值的生命周期。一位高级工程师演示了一个早期的原型。输出读起来很生硬。他们将 Temperature 从默认的 1.0 提高到 0.7,演示成功了。PR 标题是“让演示不那么机械”。数值发布了。

三个月后,一位客户报告称,针对类似问题的两个回答看起来太像了。有人动用了 top_p,将其从 1.0 降低到 0.85,以在长尾分布中引入更多变化,发布更改,关闭工单。没有人针对新数值重新运行评估,因为评估得分并不是投诉点。

又过了一个季度,一次事故复盘发现长文本输出中存在重复。有人添加了 frequency_penalty: 0.4。产生重复的模型在六周后被废弃。但惩罚项留了下来。

十八个月后,团队升级了基座模型。继承下来的采样配置——temperature 0.7, top-p 0.85, frequency_penalty 0.4——是针对前一个模型的怪癖进行调优的。新模型具有不同的 Logit 动态、不同的默认重复行为,通常甚至推荐完全不同的采样器。正如最近的参考指南所指出的,供应商推荐的默认值在当前这一代模型中差异巨大,对一个模型有效的数值不太可能对下一个模型也是最优的。

这个故事中没有任何轻率之处。每一个决定在当时都是理性的。漂移是当理性的决定不断累积,却缺乏重新审视的过程时所发生的结果。

为什么评估套件捕捉不到它

采样配置最诱人的一点是,评估套件(Eval Suite)永远不会对它有异议。评估是针对你运行的任何采样参数进行评分的,因此任何漂移都会内化到基线中。无论评估是每天运行还是每季度运行,轨迹都是一样的:分数反映了当前的配置,当前的配置反映了堆积的历史,而历史没有代言人。

这在结构上不同于 Prompt 回归,后者在有人更改 Prompt 并重新运行评估的那一刻就会浮出水面。为两个版本前的模型选择的采样参数对于评估来说是不可见的,因为评估不记得选择该参数时的数值是多少,它原本要修复什么,或者它要修复的问题是否依然存在。

有一个实验可以打破这种魔咒:保持 Prompt 和模型固定,改变采样器,在小范围内重新网格化 Temperature 和 Top-P(例如,Temperature 取 1,Top-P 取 1),然后重新评分。大多数第一次运行这个实验的团队都会发现,继承下来的那个点并不是局部最优解。同样的实验通常还会显示,一个或两个旧的惩罚参数可以被完全移除而不会损失质量——因为最近的前沿模型已经在很大程度上解决了重复问题,而这些惩罚项最初引入就是为了缓解这些问题。现在,这些惩罚项偶尔甚至会抑制有用的重复,比如精确技术术语的第二次出现。

这个实验成本很低。但由于没人负责,所以没人运行。

规范的采样应该是怎样的

能够规模化的模式是将采样配置视为一等公民,采用与 Prompt 相同的规范进行管理。这意味着四件事,每一件都不稀奇。

第一,数值旁附带理由。每一个非默认的采样参数在发布时都应附带结构化注释,指明它是针对哪个模型版本调优的、产生的评估增量,以及它所修复的故障。“temperature: 0.7 // 2024-09 针对 gpt-4o-2024-08-06 选定;简洁度评估提升 3 个百分点;替换默认值 1.0”是一个理由。“temperature: 0.7”则是民间传说。这个理由是未来的工程师用来决定是否保留该数值的依据。

第二,对“三元组”进行版本控制,而不仅仅是 Prompt。LLM 应用中的行为单元是“模型+提示词+采样”三元组。一个只对 Prompt 进行版本控制的团队发布的是他们无法复现的行为。生产环境 Prompt 平台越来越多地将采样配置打包进版本工件中,这样回滚就能回滚一切,且评估结果绑定的是特定的三元组,而不是“截至昨天的 Prompt”。

第三,定期进行采样审计。每季度一次即可。审计是针对当前模型和当前评估进行的重新网格化,并带有书面结论:哪些参数仍是最优的,哪些可以移除,哪些需要重新调优。产出是两个 PR——一个移除废弃参数,一个更新现行参数——以及一份成为下次审计依据的一页简报。如果团队发布速度更快,那么每当基座模型发生变化时就运行一次,因为那一刻继承的采样配置最不可能保持正确。

第四,对未记录的更改进行报警的回归防护。如果采样参数发生了更改,但 PR 中没有附带相应的理由更新和评估增量,则 CI 检查失败。这听起来很官僚,但却是整套方案中最廉价的机制,因为采样配置足够小,误报率基本为零。

模型升级陷阱

捕捉采样漂移 (sampling drift) 最具杠杆效应的时机是基础模型升级。这也是大多数团队处理得最糟糕的时刻。

主流的模式是更换模型标识符,运行评估 (eval),看到评分没有下降,然后发布。针对前一个模型调优的采样配置——在未被触碰的情况下——直接被沿用。在接下来的六个月里,应用程序运行在一个针对底层模型已不再表现出的行为进行优化的采样器上。

这很少会导致灾难性的后果。它更多时候是一种缓慢的流失。对前一个模型合适的 temperature 值,产生的输出可能会比新模型所能达到的效果略显保守或略显刻板。对前一个模型合适的 frequency penalty 有时会抑制有用的重复。对前一个模型合适的 top-p 值会裁剪掉新模型能够很好利用的概率分布长尾。评估中不会体现这些影响,因为评估也是在相同的采样器上运行的。

解决方法是将采样器重新调优作为模型升级清单的一部分,而不是一个单独的项目。当配置中的模型标识符更改时,PR 模板应要求提供重新网格化 (regridded) 的采样器,或者明确注明“保留继承值,请参阅审核日志”并附上说明理由的审计链接。供应商文档对此有明确说明——例如,Azure OpenAI 的复现性指南 指出系统指纹随后端更新而变化,这与行为一致性属于同类事件。

一个相关的准则:停止同时调整两个会相互干扰的惩罚参数。供应商推荐的模式是调整 temperature top-p,而不是两者同时调整。两者的相互作用难以推导,而一个同时调整这两者的配置,注定会让六个月后的继任工程师无法调试。选一个。在理由中记录这一选择。

采样参数是契约的一部分

架构层面的认知是,采样参数不仅仅是“超参数”。它们是你的应用程序与用户之间建立的行为契约的一部分。模型决定了可能性。提示词 (prompt) 决定了请求内容。采样器决定了在给定提示词的情况下,用户实际上看到的是模型可能的响应中的哪一个。

三个旋钮。行为的三个独立贡献者。如果一个团队严谨地对其中之一进行版本控制(提示词),有纪律地管理另一个(通常固定的模型标识符),却对第三个(采样器)听之任之,那么他们交付的行为就只受到部分控制。当生产环境中出现异常,团队回滚了提示词但回归测试仍然失败时,采样器就是那个没人想到去检查的隐形第三轴。

修复方法并不华丽。它包括一条理由注释、一个版本化的三元组、季度审计、CI 守卫,以及包含采样器的模型升级清单。这些都不是研究难题。它们是工程运营问题,会默默地累积产生负面影响,直到有人决定不再放任不管。

能够持续做到这一点的团队,并不是那些拥有最整洁采样器配置的团队。而是那些在“此数值存在”与“为何存在、针对哪个模型、评估增量 (eval delta) 是多少”之间距离最短的团队。采样漂移填补了这段距离。缩短这段距离就是工作的核心。

References:Let's stay in touch and Follow me for more thoughts and updates