投机解码
Speculative Engine 模块架构分析
1. 整体架构
┌─────────────────────────────────────────────────────────────────┐
│ SpeculativeEngine │
│ (继承自 EngineBase,是推测解码引擎的主入口) │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────────┐ ┌──────────────────┐ ┌────────────────┐│
│ │ ProposeExecutor │ │ ScoreExecutor │ │SpeculativeSampler│
│ │ (草稿模型执行器) │ │ (验证模型执行器) │ │ (采样器) ││
│ └────────┬─────────┘ └────────┬─────────┘ └────────────────┘│
│ │ │ │
│ ┌────────┴─────────────────────┴───────────┐ │
│ │ 具体实现类 │ │
│ │ ┌─────────────┐ ┌─────────────┐ │ │
│ │ │VanillaExec │ │ MTPExecutor │ │ │
│ │ │(标准草稿模型)│ │(多token预测) │ │ │
│ │ └─────────────┘ └──────┬──────┘ │ │
│ │ │ │ │
│ │ ┌──────┴──────┐ │ │
│ │ │EagleExecutor│ │ │
│ │ │(EAGLE算法) │ │ │
│ │ └─────────────┘ │ │
│ └──────────────────────────────────────────┘ │
│ │
│ ┌──────────────────────────────────────────┐ │
│ │ SpeculativeScheduler │ │
│ │ (推测解码调度器) │ │
│ └───────── ─────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
2. 核心组件详解
2.1 SpeculativeEngine (主引擎)
职责: 协调整个推测解码流程
关键方法:
step()- 主循环的一次迭代,根据不同模式调用不同的处理流程spStep()- 标准推测解码步骤 (Vanilla 模式)mtpStep()- MTP/EAGLE 模式的推测解码步骤normStep()- 普通解码步骤 (不使用推测)
支持的推测解码类型 (sp_type_):
| 类型 | 说明 |
|---|---|
vanilla | 传统小模型草稿 |
mtp | Multi-Token Prediction |
eagle | EAGLE 算法 |
eagle3 | EAGLE3 算法 |
2.2 ProposeExecutor (提议执行器)
抽象接口:
class ProposeExecutor {
virtual absl::Status propose(streams, skip_check) = 0; // 生成草稿 tokens
virtual size_t reserveStep() const = 0; // 预留步数
virtual absl::Status normalProcess(streams) = 0; // 普通处理
};
三种实现:
| 实现类 | 原理 | 特点 |
|---|---|---|
VanillaExecutor | 使用独立的小型草稿模型 | 传统方法,需要额外模型 |
MTPExecutor | 多 token 预测头,共享主干 | 每个 MTP 模块预测下一个位置的 token |
EagleExecutor | 继承 MTPExecutor,使用 EAGLE 树结构 | 更高效的投机采样 |
2.3 ScoreExecutor (评分执行器)
职责: 使用目标模型验证草稿 tokens
class ScoreExecutor {
absl::Status score(streams, skip_check); // 验证提议的 tokens
absl::Status normalProcess(streams); // 普通前向传播
};
- 内部包含两个
NormalExecutor:一个用于 score,一个用于普通处理 - 使用
ScoreBatchStreamProcessor进行批处理
2.4 SpeculativeSampler (推测采样器)
职责: 实现接受/拒绝采样逻辑
两种采样模式:
| 模式 | 触发条件 | 特点 |
|---|---|---|
streamSample | top-k=1 或强制流式采样 | 逐流处理,简单高效 |
batchSample | 包含 top-p 采样 | 批量处理,支持随机采样 |
采样算法:
top1Sample: 贪婪采样,直接比较 token IDstochasticSample: 随机采样,基于概率拒绝
// 拒绝采样核心逻辑
while (accept_len < propose_step) {
if (random > score_prob / propose_prob) {
// 拒绝,使用修正后的概率重新采样
new_p = max(score_probs - propose_probs, 0)
resample from normalized new_p
break;
}
accept_token();
}
2.5 SpeculativeScheduler (调度器)
职责: 管理请求调度,区分推测和普通解码
class SpeculativeScheduler : public FIFOScheduler {
std::list<GenerateStreamPtr> pending_sp_run_streams_; // 等待推测解码的流
schedule(reserve_step) {
// 1. 优先返回待处理的推测流
// 2. 分离禁用推测的流和启用推测的流
}
};