Defuser 0.0.24__tar.gz → 0.0.26__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. {defuser-0.0.24 → defuser-0.0.26}/Defuser.egg-info/PKG-INFO +2 -2
  2. {defuser-0.0.24 → defuser-0.0.26}/PKG-INFO +2 -2
  3. {defuser-0.0.24 → defuser-0.0.26}/README.md +1 -1
  4. {defuser-0.0.24 → defuser-0.0.26}/defuser/model_registry.py +12 -0
  5. {defuser-0.0.24 → defuser-0.0.26}/pyproject.toml +2 -2
  6. {defuser-0.0.24 → defuser-0.0.26}/tests/test_candidate_coverage.py +19 -0
  7. {defuser-0.0.24 → defuser-0.0.26}/tests/test_convert_model.py +53 -0
  8. {defuser-0.0.24 → defuser-0.0.26}/tests/test_meta_model_defusion.py +48 -0
  9. {defuser-0.0.24 → defuser-0.0.26}/Defuser.egg-info/SOURCES.txt +0 -0
  10. {defuser-0.0.24 → defuser-0.0.26}/Defuser.egg-info/dependency_links.txt +0 -0
  11. {defuser-0.0.24 → defuser-0.0.26}/Defuser.egg-info/requires.txt +0 -0
  12. {defuser-0.0.24 → defuser-0.0.26}/Defuser.egg-info/top_level.txt +0 -0
  13. {defuser-0.0.24 → defuser-0.0.26}/LICENSE +0 -0
  14. {defuser-0.0.24 → defuser-0.0.26}/defuser/__init__.py +0 -0
  15. {defuser-0.0.24 → defuser-0.0.26}/defuser/checkpoint_ops.py +0 -0
  16. {defuser-0.0.24 → defuser-0.0.26}/defuser/defuser.py +0 -0
  17. {defuser-0.0.24 → defuser-0.0.26}/defuser/modeling/__init__.py +0 -0
  18. {defuser-0.0.24 → defuser-0.0.26}/defuser/modeling/glm4v.py +0 -0
  19. {defuser-0.0.24 → defuser-0.0.26}/defuser/modeling/model_patches.py +0 -0
  20. {defuser-0.0.24 → defuser-0.0.26}/defuser/modeling/moe_experts_interface.py +0 -0
  21. {defuser-0.0.24 → defuser-0.0.26}/defuser/modeling/replace_modules.py +0 -0
  22. {defuser-0.0.24 → defuser-0.0.26}/defuser/modeling/runtime_defusion.py +0 -0
  23. {defuser-0.0.24 → defuser-0.0.26}/defuser/modeling/unfused_moe/__init__.py +0 -0
  24. {defuser-0.0.24 → defuser-0.0.26}/defuser/modeling/unfused_moe/common.py +0 -0
  25. {defuser-0.0.24 → defuser-0.0.26}/defuser/modeling/unfused_moe/glm4_moe.py +0 -0
  26. {defuser-0.0.24 → defuser-0.0.26}/defuser/modeling/unfused_moe/glm4_moe_lite.py +0 -0
  27. {defuser-0.0.24 → defuser-0.0.26}/defuser/modeling/unfused_moe/mixtral.py +0 -0
  28. {defuser-0.0.24 → defuser-0.0.26}/defuser/modeling/unfused_moe/qwen2_moe.py +0 -0
  29. {defuser-0.0.24 → defuser-0.0.26}/defuser/modeling/unfused_moe/qwen3_moe.py +0 -0
  30. {defuser-0.0.24 → defuser-0.0.26}/defuser/modeling/unfused_moe/qwen3_next.py +0 -0
  31. {defuser-0.0.24 → defuser-0.0.26}/defuser/modeling/unfused_moe/qwen3_omni_moe.py +0 -0
  32. {defuser-0.0.24 → defuser-0.0.26}/defuser/modeling/update_module.py +0 -0
  33. {defuser-0.0.24 → defuser-0.0.26}/defuser/utils/__init__.py +0 -0
  34. {defuser-0.0.24 → defuser-0.0.26}/defuser/utils/common.py +0 -0
  35. {defuser-0.0.24 → defuser-0.0.26}/defuser/utils/device.py +0 -0
  36. {defuser-0.0.24 → defuser-0.0.26}/defuser/utils/hf.py +0 -0
  37. {defuser-0.0.24 → defuser-0.0.26}/defuser/utils/model.py +0 -0
  38. {defuser-0.0.24 → defuser-0.0.26}/setup.cfg +0 -0
  39. {defuser-0.0.24 → defuser-0.0.26}/setup.py +0 -0
  40. {defuser-0.0.24 → defuser-0.0.26}/tests/test_device_utils.py +0 -0
  41. {defuser-0.0.24 → defuser-0.0.26}/tests/test_filter_rules.py +0 -0
  42. {defuser-0.0.24 → defuser-0.0.26}/tests/test_moe_experts_interface.py +0 -0
  43. {defuser-0.0.24 → defuser-0.0.26}/tests/test_replace_modules_tracker.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: Defuser
3
- Version: 0.0.24
3
+ Version: 0.0.26
4
4
  Summary: Model defuser helper for HF Transformers.
5
5
  Author-email: ModelCloud <qubitium@modelcloud.ai>
6
6
  License-Expression: Apache-2.0
@@ -93,7 +93,7 @@ Defuser currently supports the following `transformers>=5.3.0` `model_type` valu
93
93
  | Pattern | Supported model types | Defused op performed ⚙️ |
94
94
  | --- |-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| --- |
95
95
  | Standard routed expert tensors 🧱 | `deepseek_v2`, `dots1`, `ernie4_5_moe`, `ernie4_5_vl_moe`, `exaone_moe`, `flex_olmo`, `glm4_moe_lite`, `glm4v_moe`, `hunyuan_v1_moe`, `jamba`, `laguna`, `lfm2_moe`, `minimax`, `minimax_m2`, `olmoe`, `qwen3_vl_moe`, `solar_open`, `solar_open2` | Splits fused expert tensors or registered expert buffers into numbered expert `nn.Linear` modules with per-expert `gate_proj`, `up_proj`, and `down_proj`. |
96
- | Mixed sparse and shared experts | `deepseek_v3`, deepseek_v4`, `glm_moe_dsa`, `qwen3_5_moe`, `qwen3_5_moe_text` | Runtime expert tensor defusion for routed experts while preserving the model's shared-expert path. |
96
+ | Mixed sparse and shared experts | `deepseek_v3`, `deepseek_v32`, `deepseek_v4`, `glm_moe_dsa`, `qwen3_5_moe`, `qwen3_5_moe_text`, `qwen4_exp`, `qwen4_exp_text` | Runtime expert tensor defusion for routed experts while preserving the model's shared-expert path. |
97
97
  | Transposed or packed expert tensors | `gpt_oss`, `phimoe` | Splits transposed fused expert `gate_up_proj` tensors into per-expert `gate_proj` + `up_proj`, preserves expert bias when present, and converts expert tensors into numbered expert `nn.Linear` modules. |
98
98
  | Flattened expert layout | `dbrx` | Rebuilds the flattened DBRX expert FFN weights into numbered expert `gate_proj`, `up_proj`, and `down_proj` `nn.Linear` modules. |
99
99
  | Batched expert-input execution | `llama4` | Runtime expert tensor defusion plus preservation of the llama4 batched expert-input execution contract. |
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: Defuser
3
- Version: 0.0.24
3
+ Version: 0.0.26
4
4
  Summary: Model defuser helper for HF Transformers.
5
5
  Author-email: ModelCloud <qubitium@modelcloud.ai>
6
6
  License-Expression: Apache-2.0
@@ -93,7 +93,7 @@ Defuser currently supports the following `transformers>=5.3.0` `model_type` valu
93
93
  | Pattern | Supported model types | Defused op performed ⚙️ |
94
94
  | --- |-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| --- |
95
95
  | Standard routed expert tensors 🧱 | `deepseek_v2`, `dots1`, `ernie4_5_moe`, `ernie4_5_vl_moe`, `exaone_moe`, `flex_olmo`, `glm4_moe_lite`, `glm4v_moe`, `hunyuan_v1_moe`, `jamba`, `laguna`, `lfm2_moe`, `minimax`, `minimax_m2`, `olmoe`, `qwen3_vl_moe`, `solar_open`, `solar_open2` | Splits fused expert tensors or registered expert buffers into numbered expert `nn.Linear` modules with per-expert `gate_proj`, `up_proj`, and `down_proj`. |
96
- | Mixed sparse and shared experts | `deepseek_v3`, deepseek_v4`, `glm_moe_dsa`, `qwen3_5_moe`, `qwen3_5_moe_text` | Runtime expert tensor defusion for routed experts while preserving the model's shared-expert path. |
96
+ | Mixed sparse and shared experts | `deepseek_v3`, `deepseek_v32`, `deepseek_v4`, `glm_moe_dsa`, `qwen3_5_moe`, `qwen3_5_moe_text`, `qwen4_exp`, `qwen4_exp_text` | Runtime expert tensor defusion for routed experts while preserving the model's shared-expert path. |
97
97
  | Transposed or packed expert tensors | `gpt_oss`, `phimoe` | Splits transposed fused expert `gate_up_proj` tensors into per-expert `gate_proj` + `up_proj`, preserves expert bias when present, and converts expert tensors into numbered expert `nn.Linear` modules. |
98
98
  | Flattened expert layout | `dbrx` | Rebuilds the flattened DBRX expert FFN weights into numbered expert `gate_proj`, `up_proj`, and `down_proj` `nn.Linear` modules. |
99
99
  | Batched expert-input execution | `llama4` | Runtime expert tensor defusion plus preservation of the llama4 batched expert-input execution contract. |
@@ -67,7 +67,7 @@ Defuser currently supports the following `transformers>=5.3.0` `model_type` valu
67
67
  | Pattern | Supported model types | Defused op performed ⚙️ |
68
68
  | --- |-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| --- |
69
69
  | Standard routed expert tensors 🧱 | `deepseek_v2`, `dots1`, `ernie4_5_moe`, `ernie4_5_vl_moe`, `exaone_moe`, `flex_olmo`, `glm4_moe_lite`, `glm4v_moe`, `hunyuan_v1_moe`, `jamba`, `laguna`, `lfm2_moe`, `minimax`, `minimax_m2`, `olmoe`, `qwen3_vl_moe`, `solar_open`, `solar_open2` | Splits fused expert tensors or registered expert buffers into numbered expert `nn.Linear` modules with per-expert `gate_proj`, `up_proj`, and `down_proj`. |
70
- | Mixed sparse and shared experts | `deepseek_v3`, deepseek_v4`, `glm_moe_dsa`, `qwen3_5_moe`, `qwen3_5_moe_text` | Runtime expert tensor defusion for routed experts while preserving the model's shared-expert path. |
70
+ | Mixed sparse and shared experts | `deepseek_v3`, `deepseek_v32`, `deepseek_v4`, `glm_moe_dsa`, `qwen3_5_moe`, `qwen3_5_moe_text`, `qwen4_exp`, `qwen4_exp_text` | Runtime expert tensor defusion for routed experts while preserving the model's shared-expert path. |
71
71
  | Transposed or packed expert tensors | `gpt_oss`, `phimoe` | Splits transposed fused expert `gate_up_proj` tensors into per-expert `gate_proj` + `up_proj`, preserves expert bias when present, and converts expert tensors into numbered expert `nn.Linear` modules. |
72
72
  | Flattened expert layout | `dbrx` | Rebuilds the flattened DBRX expert FFN weights into numbered expert `gate_proj`, `up_proj`, and `down_proj` `nn.Linear` modules. |
73
73
  | Batched expert-input execution | `llama4` | Runtime expert tensor defusion plus preservation of the llama4 batched expert-input execution contract. |
@@ -16,6 +16,9 @@ class PATCH(str, Enum):
16
16
 
17
17
 
18
18
  MODEL_CONFIG = {
19
+ "axk2": {
20
+ "min_transformers_version": MIN_SUPPORTED_TRANSFORMERS_VERSION,
21
+ },
19
22
  "cohere2_moe": {
20
23
  "min_transformers_version": MIN_SUPPORTED_TRANSFORMERS_VERSION,
21
24
  },
@@ -34,6 +37,9 @@ MODEL_CONFIG = {
34
37
  "deepseek_v3": {
35
38
  "min_transformers_version": MIN_SUPPORTED_TRANSFORMERS_VERSION,
36
39
  },
40
+ "deepseek_v32": {
41
+ "min_transformers_version": MIN_SUPPORTED_TRANSFORMERS_VERSION,
42
+ },
37
43
  "deepseek_v4": {
38
44
  "min_transformers_version": MIN_SUPPORTED_TRANSFORMERS_VERSION,
39
45
  },
@@ -140,6 +146,12 @@ MODEL_CONFIG = {
140
146
  ),
141
147
  ],
142
148
  },
149
+ "qwen4_exp": {
150
+ "min_transformers_version": MIN_SUPPORTED_TRANSFORMERS_VERSION,
151
+ },
152
+ "qwen4_exp_text": {
153
+ "min_transformers_version": MIN_SUPPORTED_TRANSFORMERS_VERSION,
154
+ },
143
155
  "glm4_moe": {
144
156
  "min_transformers_version": MIN_SUPPORTED_TRANSFORMERS_VERSION,
145
157
  PATCH.REPLACE_MODULE: [
@@ -4,12 +4,12 @@
4
4
  # Contact: qubitium@modelcloud.ai, x.com/qubitium
5
5
 
6
6
  [build-system]
7
- requires = ["setuptools>=77.0.1,<83"]
7
+ requires = ["setuptools>=77.0.1,<85"]
8
8
  build-backend = "setuptools.build_meta"
9
9
 
10
10
  [project]
11
11
  name = "Defuser"
12
- version = "0.0.24"
12
+ version = "0.0.26"
13
13
  description = "Model defuser helper for HF Transformers."
14
14
  readme = "README.md"
15
15
  requires-python = ">=3.9"
@@ -161,6 +161,22 @@ STANDARD_MOE_CASES = [
161
161
  "route_indices": [[0], [1], [2], [3], [0]],
162
162
  "expert_attrs": ("gate_proj", "up_proj", "down_proj"),
163
163
  },
164
+ {
165
+ "model_type": "deepseek_v32",
166
+ "module_path": "transformers.models.deepseek_v32.modeling_deepseek_v32",
167
+ "class_name": "DeepseekV32Experts",
168
+ "config_module": "transformers.models.deepseek_v32.configuration_deepseek_v32",
169
+ "config_name": "DeepseekV32Config",
170
+ "config_updates": {
171
+ "hidden_size": 64,
172
+ "moe_intermediate_size": 32,
173
+ "n_routed_experts": 4,
174
+ "hidden_act": "silu",
175
+ },
176
+ "input_dim": 64,
177
+ "route_indices": [[0], [1], [2], [3], [0]],
178
+ "expert_attrs": ("gate_proj", "up_proj", "down_proj"),
179
+ },
164
180
  {
165
181
  "model_type": "dots1",
166
182
  "module_path": "transformers.models.dots1.modeling_dots1",
@@ -547,6 +563,7 @@ ALL_CANDIDATE_MODEL_TYPES = {
547
563
  "dbrx",
548
564
  "deepseek_v2",
549
565
  "deepseek_v3",
566
+ "deepseek_v32",
550
567
  "dia",
551
568
  "dots1",
552
569
  "ernie4_5_moe",
@@ -586,6 +603,8 @@ ALL_CANDIDATE_MODEL_TYPES = {
586
603
  "qwen3_next",
587
604
  "qwen3_omni_moe",
588
605
  "qwen3_vl_moe",
606
+ "qwen4_exp",
607
+ "qwen4_exp_text",
589
608
  "solar_open",
590
609
  "solar_open2",
591
610
  "zamba2",
@@ -38,6 +38,8 @@ from transformers.models.qwen3_next.modeling_qwen3_next import (
38
38
  Qwen3NextSparseMoeBlock,
39
39
  )
40
40
  from transformers.models.qwen3_omni_moe.configuration_qwen3_omni_moe import Qwen3OmniMoeConfig
41
+ from transformers.models.qwen4_exp.configuration_qwen4_exp import Qwen4ExpTextConfig
42
+ from transformers.models.qwen4_exp.modeling_qwen4_exp import Qwen4ExpForCausalLM
41
43
  from transformers.models.gpt_oss.modeling_gpt_oss import GptOssConfig, GptOssForCausalLM
42
44
  from transformers.models.phimoe.modeling_phimoe import PhimoeConfig, PhimoeForCausalLM
43
45
  from transformers.models.llama4.modeling_llama4 import Llama4Config, Llama4ForConditionalGeneration
@@ -176,6 +178,39 @@ def _tiny_qwen3_5_moe_config():
176
178
  )
177
179
 
178
180
 
181
+ def _tiny_qwen4_exp_text_config():
182
+ return Qwen4ExpTextConfig(
183
+ vocab_size=64,
184
+ hidden_size=16,
185
+ num_hidden_layers=2,
186
+ num_attention_heads=4,
187
+ num_key_value_heads=2,
188
+ head_dim=4,
189
+ moe_intermediate_size=8,
190
+ shared_expert_intermediate_size=8,
191
+ num_experts=3,
192
+ num_experts_per_tok=2,
193
+ max_position_embeddings=32,
194
+ layer_types=["linear_attention", "qwen_sparse_attention"],
195
+ linear_num_key_heads=2,
196
+ linear_num_value_heads=4,
197
+ linear_key_head_dim=4,
198
+ linear_value_head_dim=4,
199
+ linear_conv_kernel_dim=2,
200
+ hc_count=2,
201
+ hc_lowrank=4,
202
+ ple_layer_ids=[],
203
+ bos_token_id=1,
204
+ eos_token_id=2,
205
+ pad_token_id=0,
206
+ indexer_n_heads=2,
207
+ indexer_kv_heads=1,
208
+ indexer_head_dim=4,
209
+ indexer_budget=8,
210
+ indexer_compress_ratio=2,
211
+ )
212
+
213
+
179
214
  def _tiny_mixtral_config():
180
215
  return MixtralConfig(
181
216
  vocab_size=128,
@@ -739,6 +774,24 @@ def test_qwen3_5_moe():
739
774
  torch.testing.assert_close(expert0.down_proj.weight, expected_down)
740
775
 
741
776
 
777
+ def test_qwen4_exp_text_preserves_forward():
778
+ model = Qwen4ExpForCausalLM(_tiny_qwen4_exp_text_config()).eval()
779
+ input_ids = torch.tensor([[1, 7, 8, 2]])
780
+
781
+ with torch.inference_mode():
782
+ expected = model(input_ids=input_ids, use_cache=False).logits
783
+
784
+ assert convert_model(model, cleanup_original=False)
785
+ assert model.config.model_type == "qwen4_exp_text"
786
+ experts = model.model.layers[0].mlp.experts
787
+ assert hasattr(experts, "0")
788
+ assert not hasattr(experts, "gate_up_proj")
789
+
790
+ with torch.inference_mode():
791
+ actual = model(input_ids=input_ids, use_cache=False).logits
792
+ torch.testing.assert_close(actual, expected, rtol=1e-5, atol=1e-7)
793
+
794
+
742
795
  @pytest.mark.skipif(not torch.cuda.is_available(), reason="CUDA required")
743
796
  def test_qwen3_5_moe_runtime_defusion_preserves_cuda_device():
744
797
  model = Qwen3_5MoeForConditionalGeneration(_tiny_qwen3_5_moe_config()).cuda().eval()
@@ -155,6 +155,8 @@ def _build_model_config(case: dict):
155
155
  config.ffn_config.ffn_act_fn = {"name": "silu"}
156
156
  elif model_type == "deepseek_v3":
157
157
  config.first_k_dense_replace = 0
158
+ elif model_type == "deepseek_v32":
159
+ config.mlp_layer_types = ["sparse"] * config.num_hidden_layers
158
160
  elif model_type == "ernie4_5_vl_moe":
159
161
  config.text_config.moe_intermediate_size = [32, 32]
160
162
  config.text_config.rope_parameters = {
@@ -300,6 +302,17 @@ def _validate_defused_module(case: dict, module) -> None:
300
302
 
301
303
 
302
304
  META_MODEL_CASES = [
305
+ {
306
+ "model_type": "axk2",
307
+ "mode": "convert",
308
+ "model_module": "transformers.models.axk2.modeling_axk2",
309
+ "model_class": "AXK2ForCausalLM",
310
+ "config_module": "transformers.models.axk2.configuration_axk2",
311
+ "config_class": "AXK2Config",
312
+ "target_class_paths": ("transformers.models.axk2.modeling_axk2.AXK2Experts",),
313
+ "validator": "experts",
314
+ "min_targets": 1,
315
+ },
303
316
  {
304
317
  "model_type": "dbrx",
305
318
  "mode": "convert",
@@ -331,6 +344,19 @@ META_MODEL_CASES = [
331
344
  "validator": "experts",
332
345
  "min_targets": 2,
333
346
  },
347
+ {
348
+ "model_type": "deepseek_v32",
349
+ "mode": "convert",
350
+ "model_module": "transformers.models.deepseek_v32.modeling_deepseek_v32",
351
+ "model_class": "DeepseekV32ForCausalLM",
352
+ "config_module": "transformers.models.deepseek_v32.configuration_deepseek_v32",
353
+ "config_class": "DeepseekV32Config",
354
+ "target_class_paths": (
355
+ "transformers.models.deepseek_v32.modeling_deepseek_v32.DeepseekV32Experts",
356
+ ),
357
+ "validator": "experts",
358
+ "min_targets": 2,
359
+ },
334
360
  {
335
361
  "model_type": "deepseek_v4",
336
362
  "mode": "convert",
@@ -724,6 +750,28 @@ META_MODEL_CASES = [
724
750
  "validator": "experts",
725
751
  "min_targets": 2,
726
752
  },
753
+ {
754
+ "model_type": "qwen4_exp",
755
+ "mode": "convert",
756
+ "model_module": "transformers.models.qwen4_exp.modeling_qwen4_exp",
757
+ "model_class": "Qwen4ExpForConditionalGeneration",
758
+ "config_module": "transformers.models.qwen4_exp.configuration_qwen4_exp",
759
+ "config_class": "Qwen4ExpConfig",
760
+ "target_class_paths": ("transformers.models.qwen4_exp.modeling_qwen4_exp.Qwen4ExpTextExperts",),
761
+ "validator": "experts",
762
+ "min_targets": 2,
763
+ },
764
+ {
765
+ "model_type": "qwen4_exp_text",
766
+ "mode": "convert",
767
+ "model_module": "transformers.models.qwen4_exp.modeling_qwen4_exp",
768
+ "model_class": "Qwen4ExpForCausalLM",
769
+ "config_module": "transformers.models.qwen4_exp.configuration_qwen4_exp",
770
+ "config_class": "Qwen4ExpTextConfig",
771
+ "target_class_paths": ("transformers.models.qwen4_exp.modeling_qwen4_exp.Qwen4ExpTextExperts",),
772
+ "validator": "experts",
773
+ "min_targets": 2,
774
+ },
727
775
  {
728
776
  "model_type": "qwen3_moe",
729
777
  "mode": "replace",
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes