|
40 | 40 | from maxtext.layers.quantizations import AqtQuantization as Quant |
41 | 41 | from maxtext.models import ( |
42 | 42 | deepseek, |
| 43 | + deepseek4, |
43 | 44 | deepseek_batchsplit, |
44 | 45 | deepseek_batchsplit_fp8, |
45 | 46 | gemma, |
@@ -457,6 +458,10 @@ def get_decoder_layers(self): |
457 | 458 | deepseek.DeepSeekDenseLayerToLinen, |
458 | 459 | deepseek.DeepSeekMoELayerToLinen, |
459 | 460 | ] |
| 461 | + case DecoderBlockType.DEEPSEEK4: |
| 462 | + return ( |
| 463 | + [deepseek4.DeepSeek4ScannableBlockToLinen] if self.config.scan_layers else [deepseek4.DeepSeek4LayerToLinen] |
| 464 | + ) |
460 | 465 | case DecoderBlockType.GEMMA: |
461 | 466 | return [gemma.GemmaDecoderLayerToLinen] |
462 | 467 | case DecoderBlockType.GEMMA2: |
@@ -534,6 +539,7 @@ def get_norm_layer(self, num_features: int): |
534 | 539 | DecoderBlockType.MISTRAL, |
535 | 540 | DecoderBlockType.MIXTRAL, |
536 | 541 | DecoderBlockType.DEEPSEEK, |
| 542 | + DecoderBlockType.DEEPSEEK4, |
537 | 543 | DecoderBlockType.GEMMA, |
538 | 544 | DecoderBlockType.GEMMA2, |
539 | 545 | DecoderBlockType.GEMMA3, |
@@ -999,6 +1005,17 @@ def __call__( |
999 | 1005 | previous_chunk, |
1000 | 1006 | slot, |
1001 | 1007 | ) |
| 1008 | + elif cfg.decoder_block == DecoderBlockType.DEEPSEEK4: |
| 1009 | + y = self._apply_deepseek4_scanned_blocks( |
| 1010 | + y, |
| 1011 | + decoder_segment_ids, |
| 1012 | + decoder_positions, |
| 1013 | + deterministic, |
| 1014 | + model_mode, |
| 1015 | + previous_chunk, |
| 1016 | + slot, |
| 1017 | + decoder_input_tokens, |
| 1018 | + ) |
1002 | 1019 | else: |
1003 | 1020 | RemattedBlockLayer = RemattedBlockLayers[0] |
1004 | 1021 | scan_length = int(cfg.num_decoder_layers / cfg.inhomogeneous_layer_cycle_interval) |
@@ -1133,7 +1150,7 @@ def __call__( |
1133 | 1150 | "is_nope_layer": llama4.determine_is_nope_layer(lyr, self.config.nope_layer_interval), |
1134 | 1151 | "is_moe_layer": llama4.determine_is_moe_layer(lyr, self.config.interleave_moe_layer_step), |
1135 | 1152 | } |
1136 | | - if cfg.decoder_block in (DecoderBlockType.QWEN3_NEXT, DecoderBlockType.QWEN3_5): |
| 1153 | + if cfg.decoder_block in (DecoderBlockType.QWEN3_NEXT, DecoderBlockType.QWEN3_5, DecoderBlockType.DEEPSEEK4): |
1137 | 1154 | layer_kwargs = {"layer_idx": lyr} |
1138 | 1155 | kv_cache = None |
1139 | 1156 | if kv_caches is not None: |
@@ -1355,6 +1372,117 @@ def _apply_gemma4_scanned_blocks( |
1355 | 1372 |
|
1356 | 1373 | return y |
1357 | 1374 |
|
| 1375 | + def _apply_deepseek4_scanned_blocks( |
| 1376 | + self, |
| 1377 | + y, |
| 1378 | + decoder_segment_ids, |
| 1379 | + decoder_positions, |
| 1380 | + deterministic, |
| 1381 | + model_mode, |
| 1382 | + previous_chunk, |
| 1383 | + slot, |
| 1384 | + decoder_input_tokens, |
| 1385 | + ): |
| 1386 | + """Applies DeepSeek V4 scanned decoder blocks. |
| 1387 | +
|
| 1388 | + DeepSeek V4 natively has 44 layers, but we explicitly drop the final MTP module (Layer 43) |
| 1389 | + for now, strictly evaluating the 43 standard hidden layers. |
| 1390 | +
|
| 1391 | + The layout perfectly maps to the 43 remaining elements in the config array: |
| 1392 | + - 2 Prefix layers (Indices 0, 1): compress_ratio = [0, 0] |
| 1393 | + - 40 Scanned layers (Indices 2 to 41): 20 perfectly repeating chunks of [4, 128] |
| 1394 | + - 1 Suffix layer (Index 42): compress_ratio = [4] |
| 1395 | +
|
| 1396 | + Total evaluated layers: 2 + 40 + 1 = 43 layers. |
| 1397 | + """ |
| 1398 | + |
| 1399 | + cfg = self.config |
| 1400 | + mesh = self.mesh |
| 1401 | + |
| 1402 | + broadcast_args = ( |
| 1403 | + decoder_segment_ids, |
| 1404 | + decoder_positions, |
| 1405 | + deterministic, |
| 1406 | + model_mode, |
| 1407 | + slot, |
| 1408 | + previous_chunk, |
| 1409 | + ) |
| 1410 | + |
| 1411 | + layer_call_kwargs = { |
| 1412 | + "previous_chunk": previous_chunk, |
| 1413 | + "slot": slot, |
| 1414 | + "decoder_input_tokens": decoder_input_tokens, |
| 1415 | + } |
| 1416 | + |
| 1417 | + # 1. Prefix Unrolling (Layers 0, 1) |
| 1418 | + # These layers use Hash Routing and compress_ratio=0. |
| 1419 | + for layer_idx in range(2): |
| 1420 | + prefix_layer = deepseek4.DeepSeek4LayerToLinen( |
| 1421 | + config=cfg, |
| 1422 | + mesh=mesh, |
| 1423 | + name=f"layers_{layer_idx}", |
| 1424 | + quant=self.quant, |
| 1425 | + model_mode=self.model_mode, |
| 1426 | + layer_idx=layer_idx, |
| 1427 | + ) |
| 1428 | + y, _ = prefix_layer( |
| 1429 | + y, |
| 1430 | + decoder_segment_ids, |
| 1431 | + decoder_positions, |
| 1432 | + deterministic, |
| 1433 | + model_mode, |
| 1434 | + **layer_call_kwargs, |
| 1435 | + ) |
| 1436 | + |
| 1437 | + # 2. Chunked Scanning (Layers 2 to 41) |
| 1438 | + # These 40 layers perfectly alternate CSA (4) and HCA (128). |
| 1439 | + num_full_blocks = 20 |
| 1440 | + if num_full_blocks > 0: |
| 1441 | + ScannableBlockToLinen = deepseek4.DeepSeek4ScannableBlockToLinen |
| 1442 | + policy = self.get_remat_policy() |
| 1443 | + RemattedDeepSeek4Block = self.set_remat_policy([ScannableBlockToLinen], policy)[0] |
| 1444 | + |
| 1445 | + y, _ = nn.scan( |
| 1446 | + RemattedDeepSeek4Block, |
| 1447 | + variable_axes={ |
| 1448 | + "params": cfg.param_scan_axis, |
| 1449 | + "cache": 0, |
| 1450 | + "intermediates": 0, |
| 1451 | + "aqt": 0, |
| 1452 | + "_overwrite_with_gradient": 0, |
| 1453 | + }, |
| 1454 | + split_rngs={"params": True, "dropout": cfg.enable_dropout}, |
| 1455 | + in_axes=(nn.broadcast,) * len(broadcast_args), |
| 1456 | + length=num_full_blocks, |
| 1457 | + metadata_params={ |
| 1458 | + nn.PARTITION_NAME: "layers", |
| 1459 | + "abstract_init": False, |
| 1460 | + }, |
| 1461 | + )(config=cfg, mesh=mesh, quant=self.quant, model_mode=model_mode, name="scanned_blocks",)(y, *broadcast_args) |
| 1462 | + |
| 1463 | + # 3. Suffix Unrolling (Layer 42) |
| 1464 | + # Layer 42 is the final CSA block (4). |
| 1465 | + # The 44th MTP layer (compress_ratio=0) is dropped/excluded. |
| 1466 | + for layer_idx in range(42, 43): |
| 1467 | + suffix_layer = deepseek4.DeepSeek4LayerToLinen( |
| 1468 | + config=cfg, |
| 1469 | + mesh=mesh, |
| 1470 | + name=f"layers_{layer_idx}", |
| 1471 | + quant=self.quant, |
| 1472 | + model_mode=self.model_mode, |
| 1473 | + layer_idx=layer_idx, |
| 1474 | + ) |
| 1475 | + y, _ = suffix_layer( |
| 1476 | + y, |
| 1477 | + decoder_segment_ids, |
| 1478 | + decoder_positions, |
| 1479 | + deterministic, |
| 1480 | + model_mode, |
| 1481 | + **layer_call_kwargs, |
| 1482 | + ) |
| 1483 | + |
| 1484 | + return y |
| 1485 | + |
1358 | 1486 | def _apply_gemma4_small_layers( |
1359 | 1487 | self, |
1360 | 1488 | y, |
|
0 commit comments