Skip to content

Commit 07344c7

Browse files
committed
Address PR feedback for DeepSeek-V4 integration
1 parent 9a571d5 commit 07344c7

6 files changed

Lines changed: 22 additions & 13 deletions

File tree

src/maxtext/configs/models/deepseek4-284b.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,10 @@ indexer_head_dim: 128
3636
indexer_n_heads: 64
3737
indexer_topk: 512
3838

39-
# Note: Layers (0, 1, 2) are prefix layers.
39+
# Note: Layers (0, 1, 2) are prefix layers as `first_num_hash_layers=3`.
4040
# The 44th layer (MTP module with compress_ratio=0) has been explicitly dropped for now.
4141
# This leaves exactly 43 layers: 3 prefix [0,0,4] + 40 scanned.
42+
# `compress_ratio=0` uses sliding window attention. In this case, layer (0, 1).
4243
compress_ratios: [0, 0, 4, 128, 4, 128, 4, 128, 4, 128, 4, 128, 4, 128, 4, 128, 4, 128, 4, 128, 4, 128, 4, 128, 4, 128, 4, 128, 4, 128, 4, 128, 4, 128, 4, 128, 4, 128, 4, 128, 4, 128, 4]
4344

4445
# --- MoE configuration ---
@@ -57,7 +58,6 @@ o_lora_rank: 1024
5758
sliding_window_size: 128
5859

5960
# --- RoPE ---
60-
6161
rope_type: "default"
6262
rope_max_timescale: 10000 # Main RoPE theta
6363
compressed_rope_max_timescale: 160000 # Compressed RoPE theta

src/maxtext/layers/attention_compressed.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -697,6 +697,9 @@ def __init__(
697697
self.q_lora_rank = q_lora_rank
698698
self.compress_ratio = compress_ratio
699699

700+
if self.compress_ratio == 0:
701+
attention_type = AttentionType.LOCAL_SLIDING
702+
700703
super().__init__(
701704
config=config,
702705
num_query_heads=num_query_heads,

src/maxtext/layers/decoders.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1238,6 +1238,7 @@ def __call__(
12381238
previous_chunk=previous_chunk,
12391239
slot=slot,
12401240
kv_cache=kv_cache,
1241+
decoder_input_tokens=decoder_input_tokens,
12411242
attention_metadata=attention_metadata,
12421243
**layer_call_kwargs,
12431244
)
@@ -1481,7 +1482,12 @@ def _apply_deepseek4_scanned_blocks(
14811482
}
14821483

14831484
# 1. Prefix Unrolling
1484-
# These layers use Hash Routing.
1485+
# Prefix layers are unrolled (unscanned) for two architectural reasons:
1486+
# 1. Heterogeneous Attention: JAX nn.scan requires identical computation graphs, but the first few layers
1487+
# use different attention configurations (e.g., DeepSeek-V4 uses compress_ratios [0, 0, 4] for layers 0, 1, 2).
1488+
# 2. Static Hash Routing: The first `first_num_hash_layers` (which is 3 for DeepSeek-V4) use deterministic
1489+
# token-to-expert Hash Routing instead of learned top-k routing.
1490+
# Therefore, these prefix layers are instantiated individually before we scan the remaining uniform blocks.
14851491
num_hash_layers = cfg.first_num_hash_layers
14861492
for layer_idx in range(num_hash_layers):
14871493
prefix_layer = deepseek4.DeepSeek4LayerToLinen(

src/maxtext/models/deepseek4.py

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -93,12 +93,6 @@ def __init__(
9393
if compress_ratio is None:
9494
compress_ratio = config.compress_ratios[layer_idx]
9595

96-
# Route to LOCAL_SLIDING if compression is disabled for this layer,
97-
# otherwise default to the globally configured attention type (e.g., COMPRESSED).
98-
layer_attention_type = (
99-
AttentionType.LOCAL_SLIDING if compress_ratio == 0 else AttentionType(self.config.attention_type)
100-
)
101-
10296
self.self_attention = attention_compressed.CompressedAttention(
10397
config=self.config,
10498
compress_ratio=compress_ratio,
@@ -108,7 +102,7 @@ def __init__(
108102
max_target_length=self.config.max_target_length,
109103
max_prefill_predict_length=self.config.max_prefill_predict_length,
110104
attention_kernel=self.config.attention,
111-
attention_type=layer_attention_type,
105+
attention_type=AttentionType(self.config.attention_type),
112106
inputs_q_shape=self.dummy_inputs_shape,
113107
inputs_kv_shape=self.dummy_inputs_shape,
114108
mesh=self.mesh,

src/maxtext/utils/globals.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@
7575
"deepseek2-16b": "deepseek-ai/DeepSeek-V2-Lite",
7676
"deepseek3-671b": "deepseek-ai/DeepSeek-V3",
7777
"deepseek3.2-671b": "deepseek-ai/DeepSeek-V3.2",
78-
"deepseek4": "deepseek-ai/DeepSeek-V4-Flash",
78+
"deepseek4-284b": "deepseek-ai/DeepSeek-V4-Flash",
7979
"gpt-oss-20b": "openai/gpt-oss-20b",
8080
"gpt-oss-120b": "openai/gpt-oss-120b",
8181
"qwen3-omni-30b-a3b": "Qwen/Qwen3-Omni-30B-A3B-Instruct",

tests/unit/train_compile_test.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -804,9 +804,14 @@ def test_deepseek32(self):
804804
)
805805
)
806806

807-
def test_deepseek4(self):
807+
@parameterized.named_parameters(
808+
{"testcase_name": "scanned", "scan_layers": "true"},
809+
{"testcase_name": "unscanned", "scan_layers": "false"},
810+
)
811+
@pytest.mark.cpu_only
812+
def test_deepseek4(self, scan_layers):
808813
# test deepseek4 compile
809-
compiled_trainstep_file = "/tmp/test_deepseek4.pickle"
814+
compiled_trainstep_file = f"/tmp/test_deepseek4_{scan_layers}.pickle"
810815
train_compile_main(
811816
(
812817
"",
@@ -818,6 +823,7 @@ def test_deepseek4(self):
818823
"model_name=deepseek4-284b",
819824
"per_device_batch_size=1",
820825
"max_target_length=1024",
826+
f"scan_layers={scan_layers}",
821827
"attention=dot_product",
822828
"dtype=bfloat16",
823829
"weight_dtype=bfloat16",

0 commit comments

Comments
 (0)