介绍 Gemma 4 如何通过 MTP 草稿模型预测多个 token,再由主模型一次验证,并说明 llama.cpp 本地部署方式。文中涉及的四位草稿模型从 97.8 MB 缩至 59.2 MB,实际性能测量留待后续文章。
本文将循序渐进地介绍如何在本地桌面级 GPU 系统上,通过 llama.cpp 运行 Gemma 4 的多 token 预测(MTP)drafter,实现推测解码。这是一个简短系列的第一篇:本篇解释 drafter 是什么、为什么要使用它,下一篇给出实测数据。
项目目录:xbill9/gemma4-dev/tree/main/local-llamacpp-3050oem-2b-q4_0
Gemma 4 为每种规模的模型都配备了一个小型伴随模型,也就是 drafter。它会猜测接下来的几个 token,让主模型在一次前向传播中完成验证。Google 的 QAT drafter 在训练时就将权重约束到了 4-bit 网格上;按这种格式存储后,体积从 97.8 MB 缩小到 59.2 MB,目前已发布到 Hugging Face。
本仓库中的运行环境使用本地硬件部署 Gemma 4 E2B 和 E4B:一台配备 RTX 3050 OEM 的台式机,以及一台配备 GTX 1650 Ti 的笔记本。两者运行的主模型,都已经是精确保留 QAT 权重的 4-bit 构建版本。Google 也为每个 Gemma 4 模型发布了对应的 drafter,而 llama.cpp 现在已经能够运行它们。
本篇介绍三件事:推测解码如何工作,Gemma 4 的 drafter 与常规草稿模型有何不同,以及这些运行环境所使用的、由 Google QAT drafter 精确重新打包而成的 Q4_0 版本。
语言模型每次前向传播生成一个 token,而每次前向传播都要读取全部权重。对于小型 GPU 上的单用户场景,计算量不大,显存数据传输量却很大:每一步中,显卡的大部分时间都花在搬运权重上,而不是拿这些权重做计算。
这意味着每一步都有闲置算力。在一次前向传播中验证多个 token,只需要读取一次相同的权重,再多做一点计算,因此耗时只比生成一个 token 略多。推测解码就是为了利用这部分闲置算力。
每一步分为两个部分。
起草(Draft)。一个小而快的模型猜测接下来的几个 token。
验证(Verify)。主模型称为 target,它对所有猜测一次性执行前向传播,逐个检查它们是否符合自己原本会生成的结果。
target 从头开始接受这些猜测,直到遇到第一个不认可的 token。它会丢弃这个 token 及其后的全部猜测,并在该位置补上一个自己生成的 token。因此,每一步至少生成一个 token;如果所有猜测都正确,最多可以生成“起草 token 数加一”个 token。
输出仍由 target 决定:每个 token 要么与 target 原本会选择的结果一致,要么就是 target 自己给出的替代结果。drafter 改变的只是每次昂贵的前向传播能够产出多少个 token。
Google 的模型卡是这样描述的:
在推测解码流程中,草稿模型会提前预测多个 token,然后由 target 模型并行验证。
传统的草稿模型通常是同系列模型的一个较小版本,有自己的层、自己的 KV cache,也需要独立处理整段对话。Gemma 4 的 drafter 则是 target 的附加组件。Google 将这种方法称为多 token 预测,并将 drafter 描述为一个轻量的 4 层模型,使用 target 模型的激活值和 KV cache。
Hugging Face 上 E2B drafter 的 config.json 展示了它有多小:
"architectures": ["Gemma4AssistantForCausalLM"],
"backbone_hidden_size": 1536,
"hidden_size": 256,
"num_hidden_layers": 4,
"num_kv_shared_layers": 4,
"layer_types": ["sliding_attention", "sliding_attention", "sliding_attention", "full_attention"],
"vocab_size": 262144,
"tie_word_embeddings": true
由此带来两个结果。首先,drafter 不需要为对话维护独立的 cache,所以它的显存开销只有权重和一个小型工作缓冲区。其次,它的每次猜测都以 target 针对当前 token 已经计算出的结果为起点,这也是如此小的模型仍然能猜得准的原因。
这个 checkpoint 还为输出层提供了一条基于聚类的计算捷径(num_centroids: 2048)。llama.cpp 的转换器没有保留这条捷径,而是对整个词表计算分数。
🟢 单用户回答更快。在受显存带宽限制的 GPU 上,一次验证两三个 token 的前向传播,就能完成原本两三次前向传播的工作。Google 的模型卡宣称最高可提速 3 倍。
🟢 不需要重新训练,也不需要修改主模型。target 文件、配置和上下文保持原样;只需增加一个 drafter 文件和两个服务端参数。
🟢 显存开销小。drafter 共享 target 的 KV cache,因此只需要存放自身权重和一个小型工作缓冲区。
⚠️ 收益取决于文本内容。代码等可预测性较高的输出更容易猜中;自由发挥的故事则较难猜中,每次被拒绝的猜测都会浪费计算。
⚠️ 收益取决于负载。多个用户同时使用时,GPU 本来就很忙,可用于验证猜测的闲置算力会减少。第二篇将测量它在什么情况下不再划算。
⚠️ 当候选分数非常接近时,贪心解码的文本可能发生变化。两个词的分数几乎相同时,在一次批量前向传播中验证多个 token,可能让最终选择偏向另一个词;可能的原因是批量计算的舍入方式不同,但本文没有验证这一点。回答仍然由 target 决定;第二篇会展示具体分数。
Google 为每种规模的 Gemma 4 发布了两种 drafter:用于 bf16 模型的 -it-assistant,以及用于 QAT 构建版本的 -it-qat-q4_0-unquantized-assistant。Google 的 QAT 模型卡明确说明了它们的搭配要求:
当 QAT target 模型与 assistant 模型配合使用多 token 预测(推测解码)时,assistant 模型也必须是精度相同的 QAT checkpoint,以确保兼容性。
这些运行环境使用的是精确 Q4_0 QAT 版本的 E2B 和 E4B,因此搭配的也是 QAT drafter。
Google 以 bf16 格式发布 QAT drafter,但权重值已经落在 4-bit 网格上:每个权重矩阵中,每组 32 个值组成的块最多只有 16 个不同的值。这恰好符合 Q4_0 的布局,因此可以直接按 4 bit 存储权重,无需再次舍入。
llama.cpp 的转换器会将 drafter 写成 Q8_0。gguf_exact.py 也是生成精确主模型 GGUF 文件所用的构建工具,它会找出每个块在训练中形成的量化步长,改用 Q4_0 存储 drafter。所有块都符合这个量化网格,没有例外。
精确 Q4_0 文件比 Q8_0 小 39%;按相对误差衡量,它与 Google 原始权重的接近程度是 Q8_0 的 3.6 倍,这些数字根据构建报告计算得出。E4B drafter 的结果也一样:59.7 MB,而 Q8_0 为 98.7 MB。
这两个 drafter 均已发布,并附有构建脚本和验证依据:
xbill9/gemma-4-E2B-it-qat-assistant-q4_0-exact-gguf
xbill9/gemma-4-E4B-it-qat-assistant-q4_0-exact-gguf
在这些运行环境中,make draft 会下载固定 revision 的文件,并检查其哈希值:
060f5a0158f8120d25137866b90e04e21cd0d2d23de1db7a9cc3b7f00e60bd11 gemma-4-E2B-it-qat-assistant-q4_0-exact.gguf
dc965cb963e56b86fbc04db8efec83163886085e88514574650a57fa55a2ee24 gemma-4-E4B-it-qat-assistant-q4_0-exact.gguf
llama.cpp 为 Gemma 4 的 drafter 提供了专门的推测解码类型 draft-mtp。在常规服务端命令中增加两个参数:
llama-server -m gemma-4-E2B-it-q4_0-exact.gguf -ngl 99 -fa 1 \
-md gemma-4-E2B-it-qat-assistant-q4_0-exact.gguf \
--spec-type draft-mtp -ngld all --spec-draft-n-max 2
服务端日志会确认 drafter 已加载,并针对每个请求报告 target 接受了多少个猜测:
I common_speculative_init_result: loading draft model '/home/xbill/models/gemma-4-E2B-it-qat-assistant/gemma-4-E2B-it-qat-assistant-q4_0-exact.gguf'
I slot print_timing: id 0 | task 8 | draft acceptance = 0.84656 ( 160 accepted / 189 generated), mean len = 2.68
这个请求使用的是编程 prompt:189 个猜测中有 160 个被接受,target 每次前向传播平均产出 2.68 个 token。
测试在 RTX 3050 上进行,上下文长度为 8,192 个 token,单独运行 E2B target 时占用 2,795 MiB 显存:
精确 drafter 的显存开销比 Q8_0 转换版本少三分之一。E4B 也呈现相同规律:分别增加 84 MiB 和 122 MiB。在只有 4 GB 显存的笔记本显卡上,省下的每一 MB 都可以留给上下文或作为余量。
文件变小也没有改变猜测结果:使用 Q4_0、Q8_0 和 Google 的 bf16 drafter 时,target 接受草稿 token 的比例相同。第二篇会介绍这对速度意味着什么。
本文测量的是 llama.cpp 的 draft-mtp 路径。此外,还有两种运行方式:
Hugging Face Transformers:向 generate() 传入 assistant_model=,这是 Google 文档介绍的方式。
vLLM:使用 --speculative-config '{"method":"mtp", ...}',本仓库也在 Cloud TPU v5e 上测量了这条路径。
每多猜一个 token,都必须保证前面的猜测正确,后面的猜测才有机会被接受。在 RTX 3050 上,两个模型的最佳设置都是每步起草两个 token;在配备 GTX 1650 Ti 的笔记本上,最佳设置则是一个。只有面对代码等高度可预测的输出时,才应提高这个数量。
对于通过 llama.cpp 部署的 Gemma 4 QAT target,应选择精确 Q4_0 QAT drafter。它符合 Google 对 target 与 drafter 精度一致的要求,文件最小、最接近 Google 原始权重、显存开销最低,而且 target 接受其猜测的比例与更大的文件相同。
当 GPU 受显存带宽限制,且只有一个或少数几个用户时,可以启用它。下一篇会测量它究竟能快多少、对哪些文本有效,以及用户增加到什么程度后,drafter 就不再划算。
本文的目标是解释 Gemma 4 MTP drafter 的推测解码机制,并介绍 Google QAT drafter 的精确 4-bit 重新打包版本。方案的关键在于 Google 对 drafter 的设计:一个复用 target 状态和 KV cache 的 4 层模型,训练时采用与 QAT target 相同的 4-bit 网格。结果如下:
🟢 drafter 负责猜测,target 在一次前向传播中验证多个 token,而每个 token 仍由 target 决定。
🟢 Gemma 4 的 drafter 不维护自己的 KV cache:它由 4 层、宽度为 256 的网络组成,读取 target 的隐藏状态。
🟢 精确 Q4_0 QAT drafter 已发布到 Hugging Face:E2B 为 59.2 MB,E4B 为 59.7 MB,比 llama.cpp 转换得到的 Q8_0 小 39–40%,与 Google 原始权重的接近程度达到其 3.6 倍。
🟢 E2B drafter 增加 80 MiB GPU 显存占用,Q8_0 则增加 120 MiB,bf16 增加 188 MiB。
⚠️ 收益取决于文本内容和用户数量;第二篇会给出实测数据。
⚠️ 批量验证时,如果候选分数非常接近,贪心解码生成的文本可能发生变化。
范围:Google 为 Gemma 4 E2B 和 E4B 发布的 QAT drafter,使用 gguf_exact.py 重新打包,通过 llama.cpp 77c4540ce 部署。测试于 2026-10-14 在一张 RTX 3050 OEM(8 GB)上进行,上下文长度为 8,192 个 token。有关 drafter 的描述来自 Google 的模型卡、MTP 文档,以及各 checkpoint 的 config.json。
向本地 llama.cpp 部署添加 Gemma 4 MTP drafter 的方案,已经通过逐步推进、逐项验证的方式得到验证。
xbill9/gemma-4-E2B-it-qat-assistant-q4_0-exact-gguf | Hugging Face
xbill9/gemma-4-E4B-it-qat-assistant-q4_0-exact-gguf | Hugging Face
google/gemma-4-E2B-it-qat-q4_0-unquantized-assistant | Hugging Face
google/gemma-4-E2B-it-assistant | Hugging Face
xbill9/gemma-4-E2B-it-qat-q4_0-exact-gguf | Hugging Face
local-llamacpp-3050oem-2b-q4_0 | GitHub
在二手 8 GB RTX 3050 上运行 Gemma 4 | dev.to
如需进一步处理,可以考虑屏蔽此人和/或举报滥用行为。