Update modeling_neollm.py
Browse files- modeling_neollm.py +206 -14
modeling_neollm.py
CHANGED
|
@@ -12,6 +12,10 @@ factorised attention log-priors (Litman & Guo, 2026), optional StackMemory
|
|
| 12 |
(Zhang et al., NeurIPS 2025), and optional HOLA-derived episodic memory for
|
| 13 |
the FlashAttention-2 IHA seq-expand path (Cui, 2026).
|
| 14 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 15 |
Attention stack (orthogonal, all active simultaneously when enabled):
|
| 16 |
1. Gated Attention (use_gated_attention implicit via q_proj gate chunk):
|
| 17 |
applies a head-specific elementwise sigmoid gate to the concatenated
|
|
@@ -105,7 +109,11 @@ except ImportError:
|
|
| 105 |
|
| 106 |
from transformers.generation import GenerationMixin
|
| 107 |
from transformers.masking_utils import create_causal_mask
|
| 108 |
-
from transformers.modeling_flash_attention_utils import
|
|
|
|
|
|
|
|
|
|
|
|
|
| 109 |
from transformers.modeling_layers import GradientCheckpointingLayer
|
| 110 |
from transformers.modeling_outputs import (
|
| 111 |
BaseModelOutputWithPast,
|
|
@@ -121,6 +129,7 @@ from transformers import AutoConfig, AutoModel, AutoModelForCausalLM
|
|
| 121 |
|
| 122 |
torch._dynamo.config.capture_scalar_outputs = True
|
| 123 |
logger = logging.get_logger(__name__)
|
|
|
|
| 124 |
|
| 125 |
# ── Optional flash_attn direct import (required only for IHA seq-expand, P>1) ──
|
| 126 |
# Attempted once at module load time so the symbols are available when
|
|
@@ -1351,6 +1360,93 @@ def repeat_kv(hidden_states: torch.Tensor, n_rep: int) -> torch.Tensor:
|
|
| 1351 |
return hidden_states.reshape(batch, num_key_value_heads * n_rep, slen, head_dim)
|
| 1352 |
|
| 1353 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1354 |
def causal_first_difference(x: torch.Tensor) -> torch.Tensor:
|
| 1355 |
return x - F.pad(x[..., :-1, :], (0, 0, 1, 0))
|
| 1356 |
|
|
@@ -1795,7 +1891,12 @@ def affine_scaled_flash_attention_forward(
|
|
| 1795 |
"""
|
| 1796 |
# ── Term 1: standard flash / sdpa output ─────────────────────────────
|
| 1797 |
# dropout=0.0: we apply dropout to the combined output below instead.
|
| 1798 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1799 |
flash_out, _ = attn_fn(
|
| 1800 |
module,
|
| 1801 |
query,
|
|
@@ -4010,6 +4111,18 @@ class NeoLLMAttention(nn.Module):
|
|
| 4010 |
# was designed for the head-expand layout and would mismatch here.
|
| 4011 |
# For P=1 or no IHA: the existing branch logic in _apply_mea_head_mixing
|
| 4012 |
# is unchanged and handles both the pseudo-slot-aware and normal cases.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4013 |
if _iha_seq_expand:
|
| 4014 |
k, v = self._apply_mea_head_mixing(k, v, _force_standard=True)
|
| 4015 |
else:
|
|
@@ -4033,6 +4146,23 @@ class NeoLLMAttention(nn.Module):
|
|
| 4033 |
position_ids=position_ids,
|
| 4034 |
)
|
| 4035 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4036 |
# ── IHA: local sliding-window mask for non-seq-expand path (P=1) ─────
|
| 4037 |
# For P>1 (seq-expand): the sliding window is expressed as window_size
|
| 4038 |
# in flash_attn_func and handled inside _iha_seq_expand_flash_forward.
|
|
@@ -4164,7 +4294,7 @@ class NeoLLMAttention(nn.Module):
|
|
| 4164 |
q,
|
| 4165 |
k,
|
| 4166 |
v,
|
| 4167 |
-
|
| 4168 |
scaling=self.scaling,
|
| 4169 |
alpha=alpha,
|
| 4170 |
beta=beta,
|
|
@@ -4174,6 +4304,11 @@ class NeoLLMAttention(nn.Module):
|
|
| 4174 |
else:
|
| 4175 |
if self.config._attn_implementation == "eager":
|
| 4176 |
attn_fn = eager_attention_forward
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4177 |
else:
|
| 4178 |
attn_fn = ALL_ATTENTION_FUNCTIONS[self.config._attn_implementation]
|
| 4179 |
backend_kwargs = kwargs
|
|
@@ -4187,7 +4322,7 @@ class NeoLLMAttention(nn.Module):
|
|
| 4187 |
q,
|
| 4188 |
k,
|
| 4189 |
v,
|
| 4190 |
-
|
| 4191 |
dropout=0.0 if not self.training else self.attention_dropout,
|
| 4192 |
scaling=self.scaling,
|
| 4193 |
**backend_kwargs,
|
|
@@ -4414,6 +4549,21 @@ class NeoLLMDecoderLayer(GradientCheckpointingLayer):
|
|
| 4414 |
self.siamese_attn_x_scale_init = float(
|
| 4415 |
getattr(config, "siamese_attn_x_scale_init", 1.0)
|
| 4416 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4417 |
# Controls only the first pre-attention normalisation applied directly
|
| 4418 |
# to the embedding stream. Defaults to True for checkpoint/config
|
| 4419 |
# backward compatibility. When False, layer 0 does not instantiate
|
|
@@ -4710,9 +4860,10 @@ class NeoLLMDecoderLayer(GradientCheckpointingLayer):
|
|
| 4710 |
return delta + lr_delta + residual
|
| 4711 |
|
| 4712 |
def _siamese_stream_scale(self, ref: torch.Tensor) -> torch.Tensor:
|
| 4713 |
-
|
| 4714 |
-
|
| 4715 |
-
|
|
|
|
| 4716 |
|
| 4717 |
def forward_siamesenorm(
|
| 4718 |
self,
|
|
@@ -5647,13 +5798,54 @@ class NeoLLMModel(NeoLLMPreTrainedModel):
|
|
| 5647 |
0, inputs_embeds.shape[1], device=inputs_embeds.device
|
| 5648 |
).unsqueeze(0)
|
| 5649 |
|
| 5650 |
-
|
| 5651 |
-
|
| 5652 |
-
|
| 5653 |
-
|
| 5654 |
-
|
| 5655 |
-
|
| 5656 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 5657 |
|
| 5658 |
hidden_states = inputs_embeds
|
| 5659 |
use_siamesenorm = bool(getattr(self.config, "use_siamesenorm", False))
|
|
|
|
| 12 |
(Zhang et al., NeurIPS 2025), and optional HOLA-derived episodic memory for
|
| 13 |
the FlashAttention-2 IHA seq-expand path (Cui, 2026).
|
| 14 |
|
| 15 |
+
The FlashAttention training paths deliberately use dense right-padded
|
| 16 |
+
attention with a shared dtype and compilation contract across IHA and non-IHA.
|
| 17 |
+
See ``NeoLLMModel.forward`` for its padding/packing constraints.
|
| 18 |
+
|
| 19 |
Attention stack (orthogonal, all active simultaneously when enabled):
|
| 20 |
1. Gated Attention (use_gated_attention implicit via q_proj gate chunk):
|
| 21 |
applies a head-specific elementwise sigmoid gate to the concatenated
|
|
|
|
| 109 |
|
| 110 |
from transformers.generation import GenerationMixin
|
| 111 |
from transformers.masking_utils import create_causal_mask
|
| 112 |
+
from transformers.modeling_flash_attention_utils import (
|
| 113 |
+
FlashAttentionKwargs,
|
| 114 |
+
_flash_attention_forward,
|
| 115 |
+
flash_attn_supports_top_left_mask,
|
| 116 |
+
)
|
| 117 |
from transformers.modeling_layers import GradientCheckpointingLayer
|
| 118 |
from transformers.modeling_outputs import (
|
| 119 |
BaseModelOutputWithPast,
|
|
|
|
| 129 |
|
| 130 |
torch._dynamo.config.capture_scalar_outputs = True
|
| 131 |
logger = logging.get_logger(__name__)
|
| 132 |
+
_NEOLLM_FA_USE_TOP_LEFT_MASK = flash_attn_supports_top_left_mask()
|
| 133 |
|
| 134 |
# ── Optional flash_attn direct import (required only for IHA seq-expand, P>1) ──
|
| 135 |
# Attempted once at module load time so the symbols are available when
|
|
|
|
| 1360 |
return hidden_states.reshape(batch, num_key_value_heads * n_rep, slen, head_dim)
|
| 1361 |
|
| 1362 |
|
| 1363 |
+
def _flash_target_dtype(
|
| 1364 |
+
query: torch.Tensor,
|
| 1365 |
+
module: nn.Module,
|
| 1366 |
+
) -> Optional[torch.dtype]:
|
| 1367 |
+
"""Return the half dtype required by FlashAttention for FP32 Q/K states.
|
| 1368 |
+
|
| 1369 |
+
PyTorch RMSNorm intentionally returns FP32 under BF16 autocast. IHA's
|
| 1370 |
+
pseudo-head einsums cast those states back through autocast, while the
|
| 1371 |
+
standard path has no equivalent operation. Resolve the target here so
|
| 1372 |
+
both routes enter every FlashAttention backend with the same dtype instead
|
| 1373 |
+
of relying on a backend-specific compatibility cast.
|
| 1374 |
+
"""
|
| 1375 |
+
if query.dtype != torch.float32:
|
| 1376 |
+
return None
|
| 1377 |
+
device_type = query.device.type
|
| 1378 |
+
if torch.is_autocast_enabled(device_type):
|
| 1379 |
+
return torch.get_autocast_dtype(device_type)
|
| 1380 |
+
if hasattr(module.config, "_is_quantized"):
|
| 1381 |
+
return module.config.dtype
|
| 1382 |
+
return next(
|
| 1383 |
+
layer.weight.dtype
|
| 1384 |
+
for layer in module.modules()
|
| 1385 |
+
if isinstance(layer, nn.Linear)
|
| 1386 |
+
)
|
| 1387 |
+
|
| 1388 |
+
|
| 1389 |
+
def neollm_flash_attention_forward(
|
| 1390 |
+
module: nn.Module,
|
| 1391 |
+
query: torch.Tensor,
|
| 1392 |
+
key: torch.Tensor,
|
| 1393 |
+
value: torch.Tensor,
|
| 1394 |
+
attention_mask: Optional[torch.Tensor],
|
| 1395 |
+
dropout: float = 0.0,
|
| 1396 |
+
scaling: Optional[float] = None,
|
| 1397 |
+
sliding_window: Optional[int] = None,
|
| 1398 |
+
softcap: Optional[float] = None,
|
| 1399 |
+
is_causal: Optional[bool] = None,
|
| 1400 |
+
s_aux: Optional[torch.Tensor] = None,
|
| 1401 |
+
**kwargs: Unpack[TransformersKwargs],
|
| 1402 |
+
):
|
| 1403 |
+
"""Compile-stable HF FlashAttention bridge for NeoLLM.
|
| 1404 |
+
|
| 1405 |
+
This mirrors the Transformers FA2/FA3 integration but deliberately does
|
| 1406 |
+
not forward ``module.layer_idx``. That integer is not consumed by the
|
| 1407 |
+
current FA2/FA3 implementation (it is discarded through ``**kwargs``), yet
|
| 1408 |
+
Dynamo guards its value and otherwise compiles one copy per decoder layer.
|
| 1409 |
+
Keeping the bridge local preserves the public integer attribute for model
|
| 1410 |
+
tooling, checkpoints, and diagnostics without making it part of the
|
| 1411 |
+
attention graph signature.
|
| 1412 |
+
"""
|
| 1413 |
+
if kwargs.get("output_attentions", False):
|
| 1414 |
+
logger.warning_once(
|
| 1415 |
+
"Flash Attention does not support `output_attentions=True`. "
|
| 1416 |
+
"Please set attention to `eager` to request attention weights."
|
| 1417 |
+
)
|
| 1418 |
+
|
| 1419 |
+
seq_len = query.shape[2]
|
| 1420 |
+
if any(dim == 0 for dim in query.shape):
|
| 1421 |
+
raise ValueError(
|
| 1422 |
+
"FlashAttention does not support a query tensor with a zero dimension."
|
| 1423 |
+
)
|
| 1424 |
+
|
| 1425 |
+
query = query.transpose(1, 2)
|
| 1426 |
+
key = key.transpose(1, 2)
|
| 1427 |
+
value = value.transpose(1, 2)
|
| 1428 |
+
is_causal = is_causal if is_causal is not None else module.is_causal
|
| 1429 |
+
|
| 1430 |
+
attn_output = _flash_attention_forward(
|
| 1431 |
+
query,
|
| 1432 |
+
key,
|
| 1433 |
+
value,
|
| 1434 |
+
attention_mask,
|
| 1435 |
+
query_length=seq_len,
|
| 1436 |
+
is_causal=is_causal,
|
| 1437 |
+
dropout=dropout,
|
| 1438 |
+
softmax_scale=scaling,
|
| 1439 |
+
sliding_window=sliding_window,
|
| 1440 |
+
softcap=softcap,
|
| 1441 |
+
use_top_left_mask=_NEOLLM_FA_USE_TOP_LEFT_MASK,
|
| 1442 |
+
target_dtype=None, # NeoLLMAttention normalizes Q/K/V before dispatch.
|
| 1443 |
+
attn_implementation=module.config._attn_implementation,
|
| 1444 |
+
s_aux=s_aux.to(query.dtype) if s_aux is not None else None,
|
| 1445 |
+
**kwargs,
|
| 1446 |
+
)
|
| 1447 |
+
return attn_output, None
|
| 1448 |
+
|
| 1449 |
+
|
| 1450 |
def causal_first_difference(x: torch.Tensor) -> torch.Tensor:
|
| 1451 |
return x - F.pad(x[..., :-1, :], (0, 0, 1, 0))
|
| 1452 |
|
|
|
|
| 1891 |
"""
|
| 1892 |
# ── Term 1: standard flash / sdpa output ─────────────────────────────
|
| 1893 |
# dropout=0.0: we apply dropout to the combined output below instead.
|
| 1894 |
+
attn_impl = module.config._attn_implementation
|
| 1895 |
+
attn_fn = (
|
| 1896 |
+
neollm_flash_attention_forward
|
| 1897 |
+
if attn_impl in {"flash_attention_2", "flash_attention_3"}
|
| 1898 |
+
else ALL_ATTENTION_FUNCTIONS[attn_impl]
|
| 1899 |
+
)
|
| 1900 |
flash_out, _ = attn_fn(
|
| 1901 |
module,
|
| 1902 |
query,
|
|
|
|
| 4111 |
# was designed for the head-expand layout and would mismatch here.
|
| 4112 |
# For P=1 or no IHA: the existing branch logic in _apply_mea_head_mixing
|
| 4113 |
# is unchanged and handles both the pseudo-slot-aware and normal cases.
|
| 4114 |
+
# Standard FlashAttention layers use the dense right-padded training
|
| 4115 |
+
# contract even inside a mixed IHA schedule. Keep ``attention_mask``
|
| 4116 |
+
# itself untouched for IHA packing detection and auxiliary operators;
|
| 4117 |
+
# only the backend argument is normalized to ``None``.
|
| 4118 |
+
backend_attention_mask = attention_mask
|
| 4119 |
+
if (
|
| 4120 |
+
self.training
|
| 4121 |
+
and self.config._attn_implementation
|
| 4122 |
+
in {"flash_attention_2", "flash_attention_3"}
|
| 4123 |
+
):
|
| 4124 |
+
backend_attention_mask = None
|
| 4125 |
+
|
| 4126 |
if _iha_seq_expand:
|
| 4127 |
k, v = self._apply_mea_head_mixing(k, v, _force_standard=True)
|
| 4128 |
else:
|
|
|
|
| 4146 |
position_ids=position_ids,
|
| 4147 |
)
|
| 4148 |
|
| 4149 |
+
# Normalize FlashAttention inputs for every topology, not only the
|
| 4150 |
+
# non-IHA fallback. RMSNorm produces FP32 under BF16 autocast; IHA's
|
| 4151 |
+
# pseudo-head einsums happened to cast it back implicitly, whereas the
|
| 4152 |
+
# standard route reached the Transformers wrapper in FP32. An explicit
|
| 4153 |
+
# dispatch-boundary cast gives IHA and non-IHA identical dtype behavior,
|
| 4154 |
+
# avoids hidden backend casts/warnings, and keeps FP32 work where it is
|
| 4155 |
+
# intentional (normalization, RoPE/REPO and momentum calculations).
|
| 4156 |
+
if self.config._attn_implementation in {
|
| 4157 |
+
"flash_attention_2",
|
| 4158 |
+
"flash_attention_3",
|
| 4159 |
+
}:
|
| 4160 |
+
flash_dtype = _flash_target_dtype(q, self)
|
| 4161 |
+
if flash_dtype is not None:
|
| 4162 |
+
q = q.to(flash_dtype)
|
| 4163 |
+
k = k.to(flash_dtype)
|
| 4164 |
+
v = v.to(flash_dtype)
|
| 4165 |
+
|
| 4166 |
# ── IHA: local sliding-window mask for non-seq-expand path (P=1) ─────
|
| 4167 |
# For P>1 (seq-expand): the sliding window is expressed as window_size
|
| 4168 |
# in flash_attn_func and handled inside _iha_seq_expand_flash_forward.
|
|
|
|
| 4294 |
q,
|
| 4295 |
k,
|
| 4296 |
v,
|
| 4297 |
+
backend_attention_mask,
|
| 4298 |
scaling=self.scaling,
|
| 4299 |
alpha=alpha,
|
| 4300 |
beta=beta,
|
|
|
|
| 4304 |
else:
|
| 4305 |
if self.config._attn_implementation == "eager":
|
| 4306 |
attn_fn = eager_attention_forward
|
| 4307 |
+
elif self.config._attn_implementation in {
|
| 4308 |
+
"flash_attention_2",
|
| 4309 |
+
"flash_attention_3",
|
| 4310 |
+
}:
|
| 4311 |
+
attn_fn = neollm_flash_attention_forward
|
| 4312 |
else:
|
| 4313 |
attn_fn = ALL_ATTENTION_FUNCTIONS[self.config._attn_implementation]
|
| 4314 |
backend_kwargs = kwargs
|
|
|
|
| 4322 |
q,
|
| 4323 |
k,
|
| 4324 |
v,
|
| 4325 |
+
backend_attention_mask,
|
| 4326 |
dropout=0.0 if not self.training else self.attention_dropout,
|
| 4327 |
scaling=self.scaling,
|
| 4328 |
**backend_kwargs,
|
|
|
|
| 4549 |
self.siamese_attn_x_scale_init = float(
|
| 4550 |
getattr(config, "siamese_attn_x_scale_init", 1.0)
|
| 4551 |
)
|
| 4552 |
+
siamese_stream_scale = (
|
| 4553 |
+
1.0
|
| 4554 |
+
if not self.siamese_depth_scaling
|
| 4555 |
+
else 1.0 / math.sqrt(2.0 * float(layer_idx + 1))
|
| 4556 |
+
)
|
| 4557 |
+
# A tensor buffer keeps the depth-dependent value out of Python control
|
| 4558 |
+
# flow during forward. Computing it from ``self.layer_idx`` inside a
|
| 4559 |
+
# Dynamo resume frame specialized that frame once per decoder layer.
|
| 4560 |
+
# Non-persistent preserves checkpoint compatibility: the value is fully
|
| 4561 |
+
# determined by layer_idx and the config on every construction.
|
| 4562 |
+
self.register_buffer(
|
| 4563 |
+
"_siamese_stream_scale_value",
|
| 4564 |
+
torch.tensor(siamese_stream_scale, dtype=torch.float32),
|
| 4565 |
+
persistent=False,
|
| 4566 |
+
)
|
| 4567 |
# Controls only the first pre-attention normalisation applied directly
|
| 4568 |
# to the embedding stream. Defaults to True for checkpoint/config
|
| 4569 |
# backward compatibility. When False, layer 0 does not instantiate
|
|
|
|
| 4860 |
return delta + lr_delta + residual
|
| 4861 |
|
| 4862 |
def _siamese_stream_scale(self, ref: torch.Tensor) -> torch.Tensor:
|
| 4863 |
+
return self._siamese_stream_scale_value.to(
|
| 4864 |
+
device=ref.device,
|
| 4865 |
+
dtype=ref.dtype,
|
| 4866 |
+
)
|
| 4867 |
|
| 4868 |
def forward_siamesenorm(
|
| 4869 |
self,
|
|
|
|
| 5798 |
0, inputs_embeds.shape[1], device=inputs_embeds.device
|
| 5799 |
).unsqueeze(0)
|
| 5800 |
|
| 5801 |
+
# ── Compile-stable FlashAttention training mask contract ─────────────
|
| 5802 |
+
# The Transformers FA2/FA3 wrapper treats a 2-D padding mask as a
|
| 5803 |
+
# variable-length problem: it branches between ``None`` and a tensor,
|
| 5804 |
+
# calls ``nonzero`` to unpad it, and specializes on both the resulting
|
| 5805 |
+
# token count and ``layer_idx``. With batches containing different
|
| 5806 |
+
# amounts of padding, Dynamo therefore recompiles layer by layer and
|
| 5807 |
+
# retains several compiled graphs, which can *increase* VRAM precisely
|
| 5808 |
+
# when IHA is disabled. IHA's seq-expand kernel does not use that
|
| 5809 |
+
# wrapper, so it did not expose the same behavior.
|
| 5810 |
+
#
|
| 5811 |
+
# Training in this project has a strict dense, causal, right-padding
|
| 5812 |
+
# contract (no packed sequences and no interior holes). Under that
|
| 5813 |
+
# contract, valid queries occur before every padded key and causal
|
| 5814 |
+
# attention cannot see those future padded positions. Outputs for
|
| 5815 |
+
# padded queries are discarded by the masked objectives. Passing
|
| 5816 |
+
# ``None`` to standard decoder attention backends is thus equivalent on
|
| 5817 |
+
# trainable tokens while keeping one fixed dense kernel topology.
|
| 5818 |
+
#
|
| 5819 |
+
# IMPORTANT: the original ``attention_mask`` remains intact above and
|
| 5820 |
+
# outside the decoder: it still builds ``position_ids`` and is still
|
| 5821 |
+
# consumed by CCE/TWEO/NITP/temporal/NextLat and label masking. Do not
|
| 5822 |
+
# broaden this branch to packed/left-padded data. Validate that kind
|
| 5823 |
+
# of input at the data-pipeline boundary rather than with a tensor-value
|
| 5824 |
+
# check here, because a runtime ``all()``/``nonzero()`` would recreate
|
| 5825 |
+
# the graph breaks this branch is intended to remove. Evaluation,
|
| 5826 |
+
# generation and non-FlashAttention backends retain standard mask
|
| 5827 |
+
# construction below. IHA receives the original 2-D mask only as a
|
| 5828 |
+
# static dense/padded sentinel for its packing detector; its direct
|
| 5829 |
+
# kernel intentionally does not unpad fixed-length right-padded batches.
|
| 5830 |
+
use_dense_right_padded_flash_train = (
|
| 5831 |
+
self.training
|
| 5832 |
+
and self.config._attn_implementation
|
| 5833 |
+
in {"flash_attention_2", "flash_attention_3"}
|
| 5834 |
+
)
|
| 5835 |
+
if use_dense_right_padded_flash_train:
|
| 5836 |
+
causal_mask = (
|
| 5837 |
+
attention_mask
|
| 5838 |
+
if bool(getattr(self.config, "use_iha", False))
|
| 5839 |
+
else None
|
| 5840 |
+
)
|
| 5841 |
+
else:
|
| 5842 |
+
causal_mask = create_causal_mask(
|
| 5843 |
+
config=self.config,
|
| 5844 |
+
inputs_embeds=inputs_embeds,
|
| 5845 |
+
attention_mask=attention_mask,
|
| 5846 |
+
past_key_values=None,
|
| 5847 |
+
position_ids=position_ids,
|
| 5848 |
+
)
|
| 5849 |
|
| 5850 |
hidden_states = inputs_embeds
|
| 5851 |
use_siamesenorm = bool(getattr(self.config, "use_siamesenorm", False))
|