temperature-top-p-drift-by-backend · ZH · 2026-11-04

同一个 temperature=0 打六个后端:为什么『确定性』参数在换厂商后仍然漂移

同一个 temperature=0 在不同厂商的 LLM 后端上输出仍可能漂移,原因在于各厂商对 temperature、top_p 和默认采样的实现差异。本文梳理这些差异,并给出换后端时钉住采样参数、减少输出漂移的实用方法。

为什么 temperature=0 不等于完全确定

很多开发者习惯把 temperature=0 当作“确定性模式”,但在不同厂商的 API 之间切换时,会发现输出仍然有差异。原因不在你的代码,而在各厂商对采样参数的处理方式并不统一。

temperature 只是采样策略中的一个旋钮。即使把它设为 0,是否真正走贪心解码、是否仍然受 topp 影响、默认的 topk 或惩罚项是否生效,各家的实现都可能不同。

各厂商对 temperature 的处理差异

  • 是否把 temperature=0 解释为贪心解码:部分厂商在 temperature 极低时退化为取概率最高的 token,另一些厂商仍保留采样过程,只是把分布压得非常尖锐。
  • temperature 的有效范围与截断:有的 API 对 temperature 取值有上限或下限,传入超出范围的值可能被截断或报错。
  • temperature 与 topp 的优先级:有的实现先按 temperature 缩放 logits,再应用 topp;有的顺序相反,结果自然不同。

这些差异不会写在你的调用代码里,但会直接反映在输出上。

top_p 与默认采样的隐藏变量

topp(核采样)是另一个常被忽略的变量。即使你只设置了 temperature,很多后端仍有默认的 topp 值在起作用。

  • 有的厂商默认 top_p=1,即不截断;有的默认值小于 1,会主动裁掉长尾。
  • 部分后端还默认启用 top_k、重复惩罚(frequency/presence penalty)等参数,这些都会改变最终分布。
  • 不同厂商对“默认值”的定义不同,文档里未必显式列出,需要实际测试确认。

因此,只钉住 temperature 并不足以复现另一家的输出。

换后端时要钉住哪些参数

为了让输出在切换后端时尽量可预期,建议在请求里显式指定以下参数,而不是依赖默认值:

  • temperature:明确写出你想要的数值,不要留空。
  • top_p:显式设为 1 或你验证过的值,避免默认截断干扰。
  • top_k(若 API 支持):显式关闭或设定固定值。
  • 重复惩罚类参数:显式设为中性值(如 1.0 或不启用)。
  • max_tokens:固定上限,避免因截断位置不同造成差异。

显式声明这些参数后,不同后端之间的差异会缩小,但不会完全消失——底层模型权重和推理实现本身仍有区别。

实践建议

  • 建立参数基线:在切换后端前,用一组固定 prompt 对比各后端的输出,记录哪些参数需要显式覆盖。
  • 不要假设默认值一致:把每个后端的默认采样参数当作未知量,逐一确认。
  • 接受残余漂移:即使参数完全一致,不同模型家族的输出风格和 token 分布仍有差异,temperature=0 只能减少随机性,不能保证跨厂商逐字一致。
  • 用聚合层统一参数:通过一个 API key 调用多个模型时,在客户端统一注入采样参数,可以减少因后端默认值不同带来的意外。

把采样参数当作接口契约的一部分显式管理,比依赖“temperature=0 就确定”的直觉更可靠。