Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -99,5 +99,11 @@ def validate_architecture(self):
def layers_block_type(self):
return (self.block_types * 100)[: self.num_hidden_layers]

@property
def layer_types(self):

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm why not changed it directly in layers block types instead? Id like to avoid having so many layer types living side by side

# Describes the layers for the generic cache / mask utilities (the modeling itself uses `layers_block_type`):
# recurrent blocks keep their own state (no KV cache), attention blocks always use local (sliding window) attention
return ["linear_attention" if x == "recurrent" else "sliding_attention" for x in self.layers_block_type]


__all__ = ["RecurrentGemmaConfig"]
Original file line number Diff line number Diff line change
Expand Up @@ -652,13 +652,17 @@ def forward(
position_ids = torch.arange(hidden_states.shape[1], device=hidden_states.device) + past_seen_tokens
position_ids = position_ids.unsqueeze(0)

causal_mask = create_sliding_window_causal_mask(
config=self.config,
inputs_embeds=inputs_embeds,
attention_mask=attention_mask,
past_key_values=past_key_values,
position_ids=position_ids,
)
# It may already have been prepared by e.g. `generate`
if isinstance(attention_mask, dict):
causal_mask = attention_mask["sliding_attention"]

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

layer_types maps recurrent blocks to "linear_attention" and attention blocks to "sliding_attention". When generate has already prepared attention_mask as a dict, this line always takes attention_mask["sliding_attention"] and uses that one tensor for every layer. A RecurrentGemma whose block_types are all "recurrent" (or a generate path that only filled linear_attention) will KeyError here. Even on the usual mixed stack, the linear/recurrent layers are then masked with the sliding-window tensor rather than the linear_attention mask that was prepared for them.

If recurrent blocks ignore the mask and only the attention blocks need the sliding window, please say so in the comment — but I'd still use .get("sliding_attention") and fall back to create_sliding_window_causal_mask(...) when that key is missing. If they do consume the mask, the dict should be passed through (or indexed per layer_types[i]) so the linear-attention entry is not dropped. The new skip on test_recurrent_layers_mask_padding_on_continued_forward is fair given the missing chunked-continuation support, but it means padded continued generation stays untested after this fix.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the model is so old, that it would require too much effort to fix it up properly imo

some of your initial points are more theoretical issues which are not really important

else:
causal_mask = create_sliding_window_causal_mask(
config=self.config,
inputs_embeds=inputs_embeds,
attention_mask=attention_mask,
past_key_values=past_key_values,
position_ids=position_ids,
)

hidden_states = hidden_states * self.normalizer.type(hidden_states.dtype)

Expand Down
7 changes: 7 additions & 0 deletions tests/models/recurrent_gemma/test_modeling_recurrent_gemma.py
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,13 @@ def test_assisted_decoding_matches_greedy_search(self):
def test_left_padding_compatibility(self):
pass

@unittest.skip(
"RecurrentGemma's recurrent block has no chunked-continuation support: a cached multi-token forward is "
"treated as a new prefill, so the split-vs-single comparison cannot match regardless of padding masking."
)
def test_recurrent_layers_mask_padding_on_continued_forward(self):
pass

Comment on lines +184 to +190

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it was skipped before. I don't want to handle this in the current PR.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yea its expected tbh

@pytest.mark.generate
@unittest.skip(reason="Relies on `past_key_values` returned by the model. Not supported with recurrent gemma")
def test_assisted_decoding_sample(self):
Expand Down
Loading