惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

MyScale Blog
MyScale Blog
Microsoft Azure Blog
Microsoft Azure Blog
H
Help Net Security
N
News and Events Feed by Topic
Recent Announcements
Recent Announcements
D
Docker
M
MIT News - Artificial intelligence
L
LangChain Blog
I
InfoQ
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
P
Proofpoint News Feed
博客园_首页
MongoDB | Blog
MongoDB | Blog
美团技术团队
S
Schneier on Security
G
GRAHAM CLULEY
月光博客
月光博客
有赞技术团队
有赞技术团队
Vercel News
Vercel News
Scott Helme
Scott Helme
P
Privacy International News Feed
Last Week in AI
Last Week in AI
Recorded Future
Recorded Future
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
The Cloudflare Blog
Attack and Defense Labs
Attack and Defense Labs
Google Online Security Blog
Google Online Security Blog
Simon Willison's Weblog
Simon Willison's Weblog
量子位
S
Security @ Cisco Blogs
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
V
Visual Studio Blog
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
NISL@THU
NISL@THU
N
Netflix TechBlog - Medium
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
Recent Commits to openclaw:main
Recent Commits to openclaw:main
Spread Privacy
Spread Privacy
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
小众软件
小众软件
罗磊的独立博客
Security Archives - TechRepublic
Security Archives - TechRepublic
T
Threatpost
L
Lohrmann on Cybersecurity
www.infosecurity-magazine.com
www.infosecurity-magazine.com
S
Security Affairs
Cloudbric
Cloudbric
爱范儿
爱范儿
H
Heimdal Security Blog
PCI Perspectives
PCI Perspectives

Surmon.me

一人有限集团 你就是不敢 人类正在退出人类 AI 代替不了这样的你 脉冲点火背后的架构设计 基于 Cloudflare 生态的 AI Agent 实现 NodePress 支持用户登录了 从统计学习到通用智能 2025 投资报告:走慢的路 无依之地 会杀人的菩萨 无我不是共识 文化的积重与偏见 当下即安 科学的尽头是态度 无我不是 Egoless 信仰不因恐惧而存在 世间无解的矛与盾 先别急着做些什么 佛不需要你的皈依 真理的幻觉 两扇大门 造心里的浮屠 自胜者强 逻辑与智慧 真的相 快乐的秘密 只需愿意 是名体验 最深沉的梦 森林里倒下的树 现象与相 庸人自扰 React 与 Vue 的完美融合 开心就好吗 与原生家庭和解 两支毒箭 怎么自净其意 一尘不染 一片白云 让风穿膛而过 喝下去,然后闭嘴 活在当下 当纠结发生时 唯「我」独尊 一场把戏(时间) 一场把戏(二元对立) “我” 和 “我” 谁是众生? 船里没有人 玫瑰不需要说话 没有人能渡任何人 你我为轮,使之不再 当我们在谈论独立时 自我约束就是最好的自我接纳 从善与恶的表象出发 佛法不是心理学 别人眼中的你并不是你 高高山上走 祝你心想事成 祝你的噩梦早日发生 道是无情却有情 裙子只为自己而穿 不要盲目地评估自己 先别急着 “爱自己” 让生命欣然舞动 你无法复制乔布斯 符号不是目的 如果一件事发生了 每当我起心动念时 爱出者爱返 理解不是尊重的基础 在没有解决自己的问题之前 “知足常乐” 不是比较 逻辑是无法成为信仰的 买不到的自由 成为诵经者 伤口听不懂大道理 是立场让你不自由 - Unfreedom 天雨大不润无根之草 做自己的神 当心诱惑本身 牛洞冥思录 修罗启示录 让大脑自举 我更喜欢叫它无梦寺 存在主义也许不是解药 出南洋记 2022 的所有答复 没意义的表达 思考的记录 故宫暂行之幻想 极端的比较 解构的终极 舍利子是如何炼成的 心要野 佛教的偏见 文艺青年 我是动物 知行合一
创造力是温柔的谎言
Surmon · 2026-03-30 · via Surmon.me

创造力是温柔的谎言精选

调用大模型的时候,总会看到几个耳熟能详的参数:Temperature、Top-p、Top-k。文档里通常的解释都是:控制输出的随机性。也就是:Temperature 和 Top-p 的值越高,模型输出的结果会越随机、越富有创造性,反之,数值越低,输出的结果就越确定、越保守。

随机性,到底是个什么意思?为啥随机性就可以表现为创造性?

回答这个问题,得先从一个最朴素的问题开始:模型是如何回答问题的。


我之前在 《从统计学习到通用智能》 中曾经提到过,大模型在输出文本的时候,本质上是在 滚动地预测下一个最有可能出现的词

而预测机制大概可以拆分为三个具体的逻辑步骤:生成分数 → 转换概率 → 加权采样。

模型的打分机制

模型在回答问题时,并不是一次性把整句话想好再说出来,而是一个词元一个词元地往外蹦,每次输出一个词元(Token)之前,它都会把目前为止的所有内容(包括输入的问题和已经输出的部分回答)重新扫一遍,然后给词汇表(Vocabulary)里的每一个词元打一个分 —— 这个分在技术上叫 Logit

由于目前一些技术名词已经有了 正式的中文命名 ,下文中就用「词元」来代替 Token,用「词汇表」来代替 Vocabulary。

比如,假设用户问:博主写过哪些关于前端的文章?

模型收到这个问题之后,会把它认识的所有词元全部扫一遍,然后给每个词元打分。

这个打分过程本身很复杂,是整个 Transformer 架构的核心。

简单说的话:模型把当前所有输入按照词元切分,经过层层注意力计算(Attention)让每个词元都「读懂」上下文,最后通过矩阵乘法得到每个词元的分数,相关程度越高,打分越高。 类似于之前提到过的 向量嵌入中的相似度搜索 ,只是这里要打的不是语义相似度,而是「在当前上下文里出现的可能性」。

不过,具体怎么算,是 Transformer 内部的事。作为调用方,只需要知道:词汇表里的每一个词元,都会有一个对应的分数。 类似这样:

词元(Token) 分数(Logit)
TypeScript 3.1
React 3.0
Vue 2.8
禅修 0.24
摩托车 0.1
... ...

即便是一些完全不相关的词元,比如「摩托车」和「禅修」,它们也有分,只是分很低。

分数转换为概率

分打完了,下一步模型的任务就是从这些词元中选一个最合适的去输出。

最直接的想法是:直接挑分值最高的那个不就行了吗?

在技术上,这完全可行,甚至这种策略也有个名字,叫 Greedy Decoding (贪心解码)。也就是每一步中,模型都会选择分值最高(匹配度最高)的词元,永远追求局部最优解,而不考虑整体的输出效果。

但贪心解码有一个明显的问题:同样的问题,永远只会得到同样的答案。

还是刚才的例子,用户问:博主写过哪些关于前端的文章?

模型会永远输出:博主,写,过,关于,TypeScript,的,文章。

永远是 TypeScript,不会是 React,哪怕分数只是差了 0.1。

这样生成的文字陷入一种机械的重复感,AI 更像是在复读,而不是思考。就像我们用手机输入法一直点第一个「建议词」,最后打出来的一直就是那几句车轱辘话一样。

为了解决这个问题,有人提出了 Beam Search (束搜索)。它的思路是:不只盯着分值最高的那条分支走到黑,而是走每一步的同时,保留分值最高的 k 条候选路径,最后选整体概率最高的那条。

还是前面的例子,假设 k=2,在挑选「关于」之后的词元的时候,会同时保留「TypeScript」和「React」两条路;接下来在每条路的基础上继续延伸,再各自保留最优的两个分支,以此类推。最终从所有走完的路径里,挑出整体概率最高的那条作为输出。

Beam Search 确实比贪心解码更「聪明」一点,它不会因为某一步的局部最优而错过更好的整体结果。但它也有自己的问题:输出往往过于保守,容易陷入重复,而且计算成本随 k 值的增大显著上升。

这里其实还有个更根本的问题是:人类的自然语言本来就不遵循「整体概率最高」的规律。许多直击心灵的好句子,往往都不是文字逻辑上的「最优解」,所谓的「人味」也就是从这里来的。

所以实际上,这两种确定性策略都只会在特定的、需要稳定性和可预测性的场景使用(比如搜索)。而在需要「创造性」的场景中,模型并不会只盯着分值最高的「第一名」,而是需要给每个词元一个「被选中的机会」,分越高机会越大,分越低机会越小,但不能直接为零。

要做到这一点,就需要先把分数转换成概率。这里用到的是一个叫 Softmax 的函数,这个函数说来也简单,就是 把所有词元的分数归一化,让它们加起来等于 100%。

这里不能直接用 Logit 分数来表示这个「机会」,因为 Logit 是原始分数,它可以是任意数值,没有上下界,无法直接用来做概率采样。

还是以上面的例子为例(假设词汇表里只有这几个词元),把各自的分数代入 Softmax,算出来的概率大致是:

词元(Token) 分数(Logit) Softmax 计算 概率
TypeScript 3.1 22.20 / 61.10 36.3%
React 3.0 20.09 / 61.10 32.9%
Vue 2.8 16.44 / 61.10 26.9%
禅修 0.24 1.27 / 61.10 2.1%
摩托车 0.1 1.11 / 61.10 1.8%

可以看到,三个「前端」有关的词元,它们的概率加起来已经超过了 96%,「禅修」和「摩托车」加在一起连 4% 都不到。分高的词概率高,分低的词概率低,但 只要概率不是零,就永远有被选中的可能

而整个公式的计算过程,如果用 JavaScript 来实现的话,大概是这样的:

        
        

123456789101112131415

// 由模型打分得出的原始分数(Logit) const logits = [3.1, 3.0, 2.8, 0.24, 0.1]; // 这里对每个 Logit 取自然指数 e^z(Math.E 是自然常数,约等于 2.718) const exps = logits.map((z) => Math.exp(z)); // [22.20, 20.09, 16.44, 1.27, 1.11] // 把所有指数加起来,得到分母(归一化常数) const sum = exps.reduce((acc, val) => acc + val, 0); // 61.10 // 每个指数除以分母,得到概率 const probs = exps.map((exp) => exp / sum); // [0.363, 0.329, 0.269, 0.021, 0.018] // [36.3%, 32.9%, 26.9%, 2.1%, 1.8%]

基于概率的随机采样

现在概率有了,模型去「随机抽」就简单多了。

可以把它想象成,在一条数轴上按概率分配区间,每个词元按照自身的概率作为比例来占据数轴的一部分。然后生成一个 0 到 100 的随机数,落在哪个区间就选哪个词元。这样每个词元被选中的概率,刚好就等于它的概率数值。

输出完这个词元,再把它加进输入,重新打分,重新算概率,重新抽…… 如此往复,直到输出一个代表「我说完了」的终止符。

这就是大模型「说话」的全过程,没有计划,没有草稿,每一步都只是在问自己:接下来最可能出现的词元是什么?

而这个「随机抽」的过程,有一个专业的名字,叫随机采样(Random Sampling)。按照这种随机的模式来输出,内容就有了新鲜感,也就是「人味」。

但随机采样本身还有问题:到底随机到啥程度?业务决定还是模型决定? 这就引出了文章一开始提到的三个参数:Temperature、Top-p、Top-k。

概率差距(Temperature)

Temperature 就是「温度」,通过调低或调高这个 T,就可以让词元的概率分布变得更「尖锐」或者更「平滑」。

它的原理是:在 Softmax 计算概率之前,给原来公式里的分子和分母分别都除以这个 T,从而改变每个词元之间的概率差距。

也就是公式变成了 e^(zi/T) / Σ e^(zj/T)

  • T 越小,差距越大,高分词元的优势被放大。
  • T 越大,差距越小,所有词元的机会趋于均等。

这一步看起来微不足道,但带来的效果非常剧烈。

T 调低(比如 T=0.1)时,每个词元的分数都会先除以 0.1,也就是放大 10 倍。原本 TypeScript 和 React 只差了 0.1 分,放大后差距变成 1 分。而 Softmax 里有指数运算,线性的差距在指数面前会被疯狂放大。

最终算出来的概率,TypeScript 从原来的 36.3% 暴涨到约 70.5%,React 从 32.9% 跌到 25.9%,Vue 只剩 3.5%,「禅修」和「摩托车」基本接近于零。

词元(Token) 分数(Logit) T=1.0 概率 T=0.1 概率
TypeScript 3.1 36.3% 70.5%
React 3.0 32.9% 25.9%
Vue 2.8 26.9% 3.5%
禅修 0.24 2.1% ≈0%
摩托车 0.1 1.8% ≈0%

这就形成了一个类似「赢家通吃」的局面:模型几乎每次都只会选 TypeScript,输出变得稳定、确定,同时也很死板。

T 调高(比如 T=2.0)时,每个词元的分数都除以 2,差距被压缩了一半。原本悬殊的差距被抹平,第一名的优势也变得不再明显。

词元(Token) 分数(Logit) T=1.0 概率 T=2.0 概率
TypeScript 3.1 36.3% 30.5%
React 3.0 32.9% 29.1%
Vue 2.8 26.9% 26.3%
禅修 0.24 2.1% 7.3%
摩托车 0.1 1.8% 6.8%

最终算出来的概率里,连「摩托车」这种完全不相关的词元,都有了相当的概率(6.8%)被选中。输出变得多样,有时候冒出意想不到的词,但也有时候像在胡说八道。

Temperature 这名字也起得很应景。

  • 低温让分子运动减缓,结构稳固且确定(冷静理智)。
  • 高温让分子剧烈活动,不可预测且随机(热情奔放)。

老外也是懂意象的。

候选排除(Top-k / Top-p)

Temperature 解决了「概率差距」的问题,但还有另一个隐患没有处理。

词汇表里有几万到几十万甚至更多数量的词元,头部那几个词元的概率加起来可能已经到了 95%,但剩下那 5% 被稀释在了几十万个词元上。每个词元的概率都极低,但数量非常庞大。只要运气够好(或者模型够傻),那些完全不相关的词元,也有机会被随机采样选中。

于是,就可能会出现这样的句子:「他打开门,发现里面有一台正在呼吸的电视机」。你可能也会觉得:哎,不错,有点东西。

但更多时候,它是这样的:你还是问「博主写过哪些前端相关的文章」,结果它回答「摩托车脉冲点火的架构与设计」。

这就称不上是创意了,这算事故,P0 级别的。

Top-kTop-p 本质上是介于贪心解码和完全随机采样之间的方法。它既不像贪心解码那样只认第一名,也不像完全随机采样那样对所有词元一视同仁,它负责的是:在采样之前,把诸如「摩托车」、「禅修」、「股票」这类上下文无关的「长尾垃圾词」排除掉。

Top-k 的逻辑直接粗暴:只保留分数最高的前 k 个词元,其余的全部丢弃,概率直接归零。 k=10,就只从前十名里选。k=1,就退回到了贪心解码。

还是用刚才的例子:如果设置 Top-k=3,那么保留的就是 TypeScript(36.3%)、React(32.9%)、Vue(26.9%)这三个词元,「禅修」和「摩托车」就直接被丢弃了,然后把这三个词元的概率重新归一化,让它们加起来重新等于 100%,再进行采样。

词元 原始概率 Top-k=3 后(归一化)
TypeScript 36.3% 37.8%
React 32.9% 34.2%
Vue 26.9% 28.0%
禅修 2.1% ✕ 丢弃
摩托车 1.8% ✕ 丢弃

Top-p 的全称是 Top Cumulative Probability,也叫核采样(Nucleus Sampling)。它的逻辑动态一些:从概率最高的词元开始往下累加概率,累加到超过阈值 p 就停,剩下的全部丢弃。 p=0.9,就意味着只保留累计概率能覆盖 90% 的那些词元,不管这个集合里有几个词元。

同样的例子:TypeScript 36.3%,加上 React 32.9%,已经到了 69.2%;再加上 Vue 26.9%,累计概率达到 96.1%,超过了 0.9 的阈值,停止。「禅修」和「摩托车」两个词元被排除。而如果把 p 设为 0.6,那只需要 TypeScript(36.3%)加上 React(32.9%)累计到 69.2% 就够了,Vue 也不要了。

词元 原始概率 累计概率 Top-p=0.9 后(归一化)
TypeScript 36.3% ↓ 36.3% 37.8%
React 32.9% ↓ 69.2% 34.2%
Vue 26.9% ✓ 96.1% 28.0%
禅修 2.1% ✕ 丢弃
摩托车 1.8% ✕ 丢弃

这两个参数解决的是同一个问题,但角度不同:Top-k 固定候选词元的数量,Top-p 固定候选词元的概率密度。 当概率分布比较平坦时,Top-p 会自动多保留几个候选;分布集中时,又会自动收窄。相比之下,Top-k 的 k 值选多少很难提前确定,对不同的输入,同一个 k 值的效果可能差异很大。

这也是为什么两者经常叠用:先用 Top-k 砍掉数量上的长尾,再用 Top-p 按密度做二次收束。 如果几个参数同时启用,执行顺序就会是:Top-k → Top-p → Temperature。

为了便于直观感受,我用 Claude 生成了一个 DEMO,可以在下面测试效果或者 新窗口打开

创造力的调节指南

现在 Temperature、Top-k、Top-p 这三个参数的含义已经很清楚了,懂了原理也得落地。

参考 OpenAI 的官方建议,一般的实践原则是:

  1. Temperature 和 Top-p 只调其中一个。
  2. 优先调 Temperature。
  3. 推理模型尽量不要调这些参数(不需要)。

但如果你对模型的极限也充满了好奇,想要更加「精准地胡造」,不妨试试这些简单粗暴的配置思路:

确定性任务(代码生成、事实问答、数据提取)

Temperature 调到极低(0.1 甚至更低),Top-p 设为 1.0,Top-k 设为 1。输出会非常稳定、保守,几乎每次都选概率最高的词。

平衡场景(日常对话、内容摘要、普通写作)

Temperature 保持在 0.7 ~ 1.0,Top-p 设为 0.9,Top-k 设为 40 ~ 60。在确定性和多样性之间保持一个平衡,回答自然又带有变化,出错的概率也比较低。这也是大多数模型的默认配置区间,也是 NodePress AI 摘要能力的 默认配置

创造性任务(故事生成、头脑风暴、诗歌、营销文案)

Temperature 拉到 1.2 ~ 1.5,Top-p 设为 0.95,Top-k 设为 80 ~ 100。输出会更大胆、更容易跳出常规逻辑,但也更容易跑题或胡说八道,需要多筛一轮。

极度随机(游戏 NPC 对话、艺术实验)

Temperature 超过 1.5,Top-p 和 Top-k 全部放开。每个词的概率被拉得几乎均等,输出天马行空,狂荡不羁。这种配置下,大部分结果可能没有意义,靠的是多次尝试里偶尔出现的惊喜。

温柔的谎言

总的来说,我们每一次调高 Temperature 的「温度」,或者拓宽 Top-p 的阈值,都是在告诉模型:允许你适当地「胡编」,允许你更大胆一些。它本质上是希望模型 在「合理」的范围内,制造适当的意外。

这通常被称作:增加创造力

而人对「创造力」的感知,大部分时候就是来自于这份「意外」。比如那首广为人知的:灯,把黑夜烫了一个洞。

换句话说,AI 的「创造」来源,并不是无聊的 Top1,也不是荒谬的长尾词,而是概率分布的「边缘」采样。甚至也可以认为:AI 不是在「创造」,它只是在不断地「故意没选最优解」。

但如果认真去追问「创造力」这个词。

如果「创造力」的定义是:包含了情感温度、联想幻想、故事体验、独一无二的这个过程的话,那模型从未实现过创造。 它永远只是在概率的公式里随机跳跃,而且还是伪随机。

它有结果,但没有真正意义上的创造过程。 它不知道自己为什么选了这个词,也没有「选」的意志,只是概率落点恰好在这里。

不过,大部分时候,人们要的本来就不是「真正的创造力」,而是「创造力所带来的结果」。 一段看起来有爆点的文案、一个「别出心裁」的转场,或者墙上挂的那副 AI 画出来的壁画…… 这些需求,机器确实可以满足。

倒是有个更严重的问题是:比起 AI 有多大「创造力」,人们似乎逐渐习惯了把这种统计意义上的受控偏离,误读成了某种有意识的灵感涌现

这种人类的自我投射,和机器毫无关系。

(完)