大模型生成原理:从Token概率到温度采样与注意力机制

发布时间:2026/10/29 12:27:13
大模型生成原理:从Token概率到温度采样与注意力机制 简介这份107页的PDF围绕ChatGPT的工作机制展开面向希望系统理解大语言模型原理的学生、开发者与技术爱好者帮助读者从Transformer架构、预训练与文本生成等基础环节逐步认识对话模型如何理解上下文并生成回复。压缩包内仅含1个PDF文件大小约4.98MB篇幅完整、便于通读与按章节检索。已有190人学习适合作为课程补充、技术入门或面试复习材料。内容覆盖预训练数据与损失优化、上下文连贯性、温度参数对输出多样性的影响以及面向特定任务的微调、对话状态管理与反馈循环等主题并讨论模型可能产生错误或误导信息的使用边界。读者可借助它建立从模型架构到对话策略的整体认知理解生成质量与参数设置之间的关系并形成对ChatGPT能力与局限的客观判断。1. 预测下一个词一句听腻了的话藏着整个机制“ChatGPT 就是在不停预测下一个词”——这句话被重复到几乎失去信息量。真把它当结论接受的人往往答不出下一层问题如果只是预测下一个词为什么它会同时出现“答非所问”和“一本正经胡说”两种失败模式为什么同一个问题问两次答案不一样为什么温度参数从 0.8 调到 0.1语气立刻从发散变成照本宣科这些现象都不是“预测下一个词”这五个字能解释的它们来自 LLM 内部的分层结构token 化、概率分布、采样策略、Transformer 的注意力权重、预训练固化的参数、以及每次对话都要重新计算的上下文。把这几层拆开“预测下一个词”才从一个玄学口号变成一条能推理、能验证的因果链。2. Token 与概率分布模型的输出从来不是“文字”在讨论 ChatGPT 为什么会聊天之前有一件事需要先明确模型没有输出过“句子”“段落”或者“回答”这类东西。它唯一会做的动作是——给定一段已经存在的 token 序列输出下一个 token 在词表上的概率分布然后从中选一个把选中的 token 接到序列末尾再重复一次。所谓的“回答”是几千次这个动作连起来之后人类读出来的错觉。2.1 一次只吐一个 token从半句话开始的续写最常见的教学切面是一个没写完的句子“The best thing about AI is its ability to”。把它喂给模型模型不会先在心里构思整段话再打出来而是先算出一个分布从里面抽一个 token比如 “learn”然后把 “learn” 接上去重新算一遍分布再抽下一个。中途每一轮它看到的都是“原始输入 自己已经写出来的部分”。这个“自己写的东西又成为自己下一步输入”的结构是后面所有现象的根源一次采样的偏差会被后续步骤继承、放大最终导向完全不同的句子。这里有个容易被忽略的细节token 不等于词。常见词通常对应一个 token罕见词会被拆成若干片段比如 “dogs” 可能被切成 “dog” “s”让 “dog” 和 “dogs” 共享同一段语义表示“q” 后面大概率跟着 “u”这类规律在分词层面就已经被统计学习到了不需要模型“懂拼写”。中文的情况更极端一个汉字可能占一个 token也可能占一个以上这直接导致了后面要说的“上下文长度估算翻车”。理解这一点之后很多争论会自动消解。比如“模型是不是在搜索训练数据里的原句”——它没有在搜索它只是在每一步做一个四万到十几万分类的分类任务词表大小而这个分类器的参数被几十亿上百亿次文本喂过。2.2 n-gram 与四万词表组合爆炸为什么救不了长上下文在神经网络接管之前语言模型的主流做法是数数统计语料里 “cat” 后面跟 “dog” 出现了多少次把频率归一化成概率。这就是 n-gram。它的机制简单到可以用几行代码验证也恰恰因为简单暴露了它无法跨越的障碍。# 组合爆炸的量级验证词表大小 Vn-gram 的理论空间是 V ** n V 40000 # 一个常见词表规模 for n in (1, 2, 3, 5, 10, 20): print(f{n:2}-gram 理论上界: {V ** n:.3e})跑一下就能看到量级的跳跃1-gram 是 4 万2-gram 是 16 亿3-gram 已经是 6.4 万亿到 20 个词的窗口时数字大得没有任何物理意义。这不只是“算力不够”的问题——就算你把全人类产生过的文本都存下来绝大多数 20-gram 组合在真实语料里出现次数是0。样本稀疏意味着概率估计直接失真没见过的组合n-gram 只能回退到更短的上下文去猜而一旦回退长距离依赖就断了。这就是为什么“数数”这条路在长上下文上彻底失效。一段 2000 字的文章里第 1 段提到的专有名词和第 20 段的一个代词指代关系任何固定窗口的 n-gram 都覆盖不到。理解了这个失效点才能理解下一章自注意力到底替代了什么。顺带一提n-gram 并不是被彻底淘汰的历史遗物。分词器里的字节对编码、某些拼写检查、输入法的联想候选都还在用它的变体。它的价值在于“局部统计可靠”缺陷在于“全局关联丢失”。2.3 logits → softmax概率是被算出来的不是被“想”出来的神经网络版本的语言模型最后一层输出的是一个与词表等长的实数向量每个位置对应一个 token 的“打分”这个打分叫 logit。logit 可以是负数、可以大于 1、可以是任意实数它本身不是概率。把它变成概率要做一步指数归一化也就是 softmax。import math def softmax(logits): # 减去最大值防止 exp 在大 logit 时溢出这是工程上的常规做法 m max(logits) exps [math.exp(z - m) for z in logits] total sum(exps) return [e / total for e in exps] logits [2.0, 1.0, 0.1, -1.0] probs softmax(logits) print([round(p, 4) for p in probs]) # 归一化后概率 print(round(sum(probs), 6)) # 恒等于 1.0这段代码里每一行的含义都值得说清。logits是模型前向计算的原始输出长度等于词表大小减去最大值是数值稳定性处理数学上不改变结果因为分子分母同乘一个常数exp把所有分数映射成正数并拉开差距——logit 差 1概率就差 e 倍最后除以总和保证概率和为 1。参数上唯一能调的是 logits 本身它由模型权重和输入决定用户改不了能改的是下一步的采样方式也就是第三章的内容。这里有一个必须点破的事实softmax 一定输出一个和为 1 的分布即使模型对答案一无所知。哪怕所有 logits 都接近 0、分布接近均匀它也会从里面抽一个 token 出来然后接着往下写。模型没有“我不知道”这个输出通道——除非训练时专门教过它说这句话。幻觉的数学根源不在别处就在这个“必须给出一个分布”的结构里。3. 温度 0.8一个除法如何改写模型的“性格”如果你只用过默认配置很容易把温度当成某种“聪明程度”旋钮——调高变聪明、调低变严谨。它不是。温度做的事情非常机械在 softmax 之前把整个 logits 向量除以一个数。就这么一个除法能同时改变输出的多样性、稳定性、重复率甚至影响你对模型“水平”的判断。3.1 温度就是 logits 除以 T从锐化到摊平把上面的 softmax 改成带温度参数的版本机制就一目了然了。import math def softmax_with_temp(logits, T1.0): # 温度 T 只做一件事在指数归一化之前把 logits 整体缩放 # T 1差距被放大分布更尖锐T 1差距被压缩分布更平坦 scaled [z / T for z in logits] m max(scaled) exps [math.exp(z - m) for z in scaled] total sum(exps) return [e / total for e in exps] logits [3.0, 1.5, 0.5, -1.0] for T in (0.2, 0.8, 1.0, 2.0): p softmax_with_temp(logits, T) print(fT{T:4} - {[round(x, 4) for x in p]})参数变化对应如下行为T 趋近 0 时指数缩放把微小差距放大成数量级差距分布几乎变成一个独热向量等价于每次都选概率最高的 token也就是贪心解码T 等于 1 时不做任何改变T 大于 1 时原本排第五、概率不到 1% 的 token 会被抬到有实际机会被抽中的位置长尾开始出现。温度 T分布形态典型表现常见用途0.1 ~ 0.3极尖锐几乎每次选同一个词容易整段复读信息抽取、分类、结构化输出0.7 ~ 0.9略平缓有变化但主体稳定语义不跑偏对话、问答的默认区间1.2 ~ 2.0明显摊平冷门 token 频繁出现容易跑题创意发散、起名、头脑风暴需要注意的一点是温度不改变 token 的相对排序只改变它们被抽中的相对机会。排第一的 token 在任何温度下都是排第一低温只是让“抽中第二名”的概率趋近于零。这意味着——温度不能把错的答案变成对的答案它只能改变你在正确答案和错误答案之间的抽签倾向。3.2 为什么是 0.8复读机与胡言乱语的中间地带0.8 这个数字不是从公式里推出来的它是经验值。往低温走模型会开始重复因为每一步都选最高概率的 token一旦进入某个高频句式后续每一步的最高概率 token 都指向同一个延续整个回答就卡死在循环里读起来像复读机。往高温走模型会开始“发散”冷门 token 被抽中的机会变大一个不合适的词进入序列后后续每一步都要基于这个错误前缀继续生成误差被继承放大最后整段话逻辑断裂。0.8 落在这样一个区间里绝大多数步骤仍然选到主流 token保证语义和语法稳定少数步骤允许同义替换、句式变化让回答不至于每次都一模一样。这个值在对话场景里经过了大量实际使用检验但它是场景相关的——写代码时 0.2 往往比 0.8 好用写小说时 0.8 又显得太保守。把这个数字当“默认”而不是“最优”是理解它的第一步。还有一层需要区分temperature 影响的是“采样随机性”不是“模型的知识量”。同一个问题T0.1 和 T0.8 拿到的都是同一个概率分布只是抽取策略不同。所以那种“把温度调低就能减少幻觉”的说法只对了一半它减少的是“随机选到错答案”的概率但对“分布里排第一的就是错答案”这种情况一点办法也没有。3.3 top-k 与 top-p给长尾加一道闸温度解决了“分布有多平”但没解决“多长的尾巴应该被允许出现”。于是有了截断策略。top-k 的做法是只保留概率最高的 k 个 token其余置零重新归一化后再采样。top-p也叫核采样的做法是按概率从高到低累加累加到超过 p 就截断只保留这一小撮。def top_p_filter(probs, p0.9): # 按概率降序排列累积到超过 p 为止剩下的长尾全部丢弃 idx sorted(range(len(probs)), keylambda i: probs[i], reverseTrue) kept, cum [], 0.0 for i in idx: kept.append(i) cum probs[i] if cum p: break # 保留项重新归一化保证仍然是一个合法分布 s sum(probs[i] for i in kept) return {i: probs[i] / s for i in kept}两者的差别在分布形状上体现得很明显。top-k 保留固定数量不管这批 token 的概率是集中在头部还是摊得很开k 个就是 k 个top-p 保留的是固定“概率质量”分布尖锐时可能只留两三个 token分布平坦时会放宽到几十个。后者适应性更强所以在对话类模型里更常见。这里有一个工程顺序问题容易被忽略温度、top-k、top-p 的执行顺序会影响结果。常见实现是先用温度缩放 logits再做 top-k/top-p 截断最后在截断后的集合上重新归一化采样。如果顺序反过来——先截断再调温度——那么被截掉的候选就再也没有机会温度的作用域被限制在了一个已经很窄的集合里两个参数互相干扰。踩过这个坑的人都懂调参调不出来效果问题往往不在参数值在参数被应用的顺序。4. 从 n-gram 到 Transformer注意力替换掉了什么到这里为止讨论的还是“怎么从一个分布里选 token”。真正决定这个分布长什么样的是模型结构。n-gram 用频率计数构造分布Transformer 用多层矩阵乘法构造分布两者的差别不在于“谁更聪明”而在于“能不能把远处的信息带过来”。4.1 n-gram 的死穴上下文一长样本立刻稀疏回到那个失效点。假设你想让模型知道“这句话里的‘它’指的是前面第三段提到的那个系统”n-gram 需要在训练语料里见过足够多“同样的长距离指代结构”才可能给出像样的概率估计。但语言的长距离依赖几乎是无穷组合样本必然稀疏。这也是为什么早期统计机器翻译在句子一长就崩——它真正缺的是表示长距离关系的能力算力并不是主要瓶颈。Transformer 的处理方式是把“距离”这个概念从结构里拿掉。序列里任意两个位置之间的关系由一个可学习的打分函数直接计算不管它们相隔 3 个 token 还是 3000 个 token计算路径长度都是 1。这就是“注意力”这个名字的来源每个位置在生成自己的表示时可以主动去“看”其他所有位置并按相关性加权。4.2 自注意力把“看最近几个词”换成“看全部并加权”自注意力的核心只有三个矩阵查询Q、键K、值V。同一个输入序列分别乘上三个可学习权重矩阵得到三组向量。然后用 Q 和 K 做点积算相关性归一化成权重再对 V 加权求和。写成代码不到二十行。import numpy as np def attention(Q, K, V, causal_maskTrue): # Q/K/V: (seq_len, d_k)由同一输入乘不同权重矩阵得到 d_k Q.shape[-1] scores Q K.T / np.sqrt(d_k) # 缩放防止点积随维度增大而爆掉 if causal_mask: seq_len scores.shape[0] # 上三角置为 -inf位置 i 只能看到 j i不能偷看未来 mask np.triu(np.ones((seq_len, seq_len)) * -1e9, k1) scores scores mask scores scores - scores.max(axis-1, keepdimsTrue) # 数值稳定 weights np.exp(scores) weights / weights.sum(axis-1, keepdimsTrue) # 每行权重和为 1 return weights V, weights几个参数的含义值得逐个说清。Q K.T得到的是一个 seq_len × seq_len 的矩阵第 i 行第 j 列表示“位置 i 对位置 j 的关注程度”/ np.sqrt(d_k)是缩放因子如果不除维度一大点积的方差就大softmax 会饱和成近似独热梯度几乎消失因果掩码把上三角设成极大负数让每个位置只能看到自己和左边这是生成式模型与双向编码器的关键分界最后对 V 加权求和得到的新表示里混入了整个可见上下文的信息。多头注意力则是在这个基础上并行做多组每组学到不同的关注模式——有的头盯相邻词有的头盯句法结构有的头负责长距离共指。多个头的结果拼接后再投影一次输出维度回到原尺寸。这套机制不依赖“距离窗口”所以它在结构上就具备处理长上下文的能力代价是计算量与序列长度的平方成正比O(n²) 的复杂度直接决定了上下文窗口为什么这么贵。4.3 权重是拟合出来的abxcx² 那个类比到底在说什么理解 Transformer 最容易卡住的地方是把注意力权重想象成人工设计的规则——比如“主语和动词要连起来”。实际上没有任何一条这样的规则被写进去。所有权重矩阵包括 Q/K/V 的投影矩阵、注意力输出的投影矩阵、前馈层的两层矩阵、嵌入表全部是随机初始化之后通过梯度下降在“预测下一个 token”这个任务上一点点调出来的。一个常用的类比是函数拟合数据里存在某种关系 y a bx cx²人不去解析地解出 a、b、c而是先随便给一组初值算预测值和真实值的误差沿误差下降的方向挪一小步重复几百万次参数自然收敛到一个能拟合数据的值。语言模型的参数规模把这个类比推到了极端——那一代模型有 1750 亿个参数它们不是 1750 亿条规则而是 1750 亿个可调的数值共同编码了“什么样的 token 序列在人类文本里更可能出现”这件事。这个类比也解释了一个常见困惑为什么模型能做题却不能可靠算数。因为它在拟合的是“文本分布的规律”数学运算的正确性只是这个分布里的一部分且是稀疏的一部分。纯靠模式匹配学到的东西在训练分布密集的地方很强在稀疏的地方很脆。4.4 1750 亿参数花在哪嵌入表、注意力矩阵、前馈层参数量不是一个笼统的数字它分布在几个差异极大的结构里各有各的作用。结构大致作用规模特点词嵌入表把 token id 映射成向量词表 × 隐藏维度占比不小但固定注意力投影矩阵计算 Q/K/V 及输出投影每层四组随层数线性增长前馈层逐位置的非线性变换容量大户通常隐藏维度的 4 倍宽参数最多输出投影把隐藏状态映射回词表打分隐藏维度 × 词表与嵌入表同量级前馈层往往是参数量的最大来源它做的事情比名字听起来朴素得多对每个位置独立地做“升维 → 非线性 → 降维”。正因为独立于其他位置它承载了大量“事实性”的模式记忆注意力层负责把信息搬来搬去前馈层负责对搬来的信息做变换。这个分工在可解释性研究里被反复观察到也是理解“为什么改上下文能改变输出、但改不动模型的固有知识”的一个切入口。4.5 预训练与微调一次固化一次塑形预训练阶段做的事情本质上就是在海量文本上反复执行“给前文、预测下一个 token、算误差、反向传播”。这个过程极其昂贵但只做一次产出的是一组固化的权重。它学到的是语言的统计规律、世界知识的部分压缩表示、以及各种文体和格式的模仿能力。这一阶段结束时模型会续写但不太会“对话”——你给它一句话它可能给你续一篇论文因为它见到的大量文本就是这种形态。微调和后续的对齐阶段改变的是“行为风格”而非“知识底座”。用对话格式的数据继续训练模型学会的是“用户说话之后应该出现一段有帮助的回答”这个模式用人类偏好数据做优化模型学会的是“在这两个回答里人选了哪个”。这也解释了一个现象微调能让模型变得更听话、更少说教但很难让它掌握训练数据里完全没有的事实。想注入新知识更经济的做法往往是放进上下文而不是重新训练。4.6 上下文窗口模型没有记忆只有每次重算这是最容易被误解的一层。多轮对话里模型看起来“记得”你前面说过什么实际上它在每一轮都把整段对话历史作为输入重新前向计算了一遍。它没有内部状态在轮次之间保留对话历史就是全部的“记忆”。工程上为了不重复计算推理框架会缓存前面 token 的 K 和 V即 KV cache避免每一轮把整个前缀重算。缓存占用大致随“层数 × 序列长度 × 隐藏维度 × 精度字节 × 2”增长序列一长显存压力就上来了。这直接解释了为什么上下文窗口有硬上限、为什么长对话的成本是超线性的、为什么超出窗口后最早的内容会被挤掉。知道这一层很多“玄学”就有了解释改一句很早之前的系统提示输出立刻变了因为那段文字重新参与了每一次注意力计算把关键信息放在对话最开头效果可能反而不如放在最后因为注意力对不同位置的敏感度并不均匀。5. 避坑与排查五个被讲错的大模型原理原理层面的误解比 API 用错更难排查因为它不会报错只会让你在错误的方向上反复调参。下面五条是实际讨论里出现频率最高的每条都按“现象 → 原因 → 解决”拆开。5.1 把温度调低当成减少幻觉的万能药现象把温度从 0.8 降到 0.1模型仍然会编造不存在的事实只是每次编得一模一样甚至更自信。原因温度只作用于采样环节不改变分布本身。如果错误答案在分布里本来就排第一低温只会让你更稳定地拿到这个错误答案。软化的分布至少还有机会抽到正确答案锐化之后连这个机会都没了。解决把温度和事实性分开治理。事实性问题靠外部检索、工具调用、结构化校验、多次采样投票来解决温度只用来控制表达风格的稳定性。判断标准也很简单——同一个问题跑十次如果十次答案一致但都是错的那问题在知识层不在采样层。5.2 以为模型“记住”了上一轮对话现象多轮对话到第十轮模型忘了第三轮说过的约束条件把历史消息里的一条删掉回答立刻变化同样的对话在别处重放结果不一致。原因模型是无状态的每一轮都把完整历史重新编码一遍。历史被删改输入就变了历史过长超出窗口早期内容被截断自然“忘记”。它记住的始终是“这次输入里有什么”并非“上次说过什么”。解决把关键约束显式写进每一轮的输入或者用系统提示固定住超长对话做摘要压缩把结论而不是原文留在上下文里需要严格状态管理时把状态放在外部存储每次按需注入。5.3 把 token 数当字数来估算上下文现象按“一个字一个 token”估算觉得 8000 字刚好塞进 8000 token 的窗口实际请求直接超限中英混排时估算偏差更大。原因分词器的切分粒度与字数无关。常见英文词可能整体一个 token罕见词被拆成多个片段中文一个字可能对应一个或多个 token标点、空格、特殊符号各有各的处理方式。不同模型的分词器还不一样。解决用对应模型的分词器实测长度不要估算在预算里预留余量给输出和系统提示长文档先分块按块处理再汇总而不是赌一次塞得进去。5.4 认为参数量大就等于知识更准现象模型在常识和写作上表现很好但问一个具体到型号参数、具体到某条冷门条款的问题就开始编。原因参数是训练语料统计规律的有损压缩不是数据库。高频事实被反复强化表示得很扎实长尾事实出现次数少压缩之后几乎不留痕迹。参数越多能编码的模式越丰富但不改变“稀疏即失真”这个本质。解决把模型当推理引擎不当知识库。需要精确事实时检索后放进上下文让它做“基于给定材料的归纳”而不是“从参数里回忆”。这个定位差异会直接改变你的提示词写法。5.5 用 n-gram 统计去解释模型的语法能力现象拿“某两个词经常一起出现”去解释模型为什么能生成通顺句子结论和实际行为对不上或者反过来因为模型偶尔犯低级语法错误就断言它“只是高级 n-gram”。原因n-gram 是单层查表Transformer 是多层非线性叠加加全局注意力两者的表达能力不在一个量级。但“表达能力更强”不等于“永远正确”它仍然是在做概率建模只是建模的粒度从固定窗口变成了可学习的全局关系。解决把 n-gram 当成教学类比不当机制解释。判断一个说法是否靠谱看它能不能预测具体现象——比如改变温度会不会影响复读率、增长上下文会不会改善共指消解。能做出可验证预测的解释才值得采信。6. 取舍这套机制够用但不承诺正确把整条链路串起来看会发现一个贯穿始终的设计取向用概率上的“大概率合理”换取通用性放弃对单次输出正确性的保证。token 化让模型摆脱了词表限制代价是字符级信息被压缩softmax 保证了输出永远合法代价是模型没有“我不知道”这个出口温度给了多样性旋钮代价是确定性和正确性之间被迫做交换自注意力换来了长距离建模能力代价是 O(n²) 的开销和昂贵的长上下文预训练固化知识代价是知识更新困难上下文重算保证了一致性代价是没有真正的记忆。每一条都不是疏忽是在“通用语言模型”这个目标下的必然取舍。想验证这些取舍是不是真的成立最省事的办法是做对照实验而不是读更多解释。固定一个提示词只改温度跑二十次统计重复率和错误率的变化固定温度只改上下文长度看共指消解在哪一步开始崩把同一个事实问题分别用“直接问”和“先给材料再问”两种方式测看差距有多大。这类实验成本很低但能把“玄学”变成可观测的量。我自己的血泪经验是早期调一个问答系统输出时好时坏我花了整整两天怀疑是温度设错了反复在 0.3 到 1.0 之间试结果毫无规律。后来把同一批问题的概率分布打印出来才发现错的那些问题正确答案在分布里根本进不了前五——问题在检索没把材料喂进去跟采样参数一点关系都没有。从那以后我每次调 temperature 之前都强制先跑一遍固定种子的对照测试确认分布本身没问题再去动采样。希望帮到你。本文还有配套的精品资源点击获取

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询