又减少目标大模型的无效验证计算?

Speculative Decoding 是一种“轻量模型先生成草稿,目标大模型再批改确认”的加速方法。它的目标,是在尽量保持最终输出服从目标模型分布的前提下,让模型一次向前推进多个 token。

图1

这条路线看起来很直接:草稿模型(draft model)多生成一些候选 token,目标模型一次性验证。如果草稿足够准确,就能减少逐 token 生成带来的等待。

但在真实服务中,问题会变复杂。Draft block 变长,不代表最终被目标模型接受的 token 更多;verification 可以并行,也不代表验证越多越划算。尤其在高并发的在线推理服务中,目标模型的 batch capacity 是有限资源,低置信度 token 的验证会直接影响整体吞吐。

所以,DSpark 关注的核心问题不是“如何让草稿模型(draft model)多猜几个 token”,而是:如何让 draft token 更容易被接受,同时让目标模型只验证更值得验证的 token。

围绕这个问题,DeepSeek 提出了两个设计:用半自回归生成缓解****并行 draft 的后缀质量衰减;用置信度调度,根据 token 被接受的概率和系统负载动态决定 verification length。

接下来,我们先看 DSpark 要解决的两个关键问题。

为什么并行 draft 后面的 token 容易掉队?
在 Speculative Decoding 中,草稿模型(draft model)的作用是提前生成候选 token。为了提高草稿生成速度,一个直接思路是让草稿模型(draft model)一次生成更长的 draft block。

Draft block 可以理解为草稿模型(draft model)在一轮中提前生成的一整段候选 token。直觉上,draft block 越长,目标模型一次接受更多 token 的机会就越大。

但真正决定加速效果的,不在于 draft block 有多长,关键是 accepted length 能有多高。

Accepted length 指的是每一轮 Speculative Decoding 中,草稿 token 最终被目标模型接受的平均数量。它越高,说明模型每一轮可以向前推进更多 token,加速效果也越明显。现在的问题是长 draft block 并不天然带来更高 accepted length。

对于现有草稿模型(draft model),大体可分成两类。

第一类是 autoregressive drafter,也就是草稿模型自己也按顺序一个 token 一个 token 地生成。这样做的好处是,后面的 token 可以依赖前面已经生成的 token,所以序列更连贯;缺点也同样明显:草稿生成本身会变慢,block 越长,draft 的计算时间越长。

第二类是 parallel drafter,也就是一次性并行生成一整段候选 token。它的优势是快,因为所有位置的 token 可以在一次 forward pass 中同时生成。Forward pass 可以理解为模型完成一次从输入到输出的完整计算过程。

但并行生成也有一个结构性问题:每个位置的 token 是同时预测的,后面的 token 并不知道前面实际采样出了什么。

DeepSeek 举了一个很直观的例子。比如上下文后面既可以接 “of course”,也可以接 “no problem”。这两个续写本身都合理。但如果每个位置独立预测,模型可能把不同续写路径混在一起,生成 “of problem” 或 “no course” 这样的组合。

这类问题被称为 multi-modal collision,意思是“多个合理续写方向被混在了一起”。这会导致一个结果:draft block 越往后,token 越容易不连贯,也越容易被目标模型拒绝。这种现象也叫 suffix decay,可以理解为“后缀接受率衰减”。用一句话说,就是草稿越往后,越容易掉队。

图2

如上图所示,重点看不同 draft position 上的 conditional acceptance。Conditional acceptance 可以理解为:在前面 token 都已经被接受的前提下,当前位置 token 继续被接受的概率。

这张图要说明的是:DFlash(上图蓝线)这类纯并行 drafter 在前几个 token 上有较强预测能力,但越往后,conditional acceptance 会明显下降。也就是说,它不是不能快速生成 draft,只是越往后越容易猜偏。

这正是并行 draft 的核心问题:它在猜一整段时,不知道自己前面到底猜中了哪条语义路径。

因此,DSpark 要解决的第一个问题是:能不能保留并行生成的速度,同时让后面的 token 感知到前面已经生成的内容。

为什么 verification 在高并发服务里不能无脑做长?
长 draft block 的另一个问题,是 verification 资源浪费。

Verification 可以理解为目标模型对草稿 token 的“批改确认”。在 Speculative Decoding 里,目标模型验证的是连续前缀。也就是说,只要中间某个 token 被拒绝,后面的 token 即使本身质量不错,也会被一起丢弃。

这就带来一个问题:如果草稿模型一次生成了很多 token,但后半段大概率会被拒绝,那么把这些 token 全部送给目标模型验证,就可能是在浪费算力。

在单个请求、低负载场景下,这种浪费也许不明显。但在真实高并发服务中,问题会被放大。

因为目标模型的 batch capacity 是有限的。Batch capacity 意思是同一轮推理中,GPU 能同时处理多少请求或 token 的计算额度。在高并发情况下,每多验证一个低价值 token,就可能挤占其他用户请求的计算资源。

这也是 DSpark 论文反复强调的工程背景:verification 不是免费的。

同样是草稿 token,代码、数学这类结构化任务通常更容易被接受;开放聊天这种自由度更高的任务,后缀 token 的不确定性更强,被拒绝的概率也更高。

系统低负载时,可以多验证一点;系统高负载时,就要更谨慎地使用验证预算。

所以,Speculative Decoding 的难点不是“能不能多猜”,而是:

草稿 token 是否足够靠谱;

这些 token 是否值得占用目标模型的验证资源。

DSpark 的两个核心设计,正是围绕这两个问题展开的。

DSpark 的第一步:给并行 draft 加一点顺序依赖
针对并行 draft 后缀容易衰减的问题,DSpark 的第一个设计是 Semi-Autoregressive Generation,也就是半自回归生成。

这个名字容易让人误解。它不是让 草稿模型(draft model) 完全回到一个 token 一个 token 的自回归生成,而是在并行生成的基础上,引入一层很轻的顺序依赖。

前面提到,parallel drafter 的优势是快:它可以在一次 forward pass 中生成一整段 draft block。但它的问题也来自这里:多个位置同时预测,后面的 token 不知道前面实际采样出了什么,因此容易出现 multi-modal collision 和 suffix decay。

DSpark 的处理方式是折中。它保留 parallel backbone,也就是负责主要计算的并行主干结构。这个部分仍然一次性处理整个 draft block,保留并行生成的速度优势。

在此基础上,DSpark 额外加入 lightweight sequential head,也就是轻量顺序模块。这个模块的作用,是在 draft block 内给后续 token 补充局部顺序信息,让它们能够参考前面已经采样出来的 token。

图3

上图可以重点看两条路径。

第一条路径是 draft token 的生成。DSpark 先通过并行主干快速生成候选 token,再通过轻量顺序模块补上 block 内的局部依赖。

第二条路径是 confidence score 的生成。DSpark 在生成草稿的同时,也会估计每个位置的 token 有多大概率通过目标模型的动态调度提供依据。

所以,图片展示的不只是一个草稿模型(draft model) 结构,而是 DSpark 的完整解码循环:先生成候选 token,再估计其可接受性,最后决定交给目标模型验证多长的前缀。

在 sequential head 的实现上,DeepSeek 主要讨论了两种方案:Markov head 和 RNN head。

Markov head 是默认方案。它只看前一个已采样 token,用一个轻量的转移偏置来调整下一个 token 的概率分布。

继续用前面的例子理解:如果前一个 token 已经采样成 “of”,Markov head 就会让后续 token 更倾向于走向 “course” 这类更连贯的组合,而不是和另一条语义路径混在一起,生成 “problem”。

RNN head 可以记录更长的 block 内历史,理论上表达能力更强。但论文实验显示,相比 Markov head,它带来的收益有限,同时部署复杂度更高。因此,DSpark 默认采用 Markov head。

这个选择很有工程意味。对于生产级在线推理服务系统来说,额外模块不能只看效果提升,还要看是否足够轻、是否引入明显延迟、是否容易接入现有推理链路。Markov head 不是最复杂的方案,但它在效果、延迟和部署成本之间更均衡。

这里的关键判断是:DSpark 不是放弃并行生成,也不是把草稿模型(draft model)重新变慢,而是在并行生成之后补上一层轻量顺序修正。

DeepSeek 的实验也支持这一点。随着 proposal length 变长,纯并行 drafter 的后缀衰减会更明显,而 DSpark 通过引入局部顺序依赖,能在更长 proposal length 下保持更好的 accepted length。Proposal length 可理解为草稿模型(draft model)每轮尝试生成的候选 token 数量。

图4

如图所示,可以关注这两个信息:一是 proposal length 变长时,DSpark 的 accepted length 优势更明显;二是 sequential head 带来的额外延迟较小。

这说明 DSpark 并不是用显著增加 draft 成本的方式换取接受率,而是用较小的顺序建模开销,补上 parallel drafter 在后缀一致性上的短板。

DSpark 的第二步:verification 不是越长越好,而是要动态调度
如果说半自回归生成解决的是“草稿 token 怎么更容易被接受”,那么 DSpark 的第二个设计,解决的是“哪些草稿 token 值得交给目标模型验证”。

这个设计叫 Confidence-Scheduled Verification,可以理解为基于置信度调度的验证。

它的核心组件是 confidence head,可以看作是一个轻量判断器,用来估计草稿 token 通过目标模型验证的概率。

更准确地说,DSpark 预测的是 prefix survival probability。它指的是:从第一个草稿 token 开始,连续通过验证并“活到当前位置”的概率。

为什么要预测这个值?因为 Speculative Decoding 的验证是前缀式的。如果第 2 个 token 被拒绝,第 3、第 4、第 5 个 token 即使本身质量不错,也会被一起丢弃。所以,第 5 个 token 是否值得验证,不只取决于它自己准不准,还取决于前面 1 到 4 个 token 能不能先通过。

这就是 prefix survival probability 的意义:它不是孤立地判断某个 token 好不好,而是判断这个位置之前的整段前缀有没有机会连续通过验证。

有了这个估计之后,DSpark 还需要决定每个请求本轮到底验证多长。这就是 verification length。

Verification length 指的是一轮 Speculative Decoding 中,每个请求有多少个 draft token 会被送给目标模型验证。

过去比较直接的做法,是设置一个固定长度,或者根据静态阈值决定是否验证。但在真实在线推理服务系统里,这样不够。

因为一个 token 是否值得验证,不只取决于它的置信度,还取决于当前系统负载。

低负载时,目标模型还有空余计算能力,多验证一些高置信 token 可能是划算的;

高负载时,batch capacity 更紧张,低置信 token 就应该尽早被剪掉,避免挤占其他请求的计算资源。

因此,DSpark 引入了 hardware-aware prefix scheduler。它可以理解为一个了解推理引擎吞吐表现和当前系统负载的调度器。

这个调度器会结合两类信息:一类是 token 层面的 prefix survival probability,另一类是系统层面的 engine throughput profile,也就是推理引擎在不同 batch size 下的吞吐曲线。然后,它会为每个请求动态选择更合适的 verification length,把目标模型的验证预算分配给预期收益更高的前缀 token。

这一步的核心变化是:verification length 不再是一个固定超参数,而是一个随请求质量和系统负载变化的调度决策。

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐