@@ -127,8 +127,7 @@ def _reshape_batch_dim_to_heads(tensor, heads):
127127 tensor = tensor .reshape (batch_size // head_size , head_size , seq_len , dim )
128128 tensor = jnp .transpose (tensor , (0 , 2 , 1 , 3 ))
129129 reshaped_tensor = tensor .reshape (batch_size // head_size , seq_len , dim * head_size )
130- axis_names = nn .logical_to_mesh_axes ((BATCH , LENGTH , HEAD ))
131- return jax .lax .with_sharding_constraint (reshaped_tensor , axis_names )
130+ return nn .with_logical_constraint (reshaped_tensor , (BATCH , LENGTH , HEAD ))
132131
133132
134133def _reshape_heads_to_batch_dim (tensor , heads ):
@@ -141,8 +140,7 @@ def _reshape_heads_to_batch_dim(tensor, heads):
141140 else :
142141 batch_size , head_size , seq_len , head_dim = tensor .shape
143142 reshaped_tensor = tensor .reshape (batch_size * head_size , seq_len , head_dim )
144- axis_names = nn .logical_to_mesh_axes ((BATCH , LENGTH , HEAD ))
145- return jax .lax .with_sharding_constraint (reshaped_tensor , axis_names )
143+ return nn .with_logical_constraint (reshaped_tensor , (BATCH , LENGTH , HEAD ))
146144
147145
148146def _reshape_heads_to_head_dim (tensor ):
@@ -151,8 +149,7 @@ def _reshape_heads_to_head_dim(tensor):
151149 b , h , s , d = tensor .shape
152150 tensor = jnp .transpose (tensor , axes = [0 , 2 , 1 , 3 ])
153151 reshaped_tensor = jnp .reshape (tensor , (b , - 1 , h * d ))
154- axis_names = nn .logical_to_mesh_axes ((BATCH , LENGTH , HEAD ))
155- return jax .lax .with_sharding_constraint (reshaped_tensor , axis_names )
152+ return nn .with_logical_constraint (reshaped_tensor , (BATCH , LENGTH , HEAD ))
156153
157154
158155def _unflatten_heads (tensor , heads ):
@@ -579,6 +576,7 @@ def _tpu_flash_attention(
579576 attention_mask : jax .Array = None ,
580577 use_base2_exp : bool = False ,
581578 use_experimental_scheduler : bool = False ,
579+ is_causal : bool = False ,
582580) -> jax .Array :
583581 """TPU Flash Attention"""
584582
@@ -656,8 +654,12 @@ def wrap_flash_attention(query, key, value, attention_mask):
656654 key , _ , key_seq_len = _pad_data_for_flash (key , heads , block_kv )
657655 value , _ , _ = _pad_data_for_flash (value , heads , block_kv )
658656
659- mask = splash_attention_mask .FullMask (_shape = (query .shape [2 ], key .shape [2 ]))
660- multi_head_mask = splash_attention_mask .MultiHeadMask (masks = (mask ,) * query .shape [1 ])
657+ if is_causal :
658+ mask = splash_attention_mask .CausalMask ((query .shape [2 ], key .shape [2 ]))
659+ multi_head_mask = splash_attention_mask .MultiHeadMask (masks = (mask ,) * query .shape [1 ])
660+ else :
661+ mask = splash_attention_mask .FullMask (_shape = (query .shape [2 ], key .shape [2 ]))
662+ multi_head_mask = splash_attention_mask .MultiHeadMask (masks = (mask ,) * query .shape [1 ])
661663
662664 segment_ids_cls = (
663665 tokamax_splash_base .SegmentIds if attention_kernel == "tokamax_ring" else splash_attention_kernel .SegmentIds
@@ -674,9 +676,14 @@ def wrap_flash_attention(query, key, value, attention_mask):
674676 # make_splash_mha is wrapped around shardmap and seq and head is already
675677 # sharded based on in_specs, therefore setting head_shards=1 and q_seq_shards=1.
676678 if attention_kernel == "tokamax_flash" :
677- mask = tokamax_splash_attention_mask .FullMask (
678- _shape = (query .shape [2 ], key .shape [2 ]),
679- )
679+ if is_causal :
680+ mask = tokamax_splash_attention_mask .CausalMask (
681+ (query .shape [2 ], key .shape [2 ]),
682+ )
683+ else :
684+ mask = tokamax_splash_attention_mask .FullMask (
685+ _shape = (query .shape [2 ], key .shape [2 ]),
686+ )
680687 splash_kernel = tokamax_splash_attention_kernel .make_splash_mha (
681688 mask = mask ,
682689 q_seq_shards = 1 , # the sizes of the axis is sharding over seq_len
@@ -1571,10 +1578,9 @@ def _cudnn_flash_attention(query: Array, key: Array, value: Array, heads: int, m
15711578 key = _reshape_data_for_cudnn_flash (key , heads )
15721579 value = _reshape_data_for_cudnn_flash (value , heads )
15731580
1574- axis_names = nn .logical_to_mesh_axes ((BATCH , LENGTH , HEAD , D_KV ))
1575- query = jax .lax .with_sharding_constraint (query , axis_names )
1576- key = jax .lax .with_sharding_constraint (key , axis_names )
1577- value = jax .lax .with_sharding_constraint (value , axis_names )
1581+ query = nn .with_logical_constraint (query , (BATCH , LENGTH , HEAD , D_KV ))
1582+ key = nn .with_logical_constraint (key , (BATCH , LENGTH , HEAD , D_KV ))
1583+ value = nn .with_logical_constraint (value , (BATCH , LENGTH , HEAD , D_KV ))
15781584
15791585 out = dpa_layer (query , key , value , mask = None )
15801586 return _reshape_data_from_cudnn_flash (out )
@@ -1788,6 +1794,7 @@ def flash_kernel(q, k, v, context):
17881794 attention_mask = context ["attention_mask" ],
17891795 use_base2_exp = context ["use_base2_exp" ],
17901796 use_experimental_scheduler = context ["use_experimental_scheduler" ],
1797+ is_causal = context .get ("is_causal" , False ),
17911798 )
17921799
17931800
@@ -1809,6 +1816,7 @@ def tokamax_flash_kernel(q, k, v, context):
18091816 attention_mask = context ["attention_mask" ],
18101817 use_base2_exp = context ["use_base2_exp" ],
18111818 use_experimental_scheduler = context ["use_experimental_scheduler" ],
1819+ is_causal = context .get ("is_causal" , False ),
18121820 )
18131821
18141822
@@ -1830,6 +1838,7 @@ def tokamax_ring_kernel(q, k, v, context):
18301838 attention_mask = context ["attention_mask" ],
18311839 use_base2_exp = context ["use_base2_exp" ],
18321840 use_experimental_scheduler = context ["use_experimental_scheduler" ],
1841+ is_causal = context .get ("is_causal" , False ),
18331842 )
18341843
18351844
@@ -1883,6 +1892,7 @@ def _apply_attention(
18831892 use_experimental_scheduler : bool = False ,
18841893 ulysses_shards : int = - 1 ,
18851894 ulysses_attention_chunks : int = 1 ,
1895+ is_causal : bool = False ,
18861896):
18871897 """Routes to different attention kernels using a module-level registry."""
18881898
@@ -1948,6 +1958,7 @@ def _apply_attention(
19481958 "float32_qk_product" : float32_qk_product ,
19491959 "use_memory_efficient_attention" : use_memory_efficient_attention ,
19501960 "dpa_layer" : dpa_layer ,
1961+ "is_causal" : is_causal ,
19511962 }
19521963
19531964 # Module-level Registry lookup
@@ -2281,6 +2292,7 @@ class AttentionOp(nn.Module):
22812292 use_experimental_scheduler : bool = False
22822293 ulysses_shards : int = - 1
22832294 ulysses_attention_chunks : int = 1
2295+ is_causal : bool = False
22842296
22852297 def setup (self ):
22862298 self .dpa_layer = None
@@ -2330,6 +2342,7 @@ def apply_attention(self, query: Array, key: Array, value: Array, attention_mask
23302342 use_experimental_scheduler = self .use_experimental_scheduler ,
23312343 ulysses_shards = self .ulysses_shards ,
23322344 ulysses_attention_chunks = self .ulysses_attention_chunks ,
2345+ is_causal = self .is_causal ,
23332346 )
23342347
23352348
@@ -2620,9 +2633,9 @@ def __call__(
26202633 rngs : nnx .Rngs = None ,
26212634 cached_kv : Optional [Dict [str , Tuple [jax .Array , jax .Array ]]] = None ,
26222635 ) -> jax .Array :
2623- axis_names = nn .logical_to_mesh_axes ( (BATCH , LENGTH , HEAD ))
2624- hidden_states = jax . lax . with_sharding_constraint ( hidden_states , axis_names )
2625- encoder_hidden_states = jax . lax . with_sharding_constraint (encoder_hidden_states , axis_names )
2636+ hidden_states = nn .with_logical_constraint ( hidden_states , (BATCH , LENGTH , HEAD ))
2637+ if encoder_hidden_states is not None :
2638+ encoder_hidden_states = nn . with_logical_constraint (encoder_hidden_states , ( BATCH , LENGTH , HEAD ) )
26262639 dtype = hidden_states .dtype
26272640 is_self_attention = encoder_hidden_states is None
26282641 if encoder_hidden_states is None :
0 commit comments