Handle left-padded batches without NaN logits
Browse files- modeling_vortex.py +17 -2
modeling_vortex.py
CHANGED
|
@@ -100,12 +100,21 @@ class VortexAttention(nn.Module):
|
|
| 100 |
value = value.repeat_interleave(repeats, dim=1)
|
| 101 |
|
| 102 |
sdpa_mask = None
|
|
|
|
| 103 |
is_causal = attention_mask is None and seq_len > 1
|
| 104 |
if attention_mask is not None:
|
| 105 |
if attention_mask.ndim == 2:
|
| 106 |
-
|
|
|
|
|
|
|
| 107 |
causal = torch.ones((seq_len, seq_len), dtype=torch.bool, device=hidden_states.device).tril()
|
| 108 |
sdpa_mask = valid_keys & causal[None, None, :, :]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 109 |
elif attention_mask.ndim == 4:
|
| 110 |
sdpa_mask = attention_mask
|
| 111 |
else:
|
|
@@ -118,6 +127,8 @@ class VortexAttention(nn.Module):
|
|
| 118 |
dropout_p=0.0,
|
| 119 |
is_causal=is_causal,
|
| 120 |
)
|
|
|
|
|
|
|
| 121 |
output = output.transpose(1, 2).contiguous().view(batch, seq_len, -1)
|
| 122 |
return self.o_proj(output)
|
| 123 |
|
|
@@ -230,7 +241,11 @@ class VortexForCausalLM(VortexPreTrainedModel):
|
|
| 230 |
else:
|
| 231 |
hidden_states = inputs_embeds
|
| 232 |
if position_ids is None:
|
| 233 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 234 |
all_hidden_states = () if output_hidden_states else None
|
| 235 |
for block in self.layers:
|
| 236 |
if output_hidden_states:
|
|
|
|
| 100 |
value = value.repeat_interleave(repeats, dim=1)
|
| 101 |
|
| 102 |
sdpa_mask = None
|
| 103 |
+
query_valid = None
|
| 104 |
is_causal = attention_mask is None and seq_len > 1
|
| 105 |
if attention_mask is not None:
|
| 106 |
if attention_mask.ndim == 2:
|
| 107 |
+
valid = attention_mask.to(dtype=torch.bool, device=hidden_states.device)
|
| 108 |
+
valid_keys = valid[:, None, None, :]
|
| 109 |
+
query_valid = valid[:, None, :, None]
|
| 110 |
causal = torch.ones((seq_len, seq_len), dtype=torch.bool, device=hidden_states.device).tril()
|
| 111 |
sdpa_mask = valid_keys & causal[None, None, :, :]
|
| 112 |
+
# SDPA returns NaN for an all-masked query row. Left padding
|
| 113 |
+
# creates exactly those rows, so give pad queries one harmless
|
| 114 |
+
# fallback key and zero their outputs after attention.
|
| 115 |
+
fallback = torch.zeros_like(sdpa_mask)
|
| 116 |
+
fallback[..., 0] = True
|
| 117 |
+
sdpa_mask = torch.where(query_valid, sdpa_mask, fallback)
|
| 118 |
elif attention_mask.ndim == 4:
|
| 119 |
sdpa_mask = attention_mask
|
| 120 |
else:
|
|
|
|
| 127 |
dropout_p=0.0,
|
| 128 |
is_causal=is_causal,
|
| 129 |
)
|
| 130 |
+
if query_valid is not None:
|
| 131 |
+
output = output * query_valid.to(dtype=output.dtype)
|
| 132 |
output = output.transpose(1, 2).contiguous().view(batch, seq_len, -1)
|
| 133 |
return self.o_proj(output)
|
| 134 |
|
|
|
|
| 241 |
else:
|
| 242 |
hidden_states = inputs_embeds
|
| 243 |
if position_ids is None:
|
| 244 |
+
if attention_mask is not None and attention_mask.ndim == 2:
|
| 245 |
+
position_ids = attention_mask.long().cumsum(-1) - 1
|
| 246 |
+
position_ids = position_ids.masked_fill(attention_mask == 0, 0)
|
| 247 |
+
else:
|
| 248 |
+
position_ids = torch.arange(hidden_states.shape[1], device=hidden_states.device).unsqueeze(0)
|
| 249 |
all_hidden_states = () if output_hidden_states else None
|
| 250 |
for block in self.layers:
|
| 251 |
if output_hidden_states:
|