---
url: /basics/sampling-params.md
description: >-
  temperature、top_p、top_k 到底改了模型的哪一步？这篇从 logits 除以温度讲起，说清各家参数的默认值与范围、为什么推理模型直接拒绝
  temperature，以及设成 0 也换不来可复现的那个坑。
---

# 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，只在你真的需要复现失败用例时才设，别把它当成稳定性的保险。
