Skip to main content

MtpSpeculative

Struct MtpSpeculative 

Source
pub struct MtpSpeculative<'model> { /* private fields */ }
Expand description

Full MTP speculative driver (requires the common feature).

Wraps ik’s common_speculative_* via the ik_llama_rs_mtp_* C++ glue. Two ways to drive it after newbegin(prompt):

  • step() — the convenience path: the glue owns the whole draft→verify→sample→commit cycle (greedy / temp), returning the committed tokens. Use this when you don’t need to constrain sampling.
  • draft() + commit() — the caller-driven path: draft returns the NextN candidates without sampling; you build the verify batch [id_last] + drafts (logits on every position), decode it on target_context_mut, pick each committed token yourself (e.g. through a crate::LlamaGrammar + sampler over target_context’s logits), then commit them. This is what lets MTP speculation run together with grammar- constrained / custom sampling — the crate never samples on this path.

Either way ik owns all KV bookkeeping (the companion cache and the target rollback happen inside the glue); the caller must not clear or roll back either cache itself.

Implementations§

Source§

impl<'model> MtpSpeculative<'model>

Source

pub fn new( model: &LlamaModel, ctx: LlamaContext<'model>, params: MtpSpeculativeParams, ) -> Result<Self, LlamaError>

Initialize the driver over a NextN model + its (mtp-enabled) context.

Takes ownership of ctx (so the driver is self-contained and can be stored in a struct); read/decode it back out via target_context / target_context_mut.

model must have been loaded with .with_mtp(true) and ctx created with .with_mtp(true). Fails with LlamaError::MtpInit for a model with 0 NextN layers (not an MTP model). Recurrent / openPangu targets (which includes the Qwen3.5 NextN family) are supported: the driver takes an internal rollback checkpoint before each verify so rejected drafts restore the recurrent state correctly.

Source

pub fn begin(&mut self, prompt: &[LlamaToken]) -> Result<usize, LlamaError>

Prompt warmup + begin. Runs the prompt through the MTP path and prepares the first draft. Returns n_past. Call once before Self::step.

Source

pub fn step(&mut self) -> Result<MtpStep, LlamaError>

Run one draft→verify→accept→commit cycle. Returns the tokens emitted this step (to append to the output) and how many drafts were accepted.

Source

pub fn draft( &mut self, n_past: i32, id_last: LlamaToken, ) -> Result<Vec<LlamaToken>, LlamaError>

Propose up to n_max draft tokens following id_last (the last committed token) at position n_past, without sampling.

This is the caller-driven entry point for running MTP speculation alongside a grammar / custom sampler (see the module example). After draft, the caller must:

  1. build the verify batch [id_last] + drafts (one sequence, logits on every position), in that order;
  2. decode it on target_context_mut;
  3. pick the committed tokens with its own grammar/sampler, reading output index i via target_context for each verify position i;
  4. call commit.

Use one round strictly as draft → verify-decode → commit: commit takes its anchor position from the n_past you pass here, so do not draft twice before committing, and build the verify batch with id_last at exactly n_past. Do not mix this path with step on the same driver — they own the loop state differently.

§Errors

LlamaError::MtpStep if the C glue rejects the draft.

Source

pub fn commit( &mut self, id_last: LlamaToken, committed: &[LlamaToken], n_draft: usize, ) -> Result<(), LlamaError>

Finalize one speculative round after the caller has decoded the verify batch and chosen its committed tokens.

id_last is the anchor token that led the verify batch (the same one passed to draft); committed is the accepted-draft prefix followed by exactly one correction/bonus token (so committed.len() == n_accepted + 1); n_draft is the number of tokens the matching draft returned.

Advances the MTP companion by the accepted count and rolls the target KV cache back to the committed prefix. The caller must not clear or roll back either KV cache itself — ik owns that bookkeeping.

§Errors

LlamaError::MtpStep if committed is empty, longer than n_draft + 1 (more tokens than the verify batch produced — which would desync the KV cache), or the glue rejects the commit.

Source

pub fn params(&self) -> MtpSpeculativeParams

The configured parameters.

Source

pub fn target_context(&self) -> &LlamaContext<'model>

Shared access to the target context — read per-position logits here for a grammar-gated commit (e.g. LlamaContext::token_data_array_ith).

Source

pub fn target_context_mut(&mut self) -> &mut LlamaContext<'model>

Mutable access to the target context — decode the verify batch here.

Source

pub fn context_mut(&mut self) -> &mut LlamaContext<'model>

Mutable access to the wrapped context (only between full generations).

Alias of target_context_mut, kept for back-compat.

Trait Implementations§

Source§

impl<'model> Debug for MtpSpeculative<'model>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Drop for MtpSpeculative<'_>

Source§

fn drop(&mut self)

Executes the destructor for this type. Read more
Source§

fn pin_drop(self: Pin<&mut Self>)

🔬This is a nightly-only experimental API. (pin_ergonomics)
Execute the destructor for this type, but different to Drop::drop, it requires self to be pinned. Read more

Auto Trait Implementations§

§

impl<'model> !Send for MtpSpeculative<'model>

§

impl<'model> !Sync for MtpSpeculative<'model>

§

impl<'model> Freeze for MtpSpeculative<'model>

§

impl<'model> RefUnwindSafe for MtpSpeculative<'model>

§

impl<'model> Unpin for MtpSpeculative<'model>

§

impl<'model> UnsafeUnpin for MtpSpeculative<'model>

§

impl<'model> UnwindSafe for MtpSpeculative<'model>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more