# PR #51145 完整报告

- 仓库：`vllm-project/vllm`
- 标题：[Bugfix][ROCm] Fix DeepSeek V4 DSpark probabilistic startup
- 合并时间：2026-08-11 22:15
- 原文链接：http://prhub.com.cn/vllm-project/vllm/pull/51145

---

# 执行摘要

- 一句话：补齐 ROCm 上 DSpark 全词表草稿标记，修复概率采样启动崩溃
- 推荐动作：这个 PR 很小但值得快速浏览，作为平台一致性 data contract 修复的范例。核心价值是提醒开发者：跨平台实现（CUDA/ROCm）必须共享同一套运行时契约（类属性、钩子方法），且同类问题应通过自动化测试或契约单测固化。可关注 speculator 读取 draft_id_to_target_id 的完整逻辑，以了解全词表与精简词表草稿模型的差异。

# 功能与动机

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 上不可用。

# 实现拆解

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`（模块 投机解码；类别 source；类型 data-contract；符号 DSparkDeepseekV4ForCausalLM）: ROCm DSpark 草稿模型类 DSparkDeepseekV4ForCausalLM 新增类属性 draft_id_to_target_id = None，与 CUDA 路径对齐，修复概率采样模式启动时的 AttributeError。

关键符号：未识别

## 关键源码片段

### `vllm/models/deepseek_v4/amd/dspark.py`

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

```python
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)

```

# 评论区精华

讨论非常简短：

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

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

- 请求评审与 CI 验证 (other): 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 跨平台投机解码的类属性契约需要保持一致。
- 风险标记：缺少测试覆盖 , 平台分支不一致 , 小范围修复

# 关联脉络

- PR #51768 [Bugfix] Guard DeepSeek V4 MRV1 piecewise CUDA graphs: 同为 DeepSeek V4 投机解码稳定性修复，共享 speculator 与 CUDA graph 链路。
- PR #51473 [ROCm][DSV4] Preserve native MXFP4 TP8 shard allocation: 同为 ROCm 平台 DeepSeek V4 适配，涉及同一模型族的多后端一致性。
- PR #46849 [MRV2][Spec] Fuse AR speculator multi-step decodes back into one CUDA graph: 投机解码基础设施演进，与本 PR 的 draft_id_to_target_id 契约同属 speculator 多后端对齐工作。