第 07 · 生成 · 7 min
选择下一个词
分布算出来了,然后呢?
到目前为止,模型已经知道如何在下一个 Token 上计算一个概率分布。要生成文本,它现在必须选出一个。这就是**采样(sampling)**这一步。
我们已经在第 01 章里瞥见过这个机制。是时候认真地回过头来看了:正是这一步,区分了一个谨慎的模型和一个有创造力的模型,区分了一个可靠的助手和一只重复的鹦鹉。
为什么不总是选概率最高的?
最简单的策略——贪婪解码(greedy decoding)——总是挑选概率最高的 Token。快速、确定、可复现。
然而,它几乎从不被单独使用。为什么?
因为贪婪解码会产生一种奇怪地平淡的文本。它会陷入循环("非常 非常 非常 有趣 有趣 有趣……")。它总是选择最循规蹈矩的词。它能生成技术上正确的句子,但毫无层次。模型是在人类文本上训练的,而人类文本永远包含某种程度的不可预测性——这种不可预测性必须出现在生成中。
由此引出了随机采样(stochastic sampling):我们按照分布随机抽取一个 Token。一个 Token 概率越高,被选中的可能性就越大——但其他 Token 也有机会。
三个杠杆
裸的随机采样会过于嘈杂。我们通常会在抽取之前应用三个过滤器:
温度(Temperature)
温度 T 在 softmax 之前对 logits 做除法。这是最强大的一个调节项。
T = 1.0—— 模型原本输出的分布(参考值)T < 1.0—— 分布变得更尖锐:高的更高,低的更低。模型变得更可预测。T → 0—— 等同于贪婪解码(只剩一个可能的 Token)。T > 1.0—— 分布被压平:低概率的选项重新抬头。模型变得有创造力,甚至古怪。T → ∞—— 均匀分布,模型完全随机抽取。
温度是一个介于可预测性和想象力之间的旋钮。
Top-k
与其允许整个词表(5 万+)的所有 Token,不如保留概率最高的 k 个,把其余的归零,再重新归一化。k = 40 是创造性写作的经典值,k = 1 则退化为贪婪解码。
优点:直接排除掉那些荒谬的 Token(概率 0.0001% 那种),免得它们靠运气被抽中。缺点:最优的 k 值取决于每一步——有时候 5 个候选就够,有时候 100 个都同样合理。
Top-p(核采样,nucleus sampling)
比 top-k 更聪明。我们保留累积概率刚好超过 p 的最小集合,然后重新归一化。
实践中,top-p ≈ 0.9 已经成为现代 LLM 的默认设置。它会自动适应模型的置信度。
再玩一次
我们在第 01 章已经见过这个可视化——这里再放一次,因为正好就是这个话题:
调节 temperature:当 temperature 为 0,模型确定且重复;当为 1.5,模型变得有创意,直至失去连贯。Top-k 与 top-p 修剪掉那些不太可能的候选词,而不影响概率高的候选。
这次,注意观察:
- 在 **Capitale(首都)**这个例子中,模型如此自信(10.0 对下一个的 5.0),以至于需要极高的温度(>1.5)才能让它输出
Paris以外的东西。这是答案已知的提示词的典型情况。 - 在 **Le ciel(天空)**第二步,几个续写在语义上都成立。在
temperature = 1.5下,你可能会得到couleur(颜色)或mer(海)而不是lumière(光)。意思仍然正确,但文本变得不那么可预测。 - 在
top-k = 1时,其他任何设置都失去意义:你已经处于贪婪模式。 - 在 Capitale 提示词上设
top-p = 0.5,只有Paris能存活下来(因为它一个就已经达到 50%)。
一些约定俗成的设置
按使用场景的典型设置:
| 场景 | Temperature | Top-p |
|---|---|---|
| 代码、结构化数据 | 0.0–0.2 | 1.0 |
| 事实性回答 | 0.3–0.5 | 0.9 |
| 通用对话 | 0.7 | 0.9 |
| 头脑风暴、创意写作 | 0.9–1.2 | 0.95 |
| 生成多样化变体 | 1.2–1.5 | 0.95 |
这些不是死规则。但你在大多数使用 LLM 的产品里会看到的就是这个量级。
还有三个值得了解的旋钮
除了温度 / top-k / top-p 之外,在各家 API 里你会反复见到几个参数。
Repetition penalty(在 OpenAI 那边叫 frequency penalty / presence penalty)。对已经出现过的 Token 进行惩罚。在不需要把温度调高的情况下,就能打破重复循环。典型取值:1.05–1.2。
Stop sequences。 一组字符串,一旦它们出现在输出中,就立即停止生成。对于结构化用法来说不可或缺:在格式化的对话里,你会用 <|im_end|> 或 \n\nUser: 来停下,避免模型自己接着替"用户"说话。
Beam search。 不再做随机采样,而是在每一步同时保留k条最优的部分序列,最后挑出整体概率最大的那一条。结果会更"平滑",但通常也更不自然。常用于机器翻译和语音识别,在创意生成中用得很少。
确定性的幻觉
最后一个微妙之处。即使 temperature = 0,对同一个模型的两次调用,在实践中也可能给出不同的结果:
- 量化(Quantization)的非确定性(INT8/FP8 计算存在误差容限)。
- 服务端的动态批处理(取决于其他请求,浮点运算的执行顺序会变化)。
- 模型版本在提供商那边悄无声息地更新。
如果你写的测试依赖 LLM 的精确输出,你会很痛苦。
接下来
到目前为止,你已经知道一个 LLM 是如何:
- 把文本切成 Token,
- 把它们变成向量,
- 通过注意力机制让它们彼此凝视,
- 堆叠 Transformer 块来精炼表示,
- 在下一个 Token 上预测一个分布,
- 用某种采样策略从中抽取一个。
然而,我们所说的"助手"——像 ChatGPT 或 Claude 这样的东西——并不只是这些。一个停在这一步的基础模型只是一个文本补全器,而不是一个助手。怎么从前者变成后者?这就是最后一章的主题:对齐(alignment)。
更新于