Qwen3 推理过程:从输入文本到下一个 Token
前面在分析 FlashAttention、Paged KV Cache 和 Paged Attention 时,我一直在研究 Qwen3 推理过程中的局部模块:Attention 是怎么计算的、KV Cache 为什么要保存、Decode 为什么需要分页访问历史 KV。把这些模块单独拆开以后,反而容易丢掉一个更基础的问题:一个输入句子究竟是怎样经过 Qwen3,最后变成下一个 Token 的?
本文从完整推理链路开始,以 Qwen3-0.6B 为例,把 Tokenizer、Embedding、RMSNorm、QKV 投影、QK-Norm、RoPE、GQA、Self-Attention、残差连接、SwiGLU MLP、LM Head 和自回归生成串起来。重点不是把模块名字罗列一遍,而是解释每一步到底在计算什么,为什么需要这样的设计,以及前后模块之间是什么关系。
下面先看完整结构图。

图中的主干很简单:输入文本先经过 Tokenizer 得到 input_ids,再查 Embedding Table 得到连续向量;向量经过 28 层 Transformer Decoder Block,最后经过 RMSNorm 和 LM Head 投影到词表空间,得到每个 Token 的 Logits,然后选择下一个 Token。新 Token 再作为下一轮 Decode 的输入,形成自回归生成循环。
需要先说明两个实现细节。第一,Qwen3 的真实 Attention 顺序是先完成 Q/K Projection,再做 QK-Norm,然后应用 RoPE;图中把 RoPE 和 QK-Norm画在同一支路上,阅读时应以这个顺序理解。第二,Qwen3-0.6B 的 MLP 中间维度应以模型配置为准,图中的局部标注只用于表示两路 Projection 和 Gate 结构。
1. 从输入文本到 Token ID
大语言模型最终处理的不是字符串,而是整数序列。
假设输入文本为:
请解释一下 Paged AttentionTokenizer 会把文本划分成若干 Token,再把每个 Token 映射为 Vocabulary 中的整数编号:
$$ input_ids=[t_0,t_1,\cdots,t_{T-1}] $$
其中:
$$ t_i\in{0,1,\cdots,V-1} $$
$V$ 是词表大小,$T$ 是当前输入序列长度。对于 Batch 输入,最终张量形状为:
$$ input_ids\in\mathbb{Z}^{B\times T} $$
这里有一个容易混淆的地方:Token ID 本身没有连续数值意义。例如 Token ID 为 100 和 101,并不表示它们在语义上比 100 和 10000 更接近。它们只是词表中的索引,因此下一步必须把离散索引映射到连续向量空间。
2. Embedding:从离散编号到连续表示
模型维护一个可训练的 Embedding Matrix:
$$ E\in\mathbb{R}^{V\times d_{model}} $$
对于 Qwen3-0.6B:
$$ d_{model}=1024 $$
每一个 Token ID 直接索引矩阵的一行:
$$ x_i=E[t_i] $$
所以整个输入序列经过 Embedding 后得到:
$$ X\in\mathbb{R}^{B\times T\times1024} $$
从数学上看,Embedding 也可以写成 One-Hot 与矩阵乘法。假设 Token $t_i$ 的 One-Hot 向量为:
$$ e_{t_i}\in\mathbb{R}^{V} $$
则:
$$ x_i=e_{t_i}^{T}E $$
由于 One-Hot 只有一个元素为 1,这个矩阵乘法实际上只是取出 $E$ 的第 $t_i$ 行。因此工程实现不会真的构造一个巨大的 One-Hot Vector,而是直接做 Lookup。
Embedding 的作用是把离散符号变成模型可以运算的连续向量。此时每个 Token 已经变成一个 1024 维向量,但向量中还没有经过上下文交互:同一个 Token 在不同句子中进入模型时,初始 Embedding 是相同的,真正的上下文语义是在后面的 Transformer 中逐层形成的。
3. Transformer Decoder Block 的整体结构
Qwen3-0.6B 由 28 个 Transformer Decoder Block 串联组成。设第 $l$ 层输入为:
$$ X_l\in\mathbb{R}^{B\times T\times1024} $$
一个 Decoder Block 可以先写成两条公式:
$$ H_l=X_l+\mathrm{Attention}(\mathrm{RMSNorm}(X_l)) $$
$$ X_{l+1}=H_l+\mathrm{MLP}(\mathrm{RMSNorm}(H_l)) $$
这两条公式基本概括了单层 Transformer 的全部结构。第一部分用 Attention 在不同 Token 之间交换信息,第二部分用 MLP 对每个 Token 的内部特征做非线性变换,两部分前面各有一个 RMSNorm,后面各有一条残差连接。
下面从 RMSNorm 开始逐层展开。
4. RMSNorm:为什么每个子模块前都要归一化
深层网络中,Hidden State 连续经过很多线性变换、Attention 和非线性模块之后,数值尺度可能逐层漂移。如果某一层的输出尺度过大,后面的 Dot Product 和 Softmax 会非常敏感;如果尺度过小,又可能造成有效信号衰减。
Qwen3 使用 RMSNorm 控制输入向量的整体尺度。
设某个 Token 的 Hidden Vector 为:
$$ x=[x_1,x_2,\cdots,x_d] $$
RMSNorm 先计算均方根:
$$ \mathrm{RMS}(x)=\sqrt{\frac{1}{d}\sum_{i=1}^{d}x_i^2+\epsilon} $$
然后归一化:
$$ \hat{x}=\frac{x}{\mathrm{RMS}(x)} $$
最后乘上可学习缩放参数:
$$ y=g\odot\hat{x} $$
其中 $g$ 与输入维度相同,$\odot$ 表示逐元素乘法。
RMSNorm 与 LayerNorm 最大的区别是:RMSNorm 不减均值,只控制向量的尺度。
LayerNorm 需要计算:
$$ \mu=\frac{1}{d}\sum_i x_i $$
和:
$$ \sigma^2=\frac{1}{d}\sum_i(x_i-\mu)^2 $$
而 RMSNorm 只需要平方、求和、开方和缩放。因此可以把 RMSNorm 理解为:不改变向量的中心位置,只防止整体幅值失控。
Qwen3 使用的是 Pre-Norm 结构,即:
Hidden States
↓
RMSNorm
↓
Attention / MLP
↓
Residual Add而不是先做子模块,再在结果上做 Norm。这样残差主干始终保留一条相对直接的信息路径,训练深层模型时更加稳定。
5. QKV 线性投影:Attention 为什么要把一个向量变成三份
经过 RMSNorm 后,Hidden States 仍然是:
$$ \hat X\in\mathbb{R}^{B\times T\times1024} $$
Self-Attention 首先通过三个线性层得到 Q、K、V:
$$ Q=\hat XW_Q $$
$$ K=\hat XW_K $$
$$ V=\hat XW_V $$
为什么同一个输入要投影成三份?可以把 Attention 看成一次可学习的信息检索。
Query 表示当前 Token 想找什么信息;Key 表示每个 Token 提供什么索引特征;Value 表示当某个 Token 被关注时,真正返回什么内容。
Attention 先计算 Q 和 K 的匹配程度:
$$ QK^T $$
再根据匹配程度对 V 加权求和:
$$ \mathrm{Softmax}(QK^T)V $$
如果不用三个独立 Projection,而直接对同一个向量做点积和加权,那么“用于匹配的信息”和“用于返回的信息”无法解耦,表达能力会受到限制。
Qwen3-0.6B 中 Query Head 数和 KV Head 数并不相同。设:
$$ H_q=16 $$
$$ H_{kv}=8 $$
$$ d_h=128 $$
则 Q 的形状为:
$$ Q\in\mathbb{R}^{B\times16\times T\times128} $$
而 K、V 的形状为:
$$ K,V\in\mathbb{R}^{B\times8\times T\times128} $$
这就引出了 Qwen3 使用的 GQA。
6. GQA:为什么 Query Head 比 KV Head 多
标准 Multi-Head Attention 中,每个 Query Head 都对应自己的一组 K/V Head。假设 Query Head 有 16 个,那么 K 和 V 也各有 16 个 Head。
Qwen3-0.6B 使用 Grouped Query Attention:
$$ H_q=16,\qquad H_{kv}=8 $$
因此每两个 Query Head 共享一组 KV Head:
$$ group_size=\frac{H_q}{H_{kv}}=2 $$
第 $qh$ 个 Query Head 对应:
$$ kvh=\left\lfloor\frac{qh}{group_size}\right\rfloor $$
例如:
Q Head 0, 1 → KV Head 0
Q Head 2, 3 → KV Head 1
Q Head 4, 5 → KV Head 2
...GQA 的直接收益出现在 Decode 阶段。KV Cache 需要为每一层、每一个历史 Token 保存 K 和 V。如果 KV Head 从 16 个减少到 8 个,KV Cache 在 Head 维度上的存储和读取开销也大约减半。
这也是为什么 GQA 对推理系统非常重要:它不仅影响模型结构,也直接影响 KV Cache 大小和 Decode 的 HBM 带宽压力。
7. QK-Norm:为什么 Q 和 K 还要再归一化一次
Qwen3 在 Q/K Projection 之后,还分别对每个 Head 的 Q 和 K 做 RMSNorm。设某个 Head 的向量为:
$$ q\in\mathbb{R}^{128},\qquad k\in\mathbb{R}^{128} $$
Attention Score 来自:
$$ s=q^Tk $$
而点积可以写成:
$$ q^Tk=|q||k|\cos\theta $$
所以 Score 不仅由方向关系决定,也受到 Q 和 K 模长的影响。如果某些 Head 的向量模长持续变大,Score 会快速增大,Softmax 可能变得非常尖锐。
QK-Norm 的作用就是在 Dot Product 之前先约束 Q 和 K 的尺度,使不同 Head 的 Score 更稳定。需要注意,这里的归一化维度是单个 Head 的 $d_h=128$,而不是整个 Hidden Size。
实际顺序可以写成:
$$ Q=\mathrm{QNorm}(\hat XW_Q) $$
$$ K=\mathrm{KNorm}(\hat XW_K) $$
$$ V=\hat XW_V $$
然后 Q 和 K 才进入 RoPE。
8. RoPE:为什么位置编码要作用在 Q 和 K 上
只使用 Self-Attention 时,模型看到的是 Token 内容之间的关系,却没有天然的位置概念。对于 Attention 来说,如果把一组 Token 的位置整体打乱,但 Q、K、V 本身不发生变化,那么矩阵计算无法自动知道“谁在前、谁在后”。
Qwen3 使用 RoPE 给 Q 和 K 注入位置信息。
先考虑二维向量:
$$ x=\begin{bmatrix}x_1\x_2\end{bmatrix} $$
位置 $m$ 对应一个旋转矩阵:
$$ R_m= \begin{bmatrix} \cos(m\theta)&-\sin(m\theta)\ \sin(m\theta)&\cos(m\theta) \end{bmatrix} $$
那么位置 $m$ 的向量变成:
$$ x_m=R_mx $$
真实模型会把 Head Dimension 按二维对子分组,对不同对子使用不同旋转频率。
RoPE 最有意思的地方是:Q 和 K 分别旋转之后,它们的点积会自然包含相对位置。
设:
$$ q_m=R_mq $$
$$ k_n=R_nk $$
则:
$$ q_m^Tk_n=(R_mq)^T(R_nk) $$
进一步得到:
$$ q_m^Tk_n=q^TR_m^TR_nk $$
旋转矩阵满足:
$$ R_m^TR_n=R_{n-m} $$
因此:
$$ q_m^Tk_n=q^TR_{n-m}k $$
最终结果与相对位置 $n-m$ 相关。
这就是 RoPE 很适合 Attention 的原因:它不是简单地把 Position Embedding 加到 Hidden State 上,而是直接修改 Q/K 的几何关系,使 Attention Score 带上相对位置信息。
V 不需要做 RoPE,因为 V 负责提供被聚合的内容,位置信息主要通过 Q/K 的匹配关系影响 Attention Weight。
9. Self-Attention:从 $QK^T$ 到 $PV$
完成 QK-Norm 和 RoPE 后,进入 Attention 的主体计算。
对于单个 Query Head,设:
$$ Q_h\in\mathbb{R}^{T\times128} $$
对应的 KV Head 为:
$$ K_{g(h)},V_{g(h)}\in\mathbb{R}^{T\times128} $$
首先计算 Score:
$$ S_h=\frac{Q_hK_{g(h)}^T}{\sqrt{128}} $$
得到:
$$ S_h\in\mathbb{R}^{T\times T} $$
这里除以 $\sqrt{d_h}$ 是为了控制 Dot Product 的尺度。假设 $q_i$ 和 $k_i$ 的元素方差都约为 1,那么:
$$ q^Tk=\sum_{r=1}^{d_h}q_rk_r $$
随着 $d_h$ 增大,点积的波动也会增大。直接送进 Softmax 时容易造成分布过度尖锐,因此通过:
$$ \frac{QK^T}{\sqrt{d_h}} $$
进行缩放。
对于因果语言模型,还要加入 Causal Mask:
$$ M_{ij}= \begin{cases} 0,&j\le i\ -\infty,&j>i \end{cases} $$
因此最终 Score 为:
$$ S=\frac{QK^T}{\sqrt{d_h}}+M $$
经过 Softmax:
$$ P_{ij}=\frac{e^{S_{ij}}}{\sum_k e^{S_{ik}}} $$
然后与 V 相乘:
$$ O=PV $$
对于第 $i$ 个 Query:
$$ o_i=\sum_jP_{ij}v_j $$
也就是说,$QK^T$ 决定“应该关注谁”,Softmax 把分数归一化成权重,$PV$ 决定“从被关注的位置拿回多少信息”。
在 Prefill 阶段,$T$ 个 Query 一次参与计算,因此这是典型的矩阵乘法问题;在 Decode 阶段,通常只有一个新 Query,但需要读取整个历史 KV,这也是 FlashAttention 和 Paged Attention 分别适合两个阶段的根本原因。
10. O Projection:为什么多个 Head 的结果还要再过一次 Linear
每个 Query Head 都会得到自己的输出:
$$ O_h\in\mathbb{R}^{T\times128} $$
16 个 Query Head 拼接后得到:
$$ O_{cat}\in\mathbb{R}^{T\times(16\times128)} $$
即:
$$ O_{cat}\in\mathbb{R}^{T\times2048} $$
随后通过输出线性层:
$$ O_{proj}=O_{cat}W_O $$
映射回:
$$ O_{proj}\in\mathbb{R}^{T\times1024} $$
这里的作用不是简单降维,而是把不同 Head 学到的信息重新混合到统一 Hidden Space 中。不同 Head 可能关注不同依赖关系,例如一个 Head 更关注局部语法,另一个 Head 更关注长距离实体关系,最终需要通过 $W_O$ 重新组合。
11. 第一条残差连接:为什么 Attention 输出不能直接替换输入
Attention 结束后,Qwen3 执行:
$$ H=X+O_{proj} $$
而不是:
$$ H=O_{proj} $$
可以把残差结构理解为:每一层不是重新生成一个完整表示,而是在原有表示上学习一个修正量。
设:
$$ y=x+F(x) $$
如果 $F(x)$ 只需要学习“当前层应该增加什么信息”,训练难度会比完全重建 $y$ 更低。
残差连接的另一个重要作用是提供直接梯度路径:
$$ \frac{\partial y}{\partial x}=I+\frac{\partial F}{\partial x} $$
即使 $\frac{\partial F}{\partial x}$ 很小,仍然存在 Identity Path。对于 28 层连续堆叠的 Transformer,这种直接路径能显著改善深层网络的训练稳定性。
在表示层面,可以理解为:
原始表示 X
+
Attention 从上下文取回的信息 ΔX
↓
新的表示 H12. 为什么 Attention 后面还需要 MLP
Attention 已经完成不同 Token 之间的信息交换,但这并不意味着 Transformer 可以省去 MLP。
Attention 更接近 Token Mixing:
Token A 从 Token B、C、D 中拿哪些信息?MLP 更接近 Channel Mixing:
当前 Token 的 1024 维特征应该如何进行非线性重组?MLP 对每个 Token 独立计算,不直接混合不同 Token。假设输入为:
$$ H\in\mathbb{R}^{B\times T\times1024} $$
那么同一个 MLP 会分别作用于每个位置:
$$ y_i=\mathrm{MLP}(h_i) $$
Attention 负责建立上下文,MLP 负责在上下文已经融合后的表示上进行更复杂的特征变换。
13. SwiGLU:Qwen3 的 MLP 为什么有两条上行支路
普通 Feed Forward Network 常见形式是:
$$ Y=W_2\phi(W_1X) $$
Qwen3 使用的是 SwiGLU 结构。它有三组线性层:
gate_proj
up_proj
down_proj先计算两条支路:
$$ G=XW_g $$
$$ U=XW_u $$
Gate 支路经过 SiLU:
$$ \mathrm{SiLU}(x)=x\sigma(x) $$
其中:
$$ \sigma(x)=\frac{1}{1+e^{-x}} $$
然后逐元素相乘:
$$ H=\mathrm{SiLU}(G)\odot U $$
最后经过 Down Projection:
$$ Y=HW_d $$
完整写成:
$$ \mathrm{MLP}(X)=W_d\left[\mathrm{SiLU}(XW_g)\odot(XW_u)\right] $$
这里 Gate Branch 的作用可以从逐元素乘法理解。对于某个中间特征 $i$:
$$ h_i=\mathrm{SiLU}(g_i)\cdot u_i $$
如果 $\mathrm{SiLU}(g_i)$ 接近 0,那么对应的 $u_i$ 会被抑制;如果 Gate 值较大,这一维特征就能通过。因此 SwiGLU 不是简单地对特征做一次固定激活,而是让一条支路动态控制另一条支路的信息流。
完成 MLP 后,再执行第二条残差:
$$ X_{l+1}=H_l+\mathrm{MLP}(\mathrm{RMSNorm}(H_l)) $$
至此,一个 Transformer Decoder Block 才完整结束。
14. 28 层 Transformer 在重复什么
Qwen3-0.6B 的 28 层并不是共享同一套权重。每层都有自己独立的:
- RMSNorm 参数;
- Q、K、V Projection;
- QK-Norm 参数;
- O Projection;
- Gate Projection;
- Up Projection;
- Down Projection。
第 $l$ 层完成:
$$ X_l\rightarrow X_{l+1} $$
整个主干为:
$$ X_0\rightarrow X_1\rightarrow\cdots\rightarrow X_{28} $$
可以把这个过程理解为逐层重写 Token Representation。Embedding 刚进入模型时只表示 Token 的静态语义,经过多层 Attention 和 MLP 后,每个位置逐渐融合上下文,并形成适合预测下一个 Token 的表示。
15. Final RMSNorm 和 LM Head
28 层 Decoder Block 结束后,模型还会执行一次 Final RMSNorm:
$$ H_{final}=\mathrm{RMSNorm}(X_{28}) $$
然后通过 LM Head 投影到 Vocabulary Space:
$$ Z=H_{final}W_{lm}^{T} $$
如果词表大小为 $V$,则:
$$ Z\in\mathbb{R}^{B\times T\times V} $$
$Z$ 就是 Logits。
对于自回归生成,只需要取最后一个位置:
$$ z=Z[:,T-1,:] $$
其中:
$$ z\in\mathbb{R}^{V} $$
这个向量对词表中的每一个 Token 给出一个未归一化分数。
通过 Softmax:
$$ p_i=\frac{e^{z_i}}{\sum_j e^{z_j}} $$
可以得到下一个 Token 的概率分布。
最简单的 Greedy Decoding 直接取:
$$ t_{next}=\arg\max_i z_i $$
Sampling 则从概率分布中随机采样:
$$ t_{next}\sim\mathrm{Categorical}(p) $$
生成 Token ID 后,再经过 Tokenizer Decode 转换成文字。
16. 自回归生成:为什么输出一个 Token 后还要再跑一次模型
Qwen3 生成的不是一次性整句话,而是逐 Token 计算条件概率:
$$ P(x_1,x_2,\cdots,x_N)=\prod_{t=1}^{N}P(x_t|x_{<t}) $$
一次完整生成过程可以写成:
Prompt
↓
Tokenizer
↓
Prefill
↓
得到第一个新 Token
↓
把新 Token 作为下一次输入
↓
Decode Step 1
↓
得到第二个新 Token
↓
Decode Step 2
↓
...这里 Prefill 和 Decode 使用的是同一个 Qwen3 模型结构,但计算形态完全不同。
Prefill 输入整个 Prompt:
$$ Q\in\mathbb{R}^{B\times H_q\times T\times d_h} $$
$$ K,V\in\mathbb{R}^{B\times H_{kv}\times T\times d_h} $$
因此 Attention 更接近大规模矩阵乘法,序列维度并行度高,适合 FlashAttention。
Decode 每一步只有一个新 Query:
$$ Q\in\mathbb{R}^{B\times H_q\times1\times d_h} $$
但历史 KV 长度不断增长:
$$ K,V\in\mathbb{R}^{B\times H_{kv}\times L\times d_h} $$
此时性能更受 KV Cache 容量和 HBM 读取影响,因此需要 Paged KV Cache 和 Paged Attention。
17. 从 Qwen3 架构回到 MiniPaged-Qwen
理解完整 Qwen3 推理链路以后,MiniPaged-Qwen 的位置就很清楚了。
在 Transformer Attention 中:
RMSNorm
↓
QKV Projection
↓
QK-Norm
↓
RoPE
↓
AttentionMiniPaged-Qwen 主要改造的是 Attention Runtime,而不是整个模型结构。
Prefill 阶段:
Q/K/V
↓
FlashAttention-style Kernel
↓
同时写入各层 KV CacheDecode 阶段:
新的 Q/K/V
↓
K/V 写入 Paged KV Cache
↓
Query 通过 Block Table 读取历史 KV
↓
Paged Attention所以 FlashAttention、Paged KV Cache 和 Paged Attention 并不是三个互相独立的概念,而是 Qwen3 推理流程中连续的三个环节。
18. 总结
从文本到下一个 Token,Qwen3 实际经历的过程可以概括为:
Text
↓
Tokenizer
↓
input_ids
↓
Embedding
↓
28 × Transformer Decoder Block
├── RMSNorm
├── QKV Projection
├── QK-Norm
├── RoPE
├── GQA Attention
├── O Projection
├── Residual Add
├── RMSNorm
├── SwiGLU MLP
└── Residual Add
↓
Final RMSNorm
↓
LM Head
↓
Logits
↓
Sampling / Argmax
↓
Next Token
↓
进入下一轮 Decode如果把每个模块的作用压缩成一句话:Embedding 把离散 Token 变成连续表示;RMSNorm 控制数值尺度;QKV Projection 构造检索所需的 Query、Key 和 Value;QK-Norm 稳定点积尺度;RoPE 把相对位置信息编码到 Q/K 的几何关系中;GQA 减少 KV Cache 和读取带宽;Attention 负责 Token 之间的信息交换;残差连接保留原表示并改善深层训练;SwiGLU MLP 在每个 Token 内部进行门控非线性特征变换;LM Head 最后把 Hidden State 投影到词表空间,得到下一个 Token 的分布。
从模型层面看,这是一条完整的自回归推理链路;从系统实现角度看,真正值得优化的位置则集中在 GEMM、归一化、Attention 和 KV Cache 管理几个部分。MiniPaged-Qwen 所做的事情,就是在不改变 Qwen3 数学模型的前提下,分别针对 Prefill 和 Decode 两种不同计算形态重写 Attention Runtime。