第 16 章 · 整个模型,端到端

在一张图上追踪一个 token(词元)穿过 Qwen3.5-0.8B 全程的路径,说清这套线性/全量注意力混合堆叠是如何拼装在一起的——然后说出从"预测下一个 token"中直接推导出来的核心局限:幻觉、没有可查询的数据库、有限的上下文、随机的输出。

前面每一章都在放大看单个组件——很容易只见树木、不见森林。这一章就是那张把每个零件放回原位的地图,最后再退后一步,正视整台机器的真实边界。

12 分钟
前向传播分词嵌入查表× 24 层最终 RMSNormLM head采样
术语表 · 12 个术语
residual stream
贯穿模型全部深度的未归一化隐藏向量(残差流)。每个块读取它、计算一个小的增量,再把结果加回去。
pre-norm block
按 x + sublayer(rmsnorm(x)) 排布的子块:先归一化输入、再做变换,然后加回到未归一化的残差主干上。这种写法让深层堆叠依然可训练。
hybrid attention
在同一个堆叠里混用两种序列混合器(混合注意力)。Qwen3.5 按固定排布交替使用线性注意力层和全量 softmax 注意力层。
Gated DeltaNet (linear attention)
一种 O(n) 的循环序列混合器,把历史压缩进一个固定大小的状态,而不是不断增长的 KV 缓存。24 层中有 18 层使用它。
grouped-query attention
多个查询头共享同一个 K/V 头的全量 softmax 注意力(分组查询注意力)。Qwen3.5 用 8 个查询头共享 2 个 KV 头,缓存缩小为原来的 1/4。
weight tying
把嵌入矩阵复用为 LM head(权重共享):同一张表在底部把 token id 映射成向量,在顶部又把向量打分成 logits。
hallucination
流畅、自信却不真实的输出(幻觉)——当不存在真实答案时,模型仍然采样了“最像真的”那个 token。
grounding
把模型输出绑定到可验证的来源(例如检索到的文档)上;基础模型默认没有任何这样的依据。
context window
模型一次能关注到的最大 token 数(Qwen3.5-0.8B 为 262,144)。
parametric memory
训练时隐式存进模型权重里的知识(参数化记忆),而不是存放在任何可查询的数据库中。
knowledge cutoff
一个时间点(知识截止日期):在它之后发生的事模型一概不知,因为训练数据到此为止。
stochastic
默认带随机性——因为是采样,同一个提示词在不同的运行中可能产出不同的结果。

一页看完整个模型

一句话总结:Qwen3.5-0.8B 就是 24 个几乎一模一样的 pre-norm 残差块叠起来,底部是嵌入表,顶部是与之共享权重的 LM head——前面各章读到的内容几乎都住在其中某个块里。 下面的海报就是那张地图:它把整个文本解码器铺成一条中央主干,左侧展开稠密 SwiGLU 前馈网络,右侧展开两种序列混合器——线性的 Gated DeltaNet 和全量的门控 GQA(分组查询注意力)。 悬停、点击或用 Tab 聚焦任意方块,下方面板会告诉你它是做什么的。

关于“整个模型”要诚实说明一点:这条主干画的是文本解码器——也就是浏览器内演示真正运行的路径。 完整的 Qwen3.5-0.8B checkpoint 是多模态的,所以海报也勾勒了可选的视觉编码器(左下角灰色部分); 在这个纯文本演示里它从未被用到。

这是 Qwen3.5-0.8B 架构的一张静态地图——不做任何模型推理。悬停、点击或用 Tab 聚焦任意方块,即可在下方面板阅读它的说明。切换按钮高亮代表层正在使用的序列混合器。
代表层的序列混合器
18 层线性、6 层全量——切换可高亮右侧对应的面板。
Qwen3.5-0.8B 混合多模态架构24 个稠密解码器层:18 层 Gated DeltaNet 线性注意力 + 6 层门控 GQA 全量注意力模型速览0.8B 稠密 checkpoint,无 MoE 路由隐藏维度 1024,24 个解码器层词表 248,320,LM head 权重共享上下文 262,144 个 tokenSwiGLU FFN 中间维度 3584视觉通路:12 层编码器,输出 1024Text config: Qwen3_5ForConditionalGeneration颜色图例:归一化为蓝色,序列混合为紫色,线性/状态为青色,FFN 为粉色,RoPE 为橙色。稠密 SwiGLU FFN每一层都有,不是混合专家(MoE)FFN 输出Gated DeltaNet 块线性注意力,循环式 O(n)门控 GQA 块全量注意力,预填充开销二次方KV 缓存:默认扁平布局;分块分页是仅原生服务端支持的可选路径,本演示未使用可选视觉通路代表性解码器层内部层类型排布,重复 6 次GDNGDNGDNGated GQA×6全量注意力层:4、8、12、16、20、24。其余各层均为线性注意力。输出 logits词表 248,320权重共享 LM head复用嵌入矩阵权重最终 RMSNorm解码器堆叠 ×24pre-norm 残差块 · 每层都有稠密 FFNRMSNorm注意力前序列块Gated DeltaNet(线性)→RMSNormMLP 前稠密 SwiGLU FFN1024 → 3584 → 1024,无 MoEtoken + 视觉嵌入输入序列文本 · 可选图像 · 可选视频输入 hidden 1024gate Linear1024 → 3584up Linear1024 → 3584SiLU(gate) · upSwiGLU 激活down Linear3584 → 1024hidden 输入q,kprojv,zprojb,aprojconvstaterecstate逐通道 Conv1D,kernel 4q/k/v 通道,SiLU门控 delta 循环β 与 g 更新循环状态卷积缓存循环状态缓存RMSNormGated + out projhidden 输入q_projQ + 门控k/v_proj2 个 KV 头Q 归一化8 个头K 归一化2 个头部分 RoPE256 维中的 64 维,θ 1e7SDPA + sigmoid 门控o_proj → hidden 1024图像/视频patch 16,tubelet 2视觉编码器 ×12hidden 768,12 个头投影到 hidden 1024文本token id · 248k本演示未使用MTP head投机解码 · 本演示未用
从这里开始——一张图里的整个模型
文本从底部进入 · 下一个 token 的分数从顶部输出

这就是 Qwen3.5-0.8B 的全貌。你的文本以 token id 的形式从底部进入,先变成向量(嵌入),然后向上流过 24 个重复的层——每一层先跨序列混合信息(注意力),再对每个 token 做变换(SwiGLU 前馈)——最后一次归一化加 LM head 把顶部的向量变成词表中每个 token 一个的分数。点击、悬停或用 Tab 聚焦任意方块即可阅读它的说明。大多数层使用便宜的“线性”混合器,少数层使用全量注意力——用上方的切换按钮对比两者。

颜色容易盖住一件事:海报里的每一个方块,都是一坨在训练结束时就冻结的权重。真正在它们之间逐层向上流动的,只有你的文本——而到了这一步,它已经不再是词语或语义,只是一个 [你的 token 数 × 1024] 的、由普通实数组成的数组。整条前向通路,就是这一个张量在通往 顶部的路上被不断地重排、相加、再重排。那些方块是程序,而张量是唯一在动的东西。

同一个块,重复 24 次

一个 token 以整数 id 进入,在嵌入矩阵里查表,变成一个 1024 维向量。这个向量就是残差流(residual stream)的起点——那条贯穿模型全部深度、不做归一化的主干道。24 层中的每一层都对它做同样的两件事:一个序列混合子块(某种注意力)和一个逐 token 的前馈子块,二者都包在如今已成标配的 pre-norm + 残差模式里。

关键在于,前馈这一半从不改变:每一层都带一个稠密的 SwiGLU MLP(1024 35841024),这个 checkpoint 里没有任何混合专家(MoE)路由。归一化用的是 RMSNorm,且只作用于子块的输入,所以残差主干本身保持未归一化,梯度可以一路传到最底层。最后一层之后, 一个最终的 RMSNorm 加上 LM head 把隐藏状态变成词表中每个 token 一个的 logits(未归一化分数)。

有人会问:到底为什么要把同一个块重复 24 次?常见的解读是:深度换来的是“组合”——靠前的层可以先把一件小而局部的事敲定,比如确定某个代词指回前面 几个 token 处的某个名字;靠后的层再借助这个已经解决的事实去判断更大的东西,比如这句话真正在说哪个分句。 每个块只往残差流里加一个很小的微调,所以叠起来之后,这些微调就能累积成单个块绝无可能独自完成的那种多步 塑形。这个直觉是有用的——但要松松地拿着:这幅图景大多来自对稠密的、纯注意力模型的研究,而它能多干净地 迁移到这套混合堆叠上(这里 24 层中有 18 层是线性循环、而非全量注意力),本身就并没有被很好地确立。

两种序列混合器

逐层确实在变的只有序列混合器。Qwen3.5 是一个混合体:它按固定的 [linear, linear, linear, full] 排布重复六次,于是 24 层中有 18 层使用线性注意力(Gated DeltaNet),其余 6 层使用全量分组查询注意力。全量注意力层是全局的—— 每个位置都能回看其他所有位置——但它的 KV 缓存随序列增长。线性层则是循环且便宜的:它们把历史折叠进一个 固定大小的状态,所以在第 10 个 token 和第 100,000 个 token 时占用的内存一样多。

3:1 的比例就是这笔交易。全量注意力是唯一能可靠地回头找回某个特定早期 token 的混合器,所以模型保留了 少量几层;线性层则以一小部分缓存的代价承担了大部分语言流。结果是:质量接近纯注意力模型,而内存占用 随上下文增长几乎不动。

还有另一种看待这台机器的方式:约 0.8B(8 亿)个参数究竟住在哪里?逐块清点一遍,你会发现 FFN 堆叠是每一层里最大的单一块——比两种序列混合器加起来还大:

参数预算——“0.8B”住在哪里
总计 852,985,920 ≈ 853M
一根条 = checkpoint 中的全部参数,按比例绘制FFN 264M嵌入 254MGDN 190M视觉 101M文本解码器 752,393,024 ≈ 752M+ 视觉 100.6M = 853M
模块算式参数量占比
SwiGLU FFN ×243 × (1,024 × 3,584) = 每层 11,010,048 × 24264.2M31.0%
嵌入(权重共享 LM head)248,320 × 1,024——只计一次:LM head 复用它254.3M29.8%
Gated DeltaNet 混合器 ×18qkv 6,291,456 + z 2,097,152 + out 2,097,152 + conv/β/衰减 57,504 = 每层 10,543,264 × 18189.8M22.2%
全量注意力(GQA)×6q 4,194,304(gate 使其翻倍)+ k 524,288 + v 524,288 + o 2,097,152 + norm 512 = 每层 7,340,544 × 644.0M5.2%
RMSNorm24 层 × 2 × 1,024 + 最终 1,0240.05M0.0%
视觉编码器(不在文本路径上)12 层 ViT——在 checkpoint 里,但这个纯文本演示从不运行它100.6M11.8%
总计264.2 + 254.3 + 189.8 + 44.0 + 0.05 + 100.6853.0M100%

所有数字都直接读自 checkpoint 的张量形状——加起来恰好是 852,985,920。两件值得注意的事:权重共享意味着那张 248,320 × 1,024 的嵌入表只花一份钱却用了两次(底部 token → 向量,顶部向量 → logits);而稠密 SwiGLU FFN 是最大的单一块——比两种序列混合器加起来还大(264.2M vs 233.8M,GDN + 注意力)。

进阶:Gated DeltaNet 层的内部 · 选读,写给好奇的你

这里展开解释上方海报里那些青色 Gated DeltaNet 方块的含义。完全可以跳过——就使用模型而言,上面的 3:1 交易已经是故事的全部。但在 18 个线性层中的任意一层内部,真正发生的是这些:

  • 投影。线性映射把输入拆成 query/key、value 加一个 z 门控,以及一对原始的 beta/衰减信号(b, a)——sigmoid 把 b 变成 β,衰减公式把 a 变成 g,它们是下面那段循环要拧的旋钮。
  • 一个短卷积。一个因果的逐通道卷积(kernel 4,所以每个通道只看最近 4 个 token),后接 SiLU 激活,在循环之前先加一点局部混合。
  • 门控 delta 规则循环是它的心脏。它只携带一个固定大小的状态,逐 token 扫过序列:β 控制每个新 token 对状态的覆写程度,g(衰减)控制旧信息被遗忘的速度。这让它对序列长度是 O(n) 的——线性(开销随 token 数同步增长),而不是二次方(全量注意力的开销随 token 数的平方增长——token 翻倍,工作量约变四倍)——而且状态大小永不增长。
  • 内存。这一层不维护随每个 token 增长的 KV 缓存,只携带一个很小的卷积缓存(最近几个 token)加上那个固定大小的循环状态——所以它的内存与上下文长度无关,是常量
  • 收尾。一个 z 门控的 RMSNorm 加一个输出投影,把结果送回 1024 维的残差流。

正是这种常量内存的循环,让 24 层中的 18 层可以不带增长的缓存运行,只剩 6 个全量注意力层需要为缓存买单。

在点出这些局限之前,还有一件事要放在尺度上看清:这是一个小模型。它的 852,985,920 个参数把它放在规模阶梯的底部附近,远低于大多数人说“大语言模型”时心里想的那些系统。这并不让它成为一个玩具 ——但它确实意味着,下面有些局限部分是关于规模的,在一个大得多的模型上会减轻(却永不消失)。

规模阶梯——这个 0.85B 模型站在哪里
log 刻度 · 参数量
10M1B1T微型端上模型约数千万小型开源模型几十亿本课程852,985,920 ≈ 0.85B前沿级约大 100–1000 倍

这里只有一个数字是精确的:在你浏览器里运行的这个模型,共 852,985,920 个参数。其余各档都是大致的 数量级——对数刻度意味着每往右一格,参数量大约翻十倍。诚实的结论是那段差距,而不是某个标题数字:最大的系统大约 是本模型的一百到一千倍。带着这段距离感,我们接下来去看:即便是一个做得很好、这个规模的模型,到底有哪些事是它 本质上做不到的。

模型不是什么

到这里你已经端到端看完了整台机器——每一个块,以及它所在的位置。同样值得精确说清的,是它没有在做什么,因为几乎每一次"这 LLM 坏了"的惊讶,都来自期待一个这套架构从未拥有过的能力。下面这些局限没有 一个是后来打上的补丁式缺陷——它们全部直接源自"预测下一个 token"本身。

它采样的是“合理”,不是“真实”

前向计算为每个候选的下一个 token 给出一个概率,然后我们从中采样。这条流水线里没有任何一步把事实与 某个来源核对。当真实的续写在训练数据中很常见时,“合理”与“真实”恰好重合,模型看上去就像“知道”。 而当不存在真实答案——或者模型压根没见过——它仍然会输出一个流畅、自信的 token。这就是幻觉

“合理” ≠ “真实”
The Eiffel Tower stands in the city of
·Paris
0.930
·France
0.030
·Lyon
0.012
·Europe
0.008
·Rome
0.005

示意性分布——为展示形状而手工挑选,并非模型的实时输出。

一个在训练数据中反复出现的事实:最可能的 token 恰好也是真实的那个。但模型从未查过任何东西——只是“真实”与“合理”在这里碰巧重合。

注意,它不是在撒谎(没有意图),也不是出了故障——它在精确地执行自己被造出来要做的事:产出一个看起来 很像的下一个 token。分布越平,它越没把握,但除非训练教过它含糊其辞,它照样会押注一个答案。

没有可查询的数据库

基础模型的“知识”是参数化的:在训练时烤进权重,而不是存放在推理时可查询的表里。 所以它无法可靠地引用一个自己没有实际记住的来源,并且带有知识截止日期——训练之后发生的事 根本不在权重里。(检索和工具可以在上面外挂一个真正的数据库,但那是外加的;你研究的这个模型本身一个也没有。)

它的记忆就是上下文窗口——而且是有限的

上下文窗口
窗口 = 262,144 token
在上下文中:120,000已遗忘:0

模型只能关注窗口之内的 token——这是一道硬上限,不是会滑动的记忆。把滑块拖过 262,144,看看最旧的区块如何掉出画框:每进来一个新 token,就得有一个旧 token 让位,而掉出去的内容除非在之后的提示词里重新提供,否则就永远消失了。这里没有长期存储;窗口就是模型全部的工作记忆。

模型唯一的工作记忆,是当前位于它的上下文窗口之内的那些 token。超过这个硬上限,最旧的 token 必须被丢弃腾位置,丢了就再也回不来。而在两次独立对话之间, 它什么也不记得——每次调用都从一片空白开始,除了你在提示词里重新提供的文本。

相同输入,不同输出

因为我们在采样,生成默认是随机的:temperature 大于零时,同一个提示词在不同 运行中可能产出不同答案。这对创意写作是特性,对任何需要复现的场景则是坑——想要确定性时就用贪心解码 (temperature 0),正如采样一章所展示的那样。

这些都不是 bug

它们不是等待修复的缺陷——而是一个一次只预测一个合理 token 的系统的诚实形状。了解它们,正是"用好 LLM" 与“被它打个措手不及”之间的分界线。这也是追完整条前向通路的真正回报:模型不再是魔法,而成为一个 你能切实推理其长处与边界的工具。

工程要点
  • Qwen3.5-0.8B 就是 24 个 pre-norm 残差块;逐层唯一变化的只有序列混合器——18 层用线性的 Gated DeltaNet,6 层用全量注意力。
  • 全量注意力是全局的,但它的 KV 缓存随序列长度增长;线性注意力便宜且循环,只维护一个固定大小的状态。3:1 的排布用一小部分内存留住了绝大部分质量。
  • 嵌入矩阵和 LM head 是同一份权重(权重共享)——一张表既负责把 token 映射进来,也负责把向量打分出去。每一层还都带一个稠密的 SwiGLU FFN——全模型没有任何混合专家(MoE)。
  • 幻觉不是故障:模型采样的是最合理的 token,而“合理”只有在该事实在训练数据中充分出现过时才恰好等于“真实”。
  • 模型没有数据库,调用之间也没有记忆——它的知识固化在权重里(带知识截止日期),它的工作记忆只有当前的上下文窗口。
  • 采样让生成默认是随机的;除非贪心解码,否则相同提示词也可能给出不同答案。
动手练习

在本页试两件事。(1)在海报中来回切换 GDN ↔ GQA,对照阅读右侧两个面板——说出全量注意力层(GQA)有、而线性层(Gated DeltaNet)没有的两样东西。(2)在下方的幻觉演示里切换到“没有真实答案”,把最高一根柱子的高度和“广为人知的事实”那一档比较——更平的分布会让模型放弃作答吗?

随堂测验
1. 24 层中有多少层使用全量注意力?
2. 这里的权重共享(weight tying)指什么?
3. 其余 18 层用的序列混合器是什么?
4. LLM 为什么会产生幻觉?
5. 推理时,LLM 的事实性知识存放在哪里?
6. 为什么同一个提示词在两次运行中可能给出两个不同的答案?