[Model] Support bidirectional (encoder-only) attention for DeepSeek e… (#52948)
Signed-off-by: Egor <erop001@gmail.com> Signed-off-by: Egor <47443236+Lossfull@users.noreply.github.com> Co-authored-by: Claude <noreply@anthropic.com>
Egor committed
Aug 19, 2026 at 19:36 UTC
e9e1630e93b13b241c4cdb52c47e35fd38c6eb46
4 files changed
+35
-3
tests/models/registry.py
+5
@@ -593,6 +593,11 @@ _EMBEDDING_EXAMPLE_MODELS = {
593
hf_overrides={"architectures": ["BertSpladeSparseEmbeddingModel"]},
594
),
595
"BgeM3EmbeddingModel": _HfExamplesInfo("BAAI/bge-m3"),
596
+ "DeepseekV3BidirectionalModel": _HfExamplesInfo(
597
+ "ai-sage/Giga-Embeddings-instruct-10B-A1.8B-0826",
598
+ trust_remote_code=True,
599
+ hf_overrides={"model_type": "deepseek_v3", "auto_map": None},
600
+ ),
601
"Gemma2Model": _HfExamplesInfo("BAAI/bge-multilingual-gemma2"),
602
"Gemma3TextModel": _HfExamplesInfo("google/embeddinggemma-300m"),
603
"GritLM": _HfExamplesInfo("parasail-ai/GritLM-7B-vllm"),
vllm/config/model.py
+6
@@ -1877,6 +1877,12 @@ class ModelConfig:
1877
# kv_lora_rank indicates that a Transformers model implementation uses MLA
1878
return getattr(self.hf_text_config, "kv_lora_rank", None) is not None
1879
# Manually maintained list of model types for vLLM model implementations
1880
+
1881
+ # Bidirectional DeepSeek variants (is_causal=False, used by some
1882
+ # embedding models) must use the non-MLA attention path, since the
1883
+ # MLA kernels only support causal attention.
1884
+ if not getattr(self.hf_text_config, "is_causal", True):
1885
+ return False
1886
return self.is_deepseek_mla
1887
1888
@property
vllm/model_executor/models/deepseek_v2.py
+23
-3
@@ -47,7 +47,11 @@ from vllm.distributed import (
47
)
48
from vllm.logger import init_logger
49
from vllm.model_executor.layers.activation import SiluAndMul
50
-from vllm.model_executor.layers.attention import Attention, RSWAAttention
50
+from vllm.model_executor.layers.attention import (
51
+ Attention,
52
+ EncoderOnlyAttention,
53
+ RSWAAttention,
54
+)
55
from vllm.model_executor.layers.attention_layer_base import AttentionLayerBase
56
from vllm.model_executor.layers.fused_moe import (
57
FusedMoEFactory,
@@ -98,7 +102,7 @@ from vllm.model_executor.models.utils import (
102
from vllm.platforms import current_platform
103
from vllm.sequence import IntermediateTensors
104
from vllm.utils.torch_utils import direct_register_custom_op
101
-from vllm.v1.attention.backend import AttentionBackend
105
+from vllm.v1.attention.backend import AttentionBackend, AttentionType
106
from vllm.v1.attention.backends.mla.indexer import (
107
DeepseekV32IndexerBackend,
108
)
@@ -553,7 +557,22 @@ class DeepseekV2Attention(nn.Module):
557
mscale = yarn_get_mscale(scaling_factor, float(mscale_all_dim))
558
self.scaling = self.scaling * mscale * mscale
559
556
- self.attn = Attention(
560
+ # DeepSeek is causal by default (decoder-only). Bidirectional
561
+ # (encoder-only) attention is used by embedding models derived from
562
+ # this architecture, which set `is_causal=False` on the HF config.
563
+ # This only applies on the non-MLA path, since the MLA kernels are
564
+ # causal-only; `ModelConfig.use_mla` already disables MLA for these
565
+ # models.
566
+ if getattr(config, "is_causal", True):
567
+ attn_type = AttentionType.DECODER
568
+ else:
569
+ attn_type = AttentionType.ENCODER_ONLY
570
+ attn_cls = (
571
+ EncoderOnlyAttention
572
+ if attn_type == AttentionType.ENCODER_ONLY
573
+ else Attention
574
+ )
575
+ self.attn = attn_cls(
576
self.num_local_heads,
577
self.qk_head_dim,
578
self.scaling,
@@ -561,6 +580,7 @@ class DeepseekV2Attention(nn.Module):
580
cache_config=cache_config,
581
quant_config=quant_config,
582
prefix=f"{prefix}.attn",
583
+ attn_type=attn_type,
584
)
585
586
def forward(
vllm/model_executor/models/registry.py
+1
@@ -230,6 +230,7 @@ _EMBEDDING_MODELS = {
230
"BertSpladeSparseEmbeddingModel": ("bert", "BertSpladeSparseEmbeddingModel"),
231
"BgeM3EmbeddingModel": ("roberta", "BgeM3EmbeddingModel"),
232
"DeciLMForCausalLM": ("nemotron_nas", "DeciLMForCausalLM"),
233
+ "DeepseekV3BidirectionalModel": ("deepseek_v2", "DeepseekV3ForCausalLM"),
234
"Gemma2Model": ("gemma2", "Gemma2ForCausalLM"),
235
"Gemma3TextModel": ("gemma3", "Gemma3Model"),
236
"GlmForCausalLM": ("glm", "GlmForCausalLM"),