一次一个 token
条件概率分解
大模型生成文本的方式是:一次一个 token,每一个 token 的选择都以前面所有 token 为条件。
这是它的本质属性。每生成一个词,模型都在问"前面已经写了这些内容,接下来哪个词最合理?"。它为词表中的每一个候选词计算概率,从中选取一个。选完之后,这个词又变成条件的一部分,影响下一个词的选择。整个文本就是这样一个词一个词地"长"出来的。
这有两个关键含义。
生成是序列性的。 早期 token 的选择会约束后续所有 token 的概率分布。一旦第一句话走上了某个方向,后续的生成就被"锁定"在与这个方向一致的路径上。开头的一个小差异,经过足够多步之后,可能让输出彻底跑偏。
生成是局部的。 模型在每一步只决定下一个 token,没有全局规划能力。如果最终输出呈现出连贯的结构,那是因为训练数据中的统计规律让"连贯的结构"本身就是高概率的 token 序列。
模型本身输出的是概率分布。从分布到具体 token 的转换,是采样策略决定的。同一个概率分布,在 temperature=0(贪心解码,直接取概率最高的 token)和 temperature=1.0(按原始概率采样)下,可能产生完全不同的 token 序列。采样策略应该在系统设计时就定下来:结构化数据提取需要低 temperature,创意写作需要较高 temperature,代码生成取中等偏低。对所有任务都用同一套策略,就像厨师做任何菜都用同样的火候。
从机制到工程影响
自回归生成的训练方式说白了就是:给模型看大量文本,反复练习"猜下一个词"。这个事实有具体的工程影响。
大模型会"编造"。 当模型碰到训练数据里没覆盖的问题时,它会生成一个统计意义上"合理"的回答——语法风格完美,但内容可能是虚构的。因为虚构内容和真实内容对模型来说概率差不多。
prompt 必然是敏感的。 由于每一步生成都以前面所有 token 为条件,prompt 的措辞变化——即便意思相同——会改变模型对候选词的打分分布。"请总结以下文本"和"对以下文本进行摘要"在语义上等价,但作为条件前缀,对应的是训练数据中不同的统计规律。语义等价不等于行为等价。
生成过程不能同时充当评估过程。 自回归生成的每一步都是对已有序列的延续。要求模型在同一次生成中否定自己前面的输出,等于要求它在条件概率链的中途推翻自己的条件——生成和评估不能在同一次大模型调用中完成,必须分两次调用。
每一次 LLM 调用都是一次抽签。 同一个 prompt 的多次调用会产生不同的输出。系统设计必须接受这个事实。
自然语言接口的代价
大模型把系统接口从形式化语言拉回了自然语言。get_user(id=42) 的含义没有任何模糊空间,但"提取文本中的关键信息"可以被解读为命名实体、核心论点、数值数据、或与查询最相关的段落——"关键"到底指什么,完全取决于模型当时的上下文推断。
形式化 API 的契约明确、可验证、可组合、版本可控。自然语言"契约"做不到这些。prompt 的含义依赖于模型的统计推断,没法自动检查理解是否正确。两段 prompt 拼在一起的效果不等于分别执行再组合。同一个 prompt 在不同模型版本上可能产生不同质量的输出。
自然语言接口的普及已经回不去了——它大幅降低了软件系统的使用门槛。正确的策略是接受自然语言作为外层接口,内部靠类型系统和结构化验证来保证精确。外层模糊,内层精确。