nemo_automodel.components.speculative.dspark.draft_minimax_m3
nemo_automodel.components.speculative.dspark.draft_minimax_m3
DSpark speculative-decoding draft model with a MiniMax M3 attention backbone.
Mirrors the Qwen3 DSpark draft’s control flow (standard GQA: separate q/k/v/o
projections, per-head norm on Q/K, K/V built by projecting the context and the
noise block separately then concatenating). The two differences from Qwen3 are
MiniMax M3’s own building blocks: per-head Gemma RMSNorm (MiniMaxM3RMSNorm),
SwiGLU-OAI activation (swiglu_oai), and partial RoPE via the gpt_oss rotary
utilities (matching the target’s own MiniMaxM3Attention/MiniMaxM3TextModel).
The draft runs dense, non-causal attention over a [context | noise-block]
layout, with visibility supplied entirely by the DFlash additive/block
attention mask. There is no block-sparse indexer and no MoE here: M3’s sparse
attention and routed experts belong to the target model, not this draft (the
draft is always dense, matching the DeepSeek V4 DSpark draft’s convention).
Module Contents
Classes
Functions
Data
_minimax_m3_flex_attention_compiled
API
Bases: Module
Dense, non-causal MiniMax M3 GQA attention over a [context | noise-block] layout.
Standard GQA (separate q/k/v/o projections, per-head Gemma RMSNorm on Q and
K before RoPE), mirroring Qwen3DSparkAttention’s control flow. M3 has no
shared K=V latent (unlike DeepSeek V4’s MLA draft), so K and V are genuinely
separate projections; there is no block-sparse indexer or MoE here (target-only
machinery, not the draft’s concern).
RoPE follows the gpt_oss rotary utilities’ broadcasting convention (x in
[B, S, H, D] layout while cos/sin apply), matching the target’s own
MiniMaxM3Attention, so RoPE is applied to Q/K before the transpose to
[B, H, S, D] for attention — not after, unlike the Gemma4/Qwen3 drafts’
own RoPE helpers, which use the opposite (post-transpose) convention.
Bases: Module
Pre-norm residual block: MiniMax M3 DSpark attention followed by a dense SwiGLU-OAI MLP.
Bases: Module
Dense SwiGLU-OAI MLP for the DSpark draft (plain nn.Linear, no MoE).
Bases: Module
DSpark draft model with a MiniMax M3 attention backbone (dense, non-causal).
Keep the rotary module’s device in sync across .to() calls.
RotaryEmbedding caches its concentration/inv_freq via
functools.cache keyed on the module instance, not a persistent
buffer, so nn.Module._apply (which only visits parameters/buffers)
never touches it. A later .to(device=...) (the training build path)
would otherwise silently leave the cached frequencies on whatever
device was current at construction, causing a device mismatch the
first time they are used against q/k on the real device. Sync
.device and drop the cache after any move so the next call
recomputes on the right device.
Use fused FlexAttention on CUDA while retaining the eager CPU test path.