Skip to content

Commit 4a932fb

Browse files
Merge pull request #4066 from AI-Hypercomputer:jackyf/gemma3_4-base-decoding-fixes
PiperOrigin-RevId: 941501455
2 parents 7014e2b + 08239eb commit 4a932fb

7 files changed

Lines changed: 332 additions & 88 deletions

File tree

src/maxtext/configs/inference/vllm.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,9 @@ logical_axis_rules: [
8888
['mlp', ['attn_dp', 'model']],
8989
['embed', []],
9090
['norm', []],
91+
['layers', []],
92+
['dense_layers', []],
93+
['moe_layers', []],
9194
# ==========================================
9295
# Inference(Prefill, Decode, Cache)
9396
# ==========================================

src/maxtext/layers/decoders.py

Lines changed: 110 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1056,6 +1056,8 @@ def __call__(
10561056
bidirectional_mask_value,
10571057
previous_chunk,
10581058
slot,
1059+
kv_caches=kv_caches,
1060+
attention_metadata=attention_metadata,
10591061
)
10601062
elif cfg.decoder_block == DecoderBlockType.GEMMA4:
10611063
bidirectional_mask_value = multimodal_input.bidirectional_mask if multimodal_input is not None else None
@@ -1068,6 +1070,8 @@ def __call__(
10681070
bidirectional_mask_value,
10691071
previous_chunk,
10701072
slot,
1073+
kv_caches=kv_caches,
1074+
attention_metadata=attention_metadata,
10711075
)
10721076
elif cfg.decoder_block == DecoderBlockType.DEEPSEEK4:
10731077
y = self._apply_deepseek4_scanned_blocks(
@@ -1303,6 +1307,8 @@ def _apply_gemma3_scanned_blocks(
13031307
bidirectional_mask,
13041308
previous_chunk,
13051309
slot,
1310+
kv_caches=None,
1311+
attention_metadata=None,
13061312
):
13071313
"""Applies Gemma3 scanned decoder blocks, handling main scan and remainders."""
13081314

@@ -1316,27 +1322,43 @@ def _apply_gemma3_scanned_blocks(
13161322
policy = self.get_remat_policy()
13171323
RemattedGemma3Block = self.set_remat_policy([gemma3.Gemma3ScannableBlockToLinen], policy)[0]
13181324

1319-
layer_call_kwargs = {"bidirectional_mask": bidirectional_mask}
13201325
layer_kwargs = {"num_of_layers": attention_pattern_length}
13211326

13221327
# Apply the main scan over the full blocks
13231328
if scan_length > 0:
1324-
broadcast_args = (
1325-
decoder_segment_ids,
1326-
decoder_positions,
1327-
deterministic,
1328-
model_mode,
1329+
kv_cache_scanned = maxtext_utils.prepare_kv_caches_for_scan(
1330+
kv_caches, scan_length, attention_pattern_length, stack=True
13291331
)
1330-
y, _ = self.scan_decoder_layers(
1332+
1333+
broadcast_args_spec = [
1334+
(decoder_segment_ids, nn.broadcast),
1335+
(decoder_positions, nn.broadcast),
1336+
(deterministic, nn.broadcast),
1337+
(model_mode, nn.broadcast),
1338+
(slot, nn.broadcast),
1339+
(None, nn.broadcast), # page_state
1340+
(previous_chunk, nn.broadcast),
1341+
(bidirectional_mask, nn.broadcast),
1342+
(kv_cache_scanned, 0 if kv_caches is not None else nn.broadcast),
1343+
(attention_metadata, nn.broadcast),
1344+
]
1345+
broadcast_args = tuple(arg for arg, _ in broadcast_args_spec)
1346+
in_axes_tuple = tuple(axis for _, axis in broadcast_args_spec)
1347+
1348+
y, returned_kv_cache = self.scan_decoder_layers(
13311349
cfg,
13321350
RemattedGemma3Block,
13331351
scan_length,
13341352
"layers",
13351353
mesh,
1336-
in_axes_tuple=(nn.broadcast,) * len(broadcast_args),
1354+
in_axes_tuple=in_axes_tuple,
13371355
model_mode=self.model_mode,
13381356
**layer_kwargs,
1339-
)(y, *broadcast_args, **layer_call_kwargs)
1357+
)(y, *broadcast_args)
1358+
1359+
maxtext_utils.update_kv_caches_after_scan(
1360+
kv_caches, returned_kv_cache, scan_length, attention_pattern_length, stacked=True
1361+
)
13401362

13411363
# Apply any remaining layers that did not fit into a full scanned block
13421364
num_remaining_layers = cfg.num_decoder_layers % attention_pattern_length
@@ -1346,16 +1368,37 @@ def _apply_gemma3_scanned_blocks(
13461368
layer = RemattedGemma3Block(
13471369
config=cfg, mesh=mesh, quant=self.quant, model_mode=self.model_mode, name="layers_remainder", **rem_layer_kwargs
13481370
) # pytype: disable=wrong-keyword-args
1349-
y, _ = layer(
1371+
1372+
remainder_kv = None
1373+
if kv_caches is not None:
1374+
start_idx = scan_length * attention_pattern_length
1375+
remainder_kv = tuple(kv_caches[start_idx : start_idx + num_remaining_layers])
1376+
1377+
y_and_kv = layer(
13501378
y,
13511379
decoder_segment_ids,
13521380
decoder_positions,
13531381
deterministic,
13541382
model_mode,
13551383
previous_chunk=previous_chunk,
13561384
slot=slot,
1357-
**layer_call_kwargs,
1385+
bidirectional_mask=bidirectional_mask,
1386+
kv_cache=remainder_kv,
1387+
attention_metadata=attention_metadata,
13581388
)
1389+
1390+
if isinstance(y_and_kv, tuple):
1391+
y = y_and_kv[0]
1392+
updated_remainder_kv = y_and_kv[1]
1393+
else:
1394+
y = y_and_kv
1395+
updated_remainder_kv = None
1396+
1397+
if kv_caches is not None and updated_remainder_kv is not None:
1398+
start_idx = scan_length * attention_pattern_length
1399+
for offset, updated_item in enumerate(updated_remainder_kv):
1400+
kv_caches[start_idx + offset] = updated_item
1401+
13591402
return y
13601403

13611404
def _apply_gemma4_scanned_blocks(
@@ -1368,6 +1411,8 @@ def _apply_gemma4_scanned_blocks(
13681411
bidirectional_mask,
13691412
previous_chunk,
13701413
slot,
1414+
kv_caches=None,
1415+
attention_metadata=None,
13711416
):
13721417
"""Applies Gemma4 scanned decoder blocks, handling main scan and remainders."""
13731418

@@ -1379,28 +1424,32 @@ def _apply_gemma4_scanned_blocks(
13791424
num_full_blocks = cfg.num_decoder_layers // block_pattern_len
13801425
remainder_layers = cfg.num_decoder_layers % block_pattern_len
13811426

1382-
broadcast_args = (
1383-
decoder_segment_ids,
1384-
decoder_positions,
1385-
deterministic,
1386-
model_mode,
1387-
)
1388-
1389-
# Pass slot/previous_chunk/bidirectional_mask by keyword only (via layer_call_kwargs),
1390-
# never positionally in broadcast_args: Gemma4DecoderLayer and Gemma4ScannableBlock
1391-
# declare slot and previous_chunk in swapped order, so positional passing misroutes them.
1392-
layer_call_kwargs = {
1393-
"slot": slot,
1394-
"previous_chunk": previous_chunk,
1395-
"bidirectional_mask": bidirectional_mask,
1396-
}
1397-
13981427
if num_full_blocks > 0:
13991428
ScannableBlockToLinen = gemma4.Gemma4ScannableBlockToLinen
14001429
policy = self.get_remat_policy()
14011430
RemattedGemma4Block = self.set_remat_policy([ScannableBlockToLinen], policy)[0]
1431+
1432+
kv_cache_scanned = maxtext_utils.prepare_kv_caches_for_scan(
1433+
kv_caches, num_full_blocks, block_pattern_len, stack=True
1434+
)
1435+
1436+
broadcast_args_spec = [
1437+
(decoder_segment_ids, nn.broadcast),
1438+
(decoder_positions, nn.broadcast),
1439+
(deterministic, nn.broadcast),
1440+
(model_mode, nn.broadcast),
1441+
(slot, nn.broadcast),
1442+
(None, nn.broadcast), # page_state
1443+
(previous_chunk, nn.broadcast),
1444+
(bidirectional_mask, nn.broadcast),
1445+
(kv_cache_scanned, 0 if kv_caches is not None else nn.broadcast),
1446+
(attention_metadata, nn.broadcast),
1447+
]
1448+
broadcast_args = tuple(arg for arg, _ in broadcast_args_spec)
1449+
in_axes_tuple = tuple(axis for _, axis in broadcast_args_spec)
1450+
14021451
# For a fully scanned block, apply it inside a nn.scan over the calculated number of full blocks
1403-
y, _ = nn.scan(
1452+
y, returned_kv_cache = nn.scan(
14041453
RemattedGemma4Block,
14051454
variable_axes={
14061455
"params": cfg.param_scan_axis,
@@ -1410,7 +1459,7 @@ def _apply_gemma4_scanned_blocks(
14101459
"_overwrite_with_gradient": 0,
14111460
},
14121461
split_rngs={"params": True, "dropout": cfg.enable_dropout},
1413-
in_axes=(nn.broadcast,) * len(broadcast_args),
1462+
in_axes=in_axes_tuple,
14141463
length=num_full_blocks,
14151464
metadata_params={
14161465
nn.PARTITION_NAME: "layers",
@@ -1424,7 +1473,11 @@ def _apply_gemma4_scanned_blocks(
14241473
num_of_layers=block_pattern_len,
14251474
name="scanned_blocks",
14261475
)(
1427-
y, *broadcast_args, **layer_call_kwargs
1476+
y, *broadcast_args
1477+
)
1478+
1479+
maxtext_utils.update_kv_caches_after_scan(
1480+
kv_caches, returned_kv_cache, num_full_blocks, block_pattern_len, stacked=True
14281481
)
14291482

14301483
# Process any remaining layers that don't fit into a full scanned block
@@ -1438,9 +1491,33 @@ def _apply_gemma4_scanned_blocks(
14381491
attention_type=attention_type,
14391492
layer_idx=layer_id,
14401493
)
1441-
y = layer(y, *broadcast_args, **layer_call_kwargs)
1442-
if cfg.scan_layers:
1443-
y = y[0]
1494+
kv_cache = kv_caches[layer_id] if kv_caches is not None else None
1495+
1496+
# inputs, decoder_segment_ids, decoder_positions, deterministic, model_mode,
1497+
# previous_chunk, page_state, slot, bidirectional_mask, kv_cache, attention_metadata
1498+
remainder_args = (
1499+
decoder_segment_ids,
1500+
decoder_positions,
1501+
deterministic,
1502+
model_mode,
1503+
previous_chunk,
1504+
None, # page_state
1505+
slot,
1506+
bidirectional_mask,
1507+
kv_cache,
1508+
attention_metadata,
1509+
)
1510+
1511+
y_and_kv = layer(y, *remainder_args)
1512+
if isinstance(y_and_kv, tuple):
1513+
y = y_and_kv[0]
1514+
new_kv = y_and_kv[1]
1515+
else:
1516+
y = y_and_kv
1517+
new_kv = None
1518+
1519+
if kv_caches is not None and new_kv is not None:
1520+
kv_caches[layer_id] = new_kv
14441521

14451522
return y
14461523

0 commit comments

Comments
 (0)