把图像量化成离散 id、与文本 BPE 合成一张表,多模态生成就退化为纯粹的 next-token prediction——统一 token 空间的全部收益与全部代价,都来自这一步。

统一词表买到了什么

合表之后,模型侧不再有「多模态」这件事:一张 embedding 表、一个 softmax、一套交叉熵,图文交错生成与纯文本续写走完全相同的代码路径。这带来三处实质简化——训练目标唯一(不需要对比损失或 diffusion 分支)、图文可任意交错而非固定「图在前文在后」、图像输出天然继承 LLM 的采样与约束工具链。

代价同样集中:量化是有损的,码本重建误差成为视觉质量的硬上限;词表变大后模态在共享 softmax 里互相挤压。两条路线的分野见 视觉 Tokenizer,本篇只谈合表这一侧。

词表合并的机械细节

文本 id 占低位、码本 id 整段追加在高位,模态边界 token 从文本词表里预留——这是所有实现的共同骨架:

import torch
 
# 单一 id 空间:文本 BPE 占低位,VQ 码本整段追加在高位
V_TEXT, V_IMAGE = 57_344, 8_192              # Chameleon 量级
BOI, EOI = 57_342, 57_343                    # 文本词表内预留的模态边界 token
IMG_BASE, VOCAB = V_TEXT, V_TEXT + V_IMAGE   # 65_536
 
# 512×512 图 → 32×32 码本网格 → 1024 个 id,首尾包边界
codes = [(r * 32 + c) % V_IMAGE for r in range(32) for c in range(32)]
seq = [BOI, *(IMG_BASE + c for c in codes), EOI]
print(VOCAB, len(seq), seq[:2])              # 65536 1026 [57342, 57344]
 
def mask_modality(logits, modality):
    """共享 softmax 必须外挂约束:否则图像段中途会蹦出文本 token。"""
    out = torch.full_like(logits, float("-inf"))
    lo, hi = (0, IMG_BASE) if modality == "text" else (IMG_BASE, VOCAB)
    out[..., lo:hi] = logits[..., lo:hi]
    out[..., EOI] = logits[..., EOI]         # 边界 token 恒可达,用于收尾
    return out
 
nxt = mask_modality(torch.randn(1, VOCAB), "image").argmax(-1).item()
assert nxt >= IMG_BASE or nxt == EOI

三条容易踩的工程约束:

  • 码本 id 绝不能进 merge 表。它们是纯追加 token,必须绕过 pre-tokenizer 与 BPE 合并逻辑,否则会被当作普通字节序列拆开。Chameleon 用 SentencePiece 训文本侧 BPE,把 8192 个码本 token 直接纳入 65,536 的词表,正是靠这种「保留符号」机制,用法见 SentencePiece
  • 边界 token 承担模态切换语义,<image>/</image> 的角色与对话模板里的角色标记同构,注册方式见 特殊 Token 与 Chat Template
  • embedding 与 lm_head 同步扩容,8192 个新 token 在 下是 33.5M 参数,不共享权重时翻倍;词表膨胀对显存与输出层计算的影响见 词表设计与裁剪

Chameleon:同表自回归的样板

Meta 的 Chameleon 是 early-fusion 路线最干净的公开实现:Gumbel-VQ 图像 tokenizer,码本 8192,512×512 图编码为 1024 个 token;文本 BPE 与码本合并为 65,536 词表;图文交错序列上做单一 next-token prediction,7B/34B 两档。

真正的贡献不在架构而在稳定性。混合模态训练在规模放大后会发散,根因是 softmax 的平移不变性叠加模态竞争:文本与图像 token 各自把自己的 logit 范数往上推,无界增长直至数值崩溃。论文给出的处方是 QK-Norm(对 attention 的 query/key 做 LayerNorm,直接掐住 logit 增长),7B 额外加 dropout,34B 改用 norm reordering。这个失效模式是统一词表特有的——纯文本训练不会遇到。

另一处实测教训:该 tokenizer 对含大量文字的图像重建极差,OCR 类任务上的短板来自 tokenizer 而非 LLM。统一词表把视觉能力的天花板前移到了量化器。

跨模态对齐的真实难题

症状根因常见对策
训练 loss 发散模态争夺共享 softmax,logit 范数无界增长QK-Norm、norm reordering
单模态遗忘 / 偏斜图像 token 数量级压过文本,梯度被视觉主导按模态加权损失、控制数据混比
「统一」只是名义上的文本与图像 embedding 收敛到近乎不相交的子空间交错数据、跨模态注意力监督
错一个 token 全图崩码本 id 是扁平原子,无前缀结构、无字节兜底加大码本、残差多级量化
空间关系错乱二维网格被展平成一维 raster 序列行分隔 token、多维位置编码

第三行最反直觉:合表并不自动产生语义对齐。码本 id 之间没有 BPE 算法原理 里那种 merge 层级——id 100 与 101 毫无关系,也没有字节级兜底保证未见内容可表达。文本 token 的可组合性在视觉侧完全不存在。

第四行对推理的影响最直接:自回归逐 token 生成图像时,一次采样偏差会沿 raster 顺序向后污染整张图,且无法像文本那样靠上下文自我纠正。解码约束与采样敏感性参见 Tokenizer 对推理的影响。

向音频与视频扩展

瓶颈从词表大小换成序列长度。音频离散化普遍用残差向量量化(RVQ),每帧产出 个码本 token,总量为 :

模态 / 编码器token 率1 分钟
512×512 图像(VQ-8192)1024 / 图—
HuBERT 语义 token50 Hz × 13,000
EnCodec 24 kHz @6 kbps75 Hz × 8 码本 = 600/s36,000
Mimi(Moshi)12.5 Hz × 8 码本 = 100/s6,000
视频 8 fps,时间维 4× 压缩≈2,048/s≈123,000

这张表解释了为什么实时语音对话必须压到 12.5 Hz 量级:600 token/s 的码率下,一分钟音频就吃掉 36k 上下文。Mimi 的做法是把语义信息蒸馏进第一个码本,低帧率下仍保住可懂度。

多码本还带来结构问题:朴素展平把序列拉长 倍。延迟模式(delay pattern)用阶梯错位换取每步并行输出 个 token:

# RVQ 每帧 K 个码本:朴素展平 K×T 步,延迟模式只需 T+K-1 步
K, T = 4, 6
frames = [[f"c{k}t{t}" for k in range(K)] for t in range(T)]
flat = [tok for f in frames for tok in f]
delay = [[frames[t - k][k] if 0 <= t - k < T else "·" for k in range(K)]
         for t in range(T + K - 1)]          # 第 k 个码本整体后移 k 帧
print(len(flat), len(delay))                 # 24 9
print(*(" ".join(r) for r in delay[:3]), sep="\n")

Gemini 系的「原生多模态」常被读成全离散统一词表,实际是混合的:音频以 16 kHz 特征形式进入统一序列,图像输出则走离散 image token。输入侧可以连续、输出侧必须离散——需要自回归生成的模态才真正需要进词表。BAAI 的 Emu3 走了更彻底的一端:32,768 码本覆盖图像与视频,纯 next-token prediction 一套目标打通理解与生成。

离散 vs 连续注入的架构分野

路线视觉表示词表变动原生生图代表
连续注入CLIP/SigLIP 特征经 projector 进输入层无否LLaVA、Qwen-VL
统一离散词表VQ 码本 id文本 + 码本合并是Chameleon、Emu3
双通路解耦理解走连续、生成走离散,共享 transformer合并但输入分流是Janus-Pro
单模型双目标连续 latent + diffusion 损失无是Transfusion

分野的判据是是否愿意为架构统一支付量化损失。连续注入在理解任务上始终占优——没有信息瓶颈;统一词表换来生成能力与目标函数的唯一性。

后两行是对这个二选一的正面反抗。Janus-Pro 的观察是理解与生成需要不同粒度的视觉表示,强行共用一个 tokenizer 必然两头妥协,于是保留统一 transformer、拆开视觉编码前端。Transfusion 更激进:不量化,图像在连续 latent 上算 diffusion 损失、文本算 LM 损失,两个目标共存于一个序列——统一的是模型而非词表。