Speculative Decoding 实战:用 EAGLE 与 Draft Model 降低 LLM 单用户延迟
背景问题:为什么 LLM 生成阶段容易慢在”一个 token 一步”
大模型在线推理通常分为两个阶段:prefill 和 decode。Prefill 负责处理输入上下文,通常计算量大但并行度高;decode 负责逐 token 生成,天然是自回归过程——第 t+1 个 token 依赖第 t 个 token,因此传统解码每次只能让目标模型向前走一步。
在低并发或中低 QPS 场景下,decode 阶段经常不是算力完全打满,而是被 HBM 参数读取、KV Cache 访问、调度开销和串行步数 共同限制。结果是:用户看到的首 token 之后,每个 token 都要等一次目标模型前向,TPOT(Time Per Output Token)偏高,单用户流式体验变差。
Speculative Decoding 的目标不是让模型”更聪明”,而是让目标模型少做串行步数:先用更便宜的方法猜出多个未来 token,再让目标模型一次性校验。如果草稿猜得准,一次目标模型前向可以接受多个 token,decode 的串行轮数就下降。
这类方法的关键价值在于:它在标准算法条件下可以保持目标模型原有输出分布,不是简单用小模型替换大模型,也不是为了速度牺牲质量的近似生成。
核心原理:草稿生成 + 目标模型并行校验
1. 两个角色:Drafter 与 Target Model
投机解码里通常有两个角色:
| 角色 | 职责 | 常见形态 |
|---|---|---|
| Drafter | 快速提出候选 token | 小模型、n-gram 规则、额外预测头、EAGLE 类 feature-level drafter |
| Target Model | 校验候选 token,决定接受/拒绝/重采样 | 对外承诺输出质量的大模型 |
一个简化流程如下:
已有上下文 x → drafter 生成候选 token:y₁, y₂, y₃, ... yₖ → target model 一次前向校验这些候选位置 → 从左到右接受连续候选 token → 遇到第一个拒绝位置后按修正分布采样,丢弃后续草稿 → 进入下一轮。
如果候选 y₁...yₖ 中前 4 个都被接受,目标模型原本需要 4 次 decode 前向,现在可能只需要一次校验前向。真正节省的是目标模型的串行 decode 轮数。
2. 接受率不是唯一指标,接受长度更重要
很多工程团队会先看 acceptance rate,即草稿 token 被目标模型接受的比例。但上线时更应该同时看 accepted tokens per target step,也就是每次目标模型校验平均能向前推进多少个 token。
原因很简单:
- 如果每轮只草稿 2 个 token,即便接受率很高,最多也只能推进 2 个;
- 如果每轮草稿 8 个 token,但接受率从第 3 个开始迅速下降,后面的候选会变成浪费。
合理的 num_speculative_tokens 通常需要结合真实 prompt、采样参数、模型对齐程度和并发水平调参。
3. 为什么它可以”不改变输出分布”
标准投机采样不是看到草稿 token 就直接采用,而是用目标模型对候选进行校验。对于采样场景,经典算法会比较 drafter 分布 q 和 target 分布 p,按接受/拒绝采样保证最终输出分布与直接从目标模型逐步采样一致。
工程上要特别注意:
- 如果只做贪心生成,通常是校验候选 token 是否与目标模型选择一致;
- 如果做 temperature/top-p 等随机采样,需要实现正确的概率校验逻辑;
- 如果为了速度私自放宽校验,就不再是严格意义上的 lossless speculative decoding,而会进入近似解码范畴。
主流方案对比:Draft Model、N-gram、Medusa、EAGLE
Draft Model:最直观,也最依赖模型匹配
Draft Model 使用一个更小、更快的语言模型预测未来 token。优点是机制清晰,接入路径成熟;缺点是需要维护第二个模型,并且 draft 与 target 的 tokenizer、chat template、领域分布、采样行为需要高度匹配。
适合场景:
- 有同族小模型,例如 7B target 对 1B/3B drafter;
- 业务 prompt 相对稳定,接受率可通过离线评估提前验证;
- 推理服务更关注单用户延迟,而不是极限高并发吞吐。
常见问题是 drafter 看起来很快,但候选不准,target 大量拒绝;最终多跑了一个模型,却没有减少多少目标模型轮数。
N-gram / Suffix:轻量,但收益有限
N-gram 或 suffix 类方法不引入额外模型,而是从上下文里复用已有片段作为候选。成本很低,适合重复性强的文本,例如代码补全、模板化回答、表格或日志格式续写。但这类方法缺乏真正语言建模能力——遇到开放式问答、推理题、多轮对话,候选质量通常有限,收益也更不稳定。
Medusa:给目标模型加多个预测头
Medusa 的思路是不维护独立小模型,而是在目标模型上增加多个轻量解码头,分别预测未来位置的 token,再用树结构候选和 tree attention 一次性验证多条路径。
优势是减少第二模型维护问题;劣势是需要训练或适配额外头部,部署与模型资产管理复杂度会上升。对于已有标准模型服务,Medusa 不是简单打开参数就能稳定落地,通常需要额外训练、兼容性验证和推理框架支持。
EAGLE:从 Token 预测转向 Feature-Level Drafting
EAGLE 不是简单用小模型逐 token 猜未来,而是利用目标模型中间层特征进行预测。早期 EAGLE 强调在 feature level 做 autoregression,后续 EAGLE-3、EAGLE-3.1 又围绕多层特征融合、动态 draft tree、长上下文鲁棒性等问题继续优化。
工程吸引力:
- 不完全依赖一个独立小语言模型;
- 可以更贴近 target model 的内部表示;
- 在低并发、长输出、代码生成等场景可能获得明显 TPOT 改善;
- 已被 vLLM、TensorRT-LLM 等推理栈纳入实践路径。
但 EAGLE 也不是无成本方案。它需要匹配目标模型的 drafter/head,需要处理 chat template、长上下文、隐藏状态提取和框架版本兼容问题。上线前仍然要用真实负载验证,而不能只看论文或单机 benchmark。
方案对比总结
| 方案 | 额外模型 | 训练需求 | 典型收益 | 维护成本 | 适用场景 |
|---|---|---|---|---|---|
| Draft Model | 需要独立小模型 | 无 | 中高 | 中 | 有同族小模型、prompt 稳定 |
| N-gram / Suffix | 无 | 无 | 低 | 极低 | 重复性文本、代码补全 |
| Medusa | 无独立模型,需额外解码头 | 需要训练 | 中高 | 较高 | 不想维护第二模型 |
| EAGLE | 需要 feature-level drafter | 需要匹配目标模型 | 高 | 较高 | 低并发、长输出、代码生成 |
工程落地:从实验到生产的实施路径
第一步:先判断瓶颈是不是 Decode TPOT
不要因为”听起来能加速”就直接上投机解码。先把服务指标拆开:
| 指标 | 含义 |
|---|---|
| TTFT | 首 token 延迟 |
| TPOT / ITL | 每个输出 token 的平均耗时 |
| Output TPS per user | 单用户输出吞吐 |
| Total throughput | 整体吞吐 |
| GPU utilization | SM、HBM、KV Cache、batch size |
| Queueing latency | 请求排队时间 |
如果瓶颈主要在超长输入 prefill、检索链路、工具调用、网络延迟或队列排队,Speculative Decoding 未必是优先项。它主要治理的是 decode 阶段的串行 token 生成。
第二步:选择可控的试点流量
推荐从以下流量开始:
- 代码补全、代码解释、结构化改写
- 模板化客服回复
- 固定格式报告生成
- 长输出摘要或文档续写
- 中低并发但用户体感延迟敏感的交互
暂时不建议从高度开放、温度较高、领域跨度极大的对话开始——这些场景 token 分布熵更高,draft 被拒绝的概率也更高。
第三步:最小化配置实验
以 vLLM 的 Draft Model 形态为例:
vllm serve <target-model> \
--speculative-config '{
"method": "draft_model",
"model": "<draft-model>",
"num_speculative_tokens": 5
}'
如果使用 EAGLE/EAGLE-3,需要对应的 drafter checkpoint,并按框架文档选择 method、target model、tensor parallel、attention backend 等参数。不要混用不匹配的 chat template,也不要把不同 tokenizer 的模型强行组合。
第四步:建立独立评估集
投机解码上线前至少准备三类评估数据:
- 真实业务 prompt:来自线上脱敏样本,覆盖主流业务输入长度和输出长度。
- 高熵 prompt:开放式创作、复杂推理、跨领域问题,用来观察最差收益。
- 回归 prompt:固定随机种子、固定采样参数,用来比较输出一致性和异常拒绝模式。
每条样本至少记录:输入 token 数、输出 token 数、temperature、top-p、接受 token 数、拒绝位置、target forward 次数、端到端延迟、TPOT、显存峰值。
第五步:灰度上线,而不是一次性替换
生产上建议把投机解码作为独立 serving profile:
profiles:
baseline:
speculative: false
spec_decode_eagle:
speculative: true
method: eagle3
num_speculative_tokens: 3
rollout: 5%
灰度期间至少观察:
- P50/P95/P99 TTFT 与 TPOT
- 每轮平均接受长度
- target model forward 次数下降比例
- GPU 显存与 KV Cache 压力
- 总吞吐变化
- 错误率、超时率、OOM、取消请求
- 不同 prompt 类型的收益差异
如果只看平均延迟,容易掩盖尾延迟恶化。尤其在高并发时,drafter 也会消耗 GPU/CPU/内存资源,可能让整体排队变长。
适用场景:什么时候值得上
适合的情况
- 低到中等并发:GPU 没有被大 batch 完全打满,target model 校验多个 token 的并行收益能释放出来。
- 长输出:输出 token 越多,decode 串行轮数越多,优化空间越大。
- token 可预测性较高:代码、格式化文本、模板化回复、重复上下文更容易产生高接受率。
- 用户关注流式速度:例如 IDE assistant、客服助手、文档生成器。
- 可维护 drafter 资产:团队能持续管理 draft model/EAGLE head 的版本、兼容性和评估。
不太适合的情况
- 主要瓶颈是 prefill 或 RAG 检索
- GPU 已被高并发 continuous batching 打满
- 输出很短,decode 轮数本来不多
- prompt 分布变化极大,接受率不稳定
- 业务不能接受额外模型资产和部署复杂度
常见误区
误区一:投机解码一定提升吞吐
它更直接改善的是 单请求 decode latency。在低并发下可能明显提升单用户输出速度;在高并发下,如果 GPU 已经靠 continuous batching 保持高利用率,额外 drafter 可能反而抢资源。吞吐是否提升要看目标模型、并发、batch、采样参数和实现细节。
误区二:小模型越小越好
drafter 太小会很快,但候选不准;drafter 太大候选更准,但成本高。最优点不是”最小模型”,而是 草稿成本 × 接受长度 × target 校验收益 的综合最优。
误区三:只测 acceptance rate
接受率高不代表端到端快。还要看每轮平均接受 token 数、额外显存、drafter 延迟、target 校验开销、服务排队变化。
误区四:把它当成质量降级策略
标准投机解码不是降级策略。它的承诺是用 target model 保持输出分布。如果为了速度跳过校验、放宽校验或直接接受小模型输出,就应该明确标记为近似模式,并重新做质量评估。
误区五:忽略 chat template 与 tokenizer
很多失败不是算法问题,而是工程拼接问题。Draft 与 target 的 tokenizer、特殊 token、system prompt、tool call 格式、停止词、采样参数只要不一致,就可能造成接受率异常下降。
上线检查清单
模型与配置
- target model 与 drafter/head 版本明确绑定
- tokenizer、chat template、special tokens、stop tokens 一致
- num_speculative_tokens 有离线 sweep 结果
- temperature/top-p/top-k 场景被覆盖
- 长上下文与短上下文都完成评估
性能指标
- 对比 baseline 的 TTFT、TPOT、端到端延迟
- 记录 accepted tokens per target step
- 记录 rejection position 分布
- 观察 P95/P99,不只看平均值
- 高并发、低并发分别测试
资源与稳定性
- 观察 GPU 显存峰值、KV Cache 使用、OOM
- 观察 drafter 是否引入额外 GPU 争用
- 观察服务取消、超时、重试对调度器的影响
- 为 speculative profile 设置独立限流和回滚开关
质量与一致性
- 固定采样参数下对比输出分布或回归样本
- 工具调用、JSON 输出、结构化输出场景单独验证
- 禁止未经标记的近似接受策略混入正式链路
- 将异常样本回灌到离线评估集
FAQ
Speculative Decoding 和 Continuous Batching 冲突吗?
不冲突,但收益关系复杂。Continuous Batching 通过调度多个请求提升 GPU 利用率;Speculative Decoding 通过减少单请求目标模型串行 decode 步数降低延迟。当并发低时,投机解码收益更容易体现;当并发高且 GPU 已满载时,额外 drafter 可能使调度更复杂,收益需要实测。
EAGLE 一定比 Draft Model 更好吗?
不一定。EAGLE 的优势是利用目标模型内部特征,减少独立小模型匹配问题,并在一些服务场景中表现较强。但 Draft Model 更直观、通用,n-gram 更轻量。选择哪种方案取决于 target model、可用 drafter、部署框架、真实 prompt 分布和维护成本。
为什么论文里的 2x、3x 到线上变成 1.2x?
常见原因包括:线上并发更高、prompt 更杂、输出更短、采样温度更高、draft 与 target 不匹配、KV Cache 压力更大、框架实现没有完全优化,或者端到端链路瓶颈并不在 decode。投机解码应该看真实流量收益,而不是只复用论文数字。
对 RAG 或 Agent 有帮助吗?
有可能,但要拆开看。RAG 和 Agent 的端到端延迟往往包含检索、工具调用、重排、网络请求和多轮规划。Speculative Decoding 只能优化模型生成阶段。如果 Agent 每次输出很短,收益有限;如果有长文档生成、长代码生成或长解释输出,收益更明显。
小结
Speculative Decoding 的核心不是”再找一个小模型替代大模型”,而是利用 drafter 提前提出候选,再由 target model 并行校验,从而减少目标模型的串行 decode 轮数。它最适合单用户延迟敏感、输出较长、token 可预测性较高、GPU 未被高并发完全打满的场景。
工程落地时,不要把它当成一个默认开启的魔法参数。正确路径是:先确认 decode 是瓶颈,再选择 drafter 方案,随后用真实流量评估接受长度、TPOT、尾延迟、显存和回滚能力。只有当这些指标同时成立,Speculative Decoding 才能从论文技巧变成稳定的生产优化手段。
主要参考资料
- vLLM Documentation: Speculative Decoding
- NVIDIA TensorRT-LLM: Speculative Sampling
- NVIDIA Triton + TensorRT-LLM: Speculative Decoding Tutorial
- NVIDIA Technical Blog: An Introduction to Speculative Decoding for Reducing Latency in AI Inference
- Leviathan et al., Fast Inference from Transformers via Speculative Decoding
- Li et al., EAGLE: Speculative Sampling Requires Rethinking Feature Uncertainty
- Cai et al., Medusa: Simple LLM Inference Acceleration Framework with Multiple Decoding Heads
- vLLM Blog: EAGLE 3.1
- vLLM Project: Speculators