【技术跟进】投机解码:从“小模型先猜”到系统级推理加速

大语言模型生成慢,原因不在“它不会一次想很多字”,而在自回归解码的机制:每生成一个 token,都要完整跑一遍目标模型。模型越大,每一步读取权重、更新 KV Cache、调度显存的成本越高。哪怕 GPU 算力很强,解码阶段也经常卡在显存带宽和串行依赖上。

投机解码(Speculative Decoding)就是围绕这个瓶颈做的一类方法。它的基本思路很像写作和审稿:先让一个便宜的草稿器快速写几步,再让真正的大模型一次性审一段。审过的就留下,出错的地方由大模型接管。只要验证规则设计正确,最终输出分布仍然等价于目标模型自己逐 token 生成。


1 为什么投机解码能加速

普通自回归生成是这样的:

flowchart LR
    P[Prompt + 已生成前缀] --> M1[目标大模型前向]
    M1 --> T1[生成 token 1]
    T1 --> M2[目标大模型前向]
    M2 --> T2[生成 token 2]
    T2 --> M3[目标大模型前向]
    M3 --> T3[生成 token 3]
    T3 --> Dots[...]

每一步都要完整跑目标模型。生成 100 个 token,就要做 100 次解码前向。投机解码改成:

flowchart LR
    P[Prompt + 已生成前缀] --> D[草稿模型快速生成 K 个候选 token]
    D --> C[候选序列]
    C --> V[目标大模型一次性并行验证]
    V --> A{接受到哪里?}
    A -->|前 m 个通过| O[输出 m 个草稿 token]
    A -->|第 m+1 个失败| F[目标模型修正失败位置]
    O --> N[进入下一轮]
    F --> N

这里省下来的不是“小模型比大模型聪明”,而是大模型的调用次数。大模型一次前向可以并行看多个位置,代价不会像逐 token 解码那样线性增加。草稿模型虽然也要算,但它通常很小,或者直接内置在目标模型里,成本远低于完整目标模型。

更直白地说:

  • 传统解码:大模型跑 10 次,生成 10 个 token;
  • 投机解码:草稿器先猜 5 个,大模型跑 1 次验证,可能一次接受 3~5 个 token;
  • 只要草稿够快、接受率够高,总延迟就会明显下降。

2 标准投机解码的完整流程

先定义几个角色:

角色 含义
Target model 目标大模型,最终输出必须服从它的分布
Draft model / Proposer 草稿生成器,负责快速提出候选 token
Verification 目标模型对草稿 token 做并行验证
Acceptance 根据验证结果接受一段前缀,拒绝后续草稿

一个完整循环可以拆成五步。

2.1 草稿生成

当前已有前缀:

$$ \begin{aligned} x_1, x_2, \dots, x_t \end{aligned} $$

草稿模型先生成一段候选:

$$ \begin{aligned} \hat{x}_{t+1}, \hat{x}_{t+2}, \dots, \hat{x}_{t+K} \end{aligned} $$

这个过程可以是普通小模型自回归,也可以是 EAGLE 的特征草稿,也可以是 MTP 模块,也可以是 DSpark 这种半自回归草稿器。

2.2 目标模型并行验证

目标模型不再只看一个 token,而是把候选 token 拼到上下文后面,一次性计算多个位置的分布:

$$ \begin{aligned} p_T(x_{t+1}&|x_{\le t}) \\ p_T(x_{t+2}&|x_{\le t}, \hat{x}_{t+1}) \\ p_T(x_{t+3}&|x_{\le t}, \hat{x}_{t+1}, \hat{x}_{t+2}) \\ \dots \end{aligned} $$

因为 Transformer 在一个序列内可以并行计算不同位置的 hidden states,所以这一步比“目标模型一步一步生成 K 次”便宜很多。

2.3 接受或拒绝

如果是贪婪解码,可以简单理解为:草稿 token 是否等于目标模型在对应位置会选的 token。

如果是采样解码,则会用更严格的拒绝采样规则,保证最终分布仍然等价于目标模型。直觉上,如果草稿分布和目标分布很接近,token 就更容易被接受;如果草稿模型猜偏了,就拒绝并让目标模型重新采样修正。

flowchart TD
    A[草稿 token 序列] --> B[目标模型计算每个位置的目标分布]
    B --> C{第 1 个 token 是否接受?"}
    C -->|否| R1[拒绝全部草稿,用目标模型采样修正]
    C -->|是| D{第 2 个 token 是否接受?}
    D -->|否| R2[接受第 1 个,修正第 2 个,丢弃后续]
    D -->|是| E{继续检查...}
    E -->|通过更多| O[接受最长合法前缀]

2.4 更新 KV Cache

被接受的 token 会进入正式上下文,目标模型验证时产生的 KV Cache 也可以复用。被拒绝位置之后的草稿 token 会丢弃。

2.5 进入下一轮

继续从最新上下文出发,重复“草稿生成 → 目标验证 → 接受/修正”。

整体流程如下:

sequenceDiagram
    participant U as 当前上下文
    participant D as 草稿生成器
    participant T as 目标大模型
    participant S as 接受/拒绝逻辑

    loop 直到生成结束
        U->>D: 输入当前前缀和必要 hidden state
        D->>D: 快速提出 K 个候选 token
        D->>T: 拼接候选序列,请目标模型并行验证
        T->>S: 返回每个位置的目标分布 / logits
        S->>S: 接受最长合法前缀
        S->>U: 追加接受 token;必要时追加目标模型修正 token
    end

投机解码能不能快,核心看三个量:

  1. 草稿成本:草稿器越便宜越好;
  2. 接受率:草稿越像目标模型,越容易一次接受更多 token;
  3. 验证效率:目标模型一次验证多个 token 时,硬件利用率是否真的提升。

3 普通小模型草稿:最朴素的投机解码

最早、最容易理解的方案,是直接找一个小模型当草稿模型。

flowchart LR
    P[当前前缀] --> S[小草稿模型]
    S --> D[候选 token 1..K]
    D --> T[目标大模型验证]
    T --> A[接受 / 拒绝]

这种方式简单、通用,不需要改目标模型结构。但它有几个麻烦:

  • 小模型太小,猜得不准,接受率低;
  • 小模型太大,草稿成本高,抵消加速;
  • tokenizer、训练数据、模型风格不一致,也会影响接受率;
  • 在开放式对话、复杂推理场景,草稿模型容易越猜越偏。

所以后来的主流工作基本都在问同一个问题:能不能做一个更便宜、更贴近目标模型的草稿器?EAGLE、MTP 和 DSpark 都是在回答这个问题,只是路线不同。


4 EAGLE:利用目标模型特征生成草稿

4.1 EAGLE-1:从 token 草稿转向特征草稿

EAGLE-1 的核心想法是:不要让一个小语言模型从头预测 token,而是利用目标大模型已经算出来的 hidden state。

目标模型在输出 token 前,会先形成高层语义特征。EAGLE 认为,与其直接预测离散 token,不如预测目标模型下一步的高层特征,然后再复用目标模型的 LM Head 转成 token 分布。

简化信息流如下:

flowchart TD
    subgraph Target[目标大模型]
        A[当前前缀] --> L1[Transformer 前面多层]
        L1 --> H[倒数第二层 hidden state]
        H --> Last[最后一层 / LM Head]
        Last --> Y[目标模型下一个 token 分布]
    end

    subgraph Eagle[EAGLE-1 草稿器]
        H --> F[轻量 draft layer]
        E[上一步采样 token 的 embedding] --> F
        F --> HP[预测下一位置 hidden state]
        HP --> Head[复用目标模型 LM Head]
        Head --> D[草稿 token]
    end

这里有一个很关键的细节:EAGLE 不是简单“少算一层”。它的草稿器是一个很小的额外模块,参数量通常只占目标模型的一小部分。它站在目标模型已经算出的高层特征上继续外推,所以草稿成本远低于重新跑完整目标模型。

为什么要把 token embedding 也喂进去?因为 hidden state 的未来走向和实际采样出的 token 有关。只知道当前特征,不知道下一步 token,未来特征会有很大不确定性。EAGLE 用“特征 + token”一起预测,缓解了这个问题。它的训练损失是 MSE 特征回归 + KL 散度分布对齐。

EAGLE-1 还常配合树状草稿和 Tree Attention(修改 Attention Mask 使每个节点只看到其祖先节点),一次前向传播就能并行验证整棵树上所有路径。草稿器不是只生成一条路径,而是展开多个候选分支,再由目标模型一次性验证整棵树。

flowchart TD
    R[当前上下文] --> A1[token A]
    R --> B1[token B]
    R --> C1[token C]
    A1 --> A2[token A2]
    A1 --> A3[token A3]
    B1 --> B2[token B2]
    C1 --> C2[token C2]
    C1 --> C3[token C3]
    Tree[目标模型用 Tree Attention 一次验证多条路径]
    A2 --> Tree
    A3 --> Tree
    B2 --> Tree
    C2 --> Tree
    C3 --> Tree

EAGLE-1 的价值在于,它证明了“贴近目标模型内部表示”的草稿器比普通小模型更有效。


4.2 EAGLE-2:动态草稿树,把预算花在更可能通过的路径上

EAGLE-1 的树一般比较固定:每层展开多少分支、展开多深,提前设好。问题是,不同上下文的难度差别很大。

有些地方非常确定:

1
Thank you very much for ...

后面可能很容易猜。

有些地方分歧很大:

1
The best solution is ...

可能接代码、数学推导、建议列表,也可能继续解释。

如果还用固定树,就会浪费很多验证预算。EAGLE-2 的核心改进是动态草稿树:根据草稿模型当前的置信度,决定哪些分支继续扩展,哪些分支提前剪掉。

flowchart TD
    R[当前上下文] --> P[草稿模型给出候选 token 及置信度]
    P --> S[计算路径分数:父节点分数 × 当前 token 置信度]
    S --> K[选择全局最有希望的节点]
    K --> E[继续扩展高分节点]
    E --> C{达到 token 预算或最大深度?}
    C -->|否| S
    C -->|是| V[目标模型验证动态草稿树]

直觉上:

  • 高置信路径更可能被连续接受,值得往深处展开;
  • 低置信路径就算展开很多,最后也大概率被拒绝;
  • 同样的草稿 token 预算,动态树比固定树更划算。

EAGLE-2 没有从根上改变 EAGLE 的草稿模型训练,它主要优化“怎么组织草稿”。这个改动看似工程,实际上很重要:投机解码不是只看草稿器强不强,还要看验证预算怎么分配。


4.3 EAGLE-3:直接预测 token,并融合多层特征

EAGLE-3 又往前走了一步。EAGLE-1/2 的草稿器主要做 feature prediction:预测下一位置的 hidden feature,再通过 LM Head 得到 token。EAGLE-3 认为,这个连续特征回归任务本身会限制扩展性,于是转向直接预测 token。

同时,它不再只依赖目标模型的高层特征,而是融合多层 hidden states。因为不同层保存的信息不同:

层级 更偏向的信息
低层 词形、局部语法、短距离模式
中层 短语结构、局部语义、任务线索
高层 全局语义、意图、下一个 token 分布

EAGLE-3 的信息流可以这样看:

flowchart TD
    subgraph Target[目标大模型]
        X[当前上下文] --> LLow[低层 hidden state]
        LLow --> LMid[中层 hidden state]
        LMid --> LHigh[高层 hidden state]
    end

    LLow --> Cat[多层特征融合]
    LMid --> Cat
    LHigh --> Cat
    Cat --> DModel[EAGLE-3 draft model]
    DModel --> Tok[直接预测草稿 token]
    Tok --> Verify[目标模型并行验证]

它还有一个关键词:Training-Time Test。可以把它理解为训练阶段尽量模拟推理阶段的使用方式,让草稿器在训练时就学会面对自己的预测结果,而不是只在“老师给的真实特征”上学习。这样能缓解训练和推理之间的分布偏移。

EAGLE-3 的变化可以总结成三句话:

  1. 从“预测 hidden feature”转向“直接预测 token”;
  2. 从“只看高层特征”转向“融合多层特征”;
  3. 从“训练时条件太理想”转向“训练时更接近推理时”。

所以 EAGLE 系列的发展脉络很清楚:

flowchart LR
    E1[EAGLE-1<br/>特征级草稿<br/>复用目标模型表示] --> E2[EAGLE-2<br/>动态草稿树<br/>置信度驱动扩展]
    E2 --> E3[EAGLE-3<br/>直接 token 预测<br/>多层特征融合<br/>Training-Time Test]

5 MTP:把草稿能力直接长进模型里

MTP 是 Multi-Token Prediction,多 token 预测。和 EAGLE 这种“给目标模型外挂一个草稿器”的思路不同,MTP 更像是在模型训练阶段就让它学会看得更远。

普通语言模型训练目标是:

1
当前位置 hidden state → 预测下一个 token

MTP 额外加入:

1
当前位置 / 后续辅助状态 → 预测下下个、下下下个 token

在一些模型中,MTP 会表现为一个或多个额外的轻量预测模块。它们通常共享主模型的 embedding 和 LM Head,只增加少量 Transformer block 或预测层。

flowchart TD
    X[输入 token 序列] --> Emb[共享 Embedding]
    Emb --> Main[主模型 Transformer]
    Main --> H[主模型 hidden state]
    H --> Head[共享 LM Head]
    Head --> Y1[主任务:预测 token t+1]

    H --> MTP[MTP 模块]
    Emb2[未来 token embedding / 移位输入] --> MTP
    MTP --> Head2[共享 LM Head]
    Head2 --> Y2[辅助任务:预测 token t+2 / t+3]

训练时,MTP 是辅助目标:

1
总损失 = 主 next-token loss + λ × MTP loss

推理时,MTP 模块就可以当内置草稿器:

sequenceDiagram
    participant P as 当前前缀
    participant M as 主模型
    participant H as MTP 模块
    participant V as 验证逻辑

    P->>M: 主模型前向,得到 hidden state 和下一个 token 分布
    M->>H: 传入 hidden state / embedding
    H->>H: 预测一个或多个未来 token
    H->>V: 提交草稿 token
    V->>M: 主模型并行验证草稿
    M->>V: 返回目标分布
    V->>P: 接受通过的 token,拒绝并修正失败位置

MTP 的优势是干净:

  • 不需要额外找一个小模型;
  • 草稿模块和主模型共享词表、embedding、LM Head,天然对齐;
  • 训练阶段的多 token 监督也可能反过来提升主模型表示质量;
  • 部署时只要推理框架支持,就能直接使用。

它的局限也明显:

  • 必须模型本身训练时就带 MTP,普通模型不能凭空获得;
  • 如果只有浅层 MTP,通常适合预测较短未来,比如 1~2 个 token;
  • 预测越远,接受率越容易下降;
  • 对不同模型、不同推理框架的支持差异很大。

所以 MTP 更像“模型原生加速接口”,而 EAGLE 更像“针对已有模型训练一个高质量草稿器”。


6 DSpark:从草稿模型优化走向系统级调度

DSpark 投机解码框架关注的不只是“怎么猜得准”,还包括“在高并发服务里,哪些草稿值得送去验证”。

它解决两个很现实的问题:

  1. 并行草稿器一次生成很长序列很快,但后面的 token 因为缺少依赖,接受率会快速下降;
  2. 高并发服务中,把低置信度草稿都送给目标模型验证,会浪费最贵的 batch capacity。

DSpark 的整体结构大致如下:

flowchart TD
    A[目标模型上一轮输出 anchor / bonus token] --> B[DFlash-style 并行 backbone]
    B --> C[一次得到多个位置的 hidden state 和 base logits]
    C --> D[Markov head / 轻量顺序 head]
    D --> E[注入 block 内 token 依赖]
    E --> F[生成草稿 token 序列]
    C --> G[Confidence head]
    G --> H[预测每个位置条件接受概率]
    F --> I[Hardware-aware prefix scheduler]
    H --> I
    I --> J[裁剪低价值后缀,只保留值得验证的 prefix]
    J --> K[目标模型并行验证]
    K --> L[接受最长合法前缀并进入下一轮]

6.1 半自回归草稿:并行速度 + 少量顺序依赖

纯并行草稿器的问题是,每个位置可能各猜各的,缺少 token 之间的依赖。比如前面想走 “of course”,后面却接成 “of problem”。这种碰撞会让越靠后的 token 越容易被拒绝。

DSpark 采用半自回归生成:

  1. 先用并行 backbone 一次性给出多个位置的基础 logits;
  2. 再用很轻的顺序模块给每个位置加一个依赖前一个 token 的 bias。

默认的 Markov head 只看前一个 token。它很简单,但足够修正大量局部搭配问题。

flowchart LR
    Base[并行 backbone 输出 base logits] --> Add[加上 transition bias]
    Prev[前一个草稿 token] --> Markov[Markov head]
    Markov --> Add
    Add --> Next[当前位置草稿 token 分布]

这让 DSpark 同时拿到两种好处:

  • 并行 backbone 保持长 block 生成吞吐;
  • Markov head 用极低成本补上局部顺序依赖,缓解后缀接受率衰减。

6.2 Confidence head:先估计值不值得验证

DSpark 还为每个草稿位置预测一个条件接受概率:

1
c_k = 第 k 个草稿 token 在前面都接受的条件下,也被目标模型接受的概率

那么长度为 j 的 prefix 存活概率就是:

1
a_j = c_1 × c_2 × ... × c_j

这个值很关键,因为投机解码真正关心的是“连续接受多少个”。第 5 个 token 单看概率高没有用,前 4 个过不了,它也不会被用到。

6.3 Hardware-aware prefix scheduler:按负载决定验证多长

传统投机解码经常固定验证 K 个 token。但生产系统里,负载是变化的:

  • 低并发时,多验证几个 token 可能很划算;
  • 高并发时,目标模型 batch capacity 很贵,低置信度 token 不该占坑;
  • 代码、数学、闲聊的接受率也不一样。

DSpark 用硬件感知调度器动态决定每个请求验证多长。它会综合:

  • 每个请求每个位置的 prefix survival probability;
  • 当前 batch size;
  • 推理引擎在不同 batch size 下的 steps-per-second 曲线;
  • 验证更多 token 带来的期望收益和额外成本。
flowchart TD
    R[多个并发请求] --> C[收集每个请求的置信度序列]
    C --> P[计算 prefix 存活概率]
    P --> Q[按边际收益排序候选 token]
    Q --> B[结合硬件吞吐曲线估计总吞吐]
    B --> S{继续加入验证 token 是否提升吞吐?}
    S -->|是| Add[加入验证 batch]
    Add --> B
    S -->|否| Stop[停止,输出每个请求的验证长度]

DSpark 的意义在于:它把投机解码从算法层推进到了系统层。以前大家主要盯着 draft model 的接受率;DSpark 进一步问:在真实服务里,目标模型每一格验证预算应该给谁?


7 结语

投机解码的核心并不复杂:便宜模型先猜,贵模型批量审。真正复杂的是,怎么让草稿既便宜又像目标模型,怎么让验证预算花在最可能通过的位置上,以及怎么在高并发系统里把吞吐和延迟一起优化。

EAGLE 系列代表了“围绕目标模型内部表示训练高质量草稿器”的路线:

  • EAGLE-1 把草稿从 token 层推进到特征层;
  • EAGLE-2 用动态树提升草稿预算利用率;
  • EAGLE-3 融合多层特征并转向直接 token 预测,进一步提升扩展性。

MTP 代表了“模型原生支持多 token 预测”的路线。它把草稿能力做进模型训练目标里,推理时自然变成内置草稿器。

DSpark 则代表了更新的趋势:不只优化草稿模型,还要优化系统调度。它用半自回归草稿保证长草稿质量,再用置信度和硬件吞吐曲线决定每个请求到底验证多长。

所以,投机解码的发展方向已经很清楚:从单纯的“小模型加速大模型”,走向“模型结构、草稿算法、验证策略、服务系统”四者协同设计。真正有价值的加速,不是实验室里某个请求快了几倍,而是在真实流量下,让更多用户稳定、更便宜地拿到目标模型质量的输出。

方法 草稿来源 核心优势 主要问题 适合场景
小模型草稿 独立小语言模型 通用、直观、易实现 对齐难,接受率不稳定 有合适 assistant model 的通用生成
EAGLE-1 目标模型特征 + 轻量草稿层 草稿更贴近目标模型 静态树可能浪费预算 需要为目标模型训练配套草稿器
EAGLE-2 EAGLE + 动态草稿树 更高效利用 token 预算 仍依赖 EAGLE 草稿质量 上下文难度变化大的生成任务
EAGLE-3 多层特征融合 + 直接 token 预测 更强、更可扩展 训练和部署复杂度更高 高性能推理框架、服务化部署
MTP 模型内置多 token 预测模块 原生对齐,无需外部小模型 必须模型架构支持 DeepSeek、GLM 等带 MTP 的模型
DSpark 半自回归草稿 + 置信调度 同时优化草稿质量和系统吞吐 工程系统复杂 高并发、生产级 LLM 服务

如果只看技术路线,可以画成这样:

flowchart TD
    SD[投机解码] --> A[外部草稿模型]
    SD --> B[目标模型特征草稿]
    SD --> C[模型内置多 token 预测]
    SD --> D[系统级调度]

    A --> A1[小模型 Assistant]
    B --> B1[EAGLE-1 特征预测]
    B1 --> B2[EAGLE-2 动态树]
    B2 --> B3[EAGLE-3 多层融合 + 直接 token]
    C --> C1[MTP]
    D --> D1[DSpark 半自回归 + 置信调度]

【技术跟进】投机解码:从“小模型先猜”到系统级推理加速
http://xuan-van.github.io/7a08b50439b7/
作者
文晋
发布于
2026年7月7日
许可协议