nemo_automodel.components.speculative.eagle.draft_deepseek
nemo_automodel.components.speculative.eagle.draft_deepseek
DeepSeek (MLA-backbone) EAGLE-3 draft model.
The Llama-style draft (draft_llama.LlamaEagle3DraftModel) covers dense
multi-head-attention targets (Llama / Phi-3 / Qwen3). DeepSeek-V3 targets use
Multi-head Latent Attention (MLA): queries and keys are produced through
low-rank q_lora / kv_lora projections, the rotary part of the head is a
separate qk_rope_head_dim slice rotated with DeepSeek’s interleaved RoPE,
and the value head dimension (v_head_dim) differs from the query/key one
(qk_nope_head_dim + qk_rope_head_dim). A Llama-shaped draft cannot represent
that, so DeepSeek targets get this dedicated draft.
This mirrors draft_llama one-to-one for everything EAGLE-3 specific (the
[embed, hidden] fused first layer, the cache_hidden = [K_list, V_list]
TTT recurrence with per-step rotary phase offset and diagonal-extension
attention, project_hidden_states / compute_logits / set_vocab_mapping
and the d2t / t2d buffers). Only the attention block is replaced with MLA.
To guarantee the draft’s rotary math matches the target’s exactly, the MLA
projection layout and the interleaved RoPE are taken from the onboarded DeepSeek
target (components/models/deepseek_v3: the MLA projection structure and
rope_utils), not reimplemented.
Scope (v1): EAGLE-3 single fused draft layer, eager attention. P-EAGLE parallel-drafting, flash-attention, and sequence packing are intentionally left to follow-ups (they are orthogonal to the MLA attention this file adds).
Module Contents
Classes
Functions
API
Bases: PreTrainedModel
DeepSeek-V3 (MLA) EAGLE-3 draft model.
The MLA counterpart to LlamaEagle3DraftModel: same public training API
(project_hidden_states / embed_input_ids / compute_logits /
set_vocab_mapping / forward) and the same d2t / t2d vocab-remap
buffers, so the EAGLE-3 trainer and checkpointing are reused unchanged.
Draft logits over the draft vocabulary (applies model.norm unless already normed).
Seed the draft embedding table from the (possibly FSDP-sharded) target embeddings.
Embed input ids with the draft embedding table.
Run one EAGLE-3 TTT draft step (eager attention; seq_lens packing not supported in v1).
Project concatenated target aux hidden states to draft hidden size (with optional fc_norm).
Populate d2t / t2d from the draft->target id map (offset form vLLM/SGLang expect).
Bases: Module
Fused EAGLE-3 first layer: [embed, hidden] -> MLA -> MLP (mirrors Eagle3LlamaDecoderLayer).
Bases: Module
MLA self-attention for the DeepSeek EAGLE-3 draft.
Driven through the shared cache_hidden = [K_list, V_list] recurrence,
exactly like Eagle3LlamaAttention: step_idx = len(K_list) is both the
TTT step index and the rotary phase offset; each step appends its rotated K/V
and attends over the step-0 keys (full T x T causal) plus one diagonal
column per later step. The only difference from the Llama attention is how
q / k / v are produced (MLA low-rank projections + interleaved RoPE on the
qk_rope_head_dim slice) and that the value head dim differs from the q/k
head dim.
Keep the RoPE rope_freqs buffer in fp32 across dtype casts.
precompute_freqs_cis returns fp32 base frequencies, but the EAGLE-3
training build casts the whole draft with a raw .to(dtype=compute_dtype)
(train_eagle3.py), and nn.Module.to rounds floating-point buffers —
so rope_freqs is downcast to bf16. The rounded frequencies dephase with
absolute position (worse with longer context, and a bf16 round-trip cannot
be undone by a later fp32 upcast), so the draft’s RoPE drifts from the fp32
target and draft acceptance erodes. Recompute fresh fp32 frequencies after
any cast that would round them, keeping the same fp32 guarantee the Llama
draft and the DeepSeek target get by recomputing their RoPE cache from
config in fp32.
Up-project the KV latent and assemble per-head q[..,qk], k[..,qk], v[..,v] (heads first).
Return (q_nope, q_pe, kv_latent, k_pe) from the MLA down/up projections.
Bases: Module
Plain SwiGLU MLP for the draft (the draft is small; it does not replicate the target MoE).
Bases: Module
Inner backbone: embed_tokens, the fc aux-projection, the fused draft layer, and norm.
Build a standard [B, 1, T, T] additive causal + padding mask for eager attention.
Read the RoPE base the way the DeepSeek target does.
transformers 5.x moved rope_theta under config.rope_parameters and
dropped the top-level attribute (DeepseekV3Config(rope_theta=...).rope_theta
raises AttributeError), so a bare getattr(config, "rope_theta", 10000.0)
always returns the fallback and the draft’s rotary phase silently diverges from
any target whose base is not 10000. The top-level read is kept only as a
fallback for older configs.