Prhub

#52948 [Model] Support bidirectional (encoder-only) attention for DeepSeek e…

原始 PR 作者 Lossfull 合并时间 2026-08-20 00:36 文件变更 4 提交数 3 评论 8 代码增减 +35 / -3

执行摘要

DeepSeek 骨干双向注意力嵌入模型支持,启用非 MLA 路径

DeepSeek-V2/V3 是 decoder-only(causal)架构,但部分 embedding 模型复用了它的骨干并改成双向(encoder-only)注意力。由于 DeepSeek 使用 MLA,而 MLA 的融合 kernel 只支持 causal attention,vLLM 当前没有任何代码路径能对 DeepSeek 骨干应用双向注意力,导致这类模型无法运行。PR body 明确说明目标是在非 MLA 注意力路径上响应 HF config 的 is_causal=False,并保证对现有 DeepSeek 模型字节级不改变行为。

该 PR 值得关注,尤其适合要新增 encoder-only 变体的模型维护者阅读:它展示了「HF 配置字段驱动注意力类型 + 全局 MLA 开关短路 + registry 复用已有因果模型实现」的组合套路,且与 Qwen2/Qwen3 双向 embedding 的处理方式一脉相承。不过运行时数值验证尚未自动化,建议在后续补一条针对双向 DeepSeek embedding 的回归测试。

讨论亮点

review 中唯一实质讨论集中在 vllm/config/model.py 的分支放置位置:DarkLight1337 指出 is_causal=False 分支应放在 use_mla property 末尾、紧邻 return self.is_deepseek_mla,而不是插在注释与 return 之间,以保持逻辑可读性。作者回复 fixed,并通过提交 Update model.py change the order of branches(82f3783)调整了顺序,随后 DarkLight1337 approve。过程中还触发了两轮 /ci run(Buildkite CI #84605、#84606)。整体是一致性维护型意见,无设计层面的争议。

实现拆解

实现按 4 步完成:

  1. 配置开关 vllm/config/model.py:在 ModelConfig.use_mla 的 vLLM 模型实现分支中新增 is_causal=False 短路返回 False。这样做让双向 DeepSeek 变体自动绕过 causal-only 的 MLA 融合 kernel,走 materialized(非 MLA)注意力路径,用户无需设置 VLLM_MLA_DISABLE=1
  2. 注意力层改造 vllm/model_executor/models/deepseek_v2.py:在 DeepseekV2Attention.__init__ 中读取 config.is_causal(默认 True),为 False 时选用 EncoderOnlyAttention 并把 AttentionType.ENCODER_ONLY 传给 self.attn,否则保持原 AttentionAttentionType.DECODER;同时补入 EncoderOnlyAttentionAttentionType 的 import。这一步是该 PR 让双向注意力真正生效的核心路径。
  3. 模型注册 vllm/model_executor/models/registry.py:在 _EMBEDDING_MODELS 中注册 DeepseekV3BidirectionalModel,映射到 deepseek_v2 模块的 DeepseekV3ForCausalLM,使其可作为 embedding 模型被 pooling runner 识别。
  4. 测试配套 tests/models/registry.py:在 _EMBEDDING_EXAMPLE_MODELS 增加 ai-sage/Giga-Embeddings-instruct-10B-A1.8B-0826 示例条目,带 trust_remote_code=Truehf_overrides(把 model_type 改写为 deepseek_v3、auto_map 置空),保证 registry import 与覆盖率测试通过。数值 parity 在 PR body 中报告,但未作为自动化测试合入 CI。
文件 模块 状态 重要度
vllm/model_executor/models/deepseek_v2.py 模型实现 modified 6.89
vllm/config/model.py 模型配置 modified 5.8
vllm/model_executor/models/registry.py 模型注册 modified 4.96
tests/models/registry.py 注册测试 modified 4.27

关键符号

ModelConfig.use_mla DeepseekV2Attention.__init__

关键源码片段

vllm/model_executor/models/deepseek_v2.py core-logic

核心实现文件:DeepseekV2Attention 根据 config.is_causal 选择 EncoderOnlyAttention/AttentionType.ENCODER_ONLY,让双向注意力在非 MLA 路径上真正生效。

# vllm/model_executor/models/deepseek_v2.py —— DeepseekV2Attention.__init__ 关键分支
if getattr(config, 'is_causal', True):
    attn_type = AttentionType.DECODER
else:
    attn_type = AttentionType.ENCODER_ONLY# 在非 MLA 路径上按配置选择双向或因果注意力:
# - decoder-only DeepSeek 保持原来的 Attention + DECODER;
# - embedding 变体(is_causal=False)改用 EncoderOnlyAttention + ENCODER_ONLY,
# 使双向注意力能够生效,同时避免使用 causal-only 的 MLA kernel。
attn_cls = EncoderOnlyAttention if attn_type == AttentionType.ENCODER_ONLY else Attention
self.attn = attn_cls(
    self.num_local_heads,
    self.qk_head_dim,
    self.scaling,
    num_kv_heads=self.num_local_heads,
    cache_config=cache_config,
    quant_config=quant_config,
    prefix=f'{prefix}.attn',
    attn_type=attn_type,
)
vllm/config/model.py configuration

ModelConfig.use_mla 的 is_causal=False 短路分支是双向 DeepSeek 自动选择非 MLA 路径的关键配置开关,review 中对该分支位置有过讨论。

# vllm/config/model.py —— ModelConfig.use_mla
@property
def use_mla(self) -> bool:
    if envs.VLLM_MLA_DISABLE:
        return False
    if self.using_transformers_backend():
        # kv_lora_rank 表示 Transformers 实现使用 MLA
        return getattr(self.hf_text_config, 'kv_lora_rank', None) is not None
​
    # 双向 DeepSeek 变体(is_causal=False,embedding 模型使用)必须走非 MLA
    # 注意力路径,因为 MLA kernel 只支持 causal attention。
    if not getattr(self.hf_text_config, 'is_causal', True):
        return False
​
    # vLLM 模型实现的手工维护模型类型列表
    return self.is_deepseek_mla

评论区精华

use_mla 中 is_causal 分支的放置位置 style

DarkLight1337 在 code review 中指出新增的 is_causal=False 分支应放在 use_mla property 末尾、紧邻 return self.is_deepseek_mla 的位置,而不是插在注释与 return 之间,以保持逻辑可读性。

结论:作者通过提交 82f3783 调整分支顺序并回复 fixed,维护者随后 approve。 · 已解决

风险与影响

风险点如下:

  1. 全局配置分支ModelConfig.use_mla 是全局 property,新增的 is_causal=False 短路对所有走 vLLM 模型实现路径的配置生效。当前实测只影响 DeepSeek MLA 类模型,但未来若有其他同时具备 is_deepseek_mla 与双向注意力的架构,也会被静默切到非 MLA 路径,需要留意该分支的通用性。
  2. 运行时正确性未入 CI:PR 只在 registry 测试中覆盖导入与映射,双向注意力的数值 parity 是作者在 RTX 5090 上手工验证的,没有自动化回归测试保护 EncoderOnlyAttention 路径。
  3. 性能差异:非 MLA 的 materialized attention 与 MLA 相比内存和计算特征不同,作为 embedding 模型使用时吞吐表现需要单独评估。
  4. 依赖 hf-overrides 变通:目标模型原生 model_type 是 deepseek_v3_bidirec,vLLM 不识别,需要 serve 时改写 model_type 并 trust-remote-code,属于外围配置依赖,不是模型内部自包含支持。

对用户:新增一类可用的 DeepSeek 骨干 embedding 模型,可通过 --runner pooling --convert embed 提供服务,但需要 --hf-overrides 改写 model_type。对现有 DeepSeek decoder-only 用户无影响,因为 is_causal 缺省为 True 时行为与之前完全一致。对系统:双向 DeepSeek 走非 MLA 路径,相关层的 kernel、显存与调度行为与 MLA 不同,是新的运行组合。对团队:改动集中在模型注册与注意力构造,代码量小、模式清晰,为后续 encoder-only/embedding 变体提供了可参考的落地范式。

核心注意力路径变更 全局配置分支 运行时数值测试未进 CI 依赖 hf-overrides 变通

关联 Issue

未识别关联 Issue

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

完整报告

参与讨论