主题
temperature 调到 0,模型就不乱说了吗
调接口时最容易手滑的一个参数,就是 temperature。新人常常默认往里填 0,觉得这样输出就稳了。
真跑起来会发现,0 并不等于可复现。要讲明白为什么,得先看模型每生成一个 token 时到底做了什么。
模型每生成一个 token,都只做一次选择
它拿到上文,算出一组分数,每个候选 token 一个,这组分数叫 logits。
分数过一遍 softmax,变成加起来等于 1 的概率。然后照着这个概率抽一次签,抽到谁就吐谁。
采样参数改的就是这两步之间。不碰模型,只碰怎么从概率里挑。
temperature 是把 logits 除以一个数
公式很短,概率等于 softmax(logits 除以 T),T 就是 temperature。
T 小于 1,分布被拉尖,高概率的 token 更容易被选中。T 大于 1,分布被压平,平时排后面的冷门 token 也有了机会。
调到 0,等价于永远取概率最大的那个(argmax),不再抽签。这也是为什么有人把 0 当成「确定性」的代名词。
top_p 和 top_k 做的是截断
同一步里还有两个参数,管的是候选范围,不是分布形状。
top_k 只看概率最高的 K 个候选,剩下的直接扔掉。top_p(核采样,nucleus sampling)换了个算法,按概率从大到小累加,凑够 p 就截断。p 取 0.95,就只在前 95% 的概率质量里抽。
OpenAI 的接口文档写得很清楚:top_p 范围 0 到 1,默认 1。它给的例子是 0.1,意思是只看累计概率最高的前 10%。
这里有个跨厂商的坑。top_k 在 OpenAI 的接口里压根不暴露,只有 Gemini 这类厂商的 generationConfig 里能设。同一段代码搬到另一家,写了 top_k 常常是白写。
同一个名字,各家的范围和默认值不一样
temperature 的取值范围各厂商并不统一。
OpenAI 是 0 到 2,默认 1,数值越大越随机。Gemini 的官方文档给的默认值是 1.0,top_p 默认 0.95,两端都能调。
把一家的默认值原样抄到另一家,输出风格多半会偏。我去年就踩过一次:照着 OpenAI 的调参笔记,把 temperature 设成 1.0、top_p 设成 0.9 搬进另一家 SDK,跑出来语气明显更飘,对着两边的参数说明来回翻了两小时才发现,对方默认的 top_p 本来就不一样。
推理模型干脆不让改 temperature
现在一批主打推理的模型,直接拒绝这个参数。
给 o1、o3-mini 这类模型传 temperature,接口返回 400,报错原文是 Unsupported parameter: 'temperature' is not supported with this model。
原因是这类模型内部自己控制采样,外部再拧温度没有意义。
我第一次撞上时以为 SDK 装旧了,升级到最新版本照样 400。只能把参数整个删掉,让它走默认。
temperature 设 0,也换不来可复现
很多人以为填 0 就是确定性输出。OpenAI 的说明是,Chat Completions 默认就是非确定性的。
想尽量复现得做两件事:设一个固定的 seed,并且保证 prompt、temperature 这些参数全都一致。
关键词是「尽量」。文档用的词是 best effort(尽力而为),后端配置一改就可能失效。判断后端有没有动过,看响应里的 system_fingerprint,它变了说明模型那一侧的配置换了。
我压测过一批 temperature 设 0 的抽取任务,同一天里 200 条请求有 3 条结果不同。就这 3 条,把一条「结果可复现」的断言搞挂了。
我通常怎么设
分类、抽取、结构化输出这类任务,temperature 直接给 0,不留余地。写作、起名、头脑风暴才往上调,0.7 到 1.0 之间试。
一次只动一个参数。官方也是这个建议:temperature 和 top_p 别一起改,两个一起动了,你就分不清是哪一个在起作用。
我的默认起点是 temperature 0.2、top_p 不动,先跑一批真实样本,看输出分布再决定往哪边调。做抽取就压到 0。
至于 seed,只在你真的需要复现失败用例时才设,别把它当成稳定性的保险。