Update modeling_neollm.py
Browse files- modeling_neollm.py +87 -16
modeling_neollm.py
CHANGED
|
@@ -65,6 +65,8 @@ References:
|
|
| 65 |
arXiv:2601.15380.
|
| 66 |
StackMemory / STACKTRANS: Zhang et al. (2025). "Recursive Transformer:
|
| 67 |
Boosting Reasoning Ability with State Stack." NeurIPS 2025.
|
|
|
|
|
|
|
| 68 |
"""
|
| 69 |
|
| 70 |
import math
|
|
@@ -5268,6 +5270,7 @@ class NeoLLMModel(NeoLLMPreTrainedModel):
|
|
| 5268 |
inputs_embeds: Optional[torch.FloatTensor] = None,
|
| 5269 |
output_hidden_states: Optional[bool] = None,
|
| 5270 |
output_attentions: Optional[bool] = None,
|
|
|
|
| 5271 |
return_dict: Optional[bool] = None,
|
| 5272 |
**kwargs: Unpack[TransformersKwargs],
|
| 5273 |
) -> Tuple:
|
|
@@ -5281,6 +5284,7 @@ class NeoLLMModel(NeoLLMPreTrainedModel):
|
|
| 5281 |
if output_attentions is not None
|
| 5282 |
else self.config.output_attentions
|
| 5283 |
)
|
|
|
|
| 5284 |
if return_dict is None:
|
| 5285 |
cfg_dict = vars(self.config)
|
| 5286 |
return_dict = cfg_dict.get(
|
|
@@ -5341,6 +5345,7 @@ class NeoLLMModel(NeoLLMPreTrainedModel):
|
|
| 5341 |
siamese_y_states = inputs_embeds if use_siamesenorm else None
|
| 5342 |
all_hidden_states = () if output_hidden_states else None
|
| 5343 |
all_attentions = () if output_attentions else None
|
|
|
|
| 5344 |
all_aux_stats = []
|
| 5345 |
|
| 5346 |
# ── StackMemory state ─────────────────────────────────────────────
|
|
@@ -5492,6 +5497,9 @@ class NeoLLMModel(NeoLLMPreTrainedModel):
|
|
| 5492 |
all_aux_stats.append(item)
|
| 5493 |
break
|
| 5494 |
|
|
|
|
|
|
|
|
|
|
| 5495 |
if (
|
| 5496 |
getattr(self.config, "use_fan_residual", True)
|
| 5497 |
and self.first_layer_fan is None
|
|
@@ -5511,18 +5519,24 @@ class NeoLLMModel(NeoLLMPreTrainedModel):
|
|
| 5511 |
all_hidden_states = all_hidden_states + (hidden_states,)
|
| 5512 |
|
| 5513 |
if not return_dict:
|
| 5514 |
-
|
| 5515 |
v
|
| 5516 |
for v in [hidden_states, None, all_hidden_states, all_attentions]
|
| 5517 |
if v is not None
|
| 5518 |
-
)
|
|
|
|
|
|
|
|
|
|
| 5519 |
|
| 5520 |
-
|
| 5521 |
last_hidden_state=hidden_states,
|
| 5522 |
past_key_values=None,
|
| 5523 |
hidden_states=all_hidden_states,
|
| 5524 |
attentions=all_attentions,
|
| 5525 |
-
)
|
|
|
|
|
|
|
|
|
|
| 5526 |
|
| 5527 |
|
| 5528 |
def _prepare_lm_labels(labels, device, pad_token_id=None):
|
|
@@ -5626,6 +5640,31 @@ def compute_liger_loss(
|
|
| 5626 |
)
|
| 5627 |
|
| 5628 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 5629 |
class NITPProjector(nn.Module):
|
| 5630 |
"""
|
| 5631 |
SwiGLU projection head for Next Implicit Token Prediction.
|
|
@@ -5895,6 +5934,7 @@ class NeoLLMForCausalLM(NeoLLMPreTrainedModel, GenerationMixin):
|
|
| 5895 |
f"Got {self.ntp_loss_backend!r}."
|
| 5896 |
)
|
| 5897 |
self._last_ntp_loss = None
|
|
|
|
| 5898 |
self._last_nitp_loss = None
|
| 5899 |
self._last_nextlat_loss = None
|
| 5900 |
self._last_nextlat_mse_loss = None
|
|
@@ -5955,6 +5995,11 @@ class NeoLLMForCausalLM(NeoLLMPreTrainedModel, GenerationMixin):
|
|
| 5955 |
return_dict: Optional[bool] = None,
|
| 5956 |
**kwargs: Unpack[TransformersKwargs],
|
| 5957 |
) -> CausalLMOutputWithPast:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 5958 |
nitp_enabled = (
|
| 5959 |
bool(getattr(self.config, "use_nitp", False))
|
| 5960 |
and self.nitp_projector is not None
|
|
@@ -5980,30 +6025,48 @@ class NeoLLMForCausalLM(NeoLLMPreTrainedModel, GenerationMixin):
|
|
| 5980 |
position_ids=position_ids,
|
| 5981 |
inputs_embeds=inputs_embeds,
|
| 5982 |
output_hidden_states=model_output_hidden_states,
|
|
|
|
| 5983 |
return_dict=return_dict,
|
| 5984 |
**kwargs,
|
| 5985 |
)
|
| 5986 |
|
| 5987 |
# Unpack: model returns (BaseModelOutputWithPast, aux_stats_list)
|
| 5988 |
# or a tuple when return_dict=False
|
|
|
|
|
|
|
| 5989 |
if isinstance(model_out, tuple):
|
| 5990 |
-
outputs
|
| 5991 |
-
if
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 5992 |
hidden_states = outputs[0]
|
|
|
|
|
|
|
| 5993 |
else:
|
| 5994 |
hidden_states = outputs.last_hidden_state
|
|
|
|
| 5995 |
else:
|
| 5996 |
outputs = model_out
|
| 5997 |
all_aux_stats = []
|
| 5998 |
hidden_states = outputs.last_hidden_state
|
|
|
|
| 5999 |
|
| 6000 |
loss = None
|
| 6001 |
ntp_loss = None
|
|
|
|
| 6002 |
nitp_loss = None
|
| 6003 |
nextlat_loss = None
|
| 6004 |
nextlat_mse_loss = None
|
| 6005 |
nextlat_kl_loss = None
|
| 6006 |
self._last_ntp_loss = None
|
|
|
|
| 6007 |
self._last_nitp_loss = None
|
| 6008 |
self._last_nextlat_loss = None
|
| 6009 |
self._last_nextlat_mse_loss = None
|
|
@@ -6030,10 +6093,22 @@ class NeoLLMForCausalLM(NeoLLMPreTrainedModel, GenerationMixin):
|
|
| 6030 |
)
|
| 6031 |
loss = ntp_loss
|
| 6032 |
|
| 6033 |
-
if
|
| 6034 |
-
|
| 6035 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 6036 |
)
|
|
|
|
|
|
|
|
|
|
| 6037 |
target_layer = int(getattr(self.config, "nitp_target_layer", 1))
|
| 6038 |
if (
|
| 6039 |
hidden_states_tuple is None
|
|
@@ -6056,9 +6131,6 @@ class NeoLLMForCausalLM(NeoLLMPreTrainedModel, GenerationMixin):
|
|
| 6056 |
loss = loss + self.config.nitp_loss_weight * nitp_loss
|
| 6057 |
|
| 6058 |
if nextlat_enabled:
|
| 6059 |
-
hidden_states_tuple = (
|
| 6060 |
-
outputs.hidden_states if hasattr(outputs, "hidden_states") else None
|
| 6061 |
-
)
|
| 6062 |
if hidden_states_tuple is None or len(hidden_states_tuple) < 2:
|
| 6063 |
raise ValueError(
|
| 6064 |
"`use_nextlat=True` requires backbone hidden states. "
|
|
@@ -6093,6 +6165,7 @@ class NeoLLMForCausalLM(NeoLLMPreTrainedModel, GenerationMixin):
|
|
| 6093 |
)
|
| 6094 |
loss = loss + aux_loss
|
| 6095 |
self._last_ntp_loss = ntp_loss.detach() if ntp_loss is not None else None
|
|
|
|
| 6096 |
self._last_nitp_loss = nitp_loss.detach() if nitp_loss is not None else None
|
| 6097 |
self._last_nextlat_loss = (
|
| 6098 |
nextlat_loss.detach() if nextlat_loss is not None else None
|
|
@@ -6117,9 +6190,7 @@ class NeoLLMForCausalLM(NeoLLMPreTrainedModel, GenerationMixin):
|
|
| 6117 |
loss=loss,
|
| 6118 |
logits=logits,
|
| 6119 |
past_key_values=None,
|
| 6120 |
-
hidden_states=
|
| 6121 |
-
if hasattr(outputs, "hidden_states")
|
| 6122 |
-
else None,
|
| 6123 |
attentions=outputs.attentions if hasattr(outputs, "attentions") else None,
|
| 6124 |
)
|
| 6125 |
|
|
@@ -6148,4 +6219,4 @@ __all__ = [
|
|
| 6148 |
|
| 6149 |
AutoConfig.register("neollm", NeoLLMConfig)
|
| 6150 |
AutoModel.register(NeoLLMConfig, NeoLLMModel)
|
| 6151 |
-
AutoModelForCausalLM.register(NeoLLMConfig, NeoLLMForCausalLM)
|
|
|
|
| 65 |
arXiv:2601.15380.
|
| 66 |
StackMemory / STACKTRANS: Zhang et al. (2025). "Recursive Transformer:
|
| 67 |
Boosting Reasoning Ability with State Stack." NeurIPS 2025.
|
| 68 |
+
TWEO: Liang et al. (2026). "Transformers Without Extreme Outliers Enables
|
| 69 |
+
FP8 Training And Quantization For Dummies." arXiv:2511.23225.
|
| 70 |
"""
|
| 71 |
|
| 72 |
import math
|
|
|
|
| 5270 |
inputs_embeds: Optional[torch.FloatTensor] = None,
|
| 5271 |
output_hidden_states: Optional[bool] = None,
|
| 5272 |
output_attentions: Optional[bool] = None,
|
| 5273 |
+
output_tweo_activations: Optional[bool] = None,
|
| 5274 |
return_dict: Optional[bool] = None,
|
| 5275 |
**kwargs: Unpack[TransformersKwargs],
|
| 5276 |
) -> Tuple:
|
|
|
|
| 5284 |
if output_attentions is not None
|
| 5285 |
else self.config.output_attentions
|
| 5286 |
)
|
| 5287 |
+
output_tweo_activations = bool(output_tweo_activations)
|
| 5288 |
if return_dict is None:
|
| 5289 |
cfg_dict = vars(self.config)
|
| 5290 |
return_dict = cfg_dict.get(
|
|
|
|
| 5345 |
siamese_y_states = inputs_embeds if use_siamesenorm else None
|
| 5346 |
all_hidden_states = () if output_hidden_states else None
|
| 5347 |
all_attentions = () if output_attentions else None
|
| 5348 |
+
tweo_activations = () if output_tweo_activations else None
|
| 5349 |
all_aux_stats = []
|
| 5350 |
|
| 5351 |
# ── StackMemory state ─────────────────────────────────────────────
|
|
|
|
| 5497 |
all_aux_stats.append(item)
|
| 5498 |
break
|
| 5499 |
|
| 5500 |
+
if output_tweo_activations:
|
| 5501 |
+
tweo_activations = tweo_activations + (hidden_states,)
|
| 5502 |
+
|
| 5503 |
if (
|
| 5504 |
getattr(self.config, "use_fan_residual", True)
|
| 5505 |
and self.first_layer_fan is None
|
|
|
|
| 5519 |
all_hidden_states = all_hidden_states + (hidden_states,)
|
| 5520 |
|
| 5521 |
if not return_dict:
|
| 5522 |
+
base_outputs = tuple(
|
| 5523 |
v
|
| 5524 |
for v in [hidden_states, None, all_hidden_states, all_attentions]
|
| 5525 |
if v is not None
|
| 5526 |
+
)
|
| 5527 |
+
if output_tweo_activations:
|
| 5528 |
+
return base_outputs + (all_aux_stats, tweo_activations)
|
| 5529 |
+
return base_outputs + (all_aux_stats,)
|
| 5530 |
|
| 5531 |
+
outputs = BaseModelOutputWithPast(
|
| 5532 |
last_hidden_state=hidden_states,
|
| 5533 |
past_key_values=None,
|
| 5534 |
hidden_states=all_hidden_states,
|
| 5535 |
attentions=all_attentions,
|
| 5536 |
+
)
|
| 5537 |
+
if output_tweo_activations:
|
| 5538 |
+
return outputs, all_aux_stats, tweo_activations
|
| 5539 |
+
return outputs, all_aux_stats
|
| 5540 |
|
| 5541 |
|
| 5542 |
def _prepare_lm_labels(labels, device, pad_token_id=None):
|
|
|
|
| 5640 |
)
|
| 5641 |
|
| 5642 |
|
| 5643 |
+
def compute_tweo_loss(
|
| 5644 |
+
block_activations: Tuple[torch.Tensor, ...],
|
| 5645 |
+
tau: float,
|
| 5646 |
+
power: float,
|
| 5647 |
+
eps: float,
|
| 5648 |
+
) -> torch.Tensor:
|
| 5649 |
+
"""
|
| 5650 |
+
Transformers Without Extreme Outliers activation regularizer.
|
| 5651 |
+
|
| 5652 |
+
Liang et al. (2026) apply a scaled Lp penalty to the final output
|
| 5653 |
+
activations of every Transformer block. The penalty is intentionally
|
| 5654 |
+
smooth rather than hinge-thresholded, so normal activations remain cheap
|
| 5655 |
+
while extreme outliers become expensive.
|
| 5656 |
+
"""
|
| 5657 |
+
if not block_activations:
|
| 5658 |
+
raise ValueError("TWEO requires at least one Transformer block activation.")
|
| 5659 |
+
|
| 5660 |
+
scale = float(tau) + float(eps)
|
| 5661 |
+
total = block_activations[0].new_zeros((), dtype=torch.float32)
|
| 5662 |
+
for activation in block_activations:
|
| 5663 |
+
scaled = activation.float().abs() / scale
|
| 5664 |
+
total = total + scaled.pow(float(power)).mean()
|
| 5665 |
+
return total / len(block_activations)
|
| 5666 |
+
|
| 5667 |
+
|
| 5668 |
class NITPProjector(nn.Module):
|
| 5669 |
"""
|
| 5670 |
SwiGLU projection head for Next Implicit Token Prediction.
|
|
|
|
| 5934 |
f"Got {self.ntp_loss_backend!r}."
|
| 5935 |
)
|
| 5936 |
self._last_ntp_loss = None
|
| 5937 |
+
self._last_tweo_loss = None
|
| 5938 |
self._last_nitp_loss = None
|
| 5939 |
self._last_nextlat_loss = None
|
| 5940 |
self._last_nextlat_mse_loss = None
|
|
|
|
| 5995 |
return_dict: Optional[bool] = None,
|
| 5996 |
**kwargs: Unpack[TransformersKwargs],
|
| 5997 |
) -> CausalLMOutputWithPast:
|
| 5998 |
+
tweo_enabled = (
|
| 5999 |
+
bool(getattr(self.config, "use_tweo", False))
|
| 6000 |
+
and labels is not None
|
| 6001 |
+
and float(getattr(self.config, "tweo_loss_weight", 0.0)) > 0.0
|
| 6002 |
+
)
|
| 6003 |
nitp_enabled = (
|
| 6004 |
bool(getattr(self.config, "use_nitp", False))
|
| 6005 |
and self.nitp_projector is not None
|
|
|
|
| 6025 |
position_ids=position_ids,
|
| 6026 |
inputs_embeds=inputs_embeds,
|
| 6027 |
output_hidden_states=model_output_hidden_states,
|
| 6028 |
+
output_tweo_activations=tweo_enabled,
|
| 6029 |
return_dict=return_dict,
|
| 6030 |
**kwargs,
|
| 6031 |
)
|
| 6032 |
|
| 6033 |
# Unpack: model returns (BaseModelOutputWithPast, aux_stats_list)
|
| 6034 |
# or a tuple when return_dict=False
|
| 6035 |
+
tweo_activations = None
|
| 6036 |
+
hidden_states_tuple = None
|
| 6037 |
if isinstance(model_out, tuple):
|
| 6038 |
+
outputs = model_out[0]
|
| 6039 |
+
if tweo_enabled and len(model_out) >= 3:
|
| 6040 |
+
all_aux_stats = model_out[-2]
|
| 6041 |
+
tweo_activations = model_out[-1]
|
| 6042 |
+
else:
|
| 6043 |
+
all_aux_stats = model_out[-1]
|
| 6044 |
+
if isinstance(outputs, torch.Tensor):
|
| 6045 |
+
hidden_states = outputs
|
| 6046 |
+
if len(model_out) > 1 and isinstance(model_out[1], tuple):
|
| 6047 |
+
hidden_states_tuple = model_out[1]
|
| 6048 |
+
elif isinstance(outputs, tuple):
|
| 6049 |
hidden_states = outputs[0]
|
| 6050 |
+
if len(outputs) > 2:
|
| 6051 |
+
hidden_states_tuple = outputs[2]
|
| 6052 |
else:
|
| 6053 |
hidden_states = outputs.last_hidden_state
|
| 6054 |
+
hidden_states_tuple = outputs.hidden_states
|
| 6055 |
else:
|
| 6056 |
outputs = model_out
|
| 6057 |
all_aux_stats = []
|
| 6058 |
hidden_states = outputs.last_hidden_state
|
| 6059 |
+
hidden_states_tuple = outputs.hidden_states
|
| 6060 |
|
| 6061 |
loss = None
|
| 6062 |
ntp_loss = None
|
| 6063 |
+
tweo_loss = None
|
| 6064 |
nitp_loss = None
|
| 6065 |
nextlat_loss = None
|
| 6066 |
nextlat_mse_loss = None
|
| 6067 |
nextlat_kl_loss = None
|
| 6068 |
self._last_ntp_loss = None
|
| 6069 |
+
self._last_tweo_loss = None
|
| 6070 |
self._last_nitp_loss = None
|
| 6071 |
self._last_nextlat_loss = None
|
| 6072 |
self._last_nextlat_mse_loss = None
|
|
|
|
| 6093 |
)
|
| 6094 |
loss = ntp_loss
|
| 6095 |
|
| 6096 |
+
if tweo_enabled:
|
| 6097 |
+
if not tweo_activations:
|
| 6098 |
+
raise ValueError(
|
| 6099 |
+
"`use_tweo=True` requires Transformer block activations. "
|
| 6100 |
+
"NeoLLMForCausalLM.forward enables them automatically "
|
| 6101 |
+
"while labels are present."
|
| 6102 |
+
)
|
| 6103 |
+
tweo_loss = compute_tweo_loss(
|
| 6104 |
+
block_activations=tweo_activations,
|
| 6105 |
+
tau=self.config.tweo_tau,
|
| 6106 |
+
power=self.config.tweo_power,
|
| 6107 |
+
eps=self.config.tweo_eps,
|
| 6108 |
)
|
| 6109 |
+
loss = loss + self.config.tweo_loss_weight * tweo_loss
|
| 6110 |
+
|
| 6111 |
+
if nitp_enabled:
|
| 6112 |
target_layer = int(getattr(self.config, "nitp_target_layer", 1))
|
| 6113 |
if (
|
| 6114 |
hidden_states_tuple is None
|
|
|
|
| 6131 |
loss = loss + self.config.nitp_loss_weight * nitp_loss
|
| 6132 |
|
| 6133 |
if nextlat_enabled:
|
|
|
|
|
|
|
|
|
|
| 6134 |
if hidden_states_tuple is None or len(hidden_states_tuple) < 2:
|
| 6135 |
raise ValueError(
|
| 6136 |
"`use_nextlat=True` requires backbone hidden states. "
|
|
|
|
| 6165 |
)
|
| 6166 |
loss = loss + aux_loss
|
| 6167 |
self._last_ntp_loss = ntp_loss.detach() if ntp_loss is not None else None
|
| 6168 |
+
self._last_tweo_loss = tweo_loss.detach() if tweo_loss is not None else None
|
| 6169 |
self._last_nitp_loss = nitp_loss.detach() if nitp_loss is not None else None
|
| 6170 |
self._last_nextlat_loss = (
|
| 6171 |
nextlat_loss.detach() if nextlat_loss is not None else None
|
|
|
|
| 6190 |
loss=loss,
|
| 6191 |
logits=logits,
|
| 6192 |
past_key_values=None,
|
| 6193 |
+
hidden_states=hidden_states_tuple,
|
|
|
|
|
|
|
| 6194 |
attentions=outputs.attentions if hasattr(outputs, "attentions") else None,
|
| 6195 |
)
|
| 6196 |
|
|
|
|
| 6219 |
|
| 6220 |
AutoConfig.register("neollm", NeoLLMConfig)
|
| 6221 |
AutoModel.register(NeoLLMConfig, NeoLLMModel)
|
| 6222 |
+
AutoModelForCausalLM.register(NeoLLMConfig, NeoLLMForCausalLM)
|