@@ -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