nemo_rl.models.automodel.draft.eagle3_llama#
EAGLE3 TTT training forward, built on automodel’s LlamaEagle3DraftModel.
Module Contents#
Classes#
Restores the |
|
Per-TTT-step loss numerators/denominators and accuracy counts. |
|
|
Functions#
Per-position KL over the draft vocab for one sequence chunk. |
|
Dense additive mask: causal AND same-document, padding excluded. |
Data#
API#
- nemo_rl.models.automodel.draft.eagle3_llama._LOSS_REDUCTION_EPS#
1e-05
- nemo_rl.models.automodel.draft.eagle3_llama._KL_CHUNK_TOKENS#
512
- class nemo_rl.models.automodel.draft.eagle3_llama._Eagle3LlamaDecoderLayerWithResidualToggle(config, layer_id: int = 0)#
Bases:
nemo_automodel.components.speculative.eagle.draft_llama.Eagle3LlamaDecoderLayerRestores the
norm_before_residualtoggle automodel’s layer lacks.Eagle3LlamaDecoderLayer.forwardalways uses the PRE-normalization hidden state as the residual (residual = hidden_statesbeforehidden_normruns) – equivalent tonorm_before_residual=False, with no toggle at all. Speculators-format checkpoints (e.g. RedHatAI/Qwen3-30B-A3B-Instruct-2507-speculator.eagle3) explicitly declarenorm_before_residual: true; loading them through the unmodified automodel layer would silently use the wrong residual convention. Onlyforwarddiffers from the parent; state dict keys and shapes are unchanged.Initialization
- forward(
- input_embeds: torch.Tensor,
- hidden_states: torch.Tensor,
- attention_mask: torch.Tensor,
- position_ids: torch.Tensor,
- cache_hidden: list[list[torch.Tensor]],
- cu_seqlens: Optional[torch.Tensor] = None,
- max_seqlen: Optional[int] = None,
- class nemo_rl.models.automodel.draft.eagle3_llama.Eagle3ForwardTerms#
Per-TTT-step loss numerators/denominators and accuracy counts.
Numerators carry gradients; denominators are detached scalars. The caller normalizes as sum_k decay^k * num_k / den_k with den_k optionally reduced across the data-parallel group.
- loss_nums: list[torch.Tensor]#
None
- loss_dens: list[torch.Tensor]#
None
- full_acc_nums: list[torch.Tensor]#
None
- full_acc_dens: list[torch.Tensor]#
None
- cond_acc_nums: list[torch.Tensor]#
None
- cond_acc_dens: list[torch.Tensor]#
None
- nemo_rl.models.automodel.draft.eagle3_llama._kl_div_per_position_chunk(
- logits: torch.Tensor,
- targets: torch.Tensor,
Per-position KL over the draft vocab for one sequence chunk.
Each position’s KL is independent, so calling this per-chunk (as the TTT loop does, alongside chunking
compute_logitsitself) is mathematically exact and caps the per-chunk TRANSIENT peak – the fp32[*, chunk, V]intermediates (log_softmax, softmax, elementwise kl) never materialize for the FULL row at once. It does NOT reduce the cumulative memory retained for backward across the whole step: none of the chunks are checkpointed, so autograd still holds onto each chunk’s saved activations until the eventual.backward().
- nemo_rl.models.automodel.draft.eagle3_llama._build_attention_mask(
- document_ids: torch.Tensor,
- total_seq_len: int,
- dtype: torch.dtype,
- device: torch.device,
Dense additive mask: causal AND same-document, padding excluded.
Used only for the TTT loop’s step-0 causal block (
Eagle3LlamaAttentionkeeps this mask constant across TTT steps – later steps attend only to their own previous-step K/V at the same position, which needs no mask). documents_ids == -1 marks padding; queries in padding attend nowhere.
- class nemo_rl.models.automodel.draft.eagle3_llama.Eagle3DraftModel(config)#
Bases:
nemo_automodel.components.speculative.eagle.draft_llama.LlamaEagle3DraftModelLlamaEagle3DraftModelwith an RL-shaped TTTforward.Everything except
forward(embedding/fc/lm_head,d2t/t2d,set_vocab_mapping,copy_embeddings_from_target) is inherited unchanged from automodel.model.layers[0]is swapped for- Class:
_Eagle3LlamaDecoderLayerWithResidualToggleright after construction (before any weights load) – same parameter names/shapes, so checkpoints round-trip unchanged.
forwardruns the WHOLE TTT unroll as a single top-level call (matching the parent’s calling convention) rather than drivingembed_input_ids/project_hidden_states/compute_logitsas separate calls: FSDP2’sfully_shardunshard/reshard hooks fire onnn.Module.__call__, and only the top-level model and each decoder layer are individuallyfully_shard-ed (seebuild_eagle3_draft_model) –embed_tokens/fc/lm_head/normare NOT, so calling their owning methods directly (bypassingdraft_model(...)) would run them against still-shardedDTensorparameters.Initialization
- set_embedding_head_trainable(trainable: bool) None#
- get_d2t_target_ids() torch.Tensor#
Absolute target token id for each draft index (offset convention).
- forward(
- fused_hidden_states: torch.Tensor,
- input_ids: torch.Tensor,
- document_ids: torch.Tensor,
- loss_mask: torch.Tensor,
- teacher_logits: torch.Tensor,
- position_ids: Optional[torch.Tensor] = None,
- ttt_steps: int = 3,
- seq_lens: Optional[torch.Tensor] = None,
TTT training forward over one packed row.
- Parameters:
fused_hidden_states – [1, T, num_aux * H_target] concatenated aux hiddens.
input_ids – [1, T] rollout token ids (target vocab).
document_ids – [1, T] per-position document index, -1 for padding.
loss_mask – [1, T] boolean positions that carry loss.
teacher_logits – [1, T, draft_vocab] policy logits pre-mapped into draft-vocab order (detached by the caller).
position_ids – [1, T]; defaults to the speculators
1 + arange.ttt_steps – unroll depth.
seq_lens – [1, batch_size] per-sample block width (each entry the fixed
seq_lenevery sample’s slot occupies in the packed row, INCLUDING that sample’s trailing padding – seeEagle3Runtime.compute_loss). Required whenattn_implementation="flash_attention_2", unused otherwise. Declaring each fixed-size block as one FlashAttention-varlen “document” is safe even though padding sits inside the block: padding is placed at each block’s TAIL, so causal masking already keeps every real token from attending to any padding position (padding comes chronologically after), and padding positions’ own outputs never enter the loss (loss_mask excludes them).