pub struct V3Model {
pub cfg: V3Config,
pub embedding: CqWeight,
pub layers: Vec<V3Layer>,
pub mhc: V3Mhc,
pub engrams: Vec<V3EngramSite>,
pub final_norm: Vec<f32>,
pub perms: HadaPerms,
/* private fields */
}Expand description
A loaded Needle 3 model.
Fields§
§cfg: V3Config§embedding: CqWeightTied embedding, [vocab_size, d_model] — also the LM head.
layers: Vec<V3Layer>§mhc: V3Mhc§engrams: Vec<V3EngramSite>§final_norm: Vec<f32>§perms: HadaPermsImplementations§
Source§impl V3Model
impl V3Model
pub fn new( cfg: V3Config, embedding: CqWeight, layers: Vec<V3Layer>, mhc: V3Mhc, engrams: Vec<V3EngramSite>, final_norm: Vec<f32>, perms: HadaPerms, ) -> Result<Self, &'static str>
Sourcepub fn decode_step(&self, cache: &mut V3Cache, token: u32) -> Vec<f32>
pub fn decode_step(&self, cache: &mut V3Cache, token: u32) -> Vec<f32>
One incremental decode step: feed token, get logits for its position.
Mathematically identical to Self::forward_sequence at the same
position — the self-consistency test asserts exactly that.
The mHC lane stream is deliberately not cached. Each position’s lanes start from its own embedding and evolve using only that position’s values; the sole cross-position dependencies are attention, the Q/K/V convolution and the Engram, and the cache carries each of those separately.
Sourcepub fn forward_sequence(&self, tokens: &[u32]) -> Vec<f32>
pub fn forward_sequence(&self, tokens: &[u32]) -> Vec<f32>
Logits for every position, (seq, logit_rows) row-major.
Mirrors upstream’s graph: the lane stream carries mhc_lanes copies of
the scaled embedding, each layer mixes down and scatters back, and the
head is the embedding itself, sliced to out_vocab.
Sourcepub fn forward_head(&self, tokens: &[u32], head: &ProbeHead) -> Vec<f32>
pub fn forward_head(&self, tokens: &[u32], head: &ProbeHead) -> Vec<f32>
Run head over the sequence without ever holding all the cells.
Prefer this to forward_cells + ProbeHead::forward: the cells cost
seq * (layers + 1) * d_model floats — 504 MB at full context on the
shipped model — where the streaming pool holds 252 KB regardless of
length.
Sourcepub fn forward_cells(&self, tokens: &[u32]) -> Vec<f32>
pub fn forward_cells(&self, tokens: &[u32]) -> Vec<f32>
Per-layer pooled states, (seq, num_layers + 1, d_model).
Cell 0 is the scaled input embedding; cell 1 + i is the lane stream
after layer i, meaned over lanes. These are what the probe heads read.
Sourcepub fn prefill(&self, tokens: &[u32], cache: &mut V3Cache) -> Vec<f32>
pub fn prefill(&self, tokens: &[u32], cache: &mut V3Cache) -> Vec<f32>
Batched prefill that also fills cache, so generation can continue
from it with Self::decode_step.
Returns the logits for the last position, which is what a caller
needs to sample the first new token. This is the path generation should
use for a prompt: stepping the prompt through decode_step costs one
full pass per position, where this pays the weight traffic once per
chunk.