今天来聊聊 LLM 的 Temperature:从 logits、softmax 到模型如何选出下一个 Token

今天来聊聊 LLM 的 Temperature:从 logits、softmax 到模型如何选出下一个 Token

很多开发者第一次接触大语言模型的 Temperature 参数时,看到的解释通常都差不多:温度越低,输出越稳定;温度越高,输出越有创造力。

这个结论确实没有问题,但如果只记住这一层的话,在真正做 RAG、Agent 或模型 API 接入时其实不太够。因为很快就会碰到一串更具体的问题:Temperature 到底改了什么?logits 和 softmax 分别是什么?模型为什么会选到概率第二高的 token?既然低概率 token 也有机会被抽中,为什么现在的大模型很少突然输出毫不相关的词?还有一个在 RAG 里经常出现的问题------我们只是在 Prompt 里写了一句"如果不知道就回答不知道",模型为什么真的会说"不知道"?

这些问题看着分散,其实都落在同一条链路上:LLM 每生成一个 token,到底经历了什么。

这篇文章就从这条链路讲起,把 Temperature、采样和幻觉之间的关系串清楚。开始!


从 RAG 里的"不知道"说起

在 RAG 系统中,我们经常会写类似这样的 Prompt:

text 复制代码
请只根据提供的资料回答问题。
如果资料中没有答案,请回答"不知道"。

资料:
Nova 是一个本地 Coding Agent。

问题:
Nova 的作者今年多少岁?

模型很大可能会回复:

text 复制代码
不知道

这里很容易产生一个错觉:模型是不是先检查了一遍资料,然后在内部得出了"我不知道"这个结论?

如果把它写成代码,大概像这样呢:

python 复制代码
if answer_not_found:
    return "不知道"

LLM 内部其实没有一个可靠的 known = trueunknown = true 状态。生成时,它一直在做同一件事:根据当前上下文,预测下一个最合适的 token。

上面的上下文里,模型看到资料没有提供作者年龄,同时 Prompt 明确规定"资料里没有答案就回答不知道"。在这种情况下,"不知道"恰好成为非常合理的一段续写。

模型不会先产生一个"我不知道"的内部结论,再把它翻译成文字。"不知道"本身就是这次生成里概率很高的一段续写。

这也解释了一个实际工程问题:只在 Prompt 里写一句"如果不知道就回答不知道",并不能彻底解决 RAG 幻觉。只要模型认为某个具体答案在当前上下文下同样很合理,它依然可能补出一个并不存在的事实。RAG 里真正可靠的约束,通常还要依赖检索质量、引用证据、相关性判断和结果校验。


一个 token 是怎么被生成出来的

先把整条链路放出来:

text 复制代码
当前上下文
    ↓
模型给词表中的候选 token 打分
    ↓
logits
    ↓
Temperature 调整 logits
    ↓
softmax 转成概率
    ↓
top-p / top-k 等策略筛选候选
    ↓
sampling(随机抽样)
    ↓
选出一个 token
    ↓
把 token 接回上下文
    ↓
继续预测下一个 token

模型生成回答时,会先选出一个 token,把它接回上下文,再根据新的上下文继续预测下一个 token。几百上千个 token 的回答,就是这个循环不断重复。


Logits:模型先给所有候选 token 打一遍分

假设当前输入是:

text 复制代码
中国的首都是

模型会根据前面的上下文,对词表里的所有 token 计算一个原始分数。为了方便理解,假设几个候选 token 的分数是:

text 复制代码
北京    8
上海    4
南京    3
东京    1

这里的 8、4、3、1 就可以理解为 logits。

Logits 不是概率。

北京 = 8 不代表北京有 80% 的概率,上海 = 4 也不代表上海有 40% 的概率。它们只表达一个相对关系:在当前上下文下,模型认为"北京"比"上海"更适合作为下一个 token。

真实模型处理的候选当然远不止几个。词表通常包含几万甚至十几万个 token,模型每生成一步,都要为这些候选计算 logits。

所以 logits 这件事可以先简单记成:

Logits 是模型对所有候选 token 给出的原始评分。

这个分数越高,说明该 token 越符合当前上下文。


Softmax:把原始分数变成概率

有了 logits 之后,还不能直接进行概率采样,因为 logits 本身不是概率。

这时就需要 softmax。

继续使用刚才的例子:

text 复制代码
北京    8
上海    4
南京    3
东京    1

经过 softmax 之后,它们会被转换成一组总和为 100% 的概率,例如:

text 复制代码
北京    97%
上海     2%
南京     1%
东京   接近 0%

softmax 的形式可以写成:

text 复制代码
P(token_i) = exp(logit_i) / Σ exp(logit)

如果只是做 LLM 应用开发,没有必要把这个公式背下来。真正需要理解的是它在做什么:

text 复制代码
logits
= 原始分数

softmax
= 把原始分数转换成概率分布

而 Temperature,恰好插在这两步之间。


Temperature:它改的是 logits 之间的差距

常见的处理形式是:

text 复制代码
softmax(logits / T)

其中 T 就是 Temperature。

假设模型原始 logits 是:

text 复制代码
北京    8
上海    4
南京    3

如果设置:

text 复制代码
T = 0.5

那么进入 softmax 之前,相当于变成:

text 复制代码
北京    16
上海     8
南京     6

原来北京和上海差 4 分,现在差 8 分。高分 token 的优势被进一步放大,最后得到的概率分布会更集中。

这就是所谓的"低温更稳定"。

反过来,如果:

text 复制代码
T = 2

则变成:

text 复制代码
北京    4
上海    2
南京    1.5

候选 token 之间的差距被压缩了。经过 softmax 后,原来排名靠后的候选也会拿到更多概率。

Temperature 做的事情很具体:改变 logits 之间的相对差距,从而改变最终概率分布的尖锐程度。 "更有创造力"或者"更稳定"只是这个变化最终表现出来的效果。

可以把它概括为:

text 复制代码
低 Temperature
→ 高分 token 优势被放大
→ 概率更集中
→ 输出更稳定

高 Temperature
→ 候选之间差距被压小
→ 次优 token 获得更多概率
→ 输出变化更多

By the way,需要补充一个细节:有些 API 允许 temperature = 0。数学上当然不能直接做 logits / 0,所以这通常是服务端的特殊处理,效果接近于尽量选择最高概率 token,也就是常说的 Greedy Decoding(贪婪解码)。


高温度为什么会更容易选到"第二名"

这一点很多人容易理解错,我们往下看。

假设模型最终得到:

text 复制代码
北京    80%
上海    10%
南京     6%
杭州     4%

有些人会把它理解成一个排行榜:

text 复制代码
第一名:北京
第二名:上海
第三名:南京

然后觉得模型应该永远选第一名,这是不对的。

采样不会保证每次都拿第一名,系统会按照这组概率抽取一次,也就是随机采样

为了直观一点,我们可以把上面的概率想象成 100 张票:

text 复制代码
北京    80 张
上海    10 张
南京     6 张
杭州     4 张

每次生成就在里面抽一张。尽管北京是最容易被抽到的,但其他 token 依然有机会。

如果把 Temperature 调高,概率分布可能会变成:

text 复制代码
北京    54%
上海    19%
南京    15%
杭州    12%

排名依然没有变:

text 复制代码
北京 > 上海 > 南京 > 杭州

北京还是第一名,上海还是第二名。

变化在于,北京从 80% 降到了 54%,后面几个候选合起来已经有接近一半的概率。

所以高温更容易选到第二、第三候选,原因很直接:这些 token 在采样池里的权重变大了。候选的相对排序通常没变,变的是每个候选最终拿到的概率。


那低概率的错误 token 为什么很少被抽中

如果模型是按概率采样,那么只要一个 token 的概率不是 0,它理论上就有机会被选中。比如:

text 复制代码
这个方案非常......

合理    50%
不错    20%
优秀    10%
有趣     8%
离谱     5%

如果"离谱"真的有 5%,那多生成几次,迟早会抽到。

问题是,现实里的不相关 token 通常根本没有这么高的概率。

上面的数字只是为了方便解释采样。真正训练得比较好的大模型,面对正常上下文时,概率分布往往更加接近:

text 复制代码
合理       30%
可靠       18%
不错       12%
成熟        8%
......

离谱      0.00000...%
香蕉      0.00000...%
东京      0.00000...%

这些完全不相关的 token,通常早就在模型训练阶段被压到了非常低的位置。

预训练做了什么

预训练阶段,模型反复做的事情其实非常朴素:

text 复制代码
给一段前文
    ↓
预测下一个 token
    ↓
和真实文本比较
    ↓
预测错了就调整参数
    ↓
继续下一次

这个过程进行到足够大的规模以后,模型就学到了大量语言、知识和代码模式。

看到:

text 复制代码
中国的首都是

"北京"的 logit 会很高,而"香蕉""TypeScript""星期三"这类 token 的 logit 会低很多。

现代 LLM 很少突然蹦出完全无关的词,主要原因就在采样之前:训练已经让这类 token 的 logits 低得多,最终概率通常接近于零。

"概率大于 0"也不意味着现实里经常发生。

5%0.000000000001% 都不是 0,但两者在实际体验上完全不是一回事。


后训练还会继续塑造这种概率分布

现代聊天模型通常也不只做预训练。

预训练之后,还会有指令微调、偏好优化、强化学习等后训练过程。不同厂商的具体方案不完全一样,但它们有一个共同效果:继续调整模型在某些上下文下倾向输出什么。

比如用户问:

text 复制代码
解释一下 React useEffect

一个经过良好后训练的助手模型,会更倾向于:

  • 直接回答当前问题;
  • 保持上下文一致;
  • 遵循用户要求的格式;
  • 减少明显无关的内容;
  • 在特定情况下拒绝或说明不确定性。

从生成机制上看,这些行为最终仍然会落实到概率分布里:某些 token 的 logits 被提高,另一些 token 的 logits 被压低。

所以"这个模型很会聊天"并不意味着外面套了无数个 if/else。很多看起来像行为规则的东西,最终仍然会反映在 token 的条件概率上。


Top-p 和 Top-k:很多尾部 token 连候选池都进不去

即使模型已经把不相关 token 的概率压得很低,实际推理系统通常还会再做一层筛选。

最常见的就是 top-p 和 top-k。

Top-p

假设当前概率分布是:

text 复制代码
合理    40%
不错    25%
可靠    15%
优秀     8%
成熟     5%
......
香蕉    0.000001%

如果:

text 复制代码
top_p = 0.9

系统会从概率最高的 token 开始依次加入候选池,直到累计概率达到大约 90%。

后面那一长串尾部 token 这次就不再参与采样。

到了这一步,尾部 token 甚至不会进入最终抽样集合。

Top-k

top-k 更直接。

比如:

text 复制代码
top_k = 50

那就只保留概率最高的 50 个 token。

剩下的 token 直接被排除。

所以实际生成过程通常可以理解成:

text 复制代码
几万 / 十几万个 token
        ↓
模型计算 logits
        ↓
Temperature 调整 logits
        ↓
softmax 生成概率
        ↓
top-p / top-k 等策略裁剪尾部
        ↓
在保留下来的候选中进行 sampling

不同模型和不同推理服务的实现细节会有差异,有些服务甚至不会把完整的采样参数暴露给开发者。但从应用开发的角度看,这条思路足够解释大多数现象。


为什么模型不太会"胡言乱语",却仍然会出现幻觉

现代大模型已经很少出现这种错误:

text 复制代码
React 的 useEffect 香蕉 东京 public 哈哈哈

这种文本在语法和语义上都明显断裂。

但它仍然会出现另一类错误:

text 复制代码
某个框架在 v3.2 版本加入了 X 功能。

这句话可能写得非常自然,术语也都对,甚至看起来很像官方文档。

问题只是:v3.2 根本没有这个功能。

为什么?

因为从 token 预测的角度看:

text 复制代码
某个框架
在
v3.2
版本
加入了
X 功能

这些 token 组合在技术文本里完全成立。

模型擅长的是判断:

在当前上下文里,什么样的文本最像一个合理回答?

但它并没有天然拥有一个外部事实数据库,能在每个 token 生成前都验证:

这句话描述的事情在真实世界里到底发生过没有?

这就是语言连贯性和事实真实性之间的差别。

模型可以非常流畅地说错。

而且越强的模型,有时错得越"像真的",因为它组织语言和领域表达的能力本身很强。

所以 RAG、搜索、数据库查询、工具调用、引用证据和结果验证一直很重要。模型负责生成一个看起来合理的回答,外部信息和验证机制负责尽量保证这个回答有事实依据。


Temperature = 0.7 为什么经常被当成默认值

0.7 经常出现在教程、SDK 示例和早期聊天应用中,因此慢慢形成了"比较通用"的印象。

但它不是行业标准,也不存在什么数学结论证明 0.7 是最优点。

它更像一个历史上的经验值。

低温通常会让输出更集中,适合:

text 复制代码
代码修改
结构化输出
严格 RAG 问答
信息抽取
工具参数生成

高一点的温度则更适合:

text 复制代码
创意写作
文案构思
方案脑暴
需要多样性的生成任务

如果是在做真正的产品,最稳妥的方法还是拿自己的任务集跑评测。

例如准备 100 个真实任务,分别测试:

text 复制代码
T = 0.1
T = 0.3
T = 0.7
T = 1.0

然后观察:

text 复制代码
任务成功率
格式正确率
事实错误率
工具调用成功率
代码测试通过率
输出多样性

最后哪个值在你的任务里表现最好,就用哪个。

Temperature 没有脱离任务场景的"最佳值"。


Temperature 为什么只是一个比较粗的控制参数

即使模型 API 允许我们设置 Temperature,它也有一个天然限制:它通常对整次生成统一生效。

比如一个 Coding Agent 在完成任务时,可能先分析代码,再想方案,然后修改文件,最后检查测试结果。

这些阶段需要的生成风格其实不一样。

分析报错时,希望它稳。

写精确代码时,希望它稳。

脑暴方案时,又希望它有一点发散。

但如果整次请求设置:

text 复制代码
temperature = 0.7

那基本意味着:

text 复制代码
第 1 个 token     T = 0.7
第 2 个 token     T = 0.7
第 3 个 token     T = 0.7
......
第 2000 个 token  T = 0.7

Temperature 本身不会理解:

text 复制代码
"现在这一步在写关键代码,应该收一点。"

"现在到了方案阶段,可以多探索几个方向。"

它只是统一调整概率分布。

所以到了复杂 Agent 里,Temperature 只能解释很小一部分行为。

一个 Coding Agent 最终能不能把任务做完,更多取决于:

  • 上下文有没有给对;
  • 工具有没有设计好;
  • 模型能不能拿到真实执行结果;
  • 出错后有没有重试或 replan;
  • 测试有没有真的跑;
  • 完成条件有没有明确检查;
  • 长任务中信息有没有被正确保留。

Temperature 会影响输出,但对一个真正跑任务的 Agent 来说,它只是很多变量中的一个。


最后再看一次生成链路

把前面的内容合在一起,模型生成一个 token 时大致会经过这几步:

text 复制代码
用户输入 + 当前上下文
        ↓
       LLM
        ↓
为词表中的候选 token 计算 logits
        ↓
Temperature 调整分数差距
        ↓
softmax 得到概率分布
        ↓
top-p / top-k 等策略裁剪候选
        ↓
      sampling
        ↓
选出一个 token
        ↓
追加回上下文,继续下一轮

理解这条链路之后,Temperature 就没那么神秘了。它控制的是解码阶段概率分布有多集中,能影响输出的稳定性和多样性,但它解释不了模型能力本身,更替代不了 RAG、工具调用、测试和验证这些工程机制。

如果你在做普通的模型 API 接入,知道它如何影响采样已经够用;如果你在做 Coding Agent,更值得花时间调的通常是上下文、工具、执行流程和完成条件。

相关推荐
不一样的少年_1 小时前
不用LangChain:用 200 行代码手搓 Agent 对话记忆与上下文压缩
人工智能·agent·ai编程
LaughingZhu1 小时前
Product Hunt 每日热榜 | 2026-08-09
人工智能·深度学习·神经网络·搜索引擎·百度
狂师1 小时前
推荐一款开源 Skill:让 AI Agent 给你做一份"能改"的 PPT,支持 上千套模板!
人工智能·agent
阿图灵1 小时前
基于 LSTM 的中文电商评论情感分类:从数据处理到 91% 准确率实战
人工智能·深度学习·分类·nlp·lstm·情感分类
用户298698530141 小时前
HTML 转 Word 指南:新手入门教程
人工智能·后端·python
冬哥聊AI1 小时前
淘天一面:Prefix Caching 原理是什么?Agent 框架怎么保证不破坏缓存?
人工智能
agent8971 小时前
实战升级|SpringBoot WebSocket实现多轮对话AI流式问答(上下文记忆+自动重连+会话隔离)
人工智能·spring boot·websocket
染指11101 小时前
80.高级RAG-LLamaIndex实际应用-金融助手
人工智能·rag·llama_index·llamaindex
Clipp_Huang1 小时前
光学跟踪系统标定
人工智能·计算机视觉·重构·机器视觉