从一条直线到大模型输出一个token十首 token 诞生与 KV-Cache建议先看从一条直线到大模型输出一个token九输出矩阵与多层堆叠上一篇拿到了输出矩阵6 条约束链全部沉淀在最后一行。这一篇让首 token 真正诞生——然后是自回归、KV-Cache以及整个系列的收官。从一条直线到大模型输出一个token十首 token 诞生与 KV-Cache从一条直线到大模型输出一个token十首 token 诞生与 KV-Cache1. 取最后一行为什么是「」2. lm_head最后一次「一行乘一列」3. Softmax分数变概率4. 选 token三种策略5. 首 token 诞生6. 自回归第二个字怎么来7. KV-Cache旧 token 的 K/V 不用重算7.1 浪费在哪7.2 缓存方案7.3 收益与代价7.4 GQA 与 MLA给 KV-Cache 瘦身的两把刀8. 收官从一条直线到一个 token8.1 十篇旅程8.2 230B 的最后一环8.3 写在系列完结9. 下一系列预告17 个问题小结系列完结)1. 取最后一行为什么是「」篇9 结尾说过输出矩阵的最后一行——「」行——是预测首 token 的全部原料。为什么偏偏是最后一行因为因果语言模型从左到右预测下一个 token训练时每个 token 的任务都是根据左边所有 token预测我右边是谁。「今天」预测「西安」「西安」预测「的」……而「」是句子的最后一个 token只有它见过全部前文——今天、西安、的、天气、怎么样一个不落。所以预测“后面是什么就用”的行向量。把 6×4096 的输出矩阵只取最后一行得到 v——1×4096 的行向量演示 1×4如图 10-1 所示。图10-1 只取最后一行「」行是全句信息的汇集点注意图 10-1 里的细节v [2.85, -0.35, 1.90, -1.32]d1 2.85 是行内最大值——这正是篇9 反复铺垫的那条线「」行 d1 在深层全面接管问完了该作答的开关信号已经就位。2. lm_head最后一次「一行乘一列」现在把 v 翻译成词表上每个候选 token 的分数。篇9 已经预告过工具lm_head——一个 4096×129,280 的权重矩阵5.3 亿参数。计算还是那个贯穿全系列的动作一行乘一列。演示用 8 个候选 token 的小词表今、晴、雨、多、阴、雪、风、很lm_head 就是 4×8 的小矩阵。v 乘它得到 8 个分数logits如图 10-2 所示。图10-2 lm_head最后一次「一行乘一列」——4096 维翻译成词表分数手算「晴」那一列图 10-2 黄色高亮列2.85 × 0.70 ( − 0.35 ) × ( − 0.30 ) 1.90 × 0.40 ( − 1.32 ) × 0.50 2.20 2.85 \times 0.70 (-0.35) \times (-0.30) 1.90 \times 0.40 (-1.32) \times 0.50 2.202.85×0.70(−0.35)×(−0.30)1.90×0.40(−1.32)×0.502.208 个 logits 全算出来候选今晴雨多阴雪风很分数0.182.200.690.940.730.540.41-0.14表10-1 8 个候选 token 的 logits演示词表真实是 129,280 个分数「晴」以 2.20 一骑绝尘。但分数还不是概率——它们甚至可以是任意实数有负数也没归一化。从分数到概率差一个 Softmax。3. Softmax分数变概率Softmax 的公式P i e z i ∑ j e z j P_i \frac{e^{z_i}}{\sum_j e^{z_j}}Pi∑jezjezi逐个候选算指数、再除以总和。手算一遍只有三步第一步逐格取指数 e^z。「晴」e^2.20 9.03「多」e^0.94 2.55「雨」e^0.69 1.99……「很」e^-0.14 0.87。指数干的事把差距放大——分数上晴只是多的 2.3 倍指数后拉开到 3.5 倍分数上「很」是负的指数后变成 0.87垫底但没归零。第二步全部加起来。1.19 9.03 1.99 2.55 2.08 1.71 1.50 0.87 20.91。第三步每格除以总和。「晴」 9.03 / 20.91 43.2%「多」 2.55 / 20.91 12.2%……8 个概率加起来恰好 100%。整个过程动图演示如图 10-3 所示4 帧循环每帧追加一步推导。图10-3 Softmax 手算全过程logits → e^z → 求和 → 概率4 帧追加式动图8 个候选的最终概率热力图如图 10-4 所示。图10-4 Softmax 后的概率颜色越深概率越高左热力图右温度对比晴 43.2%——一家独大多 12.2%、阴 9.9%、雨 9.5%——第二梯队都是合理天气描述雪 8.2%、风 7.2%——边缘候选今 5.7%、很 4.1%——陪跑为什么「今」这么低因为**「今天」已经在输入里了**——注意力机制让「」吸收过「今天」的信息模型知道时间限定已经交代过答案不需要再说一遍今天。为什么「很」垫底因为「怎么样」规定的是描述性词性副词开头“很晴”语法上勉强、语义上别扭。篇9 的 6 条约束链在概率分布上全部兑现时间限定不说今天了✓ 主体锁定说的是西安不是别处✓ 结构黏合西安的天气是完整主语✓ 领域锁定候选全是气象词✓ 词性锁定描述性开头✓ 开始开关d1 2.85 已经按下4. 选 token三种策略概率有了怎么选出那个 token三种主流策略如图 10-5 所示。图10-5 拿到概率之后怎么选三种策略贪心解码永远选概率最高的——必选「晴」。每次输出完全一样确定但呆板连续生成时容易陷入重复循环。适合代码、数学。Top-k 采样只在前 k 个候选里随机抽。比如 k2取晴、多重新归一化成 78% / 22%——多数时候选晴偶尔选多。k 是硬门槛分布很平时候选会显得太少。Top-p 采样nucleus按概率降序累加累积到 p比如 0.9就停在截断的集合里抽。候选数随分布自适应分布尖时候选少平时候选多。当前各家 API 的默认选项。**温度Temperature**是采样前的分布调节旋钮把 logits 除以 T 再 Softmax。图 10-4 右侧是三种温度的对比——T0.5 时「晴」放大到 78.6%保守T2.0 时压平到 25.0%放飞。温度不改候选排序只改集中度。本系列演示用贪心首 token 「晴」。5. 首 token 诞生把全链路串一遍这是整个系列等了 10 篇的时刻篇2「今天西安的天气怎么样」→ 6 个 token [5237, 23872, 301, 16652, 19602, 1148]篇3查嵌入表 → 6×4096篇4RoPE 把位置旋进向量篇5~8过第 1 个 Block——归一化、注意力交换信息、残差保底、FFN 深加工篇9再过 31 层 → 输出矩阵「」行 d1 全面接管本篇取「」行 → 乘 lm_head 得 129,280 个分数 → Softmax →「晴」以 43.2% 胜出从「今天西安的天气怎么样」到「晴」——一个 token 诞生了。这不是检索、不是查表而是 80.4 亿个参数接力加工出来的概率选择。回答的开头就此落地。6. 自回归第二个字怎么来一个 token 显然不够——用户要的是完整的天气播报。自回归autoregressive把刚生成的「晴」拼回输入句尾输入从 6 个 token 变成 7 个再完整走一遍前向32 层 → 取最后一行 → lm_head → Softmax → 选 token得到第二个 token「天」。循环往复像多米诺骨牌如图 10-6 所示。图10-6 自回归首 token 拼回句尾生成第二个字用伪代码表达python tokens 分词(今天西安的天气怎么样) # 6 个 while 未遇到 EOS and 长度未超限: out_matrix transformer_32层(嵌入(tokens)) v out_matrix[-1] # 取最后一行 logits v lm_head # 词表分数 probs softmax(logits / T) # 概率 next_tok 采样(probs) # 贪心 / top-k / top-p tokens.append(next_tok) # 拼回句尾 回答 反查词表(tokens[6:]) # 晴天…… 注意循环体的每一轮都要过完整的 32 层——生成是逐 token 的每个字都是一次全量前向。这带来了一个明显的浪费下一节解决。7. KV-Cache旧 token 的 K/V 不用重算7.1 浪费在哪生成「天」时输入是 7 个 token朴素做法 7 个全部过 32 层。但仔细想前 6 个 token 的 K、V 向量和上一轮算出来的一个数都不差。为什么篇7 讲过因果掩码每个 token 只能看见自己和左边的 token。「晴」拼在句尾改变不了旧 token 的视野——「西安」该看谁还是看谁它的 K/V 和注意力结果纹丝不动。这是数学上的等价不是近似。7.2 缓存方案KV-Cache 的做法把每一层算出的 K、V 缓存下来下一步只算新 token 一个的 Q、K、V——新 K/V 追加进缓存新 Q 和全部缓存 K 算注意力。对比效果如图 10-7 所示。图10-7 KV-Cache缓存每层的 K/V新 token 只算自己的 Q/K/V从矩阵视角看缓存扩充生成「晴」之前K 缓存是 6×4「晴」拼进来后只新算它那一行追加成 7×4——前 6 行原封不动如图 10-8 所示。图10-8 KV 缓存的扩充从 6×4 到 7×4——旧的逐格不动新的整行追加颜色深浅 数值大小伪代码python kv_cache [] # 每层一份 (K, V) # 首 token全量计算K/V 全部入缓存 out, kv_cache forward_32层(嵌入(tokens), cacheNone) # 后续 token只算新的 1 个 for 每一步: out, kv_cache forward_32层(嵌入(新token), cachekv_cache) # 内部新 Q × 缓存 K → 注意力新 K/V 追加进缓存 把图 10-6 和图 10-7 的机制合起来如图 10-9 所示4 帧循环动图图10-9 自回归生成 KV-Cache 全过程动图7.3 收益与代价收益生成第 N 个 token 的每步计算量从全部 N 个 token 过 32 层降到1 个新 token 过 32 层。长回答的计算量从平方级降回近线性——这是所有大模型推理引擎的标配优化没有它逐 token 生成的延迟会随回答变长急剧恶化。代价缓存要占显存。粗略公式2 × 层数 × 序列长度 × 宽度K 和 V 两份。对 LLaMA-3-8B2 × 32 层 × 长度 × 4096 维——32K 上下文时 KV-Cache 就要占约 8GBfp16长上下文的显存大头。篇6 埋的伏笔在此回收——怎么给 KV-Cache 瘦身业界有两把刀。7.4 GQA 与 MLA给 KV-Cache 瘦身的两把刀第一把刀GQA分组查询注意力Grouped-Query Attention——从头数下手。篇6 讲过标准 MHA多头注意力里 32 个 Q 头配 32 组 K/V 头。GQA 的思路Q 头保持 32 个不动K/V 头砍到 8 组每 4 个 Q 头共享 1 组 K/V。注意力的计算结构几乎不变Q 和 K 的乘法照做但缓存里每层只需存 8 组 K/V——缓存直接省 4 倍。为什么敢共享因为实验发现不同 Q 头关注的 K/V 模式有大量重叠——你查今天是时间、他查今天是日子用同一份今天的 K/V 完全够用。GQA 由 Ainslie et al. 2023 提出《GQA: Training Generalized Multi-Query Transformer Models from Multi-Head Checkpoints》LLaMA-2/3、Mistral、Qwen 全系采用篇6 出现的W_K 是 4096×1024 而不是 4096×4096就是 GQA 的痕迹——参数量也随之省了 4 倍。更激进的 MQAMulti-QueryShazeer 2019只留 1 组 K/V省 32 倍但精度损失偏大现在少用——GQA 是精度与省存的平衡点。第二把刀MLA多头潜在注意力Multi-head Latent Attention——从维度下手DeepSeek-V2/V3 的招牌设计。GQA 只是把 K/V 从 32 组砍到 8 组每组还是 128 维。MLA 更狠根本不缓存 K/V 本身缓存一个 576 维的潜在向量。原理一句话训练时让模型学会把 4096 维的上下文压缩成 512 维潜在表示外加 64 维 RoPE 位置信息用时再解压回 K/V。类比不存整本书存一本摘要——推理时按摘要重建需要的内容。代价是计算多一步解压换来的是每 token 每层缓存从 8192 个数降到约 576 个减少约 93%DeepSeek-V2 论文《DeepSeek-V2: A Strong, Economical, and Efficient Mixture-of-Experts Language Model》的实测口径——这就是 DeepSeek 敢做超长上下文的底气之一。四种方案对账以 4096 宽、32 头、每头 128 维为例每 token 每层的 KV 缓存量方案K/V 头数缓存维度×2 份相对 MHA代表模型MHA32 组2 × 4096 81921×原始 Transformer / BERTMQA1 组2 × 128 2561/32PaLM 等少用GQA-88 组2 × 1024 20481/4LLaMA-3 / Mistral / QwenMLA潜在压缩≈ 576 64≈1/14减 93%DeepSeek-V3 / R1表10-2 四种注意力的 KV-Cache 对比那些看不懂的压缩设计本质上都是在给 KV-Cache 瘦身8. 收官从一条直线到一个 token8.1 十篇旅程把 10 篇串成一条线如图 10-10 所示。图10-10 从一条直线到一个 token10 篇的完整旅程篇1 用一条过原点的直线1 个参数出发篇1 末加截距2 个篇2 分词——句子变成 token 序列篇3 嵌入查表5.3 亿篇4 RoPE篇5 Block 六步篇6 QKV篇7 注意力篇8 FFN——组件逐个上齐篇9 堆 32 层 输出矩阵75.1 亿篇10 lm_head Softmax80.4 亿→ 「晴」一句话总结系列大模型 把「一行乘一列」这个动作在 80 亿个数字上重复几万亿次再让下一个 token 从概率里诞生。8.2 230B 的最后一环篇9 承诺过篇10 结尾回补 230B 的闭环。现在所有组件都在手上了可以把它说透豆包 Seed-1.6 的 230B 和本系列的 80.4 亿共享全部原理——分词、嵌入、RoPE、注意力、FFN、残差、堆叠、lm_head、Softmax、自回归、KV-Cache一个组件都不多。区别只在三个旋钮LLaMA-3-8B本系列对账基准Seed-1.6篇1 规模感起点宽度4096约 7168深度32 层数十层FFN每层 1 个每层若干专家每 token 挑着激活总参数8.03B230B单 token 激活8.03B全激活23B稀疏激活表10-3 稠密 8B 与 MoE 230B同一套原理的两种配比MoE 的230B 总参数、23B 激活翻译过来就是模型记得多230B 的知识存量但每次只想少23B 的计算量——像一个藏书 230 万册的图书馆每次查询只动 23 万册相关的书架。KV-Cache 优化的也是同一件事的两面知识要多存、计算要少做。篇1 那个把 230B 砍到 1 个参数的思想实验至此完全闭合砍掉的是规模留下的是原理加回来的是账本看清的是骨架。8.3 写在系列完结写这个系列的初衷很简单市面上的 Transformer 教程要么从论文公式开始劝退要么停在注意力就像查字典的比喻层面。我想试试第三条路——假设读者只学过高等数学能不能把大模型输出一个 token这件事从 ywx 一路推到底。10 篇写下来最大的感受是大模型没有魔法只有工程。所谓的智能涌现拆开看是嵌入查表、一行乘一列、指数归一化这些本科生都能看懂的动作复杂度不在任何单个组件而在简单动作 × 天文数字的重复。如果这个系列让你下次再看到注意力头“KV-Cache”MoE 稀疏激活这些词时脑子里浮现的是具体的小矩阵和它的计算过程——这个系列的任务就完成了。从一条直线到「晴」。谢谢一路看到这里。9. 下一系列预告17 个问题写完这个系列最自然的感受是一个 token 如何诞生讲清楚了但围绕大模型还有一大片没讲的地。顺着本系列的思路往下问至少还有 17 个好问题。先抛三个最扎心的问题一大模型其实不知道今天是几号。它的知识冻结在训练截止那天——你问今天西安的天气它答的晴只是概率上最像答案的词不是真天气。怎么让它感知今天最直接的方案是Prompt把日期、天气数据塞进上下文本系列的输入句就是这么来的更进一步是MCP 工具调用让模型自己决定先查天气 API再回答。问题二回答总是「晴」怎么破就算接了工具模型也可能偷懒每次都返回同一个答案。RAG检索增强生成从你的私有大文档里检索真实材料再回答AI-Memory 让模型记住你是谁、你之前说过什么——变废为宝从垃圾数据里提取宝贝知识。问题三本系列只给了 6 个 token 的上下文真实对话动辄几万 token——上下文爆炸了怎么办SubAgent子代理的思路主 Agent 只留摘要细节派给子 Agent 处理。把这 17 个问题全部列出按懂你 / 有据 / 看见更多 / 变强分成四组如图 10-11 所示。图10-11 下一系列候选主题17 个问题分四组顺序和内容都可能调整欢迎留言点单A 组·让模型更懂你01 大模型如何感知【今天】Prompt、03 如何让对话更拟人角色扮演、06 让大模型了解细节Skill、08 让大模型适配你AI-MemoryB 组·让模型有据可依02 回答总是【晴】怎么办MCP、09 从垃圾里提取宝贝RAG、07 上下文爆炸了怎么办SubAgentC 组·让模型看见更多04 大模型如何看图多模态-图片、05 大模型如何感知时间多模态-视频、16 操作你的电脑GUI/Computer Use、15 多个大模型协作Multi-Agent、17 Agent 社会斯坦福 AI 小镇D 组·让模型变强10 知识从哪来预训练、11 学会听指令SFT、12 学会偏好RL、13 自己变强自进化、14 快思考与慢思考推理模型A/B 组回答怎么用好一个大模型应用层C 组回答怎么扩展它的感官与手足多模态与 AgentD 组回答怎么炼成一个大模型训练层。本系列原理篇回答的是它怎么工作——四个系列连起来就是从原理到应用的完整地图。顺序和内容都可能调整。想先看哪个评论区点单。小结这一篇让首 token 真正诞生系列收官取最后一行因果语言模型只有最后一个 token「」见过全部前文它的行向量 v1×4096是预测首 token 的唯一原料d12.85 正是篇9 的该作答开关lm_headv × W_L4096×129,280 5.3 亿参数 129,280 个 logits——全系列最后一次「一行乘一列」演示 8 个候选中「晴」2.20 最高Softmax手算三步逐格 e^z → 求和 20.91 → 相除——指数放大差距「晴」9.03/20.91 43.2% 一家独大篇9 的 6 条约束链在概率上全部兑现今仅 5.7% 因为时间已交代、很垫底因为词性不符选 token 三策略贪心确定、top-k硬门槛、top-p自适应截断温度是分布集中度旋钮T0.5→78.6%T2.0→25.0%首 token 「晴」从分词到输出10 篇全链路第一次完整跑通自回归输出拼回输入逐 token 生成完整回答每步都是全量前向KV-Cache因果掩码保证旧 K/V 永不变 → 缓存复用、只算新 token长回答从平方级降回近线性代价是显存2×层数×长度×宽度GQA 与 MLA瘦身两把刀GQA 从头数下手32 Q 头共享 8 组 K/V缓存省 4 倍LLaMA-3/Mistral/Qwen 全系MLA 从维度下手缓存 576 维潜在向量而非 K/V 本身减约 93%DeepSeek 招牌MHA/MQA/GQA/MLA 四方案对账230B 闭环Seed-1.6 与 LLaMA-3-8B 共享全部原理区别只是宽度/深度/MoE 三旋钮——“知识多存、计算少做”下一系列预告17 个问题分四组——懂你Prompt/角色扮演/Skill/Memory、有据MCP/RAG/SubAgent、看见更多多模态/Agent/GUI/AI 小镇、变强预训练/SFT/RL/自进化/快慢思考系列完结原理篇到此完结应用与训练篇17 个候选主题见第 9 节择日开写。系列目录全 10 篇从一条直线到高维空间分词与 token 表隐藏层与嵌入位置编码 RoPETransformer Block 全景与层归一化QKV 三剑客注意力权重与多头机制残差连接与前馈网络输出矩阵与多层堆叠首 token 诞生与 KV-Cache当前篇完结版权声明本文为博主原创文章遵循 CC 4.0 BY-SA 版权协议转载请附上原文出处链接和本声明。