nemo_automodel.components.speculative.mtp.core
nemo_automodel.components.speculative.mtp.core
Self-speculative acceptance-length evaluation for a model’s native MTP head.
MTP finetuning trains the existing MTPModule depths directly (see
nemo_automodel.components.loss.mtp.calculate_mtp_loss), but that loss only
reports scalar per-depth CE — it says nothing about how many tokens the MTP
head would actually get accepted under self-speculative decoding. This module
computes that acceptance-length proxy from the same per-depth outputs the loss
already consumes, without an extra model forward pass.
Acceptance is checked against the model’s own main-head greedy prediction (the
actual verifier in self-speculative decoding), not against the dataset label:
a draft is “accepted” when it agrees with what the model itself would have
produced, which can diverge from the ground-truth label whenever the main head
is imperfect. The dataset label only decides which positions are supervised
(masking ignored/padded/cross-document positions), the same role it plays in
calculate_mtp_loss.
Module Contents
Classes
Functions
API
Per-depth joint-prefix-hit counts for simulated_accept_length.
prefix_hits[k] counts positions whose greedy MTP chain is still fully
correct through depth k + 1 (argmax hit at every depth <= k), and
valid[k] counts positions supervised at every depth <= k. Kept
unreduced (shape [num_depths]) so a recipe can sum them across
microbatches and the DP/CP group before dividing once.
Cumulative per-depth left-roll of base, mirroring calculate_mtp_loss’s label roll.
fill_value only matters at trailing/cross-sub-sequence positions, which
the caller always excludes from both the hit and valid counts.
Score a model’s MTP depths against its own main-head greedy prediction.
Parameters:
The wrapped model; used to fetch the shared LM head when
mtp_per_depth_h is supplied instead of logits.
Per-depth hidden-state tensors of shape
[batch, sequence, hidden].
Per-depth logit tensors of shape
[batch, sequence, vocab].
The model’s own main-head logits, [batch, sequence, vocab], from the same forward pass. Its argmax is the acceptance
reference — not labels, which can disagree with what the
model itself would produce.
Original unshifted label tensor of shape [batch, sequence],
used only to mask ignored/padded positions out of the counts.
Label value excluded from both the hit and valid counts.
Optional per-token sub-sequence index used to mask rolls
whose source position crosses a packed-sequence boundary. Takes
precedence over cu_seqlens.
Optional cumulative sequence lengths [num_seqs+1]
(THD-pack layout) used to derive seq_idx when it is not given,
the same boundary calculate_mtp_loss uses for this batch.
Returns: MTPAcceptanceMetrics
class:MTPAcceptanceMetrics with one raw sum per depth.
Expected accepted tokens per speculative round, from prefix-hit counts.
Models greedy chain drafting: step_prefix_hits[k] / step_valid[k]
estimates the joint probability that the first k + 1 drafted tokens
all match the target’s greedy choices, i.e. that the chain survives depth
k + 1, so the expectation is 1 + sum_k P(survives depth k + 1).
Joint prefix counts keep the correlation between depths that a product of
per-step marginal accuracies discards (coincident and disjoint hits score
differently). The leading 1 counts the token the target itself emits on
every verification round, matching the accept_length convention of
the serving benchmarks (1 + accepted/drafts). A step with no
supervised positions contributes zero via the clamp_min. This is a
training-time proxy for greedy chain decoding; engine tree drafting
typically accepts more.