From 8eb3a06bc864dcc7d08c591d1d8a1315a4180706 Mon Sep 17 00:00:00 2001 From: drunkcoding Date: Fri, 14 Aug 2026 09:18:29 +0000 Subject: [PATCH 1/2] =?UTF-8?q?fix(compat):=20handle=20DeepseekV2MoE?= =?UTF-8?q?=E2=86=92DeepseekV2Moe=20rename=20in=20Transformers?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Newer Transformers renamed DeepseekV2MoE to DeepseekV2Moe (lowercase 'e') and removed the standalone DeepseekV2MoEGate class entirely. Changes: - moe_infinity/models/deepseek.py: replace hard DeepseekV2MoEGate import with getattr fallback; when the class is absent (new Transformers) fall back to the local DeepseekMoEGate which has the same raw-logits interface. - tests/python/ops/test_deepseek_v2_gate_consistency.py: resolve DeepseekV2MoE via getattr (supports both spellings); guard the two MoEGate-comparison tests with @requires_moe_gate so they skip gracefully when DeepseekV2MoEGate is unavailable. model_offload.py already had the dual-spelling guard from commit 48d5385. --- moe_infinity/models/deepseek.py | 17 ++++++++------- .../ops/test_deepseek_v2_gate_consistency.py | 21 +++++++++++++++---- 2 files changed, 27 insertions(+), 11 deletions(-) diff --git a/moe_infinity/models/deepseek.py b/moe_infinity/models/deepseek.py index 3d60b82b..0fd0ce31 100644 --- a/moe_infinity/models/deepseek.py +++ b/moe_infinity/models/deepseek.py @@ -48,25 +48,28 @@ def __init__(self, config): self.num_expert = config.n_routed_experts if self.config.model_type == "deepseek_v2": + import transformers.models.deepseek_v2.modeling_deepseek_v2 as _dsv2 from transformers.models.deepseek_v2.modeling_deepseek_v2 import ( DeepseekV2MLP, - DeepseekV2MoEGate, ) self.mlp_cls = DeepseekV2MLP - self.gate_cls = DeepseekV2MoEGate + # DeepseekV2MoEGate was removed in newer Transformers; fall back to + # the local DeepseekMoEGate which has the same raw-logits interface. + _gate_cls = getattr(_dsv2, "DeepseekV2MoEGate", None) + self.gate_cls = _gate_cls if _gate_cls is not None else DeepseekMoEGate if self.config.model_type == "deepseek_v3": from transformers.models.deepseek_v3.modeling_deepseek_v3 import ( DeepseekV3MLP, ) self.mlp_cls = DeepseekV3MLP - # V3 upstream has no standalone gate; use V2 gate (same interface) - from transformers.models.deepseek_v2.modeling_deepseek_v2 import ( - DeepseekV2MoEGate, - ) + # V3 upstream has no standalone gate; use V2 gate when available, + # otherwise fall back to the local DeepseekMoEGate. + import transformers.models.deepseek_v2.modeling_deepseek_v2 as _dsv2 - self.gate_cls = DeepseekV2MoEGate + _gate_cls = getattr(_dsv2, "DeepseekV2MoEGate", None) + self.gate_cls = _gate_cls if _gate_cls is not None else DeepseekMoEGate self.experts = nn.ModuleList( [ diff --git a/tests/python/ops/test_deepseek_v2_gate_consistency.py b/tests/python/ops/test_deepseek_v2_gate_consistency.py index 8cf3e5a3..b5f6380e 100644 --- a/tests/python/ops/test_deepseek_v2_gate_consistency.py +++ b/tests/python/ops/test_deepseek_v2_gate_consistency.py @@ -41,12 +41,23 @@ def decorator(fn): _ensure_nvtx_stub_has_annotate() +import transformers.models.deepseek_v2.modeling_deepseek_v2 as _dsv2_mod from transformers import DeepseekV2Config -from transformers.models.deepseek_v2.modeling_deepseek_v2 import ( - DeepseekV2MoE, + +DeepseekV2MoE = getattr(_dsv2_mod, "DeepseekV2Moe", None) or getattr( + _dsv2_mod, "DeepseekV2MoE", None ) -from transformers.models.deepseek_v2.modeling_deepseek_v2 import ( - DeepseekV2MoEGate as MoEGate, +if DeepseekV2MoE is None: + raise ImportError( + "Neither 'DeepseekV2Moe' nor 'DeepseekV2MoE' found in " + "transformers.models.deepseek_v2.modeling_deepseek_v2" + ) + +MoEGate = getattr(_dsv2_mod, "DeepseekV2MoEGate", None) + +requires_moe_gate = pytest.mark.skipif( + MoEGate is None, + reason="DeepseekV2MoEGate removed in this Transformers version", ) from moe_infinity.models.deepseek import DeepseekMoEBlock, DeepseekMoEGate @@ -132,6 +143,7 @@ def wait_dispatch_local(self): @requires_cuda +@requires_moe_gate def test_v2_gate_equivalence(seed_everything): """V2-Lite config: native MoEGate and simplified DeepseekMoEGate must produce identical routing because topk_method='greedy' with @@ -185,6 +197,7 @@ def test_v2_gate_equivalence(seed_everything): @requires_cuda +@requires_moe_gate def test_v2_gate_group_limited_greedy(seed_everything): """V2-full config: simplified gate MUST differ from native gate because group_limited_greedy constrains which expert groups can be selected.""" From cd52009abe5c42f4de902464c900e23344177523 Mon Sep 17 00:00:00 2001 From: drunkcoding Date: Fri, 14 Aug 2026 20:47:00 +0000 Subject: [PATCH 2/2] style: apply ruff-format and clang-format --- moe_infinity/models/deepseek.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/moe_infinity/models/deepseek.py b/moe_infinity/models/deepseek.py index 0fd0ce31..79b5a9f6 100644 --- a/moe_infinity/models/deepseek.py +++ b/moe_infinity/models/deepseek.py @@ -57,7 +57,9 @@ def __init__(self, config): # DeepseekV2MoEGate was removed in newer Transformers; fall back to # the local DeepseekMoEGate which has the same raw-logits interface. _gate_cls = getattr(_dsv2, "DeepseekV2MoEGate", None) - self.gate_cls = _gate_cls if _gate_cls is not None else DeepseekMoEGate + self.gate_cls = ( + _gate_cls if _gate_cls is not None else DeepseekMoEGate + ) if self.config.model_type == "deepseek_v3": from transformers.models.deepseek_v3.modeling_deepseek_v3 import ( DeepseekV3MLP, @@ -69,7 +71,9 @@ def __init__(self, config): import transformers.models.deepseek_v2.modeling_deepseek_v2 as _dsv2 _gate_cls = getattr(_dsv2, "DeepseekV2MoEGate", None) - self.gate_cls = _gate_cls if _gate_cls is not None else DeepseekMoEGate + self.gate_cls = ( + _gate_cls if _gate_cls is not None else DeepseekMoEGate + ) self.experts = nn.ModuleList( [