Update modeling_neollm.py
Browse files- modeling_neollm.py +22 -46
modeling_neollm.py
CHANGED
|
@@ -1911,8 +1911,8 @@ def _apply_repo_rope(
|
|
| 1911 |
n_groups = H // H_kv
|
| 1912 |
rotary_dim = inv_freq.shape[0] * 2 # inv_freq covers half the rotary dim
|
| 1913 |
|
| 1914 |
-
# inv_freq
|
| 1915 |
-
#
|
| 1916 |
# No autocast barrier: explicit .float() casts on z_q/z_k are sufficient
|
| 1917 |
# to maintain float32 precision for the trig ops. Removing the context
|
| 1918 |
# manager lets Inductor plan all intermediate tensors as part of a single
|
|
@@ -2182,37 +2182,9 @@ class NeoLLMAttention(nn.Module):
|
|
| 2182 |
d_p=_d_p,
|
| 2183 |
num_heads=config.num_attention_heads,
|
| 2184 |
)
|
| 2185 |
-
# _repo_inv_freq is registered as a non-persistent buffer by
|
| 2186 |
-
# set_repo_inv_freq(), called from NeoLLMModel.__init__ after
|
| 2187 |
-
# rotary_emb is built. Declaring it here would conflict.
|
| 2188 |
-
self._repo_attn_scaling: float = 1.0
|
| 2189 |
else:
|
| 2190 |
self.repo_module = None
|
| 2191 |
|
| 2192 |
-
def set_repo_inv_freq(
|
| 2193 |
-
self,
|
| 2194 |
-
inv_freq: torch.Tensor,
|
| 2195 |
-
attention_scaling: float,
|
| 2196 |
-
) -> None:
|
| 2197 |
-
"""
|
| 2198 |
-
Inject the rotary frequency vector from NeoLLMRotaryEmbedding so that
|
| 2199 |
-
REPO can build cos/sin inline from continuous positions.
|
| 2200 |
-
|
| 2201 |
-
Called once by NeoLLMModel.__init__ after rotary_emb is constructed.
|
| 2202 |
-
Only has effect when use_repo=True for this layer.
|
| 2203 |
-
|
| 2204 |
-
Args:
|
| 2205 |
-
inv_freq: [rotary_dim/2] — frozen inv_freq buffer from
|
| 2206 |
-
NeoLLMRotaryEmbedding.
|
| 2207 |
-
attention_scaling: float — attention_scaling from the same module.
|
| 2208 |
-
"""
|
| 2209 |
-
if self.use_repo:
|
| 2210 |
-
# Register as non-persistent buffer so .to(device) / .cuda() moves
|
| 2211 |
-
# it automatically — eliminates the DeviceCopy op that splits the
|
| 2212 |
-
# CUDAGraph into 2 partitions when _apply_repo_rope runs.
|
| 2213 |
-
self.register_buffer("_repo_inv_freq", inv_freq.float(), persistent=False)
|
| 2214 |
-
self._repo_attn_scaling = attention_scaling
|
| 2215 |
-
|
| 2216 |
def _apply_momentum_attention(
|
| 2217 |
self,
|
| 2218 |
q: torch.Tensor,
|
|
@@ -2348,6 +2320,7 @@ class NeoLLMAttention(nn.Module):
|
|
| 2348 |
attention_mask: Optional[torch.Tensor] = None,
|
| 2349 |
first_layer_fan: Optional[torch.Tensor] = None,
|
| 2350 |
attn_analysis: Optional[AttentionAnalysis] = None,
|
|
|
|
| 2351 |
**kwargs: Unpack[FlashAttentionKwargs],
|
| 2352 |
) -> tuple[torch.Tensor, Optional[torch.Tensor], Optional[torch.Tensor]]:
|
| 2353 |
input_shape = hidden_states.shape[:-1]
|
|
@@ -2385,14 +2358,14 @@ class NeoLLMAttention(nn.Module):
|
|
| 2385 |
# REPO path: f_ϕ predicts continuous per-head positions from the
|
| 2386 |
# residual stream, then cos/sin are built inline from those positions
|
| 2387 |
# so the rotation is differentiable w.r.t. REPOModule parameters.
|
|
|
|
|
|
|
|
|
|
| 2388 |
# (Li et al., 2026, §3.2 — Eq. 6–7)
|
| 2389 |
repo_a = attn_analysis.repo if attn_analysis is not None else None
|
| 2390 |
z = self.repo_module(hidden_states, repo_analysis=repo_a) # [B, H, S]
|
| 2391 |
-
|
| 2392 |
-
|
| 2393 |
-
self._repo_inv_freq,
|
| 2394 |
-
self._repo_attn_scaling,
|
| 2395 |
-
)
|
| 2396 |
else:
|
| 2397 |
# Standard path: integer positions pre-computed by NeoLLMModel.
|
| 2398 |
q, k = apply_rotary_pos_emb(q, k, cos, sin)
|
|
@@ -2773,6 +2746,7 @@ class NeoLLMDecoderLayer(GradientCheckpointingLayer):
|
|
| 2773 |
attn_res_partial: Optional[torch.Tensor] = None,
|
| 2774 |
layer_analysis: Optional[LayerAnalysis] = None,
|
| 2775 |
output_attentions: Optional[bool] = False,
|
|
|
|
| 2776 |
**kwargs: Unpack[FlashAttentionKwargs],
|
| 2777 |
) -> Tuple:
|
| 2778 |
# ── Snapshot input ────────────────────────────────────────────────
|
|
@@ -2810,6 +2784,7 @@ class NeoLLMDecoderLayer(GradientCheckpointingLayer):
|
|
| 2810 |
position_embeddings=position_embeddings,
|
| 2811 |
first_layer_fan=first_layer_fan,
|
| 2812 |
attn_analysis=layer_analysis.attention if layer_analysis is not None else None,
|
|
|
|
| 2813 |
**kwargs,
|
| 2814 |
)
|
| 2815 |
|
|
@@ -3329,17 +3304,6 @@ class NeoLLMModel(NeoLLMPreTrainedModel):
|
|
| 3329 |
|
| 3330 |
self.post_init()
|
| 3331 |
|
| 3332 |
-
# ── REPO: inject inv_freq into every attention layer that uses it ─────
|
| 3333 |
-
# Done after post_init so rotary_emb.inv_freq is already initialized.
|
| 3334 |
-
# Layers below repo_start_layer never call set_repo_inv_freq (their
|
| 3335 |
-
# use_repo flag is False) so the call is harmless for those layers.
|
| 3336 |
-
if getattr(config, "use_repo", False):
|
| 3337 |
-
for layer in self.layers:
|
| 3338 |
-
layer.self_attn.set_repo_inv_freq(
|
| 3339 |
-
self.rotary_emb.inv_freq,
|
| 3340 |
-
self.rotary_emb.attention_scaling,
|
| 3341 |
-
)
|
| 3342 |
-
|
| 3343 |
def get_input_embeddings(self):
|
| 3344 |
if self.config.use_token_generator:
|
| 3345 |
return self.token_generator
|
|
@@ -3471,6 +3435,17 @@ class NeoLLMModel(NeoLLMPreTrainedModel):
|
|
| 3471 |
position_embeddings = self.rotary_emb(hidden_states, position_ids)
|
| 3472 |
self.first_layer_fan = None
|
| 3473 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3474 |
# ── Attention Residuals state ──────────────────────────────────────
|
| 3475 |
# Full AttnRes (attn_res_num_blocks=0): sources grows by one entry per
|
| 3476 |
# decoder layer — all previous outputs are kept, max N=num_layers+1.
|
|
@@ -3531,6 +3506,7 @@ class NeoLLMModel(NeoLLMPreTrainedModel):
|
|
| 3531 |
attn_res_partial=attn_res_partial if use_attn_res else None,
|
| 3532 |
layer_analysis=layer_analysis,
|
| 3533 |
output_attentions=output_attentions,
|
|
|
|
| 3534 |
**kwargs,
|
| 3535 |
)
|
| 3536 |
hidden_states = layer_outputs[0]
|
|
|
|
| 1911 |
n_groups = H // H_kv
|
| 1912 |
rotary_dim = inv_freq.shape[0] * 2 # inv_freq covers half the rotary dim
|
| 1913 |
|
| 1914 |
+
# inv_freq arrives from rotary_emb at forward time via repo_rope_args —
|
| 1915 |
+
# already float32 on the correct device, no .to() needed, no DeviceCopy op.
|
| 1916 |
# No autocast barrier: explicit .float() casts on z_q/z_k are sufficient
|
| 1917 |
# to maintain float32 precision for the trig ops. Removing the context
|
| 1918 |
# manager lets Inductor plan all intermediate tensors as part of a single
|
|
|
|
| 2182 |
d_p=_d_p,
|
| 2183 |
num_heads=config.num_attention_heads,
|
| 2184 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2185 |
else:
|
| 2186 |
self.repo_module = None
|
| 2187 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2188 |
def _apply_momentum_attention(
|
| 2189 |
self,
|
| 2190 |
q: torch.Tensor,
|
|
|
|
| 2320 |
attention_mask: Optional[torch.Tensor] = None,
|
| 2321 |
first_layer_fan: Optional[torch.Tensor] = None,
|
| 2322 |
attn_analysis: Optional[AttentionAnalysis] = None,
|
| 2323 |
+
repo_rope_args: Optional[Tuple[torch.Tensor, float]] = None,
|
| 2324 |
**kwargs: Unpack[FlashAttentionKwargs],
|
| 2325 |
) -> tuple[torch.Tensor, Optional[torch.Tensor], Optional[torch.Tensor]]:
|
| 2326 |
input_shape = hidden_states.shape[:-1]
|
|
|
|
| 2358 |
# REPO path: f_ϕ predicts continuous per-head positions from the
|
| 2359 |
# residual stream, then cos/sin are built inline from those positions
|
| 2360 |
# so the rotation is differentiable w.r.t. REPOModule parameters.
|
| 2361 |
+
# inv_freq and attention_scaling arrive via repo_rope_args, sourced
|
| 2362 |
+
# directly from rotary_emb at forward time — no buffer on this module,
|
| 2363 |
+
# no meta-tensor issue on lm_eval / to(device) paths.
|
| 2364 |
# (Li et al., 2026, §3.2 — Eq. 6–7)
|
| 2365 |
repo_a = attn_analysis.repo if attn_analysis is not None else None
|
| 2366 |
z = self.repo_module(hidden_states, repo_analysis=repo_a) # [B, H, S]
|
| 2367 |
+
inv_freq, attn_scaling = repo_rope_args
|
| 2368 |
+
q, k = _apply_repo_rope(q, k, z, inv_freq, attn_scaling)
|
|
|
|
|
|
|
|
|
|
| 2369 |
else:
|
| 2370 |
# Standard path: integer positions pre-computed by NeoLLMModel.
|
| 2371 |
q, k = apply_rotary_pos_emb(q, k, cos, sin)
|
|
|
|
| 2746 |
attn_res_partial: Optional[torch.Tensor] = None,
|
| 2747 |
layer_analysis: Optional[LayerAnalysis] = None,
|
| 2748 |
output_attentions: Optional[bool] = False,
|
| 2749 |
+
repo_rope_args: Optional[Tuple[torch.Tensor, float]] = None,
|
| 2750 |
**kwargs: Unpack[FlashAttentionKwargs],
|
| 2751 |
) -> Tuple:
|
| 2752 |
# ── Snapshot input ────────────────────────────────────────────────
|
|
|
|
| 2784 |
position_embeddings=position_embeddings,
|
| 2785 |
first_layer_fan=first_layer_fan,
|
| 2786 |
attn_analysis=layer_analysis.attention if layer_analysis is not None else None,
|
| 2787 |
+
repo_rope_args=repo_rope_args,
|
| 2788 |
**kwargs,
|
| 2789 |
)
|
| 2790 |
|
|
|
|
| 3304 |
|
| 3305 |
self.post_init()
|
| 3306 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3307 |
def get_input_embeddings(self):
|
| 3308 |
if self.config.use_token_generator:
|
| 3309 |
return self.token_generator
|
|
|
|
| 3435 |
position_embeddings = self.rotary_emb(hidden_states, position_ids)
|
| 3436 |
self.first_layer_fan = None
|
| 3437 |
|
| 3438 |
+
# ── REPO: pass inv_freq by reference at forward time ──────────────────
|
| 3439 |
+
# rotary_emb.inv_freq is already on the correct device (managed by
|
| 3440 |
+
# NeoLLMRotaryEmbedding as a buffer) — no .to(), no DeviceCopy op.
|
| 3441 |
+
# Computed once here and passed through the decoder layer chain so
|
| 3442 |
+
# NeoLLMAttention never needs to store it as a buffer itself, avoiding
|
| 3443 |
+
# the meta-tensor issue that occurs when lm_eval calls .to(device).
|
| 3444 |
+
repo_rope_args = (
|
| 3445 |
+
(self.rotary_emb.inv_freq, self.rotary_emb.attention_scaling)
|
| 3446 |
+
if getattr(self.config, "use_repo", False) else None
|
| 3447 |
+
)
|
| 3448 |
+
|
| 3449 |
# ── Attention Residuals state ──────────────────────────────────────
|
| 3450 |
# Full AttnRes (attn_res_num_blocks=0): sources grows by one entry per
|
| 3451 |
# decoder layer — all previous outputs are kept, max N=num_layers+1.
|
|
|
|
| 3506 |
attn_res_partial=attn_res_partial if use_attn_res else None,
|
| 3507 |
layer_analysis=layer_analysis,
|
| 3508 |
output_attentions=output_attentions,
|
| 3509 |
+
repo_rope_args=repo_rope_args,
|
| 3510 |
**kwargs,
|
| 3511 |
)
|
| 3512 |
hidden_states = layer_outputs[0]
|