系列:推测解码手记

推测解码:让大模型“一次生成多个 token”的无损加速

1. 动机:自回归生成的串行瓶颈

今天的大语言模型(LLM)基本都是自回归(autoregressive)生成:每产出一个 token,就要把包括这个新 token 在内的全部上下文喂回模型,跑一次完整前向。换句话说,生成是严格串行的——第 t+1 个 token 必须等第 t 个算完。

这意味着两件事:

有没有可能让一次大模型前向顺带多产出几个 token?这正是推测解码(Speculative Decoding, SD)要解决的问题。

2. 核心思想:Draft + Verify 两阶段

SD 引入一个草稿模型(draft / small model):它比目标大模型小得多、便宜得多,但“大致同任务”。生成不再是“大模型一步步走”,而是两轮协作:

  1. 起草(Draft):用小模型一次性并行草拟出接下来的一整块候选 token(比如 4 个)。
  2. 验证(Verify):把这块候选整体交给大模型做一次并行前向,大模型对每个候选独立给出“接受 / 拒绝”的判断(基于拒绝采样)。

被接受的候选直接采用;第一个被拒绝的位置,大模型用自己的预测覆盖,并从那里继续。关键在于:无论草案多长,大模型只跑了一次前向——所以如果草案大部分被接受,我们就“用一次前向换来了多个 token”。

直觉:让便宜的小模型先“猜”一串,贵的大模型只“看一眼”就盖章。猜得越准,加速越大。

草稿模型(小)
目标模型(大)
点击「开始」观察 Draft → Verify 循环

3. 为什么无损?拒绝采样

这是 SD 最迷人的性质:输出分布与目标大模型逐 token 完全一致,零质量损失。

秘密在拒绝采样(rejection sampling)。大模型在验证时并不是“全接受”或“全拒绝”,而是按概率逐 token 重新抽样:

所以 SD 不改变模型“会说出什么”,只改变“说出得多快”。这一点对生产部署极其重要——你可以用 SD 提速,而不必担心回答质量下降。

4. 加速从哪来?接受长度 α

设一次大模型前向耗时 ≈ 1 单位,起草 k 个 token 的小模型耗时 ≈ β·k(β≪1)。若平均有 α 个候选被接受(接受长度 acceptance length),则每产出 α 个 token 的总成本 ≈ 1 + β·k。

加速比 ≈ α / (1 + β·k)。

可见:

5. 最小直觉例子

假设起草 4 个 token,大模型一次验证后接受了前 3 个、在第 4 个位置拒绝并用自己的预测替换:

在这一步里,我们相当于把“4 次”压成了“1 次”——这就是 SD 加速的来源。

6. 小结与下篇预告

觉得有用?欢迎点赞、收藏,或请作者喝咖啡 ☕️

支付宝收款码

支付宝

微信收款码

微信

💬 留言

评论由 Giscus 驱动(基于 GitHub Discussions)。 当前仓库 NaphJohn/LLM-blog 尚未启用 Discussions:请在 GitHub 仓库 Settings → General → Features 勾选 Discussions 后刷新本页,评论区即自动显示。