Prhub

#29124 [Spec] Unify the overlap stash relay behind a RelayPayload dataclass

原始 PR 作者 hnyls2002 合并时间 2026-06-25 06:36 文件变更 5 提交数 4 评论 4 代码增减 +91 / -48

执行摘要

统一 FutureMap.stash 为 RelayPayload 数据类

PR Body 中明确指出:FutureMap.stash 原本接受 Union[torch.Tensor, EagleDraftInput],内部通过类型分派处理不同 payload。替代为单一 RelayPayload 数据类可消除类型开关(解决了一个 FIXME),并为统一解码结果合约奠定基础。同时修复了 ngram 路径因缺少 bonus_tokens 导致的崩溃。

值得精读,因为引入了统一数据类设计,消除了类型分支,是清理调度层技术债务的典范。同时展示了如何处理 ngram 等特殊路径。关注点是测试覆盖尚缺,未来合并类似重构时应同步新增测试。

讨论亮点

PR 未产生 review 讨论,但 commit 历史显示了一个关键修复:在运行 ngram 模式时,直接构造 RelayPayload 会因缺少 bonus_tokens 导致崩溃。作者在最后一个 commit 中通过 is_ngram() 检查跳过了相关 stash 调用。

实现拆解

  1. 定义 RelayPayload 数据类overlap_utils.py):包含必选字段 bonus_tokens(用于非 spec 路径)和可选字段(topk_p, topk_index, hidden_states, draft_probs),并提供 from_draft_input 工厂方法从 EagleDraftInput 构造。
  2. 修改 FutureMap 核心方法overlap_utils.py):stash 方法签名从 Union[torch.Tensor, EagleDraftInput] 改为 RelayPayload_lazy_init_forward_buf 相应地接受 RelayPayload 而非 EagleDraftInput
  3. 更新所有调用点:在 scheduler.pyscheduler_pp_mixin.pydecode_schedule_batch_mixin.pyeagle_disaggregation.py 中,将对 stash 的调用均改为构造 RelayPayload 实例。
  4. 推迟 spec_info 导入overlap_utils.py):将 SpeculativeAlgorithm 等 spec 相关导入推迟到函数内部,保持模块级依赖叶化,避免循环导入。
  5. 修复 ngram 兼容性scheduler.py):在 stash 调用前增加 is_ngram() 检查,跳过 relay payload 投影,因为 ngram 的 draft input 没有 bonus_tokens
文件 模块 状态 重要度
python/sglang/srt/managers/overlap_utils.py 调度层 modified 8.3
python/sglang/srt/managers/scheduler.py 调度层 modified 6.81
python/sglang/srt/managers/scheduler_pp_mixin.py 调度层 modified 5.34
python/sglang/srt/disaggregation/decode_schedule_batch_mixin.py 分离调度 modified 5.13
python/sglang/srt/speculative/eagle_disaggregation.py 推测解码 modified 5.13

关键符号

RelayPayload RelayPayload.from_draft_input FutureMap._lazy_init_forward_buf FutureMap.stash build_eagle_disagg_draft_input

关键源码片段

python/sglang/srt/managers/overlap_utils.py core-logic

核心变更文件:定义 RelayPayload 数据类,修改 FutureMap.stash 和 _lazy_init_forward_buf 的签名,推迟 spec 导入。

@dataclass
class RelayPayload:
    """Per-iteration stash payload for the FutureMap bufs. Non-spec fills only
    `bonus_tokens`; which spec extras get relayed is decided by
    `FutureMap.spec_algo`, not by this payload's shape."""
​
    bonus_tokens: torch.Tensor
    topk_p: Optional[torch.Tensor] = None
    topk_index: Optional[torch.Tensor] = None
    hidden_states: Optional[torch.Tensor] = None
    draft_probs: Optional[torch.Tensor] = None
​
    @classmethod
    def from_draft_input(cls, draft_input: EagleDraftInput) -> "RelayPayload":
        """Factory: extract fields from EagleDraftInput. draft_probs may not exist on all subclasses."""
        return cls(
            bonus_tokens=draft_input.bonus_tokens,
            topk_p=draft_input.topk_p,
            topk_index=draft_input.topk_index,
            hidden_states=draft_input.hidden_states,
            draft_probs=getattr(draft_input, "draft_probs", None),
        )# In FutureMap._lazy_init_forward_buf (signature changed):
def _lazy_init_forward_buf(self, payload: RelayPayload):
    # Local import: keep this module leaf-dependency free.
    from sglang.srt.speculative.spec_info import SpeculativeAlgorithm
    # ... remaining init uses payload attributes

评论区精华

ngram 兼容性:stash 不允许传入 ngram draft input 正确性

在最后一个 commit (ff919001) 中修复:ngram 的 draft input 没有 bonus_tokens 属性,直接构造 RelayPayload 会导致运行时崩溃。

结论:在 stash 前添加 is_ngram() 检查,跳过 relay payload 投影。 · 已解决

风险与影响

核心调度和推测解码的重叠路径被重构,调用点分散在 5 个文件中,如果遗漏某条调用路径或错误构造 RelayPayload,可能导致 relay 数据错误。特别是 ngram 路径的修复尚未有测试覆盖,可能存在类似的边缘情况。另外,RelayPayload 中的可选字段允许 None,消费者需确保健壮性。

仅影响启用 overlap 模式且使用 speculative decoding 的调度路径。非 overlap、非 spec 路径完全不受影响。用户功能无可见变化,行为保持。为未来的解码结果统一做铺垫。

核心路径变更 缺少测试覆盖 ngram 回归已修复

关联 Issue

未识别关联 Issue

当前没有检测到明确关联的 Issue 链接,后续同步到相关引用后会出现在这里。

完整报告

参与讨论