你拧的那个旋钮,其实只作用在整条链路的一层上。
凌晨两点,有人在调试一个客服问答接口。他把 temperature 从 0.7 改到 1.5,重跑了一遍,觉得输出"活"了——回答开始有寒暄、有比喻、有一点点人情味。他又改回 0.1,输出立刻变得干巴巴。于是他做了个决定:把 1.5 写进配置文件,提交,上线。
三周后,客服系统开始答非所问。有人问退货政策,模型开始讲一段关于"信任与承诺"的散文。
这不是模型的错。这是他拧错了一个自己没搞懂的旋钮。
关于 temperature 和 top_p,网上流传的说法大多是"高温度更有创意、低温度更准确"这类半句话。它们不算错,但缺了最关键的一半:这两个参数各自作用在链路的哪一层,以及它们管不到什么。
这篇文章只追一条线:从 softmax 里的除法,一路追到 GPU 的浮点加法顺序,再追到厂商为什么开始把旋钮收回去。读完你至少能回答一个问题——你把 temperature 调高的时候,你到底希望它变什么?
同一个 prompt 问两次,为什么模型给的答案不一样?
先把链路摊开。模型每生成一个 token,内部会算出一个 logits 向量:词表里每个 token 对应一个原始分数,可正可负。分数越高,模型越"倾向"这个词。然后 softmax 把这些分数变成一组和为 1 的概率。
温度干的唯一一件事,就是在 softmax 之前,把所有 logits 除以 T:
就这一行。三个区间,三种命运。
这个"除以温度"不是大模型发明的。它来自统计物理里的玻尔兹曼分布。1985 年,Ackley、Hinton 和 Sejnowski 在玻尔兹曼机论文里就用它控制随机神经元的激活概率,后来在知识蒸馏里被用来把硬标签软化成"软目标"。今天各家 API 里的 temperature,是同一个东西的直系后代。
光看公式容易没感觉,代进去算一遍就清楚了。假设下一个词的候选只有三个:"晴"(logit 5)、"雨"(logit 3)、"鲨鱼"(logit 0)。
| 温度 T | "晴" | "雨" | "鲨鱼" |
|---|---|---|---|
| 0.5 | 98.2% | 1.80% | 0.004% |
| 1.0 | 87.6% | 11.9% | 0.59% |
| 2.0 | 69.0% | 25.4% | 5.66% |
把温度从 1 提到 2,"鲨鱼"的概率从 0.59% 涨到 5.66%——将近十倍。放在一篇八百字的长文里,这意味着模型有机会游进来一条鱼。
但真正值得盯住的,是这张表最右一列在 T=0.5 时的数字:0.004%。它没有变成 0。
这就是下一章的全部理由。
温度能把"鲨鱼"的概率压到万分之一,但压不到零。这是结构性的问题。
词表有多大?小模型几万,大模型十几万。温度是连续地重新分配整个分布的概率,它不会、也没能力把任何一个 token 的概率归零。也就是说,无论你把温度拧到多低,那十几万个荒谬候选始终留在池子里,各自带着一点点概率。
温度一高,麻烦就来了。这些长尾 token 单个看微不足道,合起来却极具分量。
2019 年,Holtzman 等人在论文《The Curious Case of Neural Text Degeneration》里给这个现象起了个名字:unreliable tail,不可靠的长尾。原文写得很直白:
翻译一下:数万个低概率候选,在聚合意义上被过度代表了。论文明确写道,问题出在"用温度参数控制分布形状,却没有充分压制那条不可靠的长尾"。
他们给出的解法就是 top_p,也叫核采样(nucleus sampling)。做法极其朴素:把 token 按概率从高到低排队,从队首开始累加概率,累到超过阈值 p 就停止,只用这一小撮候选重新归一化后采样。
关键词是"最小集合"和"动态"。分布尖锐时——比如模型很确定这里该是"晴"——核里可能只有三五个词;分布平坦时——比如一句话刚开了个"关于"——核会自动膨胀到几百个词。候选池的大小随上下文实时伸缩,这正是它比 top_k 优越的地方。
| 参数 | 它管什么 | 怎么起作用 | 什么时候失灵 |
|---|---|---|---|
| temperature | 分布的形状:陡峭还是平坦 | softmax 之前除以 T | 高温度时压不住长尾 |
| top_p | 候选池的大小(动态) | 按累积概率截断后归一化 | 分布本身已经错时无能为力 |
| top_k | 候选池的大小(固定) | 只取概率最高的 k 个 | 上下文简单时太窄,复杂时太宽 |
top_k 的问题在 2018 年就被 Fan 等人指出过:固定的 k 无法适配不同上下文。k 取小了,文本寡淡重复;k 取大了,不该进来的词被重新归一化之后概率反而被抬高了。这跟高温度压不住长尾,是同一个病根的两张脸。
p_base × p_max,低于它的全部砍掉。好处是判断"什么算低概率"不再依赖绝对数值,而是在高温度下依然稳定。它已被 Hugging Face Transformers、vLLM 等主流框架采纳。先记一条纪律,再看场景表。
这条纪律比任何推荐值都重要,而且五家厂商的官方口径几乎一字不差:
为什么?因为这两个参数改的是同一件事的两面——一个调形状,一个调截断。同时调,等于让两个变量互相掩护:输出变好了你不知道是谁的功劳,变坏了你也不知道该退哪一个。
纪律之后是取值。下面是按场景汇总的工程经验区间:
| 场景 | 温度区间 | 为什么 |
|---|---|---|
| 代码 / 数学 | 0 – 0.2 | 要的是唯一正解,随机性只会引入错误分支 |
| 信息抽取 / 分类 | 0 – 0.3 | 输出需要稳定一致,避免同一批数据两种答案 |
| 事实问答 | 0 – 0.3 | 压低幻觉概率,代价是措辞偏模板化 |
| 翻译 | 0.2 – 0.4 | 既要忠实又要句子自然,需要一点点余地 |
| 通用对话 / 商业文案 | 0.3 – 0.7 | 多数厂商默认值就落在这里 |
| 创意写作 | 0.7 – 1.0 | 需要跳出高频表达,但要守住可读性 |
| 头脑风暴 | 0.8 – 1.2 | 目标是"多而杂",后期再人工筛 |
| self-consistency 多路径投票 | 0.5 – 1.0 | 这里必须有随机性,压到 0 反而退化 |
厂商自己也会给场景表。DeepSeek 官方文档里的建议是:编程与数学 0.0,数据清洗与分析 1.0,通用对话 1.3,翻译 1.3,创意写作与诗歌 1.5。注意它把"通用对话"放在 1.3——比大多数人凭直觉设的 0.7 高不少。这说明推荐值跟模型的训练方式强相关,别人的甜蜜点搬不到你的模型上。
各家默认值也列一下,方便对照:
| 厂商 | temperature 范围 | 默认值 | top_p 默认值 |
|---|---|---|---|
| OpenAI | 0 – 2 | 1 | 1 |
| Anthropic | 0.0 – 1.0 | 1.0 | 1 |
| Google Gemini | 0.0 – 2.0 | 1.0 | 按模型而定 |
| DeepSeek | 0 – 2 | 1.0 | 1 |
| 通义千问 | [0, 2) | 0.7(非思考) 0.6(思考) | 二选一,不叠加 |
最后一条实操建议,比上面所有数字都值钱:做 A/B,别做单发。固定所有其他变量,只改一个参数,同一批 prompt 跑 10 次以上,看的是分布不是个例。单次运行的"感觉好多了",大概率是噪音。
这一章要拆的,是整篇文章里最反常识的一段。
temperature = 0 就是贪心解码:每一步都取概率最大的那个 token。按直觉,同样的输入应该得到同样的输出。但只要你真的跑过,就知道不是。
2025 年 9 月,Thinking Machines Lab 的 Horace He 写了一篇文章,专门拆这件事,标题叫《Defeating Nondeterminism in LLM Inference》。他给出的结论听起来自相矛盾:
他同时也否掉了流传最广的那个解释——"并发 + 浮点误差"这个说法没说到点子上。真正的原因是一个更技术、也更日常的词:缺批不变性(batch invariance)。
说人话:同一行计算,在 batch size 为 1 和 batch size 为 32 时,GPU 会选择不同的分块与归约策略。而浮点加法不满足结合律——
顺序一变,结果的最后几位就不同。这个差异小到绝大多数时候不影响任何东西。问题出在那些"顶一和顶二咬得极紧"的位置上。文章里举的例子非常直观:p("eggs") = 0.500,p("butter") = 0.499。差 0.001。这一次选 eggs,下一次可能翻成 butter。
而自回归生成有个要命的性质:第一个 token 分岔,后面整段文本就走上另一条路。你看到的不是"最后一个词不同",而是"整篇回答不一样"。
更麻烦的是,决定 batch 组成的不是你。同一个 prompt 你在同一秒发两次,服务器当时正在处理的其他请求数量、拼批方式、调度顺序,全都不同。对你来说,那些并发用户不是系统的输入,而是系统的不确定属性。
MoE 架构还要再叠一层:专家路由由门控决定,而门控对数值精度和输入扰动同样敏感。选哪个专家,本身就会因为上面那些微小差异而变。
有人把这件事量化了。2026 年的一篇论文提出了 背景温度(background temperature)的概念,定义为"即使名义上 T=0,由实现相关的扰动过程所诱导出的等效温度"。换句话说:你以为你设的是 T=0,实际上你设的是一个 T 略大于 0 的采样器,这个多出来的部分由服务器当下的负载、kernel 选择和精度策略共同决定。
既然 0 都不保险,工程上还有没有抓手?有,优先级从高到低。
OpenAI 官方对 seed 的措辞很克制:"our system will make a best effort to sample deterministically... Determinism is not guaranteed, and you should refer to the system_fingerprint response parameter to monitor changes in the backend."
best effort,尽力而为。seed 控制的只是"采样那一步的伪随机数",而批组成、kernel 选择、后端的静默更新,它一个都管不到。system_fingerprint 存在的意义,恰恰就是提醒你后端会变。更极端的情况是贪心解码——那时根本没有采样这一步,seed 形同虚设。
如果你的真实需求是"输出一个能解析的 JSON",正确工具是 JSON Schema / 语法约束这类结构化输出能力,不是把温度调到 0。区别在于性质:约束解码是硬约束——不合法的 token 从候选里被直接删掉,永远不可能出现;低温度只是软倾向——概率更集中,但那 0.004% 依然存在。
一句话:想让某个结果"不可能发生",靠调参做不到,靠约束才做得到。
Thinking Machines 把那套 batch-invariant 的 RMSNorm、matmul、attention 实现开源了,SGLang 等框架已经采纳。在批不变的前提下,同一 prompt 在不同 batch 里能得到逐位一致的结果——也只有在这个前提下,seed 才真正有意义。
评估模型时跑一次就下结论,等于用一个样本去推整个分布。做分类、抽取这类"要产出数据"的任务,应该多次采样取多数,或者至少做一致性检查。业界那句提醒很到位:LLM 的输出是来自分布的抽样,不是固定测量值。
反过来说——self-consistency 这类多路径推理方法,正是靠温度产生多条不同思路,再投票聚合。强行把温度压到 0,多路径直接塌缩成一条,这个能力就没了。所以"可复现"不是无条件的正确,它取决于你在做推理还是在做生成。
现在去翻 o 系列、GPT-5、R1 的文档,你会找不到温度推荐值。这不是文档偷懒。
三家厂商的处理方式,代表三种态度。
OpenAI 是直接拿走。官方明确列出:推理模型(o1、o3、o4-mini、GPT-5 系列等)不支持 temperature、top_p、presence_penalty、frequency_penalty、logprobs、top_logprobs、logit_bias。传了也不认。取而代之的是两个语义化旋钮:reasoning_effort(minimal / low / medium / high)和 verbosity。
DeepSeek 是"接受但不执行"。思考模式下,temperature、top_p、presence_penalty、frequency_penalty 均不生效。官方文档的措辞很讲究:"为了兼容已有软件,设置参数不会报错,但也不会生效。"现行 API 中,top_p 只在思考模式生效,而且区间被锁死在 0.95–1.0,低于 0.95 一律按 0.95 处理;非思考模式下固定为 1.0。
Google 是最彻底的。Gemini 3.6 Flash 及以后的模型,temperature、topP、topK 的自定义值"不被支持,设置了会被忽略",官方直接建议从请求里删掉这些参数。
为什么厂商要收回去?两个理由。
一是训练分布。推理模型是在特定采样策略下做强化学习训出来的。你改温度,等于把一个在某个分布上训练好的策略推到了分布外——思考链的质量会掉,严重时陷入无休止的重复。DeepSeek R1 的官方说明把这层因果讲得最清楚:推荐温度设在 0.5–0.7(0.6 最佳),目的是"防止无休止的重复或不连贯的输出"。它的评测设置也是 temperature 0.6 + top_p 0.95。
二是产品定位。厂商希望"想让它思考多深"由 reasoning_effort 这类可解释的旋钮控制,而不是由底层采样参数控制。用户不该需要理解 softmax 才能用好一个模型。
回到开头那个凌晨两点的人。他把温度从 0.7 改到 1.5,觉得模型"活"了。这个观察没错——高温度确实让低概率的表达获得了机会。但他没意识到的是,同一件事也让那十几万个荒谬候选一起获得了机会。
把三句话叠在一起看,整件事就清楚了。
温度改的是概率分布的形状,不改变候选集合。top_p 改的是候选池的大小,而且随上下文动态伸缩。而这两个操作,都只发生在整条链路的一层上。
它们下面一层,是浮点加法的结合顺序、batch 的组成、kernel 的选择,还有你控制不了的并发负载。它们上面一层,是厂商锁死的采样策略——在推理模型里,那一层已经对你关闭了。
所以"调参玄学"这个说法,其实是说反了。不是参数玄,是很多人从来没搞清自己在拧哪一层。
下次改 temperature 的时候,先问自己一句:我是想让它更稳,还是想让它更野?如果答案都是模糊的,那这个参数改多少,结果都只是运气。