Prhub

#51145 [Bugfix][ROCm] Fix DeepSeek V4 DSpark probabilistic startup

原始 PR 作者 tuukkjs 合并时间 2026-08-11 22:15 文件变更 1 提交数 2 评论 3 代码增减 +2 / -0

执行摘要

补齐 ROCm 上 DSpark 全词表草稿标记,修复概率采样启动崩溃

PR body 明确了根因:DSpark 草稿模型使用完整词表,草稿 token id 已与目标 token id 对齐,无需重映射;共享 DSpark speculator 在 draft_sample_method="probabilistic" 时会读取 model.draft_id_to_target_id 来决定是否需要散射,ROCm 类缺少该属性导致 AttributeError: 'DSparkDeepseekV4ForCausalLM' object has no attribute 'draft_id_to_target_id'。作者还在 Issue 评论中强调该模式当前在 ROCm 上不可用。

这个 PR 很小但值得快速浏览,作为平台一致性 data contract 修复的范例。核心价值是提醒开发者:跨平台实现(CUDA/ROCm)必须共享同一套运行时契约(类属性、钩子方法),且同类问题应通过自动化测试或契约单测固化。可关注 speculator 读取 draft_id_to_target_id 的完整逻辑,以了解全词表与精简词表草稿模型的差异。

讨论亮点

讨论非常简短:

  • tuukkjs(作者)在 Issue 评论中请求 tjtanaa 评审,并说明 draft_sample_method="probabilistic" 当前在 ROCm 上不可用。
  • claude[bot] 因 PR 来自 fork 禁用自动审查,需维护者手动处理。
  • tjtanaa 直接 APPROVED,无额外评论,说明改动风险低、判断清晰。

没有出现设计争议或未解决疑虑,属于明确的平台一致性修复。

实现拆解

  1. 变更入口:vllm/models/deepseek_v4/amd/dspark.py 中 DSparkDeepseekV4ForCausalLM 类的类级属性区域。

  2. 核心改动:在 has_own_embed_tokens = False 与 has_own_lm_head = False 之后新增类属性 draft_id_to_target_id = None,注释说明“全词表草稿:draft id 即 target id,无需重映射”,与 CUDA 路径数据契约对齐。

  3. 作用链路:共享 speculator 在概率采样模式下读取该属性,None 表示草稿 logits 已落在目标词表列,跳过散射步骤;该值必须与 CUDA 路径保持一致,否则投机采样逻辑会出现平台分叉。

  4. 测试与验证:PR 未新增自动化测试文件,验证依赖 ROCm 手工 serving 测试(DeepSeek V4 Flash DSpark,num_speculative_tokens=5,probabilistic 采样),实测启动成功且接受率 43.19%;Buildkite CI #82508 运行通过。

文件 模块 状态 重要度
vllm/models/deepseek_v4/amd/dspark.py 投机解码 modified 5.1

关键源码片段

vllm/models/deepseek_v4/amd/dspark.py data-contract

ROCm DSpark 草稿模型类 DSparkDeepseekV4ForCausalLM 新增类属性 draft_id_to_target_id = None,与 CUDA 路径对齐,修复概率采样模式启动时的 AttributeError。

class DSparkDeepseekV4ForCausalLM(nn.Module):
    # 草稿权重随目标 checkpoint 的 mtp.* 字段下发,不含 embed/head,
    # load_dspark_model 总是复用目标的 embed 与 lm_head,因此这里
    # 不声明自己的 embed/lm_head 所有权。
    has_own_embed_tokens = False
    has_own_lm_head = False
​
    # DSpark 使用全词表草稿模型:草稿 token id 本身就是目标 token id,
    # 概率采样(draft_sample_method="probabilistic")时无需把精简词表
    # 的草稿 logits 散射回目标词表列。None 即“不需要重映射”的标记。
    # CUDA 路径已有该属性,ROCm 路径此前缺失,补齐后共享 speculator
    # 不再因 AttributeError 中断启动。
    draft_id_to_target_id = None
​
    def __init__(self, *, vllm_config: VllmConfig, prefix: str = "") -> None:
        super().__init__()
        assert vllm_config.speculative_config is not None
        self.draft_model_config = vllm_config.speculative_config.draft_model_config
        self.config = self.draft_model_config.hf_config
        self.model = DSparkDeepseekV4Model(
            vllm_config=vllm_config, prefix=maybe_prefix(prefix, "model")
        )
        # 与目标模型共享 lm_head 与 logits processor(由 speculator 加载工具别名)。
        self.lm_head = ParallelLMHead(
            self.config.vocab_size,
            self.config.hidden_size,
            prefix=maybe_prefix(prefix, "lm_head"),
        )
        self.logits_processor = LogitsProcessor(self.config.vocab_size)

评论区精华

请求评审与 CI 验证 other

tuukkjs 在 Issue 评论中请求 tjtanaa 抽出时间评审这个单行修复,并说明 probabilistic 模式当前在 ROCm 上不可用;AndreasKaratzas 随后触发了 /ci run,Buildkite CI #82508 运行。

结论:tjtanaa 直接批准(APPROVED),PR 合入 main。 · 已解决

风险与影响

整体风险低,但存在以下几点:

  • 缺少自动化测试:该修复依赖手工 ROCm 验证兜底,draft_id_to_target_id 契约若被其他 speculator 路径误用,不会立刻暴露。
  • 隐式数据契约:None 承担语义标记,未来若有人传入 dict/list 或改变 speculator 的读取方式,需要同步维护 CUDA 与 ROCm 两处实现。
  • 平台分叉隐患:同类属性在 CUDA 已有而 ROCm 缺失的问题可能在其余模型/后端组合中重复出现,建议在基类或契约层统一声明。
  • 影响面有限:不涉及权重加载、显存布局或性能路径,回归风险集中在投机采样启动逻辑。

影响范围集中在 ROCm 平台 + DeepSeek V4 DSpark + draft_sample_method="probabilistic" 的启动路径,修复后不再抛出 AttributeError,用户可以正常启用概率采样的 DSpark 投机解码。对 CUDA 行为零影响,不改变权重数据格式,无性能或显存副作用。对团队而言,该修复意味着 vLLM 跨平台投机解码的类属性契约需要保持一致。

缺少测试覆盖 平台分支不一致 小范围修复

关联 Issue

未识别关联 Issue

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

完整报告

参与讨论