metrale_model_engine/traits/model/logits.rs
1// SPDX-License-Identifier: MIT OR Apache-2.0
2
3//! 2026-09-26: `ModelLogits`, 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 anyhow::Result;
10use metrale_gpu_runtime::gpu::DevicePtr;
11
12/// 2026-09-26: Reading a forward pass's output: the logits buffers, device argmax and the post-norm
13/// hidden state.
14pub trait ModelLogits {
15 fn vocab_size(&self) -> usize;
16
17 /// 2026-09-25: Copy one row of logits to the host; `dst` is `vocab_size * 2` bytes for BF16
18 /// logits.
19 fn copy_logits_to_host(&self, logits_ptr: DevicePtr, dst: &mut [u8]) -> Result<()>;
20
21 /// 2026-09-25: Whether `logits_ptr` holds FP32 logits (`vocab * 4` bytes per row). Default
22 /// `false`; `TransformerModel` returns `false` too, because its `use_fp32_logits` is fixed to
23 /// `false` in `TransformerModel::new`.
24 fn logits_ptr_is_fp32(&self, _logits_ptr: DevicePtr) -> bool {
25 false
26 }
27
28 /// 2026-09-25: The device logits buffer, where a verify pass leaves its `[k, vocab]` rows.
29 fn logits_buffer_ptr(&self) -> DevicePtr;
30
31 /// 2026-09-25: Argmax of one logits row, computed on the device.
32 fn argmax_on_device(&self, logits_ptr: DevicePtr, stream: u64) -> Result<u32>;
33
34 /// 2026-09-25: Argmax of each of `n` logits rows on the device.
35 fn argmax_batch(&self, logits_ptr: DevicePtr, n: usize, stream: u64) -> Result<Vec<u32>>;
36
37 /// 2026-09-25: The post-final-norm hidden state of the last decode step.
38 fn hidden_after_norm(&self) -> DevicePtr;
39
40 /// 2026-09-25: Whether single-token decode writes FP32 logits, read from
41 /// [`Self::decode_logits_ptr`] at 4 bytes per element. Default `false`; `TransformerModel`
42 /// returns its `use_fp32_logits`, which is always `false`.
43 fn decode_logits_fp32(&self) -> bool {
44 false
45 }
46
47 /// 2026-09-25: The buffer single-token decode last wrote its logits to: FP32 when
48 /// [`Self::decode_logits_fp32`] is true, else BF16. The default panics, so a model must
49 /// override it; `TransformerModel` does.
50 fn decode_logits_ptr(&self) -> DevicePtr {
51 unreachable!(
52 "Model::decode_logits_ptr() must be overridden alongside \
53 decode_logits_fp32() — default cannot return a valid pointer."
54 )
55 }
56}