metrale_model_engine/traits/model/
verify.rs

1// SPDX-License-Identifier: MIT OR Apache-2.0
2
3//! 2026-09-26: `ModelVerify`, one of the supertraits `Model` is made of. Its methods, default
4//! bodies and docs are the ones `Model` declared before the split.
5//!
6//! Owner: model-engine.
7//! Invariants: none beyond the types.
8
9use super::VerifyBatchedOpts;
10use crate::traits::SequenceState;
11use anyhow::{Result, bail};
12
13/// 2026-09-26: Speculative verify passes: the fixed-width, γ-wide, DFlash and batched verifies, and the
14/// GDN fold after a write-on-accept batch.
15pub trait ModelVerify {
16    /// 2026-09-25: Run `tokens` through the model as one verify pass and return the argmax id at
17    /// each position; every token advances the KV and SSM state.
18    fn decode_verify(
19        &self,
20        tokens: &[u32],
21        seq: &mut SequenceState,
22        stream: u64,
23    ) -> Result<Vec<u32>>;
24
25    /// 2026-09-25: K=2 verify (`[last, draft]`); returns the argmax id at each position.
26    fn decode_verify_graphed(
27        &self,
28        tokens: &[u32; 2],
29        seq: &mut SequenceState,
30        stream: u64,
31    ) -> Result<[u32; 2]>;
32
33    /// 2026-09-25: K=3 verify (1 verified token and 2 drafts); returns 3 argmax ids.
34    fn decode_verify_graphed_k3(
35        &self,
36        tokens: &[u32; 3],
37        seq: &mut SequenceState,
38        stream: u64,
39    ) -> Result<[u32; 3]>;
40
41    /// 2026-09-25: K=4 verify (1 verified token and 3 drafts); returns 4 argmax ids.
42    fn decode_verify_graphed_k4(
43        &self,
44        tokens: &[u32; 4],
45        seq: &mut SequenceState,
46        stream: u64,
47    ) -> Result<[u32; 4]>;
48
49    /// 2026-09-25: Whether [`Self::decode_verify_batched`] can run `ks.len()` sequences with
50    /// `ks[i]` verify rows each (the sequence's draft count plus one; the rows may differ per
51    /// sequence). Default `false`, and there is no default batched implementation: a loop of
52    /// per-sequence verifies would leave only the last sequence's rows in the shared logits
53    /// buffer.
54    fn can_batch_verify(&self, _ks: &[usize]) -> bool {
55        false
56    }
57
58    /// 2026-09-25: Verify `ks.len()` sequences in one forward. Rows are flat and sequence-major
59    /// (`tokens.len() == Σ ks`): sequence `i` holds `[last_verified, d0, ..]` in rows
60    /// `off_i..off_i + ks[i]`, with `off_i = Σ_{t<i} ks[t]`. Returns the `Σ ks` argmax ids in the
61    /// same order. On success each sequence advances by its own `ks[i]`, and the caller rewinds
62    /// by its verdict.
63    ///
64    /// Call only when [`Self::can_batch_verify`] is true. With `opts.write_on_accept` the caller
65    /// must run [`Self::gdn_fold_accepted`] with every verdict before any
66    /// `commit_accepted_prefix`. Default: an error.
67    fn decode_verify_batched(
68        &self,
69        tokens: &[u32],
70        ks: &[usize],
71        seqs: &mut [&mut SequenceState],
72        stream: u64,
73        opts: VerifyBatchedOpts,
74    ) -> Result<Vec<u32>> {
75        let _ = (tokens, ks, seqs, stream, opts);
76        bail!("decode_verify_batched: unsupported by this model")
77    }
78
79    /// 2026-09-25: DFlash verify of `tokens` (1 verified token and γ drafts). Default:
80    /// [`Self::decode_verify`].
81    fn decode_verify_graphed_kgamma(
82        &self,
83        tokens: &[u32],
84        seq: &mut SequenceState,
85        stream: u64,
86    ) -> Result<Vec<u32>> {
87        self.decode_verify(tokens, seq, stream)
88    }
89
90    /// 2026-09-25: DFlash verify. Default: [`Self::decode_verify_graphed_kgamma`].
91    fn decode_verify_dflash(
92        &self,
93        tokens: &[u32],
94        seq: &mut SequenceState,
95        stream: u64,
96    ) -> Result<Vec<u32>> {
97        self.decode_verify_graphed_kgamma(tokens, seq, stream)
98    }
99
100    /// 2026-09-25: DFlash decode and verify in one forward: `tokens[0]` is the accepted token and
101    /// `tokens[1..]` the draft block. Default: [`Self::decode_verify_graphed_kgamma`].
102    fn decode_and_verify_fused(
103        &self,
104        tokens: &[u32],
105        seq: &mut SequenceState,
106        stream: u64,
107    ) -> Result<Vec<u32>> {
108        self.decode_verify_graphed_kgamma(tokens, seq, stream)
109    }
110
111    /// 2026-09-25: After a batched verify run with `write_on_accept`, commit the GDN `h` state of
112    /// each slot `slots[i]` at `accepted_rows[i]` verify rows (anchor included), in the verify's
113    /// batch order. `Ok(true)` means the `h` states were committed here, and
114    /// `commit_accepted_prefix` then restores only conv state for those slots. `Ok(false)`
115    /// means nothing was folded. Default: `Ok(false)`.
116    fn gdn_fold_accepted(
117        &self,
118        _slots: &[usize],
119        _accepted_rows: &[u32],
120        _k_rows: usize,
121    ) -> Result<bool> {
122        Ok(false)
123    }
124}