use std::path::{Path, PathBuf};
use std::time::Duration;
use crate::core::provenance::Provenance;
const DIM: &str = "\x1b[2m";
const RESET: &str = "\x1b[0m";
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum ChatTemplateSource {
GgufEmbedded,
CliOverride,
HardcodedFallback {
name: &'static str,
},
NativeEncoding {
name: &'static str,
},
None,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum TokenizerSource {
HfTokenizerJson {
path: PathBuf,
},
GgufEmbedded,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct MoeShape {
pub n_experts: u32,
pub n_experts_per_tok: u32,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct VisionProjector {
pub mmproj_path: PathBuf,
pub mmproj_sha256: Option<String>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ArchFamily {
Gemma4,
Qwen35,
Qwen3VlText,
Deepseek4,
Llama4Reserved,
}
impl ArchFamily {
pub fn as_str(&self) -> &'static str {
match self {
ArchFamily::Gemma4 => "gemma4",
ArchFamily::Qwen35 => "qwen35",
ArchFamily::Qwen3VlText => "qwen3vl-text",
ArchFamily::Deepseek4 => "deepseek4",
ArchFamily::Llama4Reserved => "llama4",
}
}
pub fn supports_mmproj(&self) -> bool {
matches!(self, ArchFamily::Gemma4 | ArchFamily::Qwen3VlText)
}
}
#[derive(Debug, Clone)]
pub struct LoadInfo {
pub model_id: String,
pub arch_str: String,
pub arch_family: ArchFamily,
pub model_path: PathBuf,
pub on_disk_bytes: u64,
pub backend_chip: String,
pub backend: &'static str,
pub n_layers: u32,
pub hidden_size: u32,
pub vocab_size: u32,
pub n_attention_heads: u32,
pub n_key_value_heads: u32,
pub head_dim: u32,
pub sliding_window: Option<u32>,
pub full_attention_interval: Option<u32>,
pub max_context_length: Option<u32>,
pub moe: Option<MoeShape>,
pub quant_label: Option<String>,
pub quant_bpw: Option<f32>,
pub tokenizer_source: TokenizerSource,
pub eos_token_ids: Vec<u32>,
pub bos_token_id: Option<u32>,
pub chat_template_source: ChatTemplateSource,
pub provenance: Provenance,
pub vision_projector: Option<VisionProjector>,
pub load_wall_clock: Duration,
pub resident_weight_bytes: Option<u64>,
pub kv_cache_budget_bytes: Option<u64>,
pub kv_spill_active: bool,
pub tq_kv_active: bool,
pub kv_bytes_per_token_override: Option<u64>,
pub kv_fixed_bytes_per_slot_override: Option<u64>,
}
impl LoadInfo {
pub fn kv_bytes_per_token(&self) -> u64 {
if let Some(exact) = self.kv_bytes_per_token_override {
return exact;
}
let n_layers = u64::from(self.n_layers);
let n_kv = u64::from(self.n_key_value_heads);
let hd = u64::from(self.head_dim);
if n_layers == 0 || n_kv == 0 || hd == 0 {
return 0;
}
n_layers
.saturating_mul(n_kv)
.saturating_mul(hd)
.saturating_mul(4)
.saturating_mul(2)
}
pub fn kv_fixed_bytes_per_slot(&self) -> u64 {
self.kv_fixed_bytes_per_slot_override.unwrap_or(0)
}
pub fn kv_bytes_for_request(&self, prompt_tokens: u32, max_tokens: u32) -> u64 {
let per_token = self.kv_bytes_per_token();
if per_token == 0 {
return 0;
}
let total_tokens = u64::from(prompt_tokens).saturating_add(u64::from(max_tokens));
total_tokens.saturating_mul(per_token)
}
}
pub fn gemma4_slot_kv_bytes_per_token(cfg: &crate::serve::config::Gemma4Config) -> u64 {
use crate::debug::investigation_env::INVESTIGATION_ENV;
use crate::serve::config::LayerType;
cfg.layer_types
.iter()
.enumerate()
.filter(|(_, kind)| matches!(kind, LayerType::Full))
.fold(0u64, |total, (layer_idx, _)| {
let nkv = cfg.num_kv_heads_for_layer(layer_idx) as u64;
let hd = cfg.head_dim_for_layer(layer_idx) as u64;
let norms = (hd / 256).max(1);
let elems = nkv.saturating_mul(hd);
let norm_bytes = nkv.saturating_mul(norms).saturating_mul(4);
let layer_bytes = if INVESTIGATION_ENV.use_dense {
let dtype_bytes = if INVESTIGATION_ENV.f16_kv { 2 } else { 4 };
elems.saturating_mul(dtype_bytes).saturating_mul(2)
} else if INVESTIGATION_ENV.tq_codebook_bits == 0 {
elems
.saturating_div(2)
.saturating_mul(2)
.saturating_add(norm_bytes.saturating_mul(2))
} else if INVESTIGATION_ENV.hybrid_kv {
let full_f16_v = std::env::var("HF2Q_FULL_F16_KV")
.ok()
.is_some_and(|value| matches!(value.as_str(), "1" | "true" | "on"));
let v_bytes = if full_f16_v {
elems.saturating_mul(2)
} else {
elems.saturating_add(norm_bytes)
};
let xlen_bytes = if std::env::var("HF2Q_DFLASH_XLEN_SDPA").as_deref() == Ok("1") {
elems.saturating_mul(4)
} else {
0
};
elems
.saturating_mul(2)
.saturating_add(v_bytes)
.saturating_add(xlen_bytes)
} else {
elems
.saturating_mul(2)
.saturating_add(norm_bytes.saturating_mul(2))
};
total.saturating_add(layer_bytes)
})
}
pub fn gemma4_fixed_kv_bytes_per_slot(cfg: &crate::serve::config::Gemma4Config) -> u64 {
use crate::debug::investigation_env::INVESTIGATION_ENV;
use crate::serve::config::LayerType;
let (live_scaffold, active_anchor) = cfg
.layer_types
.iter()
.enumerate()
.filter(|(_, kind)| matches!(kind, LayerType::Sliding))
.fold((0u64, 0u64), |(total, anchor), (layer_idx, _)| {
let nkv = cfg.num_kv_heads_for_layer(layer_idx) as u64;
let hd = cfg.head_dim_for_layer(layer_idx) as u64;
let norms = (hd / 256).max(1);
let elems = nkv.saturating_mul(hd);
let norm_bytes = nkv.saturating_mul(norms).saturating_mul(4);
let mut per_position = elems
.saturating_mul(2)
.saturating_add(norm_bytes.saturating_mul(2));
let mut active_per_position = 0u64;
if INVESTIGATION_ENV.hybrid_kv {
let full_f16_v = std::env::var("HF2Q_FULL_F16_KV")
.ok()
.is_some_and(|value| matches!(value.as_str(), "1" | "true" | "on"));
active_per_position = active_per_position
.saturating_add(elems.saturating_mul(2))
.saturating_add(if full_f16_v {
elems.saturating_mul(2)
} else {
elems.saturating_add(norm_bytes)
});
if std::env::var("HF2Q_DFLASH_XLEN_SDPA").as_deref() == Ok("1") {
active_per_position =
active_per_position.saturating_add(elems.saturating_mul(4));
}
}
if INVESTIGATION_ENV.use_dense {
let dtype_bytes = if INVESTIGATION_ENV.f16_kv { 2 } else { 4 };
active_per_position = active_per_position
.saturating_add(elems.saturating_mul(dtype_bytes).saturating_mul(2));
}
if INVESTIGATION_ENV.tq_codebook_bits == 0 {
active_per_position = active_per_position
.saturating_add(elems)
.saturating_add(norm_bytes.saturating_mul(2));
}
per_position = per_position.saturating_add(active_per_position);
let window = cfg.sliding_window as u64;
(
total.saturating_add(per_position.saturating_mul(window)),
anchor.saturating_add(active_per_position.saturating_mul(window)),
)
});
round_up_bytes(
live_scaffold.saturating_add(active_anchor.saturating_mul(2)),
16 * 1024 * 1024,
)
}
pub fn qwen35_slot_kv_bytes_per_token(
cfg: &crate::inference::models::qwen35::Qwen35Config,
tq_kv_active: bool,
) -> u64 {
use crate::inference::models::qwen35::Qwen35LayerKind;
let full_layers = cfg
.layer_types
.iter()
.filter(|kind| matches!(kind, Qwen35LayerKind::FullAttention))
.count() as u64
+ u64::from(cfg.mtp_num_hidden_layers > 0);
let nkv = u64::from(cfg.num_key_value_heads);
let hd = u64::from(cfg.head_dim);
let per_layer = if tq_kv_active {
let norms = (hd / 256).max(1);
nkv.saturating_mul(hd)
.saturating_add(nkv.saturating_mul(norms).saturating_mul(4))
.saturating_mul(2)
} else {
nkv.saturating_mul(hd).saturating_mul(4).saturating_mul(2)
};
full_layers.saturating_mul(per_layer)
}
pub fn qwen35_fixed_kv_bytes_per_slot(cfg: &crate::inference::models::qwen35::Qwen35Config) -> u64 {
use crate::inference::models::qwen35::Qwen35LayerKind;
let linear_layers = cfg
.layer_types
.iter()
.filter(|kind| matches!(kind, Qwen35LayerKind::LinearAttention))
.count() as u64;
let conv_channels = u64::from(
2 * cfg.linear_num_key_heads * cfg.linear_key_head_dim
+ cfg.linear_num_value_heads * cfg.linear_value_head_dim,
);
let conv = conv_channels
.saturating_mul(u64::from(
cfg.linear_conv_kernel_dim.saturating_sub(1).max(1),
))
.saturating_mul(4)
.saturating_mul(2);
let recurrent = u64::from(cfg.linear_key_head_dim)
.saturating_mul(u64::from(cfg.linear_value_head_dim))
.saturating_mul(u64::from(cfg.linear_num_value_heads))
.saturating_mul(4)
.saturating_mul(2);
let live_scaffold = linear_layers.saturating_mul(conv.saturating_add(recurrent));
round_up_bytes(live_scaffold.saturating_mul(2), 16 * 1024 * 1024)
}
pub fn deepseek4_fixed_kv_bytes_per_slot(
cfg: &crate::inference::models::deepseek4::Deepseek4Config,
linear_bytes_per_token: u64,
) -> u64 {
use crate::inference::models::deepseek4::cache::Deepseek4CachePlan;
let context = cfg.sliding_window.max(1) as usize;
let live_plan = match Deepseek4CachePlan::for_context(cfg, context) {
Ok(plan) => plan,
Err(_) => return 0,
};
let context_linear = (context as u64).saturating_mul(linear_bytes_per_token);
let live_fixed = live_plan.resident_bytes.saturating_sub(context_linear);
round_up_bytes(live_fixed.saturating_mul(2), 16 * 1024 * 1024)
}
fn round_up_bytes(value: u64, quantum: u64) -> u64 {
if value == 0 || quantum == 0 {
return value;
}
value
.saturating_add(quantum.saturating_sub(1))
.saturating_div(quantum)
.saturating_mul(quantum)
}
pub trait LoadInfoBuilder {
fn build_load_info(
&self,
gguf: &mlx_native::gguf::GgufFile,
load_wall_clock: std::time::Duration,
kv_cache_budget_bytes: Option<u64>,
kv_spill_active: bool,
) -> LoadInfo;
}
pub(crate) fn model_id_from_gguf(gguf: &mlx_native::gguf::GgufFile, model_path: &Path) -> String {
gguf.metadata_string("general.name")
.map(|s| s.to_string())
.unwrap_or_else(|| {
model_path
.file_stem()
.map(|s| s.to_string_lossy().into_owned())
.unwrap_or_else(|| "unknown".to_string())
})
}
pub(crate) fn arch_str_from_gguf(gguf: &mlx_native::gguf::GgufFile) -> String {
gguf.metadata_string("general.architecture")
.unwrap_or("unknown")
.to_string()
}
pub(crate) fn on_disk_bytes(path: &Path) -> u64 {
std::fs::metadata(path).map(|m| m.len()).unwrap_or(0)
}
pub(crate) fn chat_template_source(
gguf: &mlx_native::gguf::GgufFile,
fallback_name: Option<&'static str>,
) -> ChatTemplateSource {
if gguf.metadata_string("tokenizer.chat_template").is_some() {
ChatTemplateSource::GgufEmbedded
} else if let Some(name) = fallback_name {
ChatTemplateSource::HardcodedFallback { name }
} else {
ChatTemplateSource::None
}
}
fn estimate_kv_tokens(info: &LoadInfo) -> Option<u64> {
let budget = info.kv_cache_budget_bytes?;
let per_token = u64::from(info.n_layers)
.checked_mul(u64::from(info.n_key_value_heads))?
.checked_mul(u64::from(info.head_dim))?
.checked_mul(4)?;
if per_token == 0 {
return None;
}
Some(budget / per_token)
}
fn gib(bytes: u64) -> f64 {
bytes as f64 / 1024.0 / 1024.0 / 1024.0
}
fn fmt_gib(bytes: u64) -> String {
format!("{:.2} GiB", gib(bytes))
}
fn fmt_opt_u32(v: Option<u32>) -> String {
v.map(|v| v.to_string())
.unwrap_or_else(|| "none".to_string())
}
fn fmt_opt_bytes(v: Option<u64>) -> String {
v.map(fmt_gib).unwrap_or_else(|| "none".to_string())
}
fn fmt_tokenizer_source(source: &TokenizerSource) -> String {
match source {
TokenizerSource::HfTokenizerJson { path } => {
format!("hf-tokenizer-json ({})", path.display())
}
TokenizerSource::GgufEmbedded => "gguf-embedded (<= mirrors llama-vocab.cpp)".to_string(),
}
}
fn fmt_chat_template_source(source: &ChatTemplateSource) -> String {
match source {
ChatTemplateSource::GgufEmbedded => "gguf-embedded".to_string(),
ChatTemplateSource::CliOverride => "cli-override".to_string(),
ChatTemplateSource::HardcodedFallback { name } => format!("hardcoded-fallback ({name})"),
ChatTemplateSource::NativeEncoding { name } => format!("native-encoding ({name})"),
ChatTemplateSource::None => "none".to_string(),
}
}
fn fmt_moe(moe: Option<MoeShape>) -> String {
moe.map(|m| format!("{} experts/{} active", m.n_experts, m.n_experts_per_tok))
.unwrap_or_else(|| "none".to_string())
}
fn fmt_quant(info: &LoadInfo) -> String {
let label = info.quant_label.as_deref().unwrap_or("none");
let bpw = info
.quant_bpw
.map(|v| format!("~{v:.2} bpw"))
.unwrap_or_else(|| "none".to_string());
let resident = fmt_opt_bytes(info.resident_weight_bytes);
if label == "none" {
format!("none dominant, {bpw}, mlx-native resident {resident}")
} else {
format!("{label} dominant, {bpw}, mlx-native resident {resident}")
}
}
fn fmt_provenance(provenance: &Provenance) -> String {
match provenance {
Provenance::External => "external".to_string(),
Provenance::Hf2q {
producer_version,
source_sha256,
..
} => {
let prefix: String = source_sha256.chars().take(4).collect();
format!("hf2q (producer {producer_version}, source_sha {prefix}…)")
}
}
}
fn fmt_vision(arch: ArchFamily, vision: &Option<VisionProjector>) -> String {
match vision {
Some(v) => {
let sha = v.mmproj_sha256.as_deref().unwrap_or("none");
format!("{} (sha256 {sha})", v.mmproj_path.display())
}
None if arch.supports_mmproj() => {
"mmproj-required (no mmproj loaded; pass --mmproj)".to_string()
}
None => "n/a (text-only arch)".to_string(),
}
}
fn fmt_kv_budget(info: &LoadInfo) -> String {
match info.kv_cache_budget_bytes {
Some(bytes)
if info.kv_bytes_per_token_override.is_some()
|| info.kv_fixed_bytes_per_slot_override.is_some() =>
{
format!("{} shared", fmt_gib(bytes))
}
Some(bytes) => match estimate_kv_tokens(info) {
Some(tokens) => format!("{} (~{} tokens)", fmt_gib(bytes), tokens),
None => fmt_gib(bytes),
},
None => "none".to_string(),
}
}
pub fn print_banner<W: std::io::Write>(
info: &LoadInfo,
w: &mut W,
tty: bool,
) -> std::io::Result<()> {
let (d, r) = if tty { (DIM, RESET) } else { ("", "") };
writeln!(
w,
"{d}hf2q load: backend = {} ({}){r}",
info.backend,
crate::serve::header::short_chip_label(&info.backend_chip)
)?;
writeln!(
w,
"{d}hf2q load: model = {} (arch = {}, family = {}){r}",
info.model_id,
info.arch_str,
info.arch_family.as_str()
)?;
writeln!(
w,
"{d}hf2q load: source = {} ({} on disk){r}",
info.model_path.display(),
fmt_gib(info.on_disk_bytes)
)?;
writeln!(
w,
"{d}hf2q load: layout = {} layers, {} heads ({} kv), head_dim={}, hidden={}, vocab={}{r}",
info.n_layers,
info.n_attention_heads,
info.n_key_value_heads,
info.head_dim,
info.hidden_size,
info.vocab_size
)?;
writeln!(
w,
"{d}hf2q load: features = sliding_window={}, full_attn_every={}, moe={}{r}",
fmt_opt_u32(info.sliding_window),
fmt_opt_u32(info.full_attention_interval),
fmt_moe(info.moe)
)?;
writeln!(w, "{d}hf2q load: quant = {}{r}", fmt_quant(info))?;
writeln!(
w,
"{d}hf2q load: max_ctx_train = {}, kv_budget = {}{r}",
fmt_opt_u32(info.max_context_length),
fmt_kv_budget(info)
)?;
writeln!(
w,
"{d}hf2q load: tokenizer = {}{r}",
fmt_tokenizer_source(&info.tokenizer_source)
)?;
writeln!(
w,
"{d}hf2q load: chat_template = {}{r}",
fmt_chat_template_source(&info.chat_template_source)
)?;
writeln!(
w,
"{d}hf2q load: provenance = {}{r}",
fmt_provenance(&info.provenance)
)?;
writeln!(
w,
"{d}hf2q load: vision = {}{r}",
fmt_vision(info.arch_family, &info.vision_projector)
)?;
writeln!(
w,
"{d}hf2q load: kv_spill = {}{r}",
if info.kv_spill_active {
"active"
} else {
"inactive"
}
)?;
let tq_kv_text: &str = if info.tq_kv_active {
match info.arch_family {
ArchFamily::Qwen35 => "active (8-bit Lloyd-Max + D1 SRHT, ADR-027 Phase B; F32 K/V dropped at alloc — 3.94× per-slot KV savings)",
ArchFamily::Gemma4 => "active (8-bit Lloyd-Max + D1 SRHT, ADR-007 Path C; production default; HF2Q_USE_DENSE=1 to opt out)",
_ => "active (8-bit Lloyd-Max + D1 SRHT)",
}
} else {
"inactive"
};
writeln!(w, "{d}hf2q load: tq_kv = {}{r}", tq_kv_text)?;
writeln!(
w,
"{d}hf2q load: ready in {:.2} s{r}",
info.load_wall_clock.as_secs_f64()
)?;
w.flush()
}
pub fn emit_tracing(info: &LoadInfo) {
tracing::info!(model_id = %info.model_id);
tracing::info!(arch_str = %info.arch_str);
tracing::info!(arch_family = %info.arch_family.as_str());
tracing::info!(model_path = %info.model_path.display());
tracing::info!(on_disk_bytes = info.on_disk_bytes);
tracing::info!(backend_chip = %info.backend_chip, backend = info.backend);
tracing::info!(
n_layers = info.n_layers,
hidden_size = info.hidden_size,
vocab_size = info.vocab_size,
n_attention_heads = info.n_attention_heads,
n_key_value_heads = info.n_key_value_heads,
head_dim = info.head_dim
);
tracing::info!(
sliding_window = ?info.sliding_window,
full_attention_interval = ?info.full_attention_interval,
max_context_length = ?info.max_context_length,
moe = ?info.moe
);
tracing::info!(quant_label = ?info.quant_label, quant_bpw = ?info.quant_bpw);
tracing::info!(
tokenizer_source = ?info.tokenizer_source,
eos_token_ids = ?info.eos_token_ids,
bos_token_id = ?info.bos_token_id,
chat_template_source = ?info.chat_template_source
);
tracing::info!(provenance = ?info.provenance);
tracing::info!(vision_projector = ?info.vision_projector);
tracing::info!(
load_wall_clock = ?info.load_wall_clock,
resident_weight_bytes = ?info.resident_weight_bytes,
kv_cache_budget_bytes = ?info.kv_cache_budget_bytes,
kv_spill_active = info.kv_spill_active
);
}
pub fn infer_quant_label(gguf: &mlx_native::gguf::GgufFile) -> Option<String> {
if let Some(profile) =
gguf.metadata_string(crate::quantize::ggml_quants::DEEPSEEK4_AGENTIC_Q2_METADATA_KEY)
{
return Some(profile.to_string());
}
use mlx_native::GgmlType;
use std::collections::HashMap;
let mut histogram: HashMap<&'static str, usize> = HashMap::new();
for name in gguf.tensor_names() {
let Some(info) = gguf.tensor_info(name) else {
continue;
};
if matches!(info.ggml_type, GgmlType::F32 | GgmlType::F16) {
continue;
}
let label = match info.ggml_type {
GgmlType::F32 => "F32",
GgmlType::F16 => "F16",
GgmlType::Q4_0 => "Q4_0",
GgmlType::Q8_0 => "Q8_0",
GgmlType::Q2_K => "Q2_K",
GgmlType::Q3_K => "Q3_K",
GgmlType::Q4_K => "Q4_K",
GgmlType::Q5_K => "Q5_K",
GgmlType::Q6_K => "Q6_K",
GgmlType::I16 => "I16",
GgmlType::I32 => "I32",
GgmlType::Q5_1 => "Q5_1",
GgmlType::IQ4_NL => "IQ4_NL",
GgmlType::IQ4_XS => "IQ4_XS",
};
*histogram.entry(label).or_insert(0) += 1;
}
histogram
.into_iter()
.max_by_key(|(_, n)| *n)
.map(|(k, _)| k.to_string())
}
pub fn compute_bpw(gguf: &mlx_native::gguf::GgufFile) -> Option<f32> {
use mlx_native::GgmlType;
let mut total_elements: u128 = 0;
let mut total_bytes: u128 = 0;
for name in gguf.tensor_names() {
let Some(info) = gguf.tensor_info(name) else {
continue;
};
if matches!(info.ggml_type, GgmlType::F32 | GgmlType::F16) {
continue;
}
let n_elements: usize = info.shape.iter().product();
if n_elements == 0 {
continue;
}
let block_values = info.ggml_type.block_values() as usize;
let block_bytes = info.ggml_type.block_bytes() as usize;
if block_values == 0 {
return None;
}
if n_elements % block_values != 0 {
return None;
}
let block_count = n_elements / block_values;
let tensor_bytes = block_count.checked_mul(block_bytes)?;
total_elements = total_elements.checked_add(n_elements as u128)?;
total_bytes = total_bytes.checked_add(tensor_bytes as u128)?;
}
if total_elements == 0 {
return None;
}
Some((total_bytes as f64 * 8.0 / total_elements as f64) as f32)
}
#[cfg(test)]
mod tests {
use super::*;
use std::fs::File;
use std::io::Write;
use std::path::Path;
const GGML_TYPE_F32: u32 = 0;
const GGML_TYPE_F16: u32 = 1;
const GGML_TYPE_Q4_K: u32 = 12;
const GGML_TYPE_Q6_K: u32 = 14;
const GGML_TYPE_Q8_0: u32 = 8;
const BLOCK_VALUES_Q4_K: usize = 256;
const BLOCK_BYTES_Q4_K: usize = 144;
const BLOCK_VALUES_Q6_K: usize = 256;
const BLOCK_BYTES_Q6_K: usize = 210;
const BLOCK_VALUES_Q8_0: usize = 32;
const BLOCK_BYTES_Q8_0: usize = 34;
struct TensorSpec {
name: &'static str,
shape: Vec<usize>,
ggml_type_id: u32,
byte_len: usize,
}
enum KvSpec {
String(&'static str, &'static str),
U32(&'static str, u32),
}
fn write_gguf_string(buf: &mut Vec<u8>, s: &str) {
buf.extend_from_slice(&(s.len() as u64).to_le_bytes());
buf.extend_from_slice(s.as_bytes());
}
fn write_synthetic_gguf(path: &Path, tensors: &[TensorSpec]) {
write_synthetic_gguf_with_metadata(path, &[], tensors);
}
fn write_synthetic_gguf_with_metadata(path: &Path, kvs: &[KvSpec], tensors: &[TensorSpec]) {
let mut buf: Vec<u8> = Vec::new();
buf.extend_from_slice(b"GGUF");
buf.extend_from_slice(&3u32.to_le_bytes());
buf.extend_from_slice(&(tensors.len() as u64).to_le_bytes());
buf.extend_from_slice(&(kvs.len() as u64).to_le_bytes());
for kv in kvs {
match kv {
KvSpec::String(key, value) => {
write_gguf_string(&mut buf, key);
buf.extend_from_slice(&8u32.to_le_bytes());
write_gguf_string(&mut buf, value);
}
KvSpec::U32(key, value) => {
write_gguf_string(&mut buf, key);
buf.extend_from_slice(&4u32.to_le_bytes());
buf.extend_from_slice(&value.to_le_bytes());
}
}
}
let mut data_offset: u64 = 0;
for t in tensors {
write_gguf_string(&mut buf, t.name);
buf.extend_from_slice(&(t.shape.len() as u32).to_le_bytes());
for &d in &t.shape {
buf.extend_from_slice(&(d as u64).to_le_bytes());
}
buf.extend_from_slice(&t.ggml_type_id.to_le_bytes());
buf.extend_from_slice(&data_offset.to_le_bytes());
data_offset += t.byte_len as u64;
}
while buf.len() % 32 != 0 {
buf.push(0);
}
let total_data: usize = tensors.iter().map(|t| t.byte_len).sum();
buf.extend(std::iter::repeat(0u8).take(total_data));
let mut f = File::create(path).expect("create synthetic gguf");
f.write_all(&buf).expect("write synthetic gguf");
f.flush().expect("flush synthetic gguf");
}
fn tmp_path(label: &str) -> std::path::PathBuf {
std::env::temp_dir().join(format!(
"load_info_test_{}_{}_{}.gguf",
label,
std::process::id(),
std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.map(|d| d.as_nanos())
.unwrap_or(0),
))
}
#[test]
fn arch_family_as_str_is_stable() {
assert_eq!(ArchFamily::Gemma4.as_str(), "gemma4");
assert_eq!(ArchFamily::Qwen35.as_str(), "qwen35");
assert_eq!(ArchFamily::Llama4Reserved.as_str(), "llama4");
}
#[test]
fn infer_quant_label_q4k_dominant() {
let path = tmp_path("q4k_dominant");
let tensors = vec![
TensorSpec {
name: "blk.0.attn_q.weight",
shape: vec![BLOCK_VALUES_Q4_K, 4],
ggml_type_id: GGML_TYPE_Q4_K,
byte_len: 4 * BLOCK_BYTES_Q4_K,
},
TensorSpec {
name: "blk.0.attn_k.weight",
shape: vec![BLOCK_VALUES_Q4_K, 4],
ggml_type_id: GGML_TYPE_Q4_K,
byte_len: 4 * BLOCK_BYTES_Q4_K,
},
TensorSpec {
name: "blk.0.attn_v.weight",
shape: vec![BLOCK_VALUES_Q4_K, 4],
ggml_type_id: GGML_TYPE_Q4_K,
byte_len: 4 * BLOCK_BYTES_Q4_K,
},
TensorSpec {
name: "output.weight",
shape: vec![BLOCK_VALUES_Q6_K, 4],
ggml_type_id: GGML_TYPE_Q6_K,
byte_len: 4 * BLOCK_BYTES_Q6_K,
},
];
write_synthetic_gguf(&path, &tensors);
let gguf = mlx_native::gguf::GgufFile::open(&path).expect("open synthetic gguf");
assert_eq!(infer_quant_label(&gguf), Some("Q4_K".to_string()));
let _ = std::fs::remove_file(&path);
}
#[test]
fn infer_quant_label_prefers_explicit_mixed_profile() {
let path = tmp_path("explicit_mixed_profile");
let tensors = vec![TensorSpec {
name: "blk.0.ffn_down_exps.weight",
shape: vec![BLOCK_VALUES_Q4_K, 4],
ggml_type_id: GGML_TYPE_Q4_K,
byte_len: 4 * BLOCK_BYTES_Q4_K,
}];
write_synthetic_gguf_with_metadata(
&path,
&[KvSpec::String(
crate::quantize::ggml_quants::DEEPSEEK4_AGENTIC_Q2_METADATA_KEY,
crate::quantize::ggml_quants::DEEPSEEK4_AGENTIC_Q2_NAME,
)],
&tensors,
);
let gguf = mlx_native::gguf::GgufFile::open(&path).expect("open synthetic gguf");
assert_eq!(
infer_quant_label(&gguf),
Some(crate::quantize::ggml_quants::DEEPSEEK4_AGENTIC_Q2_NAME.to_string())
);
let _ = std::fs::remove_file(&path);
}
#[test]
fn infer_quant_label_returns_none_for_pure_fp() {
let path = tmp_path("pure_fp");
let tensors = vec![
TensorSpec {
name: "norm.weight",
shape: vec![64],
ggml_type_id: GGML_TYPE_F32,
byte_len: 64 * 4,
},
TensorSpec {
name: "output_norm.weight",
shape: vec![64],
ggml_type_id: GGML_TYPE_F16,
byte_len: 64 * 2,
},
];
write_synthetic_gguf(&path, &tensors);
let gguf = mlx_native::gguf::GgufFile::open(&path).expect("open synthetic gguf");
assert_eq!(infer_quant_label(&gguf), None);
let _ = std::fs::remove_file(&path);
}
#[test]
fn infer_quant_label_matches_legacy_body() {
fn legacy(gguf: &mlx_native::gguf::GgufFile) -> Option<String> {
use mlx_native::GgmlType;
use std::collections::HashMap;
let mut histogram: HashMap<&'static str, usize> = HashMap::new();
for name in gguf.tensor_names() {
let Some(info) = gguf.tensor_info(name) else {
continue;
};
if matches!(info.ggml_type, GgmlType::F32 | GgmlType::F16) {
continue;
}
let label = match info.ggml_type {
GgmlType::F32 => "F32",
GgmlType::F16 => "F16",
GgmlType::Q4_0 => "Q4_0",
GgmlType::Q8_0 => "Q8_0",
GgmlType::Q2_K => "Q2_K",
GgmlType::Q3_K => "Q3_K",
GgmlType::Q4_K => "Q4_K",
GgmlType::Q5_K => "Q5_K",
GgmlType::Q6_K => "Q6_K",
GgmlType::I16 => "I16",
GgmlType::I32 => "I32",
GgmlType::Q5_1 => "Q5_1",
GgmlType::IQ4_NL => "IQ4_NL",
GgmlType::IQ4_XS => "IQ4_XS",
};
*histogram.entry(label).or_insert(0) += 1;
}
histogram
.into_iter()
.max_by_key(|(_, n)| *n)
.map(|(k, _)| k.to_string())
}
let path = tmp_path("legacy_match");
let tensors = vec![
TensorSpec {
name: "a",
shape: vec![BLOCK_VALUES_Q4_K, 2],
ggml_type_id: GGML_TYPE_Q4_K,
byte_len: 2 * BLOCK_BYTES_Q4_K,
},
TensorSpec {
name: "b",
shape: vec![BLOCK_VALUES_Q4_K],
ggml_type_id: GGML_TYPE_Q4_K,
byte_len: BLOCK_BYTES_Q4_K,
},
TensorSpec {
name: "c",
shape: vec![BLOCK_VALUES_Q6_K],
ggml_type_id: GGML_TYPE_Q6_K,
byte_len: BLOCK_BYTES_Q6_K,
},
TensorSpec {
name: "d",
shape: vec![BLOCK_VALUES_Q8_0, 4],
ggml_type_id: GGML_TYPE_Q8_0,
byte_len: 4 * BLOCK_BYTES_Q8_0,
},
TensorSpec {
name: "norm",
shape: vec![32],
ggml_type_id: GGML_TYPE_F32,
byte_len: 32 * 4,
},
];
write_synthetic_gguf(&path, &tensors);
let gguf = mlx_native::gguf::GgufFile::open(&path).expect("open synthetic gguf");
assert_eq!(infer_quant_label(&gguf), legacy(&gguf));
assert_eq!(infer_quant_label(&gguf), Some("Q4_K".to_string()));
let _ = std::fs::remove_file(&path);
}
#[test]
fn compute_bpw_pure_q4k() {
let path = tmp_path("pure_q4k");
let tensors = vec![TensorSpec {
name: "w",
shape: vec![BLOCK_VALUES_Q4_K],
ggml_type_id: GGML_TYPE_Q4_K,
byte_len: BLOCK_BYTES_Q4_K,
}];
write_synthetic_gguf(&path, &tensors);
let gguf = mlx_native::gguf::GgufFile::open(&path).expect("open synthetic gguf");
let bpw = compute_bpw(&gguf).expect("non-empty quant set");
assert!(
(bpw - 4.5).abs() < 0.01,
"expected ~4.5 bpw for pure Q4_K, got {bpw}"
);
let _ = std::fs::remove_file(&path);
}
#[test]
fn compute_bpw_pure_q6k() {
let path = tmp_path("pure_q6k");
let tensors = vec![TensorSpec {
name: "w",
shape: vec![BLOCK_VALUES_Q6_K],
ggml_type_id: GGML_TYPE_Q6_K,
byte_len: BLOCK_BYTES_Q6_K,
}];
write_synthetic_gguf(&path, &tensors);
let gguf = mlx_native::gguf::GgufFile::open(&path).expect("open synthetic gguf");
let bpw = compute_bpw(&gguf).expect("non-empty quant set");
assert!(
(bpw - 6.5625).abs() < 0.01,
"expected ~6.5625 bpw for pure Q6_K, got {bpw}"
);
let _ = std::fs::remove_file(&path);
}
#[test]
fn compute_bpw_mixed_types() {
let path = tmp_path("mixed");
let tensors = vec![
TensorSpec {
name: "q4k",
shape: vec![BLOCK_VALUES_Q4_K],
ggml_type_id: GGML_TYPE_Q4_K,
byte_len: BLOCK_BYTES_Q4_K,
},
TensorSpec {
name: "q8_0",
shape: vec![BLOCK_VALUES_Q8_0],
ggml_type_id: GGML_TYPE_Q8_0,
byte_len: BLOCK_BYTES_Q8_0,
},
];
write_synthetic_gguf(&path, &tensors);
let gguf = mlx_native::gguf::GgufFile::open(&path).expect("open synthetic gguf");
let bpw = compute_bpw(&gguf).expect("non-empty quant set");
let expected = (178.0 * 8.0) / 288.0; assert!(
(bpw - expected).abs() / expected < 0.05,
"expected ~{expected:.4} bpw, got {bpw}"
);
let _ = std::fs::remove_file(&path);
}
#[test]
fn compute_bpw_returns_none_for_no_quant_tensors() {
let path = tmp_path("no_quant");
let tensors = vec![
TensorSpec {
name: "norm.weight",
shape: vec![64],
ggml_type_id: GGML_TYPE_F32,
byte_len: 64 * 4,
},
TensorSpec {
name: "embd.weight",
shape: vec![32, 4],
ggml_type_id: GGML_TYPE_F16,
byte_len: 128 * 2,
},
];
write_synthetic_gguf(&path, &tensors);
let gguf = mlx_native::gguf::GgufFile::open(&path).expect("open synthetic gguf");
assert_eq!(compute_bpw(&gguf), None);
let _ = std::fs::remove_file(&path);
}
#[test]
fn load_info_struct_compiles_and_clones() {
let info = LoadInfo {
model_id: "test-model".to_string(),
arch_str: "qwen35".to_string(),
arch_family: ArchFamily::Qwen35,
model_path: PathBuf::from("/tmp/test.gguf"),
on_disk_bytes: 1024,
backend_chip: "Apple M5 Max".to_string(),
backend: "mlx-native",
n_layers: 64,
hidden_size: 4096,
vocab_size: 151_936,
n_attention_heads: 16,
n_key_value_heads: 4,
head_dim: 128,
sliding_window: None,
full_attention_interval: Some(4),
max_context_length: Some(262_144),
moe: Some(MoeShape {
n_experts: 128,
n_experts_per_tok: 8,
}),
quant_label: Some("Q4_K".to_string()),
quant_bpw: Some(4.55),
tokenizer_source: TokenizerSource::GgufEmbedded,
eos_token_ids: vec![151_643, 151_645],
bos_token_id: None,
chat_template_source: ChatTemplateSource::GgufEmbedded,
provenance: Provenance::External,
vision_projector: None,
load_wall_clock: Duration::from_secs_f64(6.84),
resident_weight_bytes: Some(16 * 1024 * 1024 * 1024),
kv_cache_budget_bytes: Some(4 * 1024 * 1024 * 1024),
kv_spill_active: false,
tq_kv_active: false,
kv_bytes_per_token_override: None,
kv_fixed_bytes_per_slot_override: None,
};
let cloned = info.clone();
assert_eq!(cloned.model_id, "test-model");
assert_eq!(cloned.arch_family.as_str(), "qwen35");
let dbg = format!("{cloned:?}");
assert!(dbg.contains("test-model"));
}
fn golden_qwen35moe_info() -> LoadInfo {
LoadInfo {
model_id: "<model_id>".to_string(),
arch_str: "qwen35moe".to_string(),
arch_family: ArchFamily::Qwen35,
model_path: PathBuf::from("<on-disk path>"),
on_disk_bytes: (29.83_f64 * 1024.0 * 1024.0 * 1024.0).round() as u64,
backend_chip: "Apple M5 Max".to_string(),
backend: "mlx-native",
n_layers: 64,
hidden_size: 4096,
vocab_size: 151_936,
n_attention_heads: 16,
n_key_value_heads: 4,
head_dim: 128,
sliding_window: None,
full_attention_interval: Some(4),
max_context_length: Some(262_144),
moe: Some(MoeShape {
n_experts: 128,
n_experts_per_tok: 8,
}),
quant_label: Some("Q4_K".to_string()),
quant_bpw: Some(4.55),
tokenizer_source: TokenizerSource::GgufEmbedded,
eos_token_ids: vec![151_645],
bos_token_id: None,
chat_template_source: ChatTemplateSource::GgufEmbedded,
provenance: Provenance::Hf2q {
producer_version: "hf2q 0.1.0".to_string(),
source_sha256: "7f3abc".to_string(),
mmproj_sha256: None,
},
vision_projector: None,
load_wall_clock: Duration::from_secs_f64(6.84),
resident_weight_bytes: Some((16.42_f64 * 1024.0 * 1024.0 * 1024.0).round() as u64),
kv_cache_budget_bytes: Some(4 * 1024 * 1024 * 1024),
kv_spill_active: false,
tq_kv_active: false,
kv_bytes_per_token_override: None,
kv_fixed_bytes_per_slot_override: None,
}
}
#[test]
fn print_banner_golden_qwen35moe() {
let info = golden_qwen35moe_info();
let mut buf = Vec::new();
print_banner(&info, &mut buf, false).expect("print banner");
let got = String::from_utf8(buf).expect("utf8");
assert_eq!(
got,
"hf2q load: backend = mlx-native (M5 Max)\n\
hf2q load: model = <model_id> (arch = qwen35moe, family = qwen35)\n\
hf2q load: source = <on-disk path> (29.83 GiB on disk)\n\
hf2q load: layout = 64 layers, 16 heads (4 kv), head_dim=128, hidden=4096, vocab=151936\n\
hf2q load: features = sliding_window=none, full_attn_every=4, moe=128 experts/8 active\n\
hf2q load: quant = Q4_K dominant, ~4.55 bpw, mlx-native resident 16.42 GiB\n\
hf2q load: max_ctx_train = 262144, kv_budget = 4.00 GiB (~32768 tokens)\n\
hf2q load: tokenizer = gguf-embedded (<= mirrors llama-vocab.cpp)\n\
hf2q load: chat_template = gguf-embedded\n\
hf2q load: provenance = hf2q (producer hf2q 0.1.0, source_sha 7f3a…)\n\
hf2q load: vision = n/a (text-only arch)\n\
hf2q load: kv_spill = inactive\n\
hf2q load: tq_kv = inactive\n\
hf2q load: ready in 6.84 s\n"
);
}
#[test]
fn print_banner_handles_absent_optional_fields() {
let mut info = golden_qwen35moe_info();
info.sliding_window = None;
info.full_attention_interval = None;
info.max_context_length = None;
info.moe = None;
info.quant_label = None;
info.quant_bpw = None;
info.resident_weight_bytes = None;
info.kv_cache_budget_bytes = None;
info.chat_template_source = ChatTemplateSource::None;
info.provenance = Provenance::External;
let mut buf = Vec::new();
print_banner(&info, &mut buf, false).expect("print banner");
let got = String::from_utf8(buf).expect("utf8");
assert!(got.contains("sliding_window=none, full_attn_every=none, moe=none"));
assert!(got.contains("quant = none dominant, none, mlx-native resident none"));
assert!(got.contains("max_ctx_train = none, kv_budget = none"));
assert!(got.contains("chat_template = none"));
assert!(got.contains("provenance = external"));
assert!(got.contains("vision = n/a (text-only arch)"));
}
#[test]
fn load_info_builder_qwen35_smoke() {
use crate::inference::models::qwen35::model::Qwen35Model;
use crate::inference::models::qwen35::{
default_layer_types, Qwen35Config, Qwen35MoeConfig, Qwen35Variant,
};
use crate::serve::api::engine_qwen35::{HybridPromptCache, Qwen35LoadedModel};
let path = tmp_path("qwen35_builder");
write_synthetic_gguf_with_metadata(
&path,
&[
KvSpec::String("general.architecture", "qwen35moe"),
KvSpec::U32("tokenizer.ggml.bos_token_id", 151_643),
KvSpec::String("tokenizer.chat_template", "{{ messages }}"),
],
&[TensorSpec {
name: "blk.0.ffn_gate_exps.weight",
shape: vec![BLOCK_VALUES_Q4_K],
ggml_type_id: GGML_TYPE_Q4_K,
byte_len: BLOCK_BYTES_Q4_K,
}],
);
let gguf = mlx_native::gguf::GgufFile::open(&path).expect("open synthetic gguf");
let cfg = Qwen35Config {
variant: Qwen35Variant::Moe,
hidden_size: 64,
num_hidden_layers: 4,
num_attention_heads: 8,
num_key_value_heads: 2,
head_dim: 16,
linear_num_key_heads: 2,
linear_num_value_heads: 2,
linear_key_head_dim: 16,
linear_value_head_dim: 16,
linear_conv_kernel_dim: 4,
full_attention_interval: 4,
layer_types: default_layer_types(4, 4),
partial_rotary_factor: 0.25,
rope_theta: 1e7,
rotary_dim: 4,
mrope_section: [1, 1, 0, 0],
mrope_interleaved: true,
rms_norm_eps: 1e-6,
max_position_embeddings: 1024,
vocab_size: 256,
attn_output_gate: true,
mtp_num_hidden_layers: 0,
mtp_use_dedicated_embeddings: true,
intermediate_size: None,
moe: Some(Qwen35MoeConfig {
moe_intermediate_size: 16,
num_experts: 4,
num_experts_per_tok: 2,
shared_expert_intermediate_size: 16,
}),
};
let loaded = Qwen35LoadedModel {
model: Qwen35Model::empty_from_cfg(cfg),
tokenizer: tokenizers::Tokenizer::new(tokenizers::models::bpe::BPE::default()),
chat_template: "{{ messages }}".to_string(),
model_id: "qwen-id".to_string(),
model_path: path.clone(),
eos_token_ids: vec![151_645],
hidden_size: 64,
vocab_size: 256,
context_length: Some(1024),
quant_type: Some("Q4_K".to_string()),
load_duration: Duration::from_millis(7),
provenance: Provenance::External,
prompt_cache: HybridPromptCache::new(),
lcp_registry: crate::serve::kv_persist::lcp_registry::LcpRegistry::new(1),
kv_metrics_sink: None,
disk_persistor: None,
lcp_hydrated_for_cfg: std::collections::HashSet::new(),
tq_kv_active: false,
persistent_kv_cache: None,
};
let info = loaded.build_load_info(
&gguf,
Duration::from_millis(7),
Some(4 * 1024 * 1024),
false,
);
assert_eq!(info.model_id, "qwen-id");
assert_eq!(info.arch_str, "qwen35moe");
assert_eq!(info.arch_family, ArchFamily::Qwen35);
assert_eq!(info.model_path, path);
assert!(info.on_disk_bytes > 0);
assert_eq!(info.n_layers, 4);
assert_eq!(info.hidden_size, 64);
assert_eq!(info.vocab_size, 256);
assert_eq!(info.n_attention_heads, 8);
assert_eq!(info.n_key_value_heads, 2);
assert_eq!(info.head_dim, 16);
assert_eq!(info.sliding_window, None);
assert_eq!(info.full_attention_interval, Some(4));
assert_eq!(info.max_context_length, Some(1024));
assert_eq!(
info.moe,
Some(MoeShape {
n_experts: 4,
n_experts_per_tok: 2
})
);
assert_eq!(info.quant_label, Some("Q4_K".to_string()));
assert_eq!(info.quant_bpw, Some(4.5));
assert_eq!(info.tokenizer_source, TokenizerSource::GgufEmbedded);
assert_eq!(info.eos_token_ids, vec![151_645]);
assert_eq!(info.bos_token_id, Some(151_643));
assert_eq!(info.chat_template_source, ChatTemplateSource::GgufEmbedded);
assert_eq!(info.provenance, Provenance::External);
assert_eq!(info.vision_projector, None);
assert_eq!(info.load_wall_clock, Duration::from_millis(7));
assert_eq!(info.resident_weight_bytes, None);
assert_eq!(info.kv_cache_budget_bytes, Some(4 * 1024 * 1024));
assert!(!info.kv_spill_active);
let _ = std::fs::remove_file(&path);
}
#[test]
fn load_info_builder_gemma_smoke() {
let path = tmp_path("gemma_builder");
write_synthetic_gguf_with_metadata(
&path,
&[
KvSpec::String("general.architecture", "gemma4"),
KvSpec::U32("tokenizer.ggml.bos_token_id", 2),
],
&[TensorSpec {
name: "blk.0.attn_q.weight",
shape: vec![BLOCK_VALUES_Q6_K],
ggml_type_id: GGML_TYPE_Q6_K,
byte_len: BLOCK_BYTES_Q6_K,
}],
);
let gguf = mlx_native::gguf::GgufFile::open(&path).expect("open synthetic gguf");
assert_eq!(arch_str_from_gguf(&gguf), "gemma4");
assert_eq!(compute_bpw(&gguf), Some(6.5625));
assert_eq!(gguf.metadata_u32("tokenizer.ggml.bos_token_id"), Some(2));
let info = LoadInfo {
model_id: "gemma-id".to_string(),
arch_str: arch_str_from_gguf(&gguf),
arch_family: ArchFamily::Gemma4,
model_path: PathBuf::from("gemma-id"),
on_disk_bytes: 0,
backend_chip: "Apple M5 Max".to_string(),
backend: "mlx-native",
n_layers: 2,
hidden_size: 32,
vocab_size: 128,
n_attention_heads: 4,
n_key_value_heads: 2,
head_dim: 8,
sliding_window: Some(1024),
full_attention_interval: None,
max_context_length: Some(4096),
moe: Some(MoeShape {
n_experts: 8,
n_experts_per_tok: 2,
}),
quant_label: infer_quant_label(&gguf),
quant_bpw: compute_bpw(&gguf),
tokenizer_source: TokenizerSource::HfTokenizerJson {
path: PathBuf::from("tokenizer.json"),
},
eos_token_ids: vec![1, 106],
bos_token_id: gguf.metadata_u32("tokenizer.ggml.bos_token_id"),
chat_template_source: chat_template_source(
&gguf,
Some("FALLBACK_GEMMA4_API_CHAT_TEMPLATE"),
),
provenance: Provenance::External,
vision_projector: None,
load_wall_clock: Duration::from_millis(12),
resident_weight_bytes: None,
kv_cache_budget_bytes: None,
kv_spill_active: false,
tq_kv_active: false,
kv_bytes_per_token_override: None,
kv_fixed_bytes_per_slot_override: None,
};
assert_eq!(info.arch_family, ArchFamily::Gemma4);
assert_eq!(info.quant_label, Some("Q6_K".to_string()));
assert!(matches!(
info.chat_template_source,
ChatTemplateSource::HardcodedFallback { name }
if name == "FALLBACK_GEMMA4_API_CHAT_TEMPLATE"
));
let _ = std::fs::remove_file(&path);
}
#[derive(Clone, Default)]
struct RecordingLayer {
events: std::sync::Arc<std::sync::Mutex<Vec<Vec<String>>>>,
}
struct FieldNameVisitor<'a> {
names: &'a mut Vec<String>,
}
impl tracing::field::Visit for FieldNameVisitor<'_> {
fn record_debug(&mut self, field: &tracing::field::Field, _value: &dyn std::fmt::Debug) {
self.names.push(field.name().to_string());
}
}
impl<S> tracing_subscriber::Layer<S> for RecordingLayer
where
S: tracing::Subscriber,
{
fn on_event(
&self,
event: &tracing::Event<'_>,
_ctx: tracing_subscriber::layer::Context<'_, S>,
) {
let mut names = Vec::new();
event.record(&mut FieldNameVisitor { names: &mut names });
self.events.lock().expect("events lock").push(names);
}
}
fn capture_emit_tracing(info: &LoadInfo) -> Vec<Vec<String>> {
use tracing_subscriber::prelude::*;
let layer = RecordingLayer::default();
let events = layer.events.clone();
let subscriber = tracing_subscriber::registry().with(layer);
tracing::subscriber::with_default(subscriber, || emit_tracing(info));
let captured = events.lock().expect("events lock").clone();
captured
}
#[test]
fn emit_tracing_emits_at_least_10_events() {
let info = golden_qwen35moe_info();
let events = capture_emit_tracing(&info);
assert!(
events.len() >= 10,
"expected at least 10 tracing events, got {}",
events.len()
);
}
#[test]
fn emit_tracing_field_names_match_load_info() {
let info = golden_qwen35moe_info();
let events = capture_emit_tracing(&info);
let names: std::collections::BTreeSet<String> = events.into_iter().flatten().collect();
let expected = [
"model_id",
"arch_str",
"arch_family",
"model_path",
"on_disk_bytes",
"backend_chip",
"backend",
"n_layers",
"hidden_size",
"vocab_size",
"n_attention_heads",
"n_key_value_heads",
"head_dim",
"sliding_window",
"full_attention_interval",
"max_context_length",
"moe",
"quant_label",
"quant_bpw",
"tokenizer_source",
"eos_token_ids",
"bos_token_id",
"chat_template_source",
"provenance",
"vision_projector",
"load_wall_clock",
"resident_weight_bytes",
"kv_cache_budget_bytes",
"kv_spill_active",
];
for field in expected {
assert!(names.contains(field), "missing tracing field {field}");
}
}
#[test]
fn kv_bytes_per_token_qwen35moe_golden_matches_f32_kv_formula() {
let info = golden_qwen35moe_info();
let expected: u64 = 64 * 4 * 128 * 4 * 2;
assert_eq!(
info.kv_bytes_per_token(),
expected,
"qwen35moe golden fixture: kv_bytes_per_token MUST be 256 KiB"
);
let total_tokens: u64 = 2048 + 2048;
assert_eq!(
info.kv_bytes_for_request(2048, 2048),
total_tokens * expected,
);
}
#[test]
fn kv_bytes_per_token_zero_when_arch_facts_missing() {
let mut info = golden_qwen35moe_info();
info.n_layers = 0;
assert_eq!(
info.kv_bytes_per_token(),
0,
"zero n_layers ⇒ 0 (synthetic loader / test fixture)"
);
let mut info = golden_qwen35moe_info();
info.n_key_value_heads = 0;
assert_eq!(info.kv_bytes_per_token(), 0, "zero n_key_value_heads ⇒ 0");
let mut info = golden_qwen35moe_info();
info.head_dim = 0;
assert_eq!(info.kv_bytes_per_token(), 0, "zero head_dim ⇒ 0");
}
#[test]
fn kv_bytes_for_request_returns_zero_when_per_token_is_zero() {
let mut info = golden_qwen35moe_info();
info.n_layers = 0;
assert_eq!(info.kv_bytes_for_request(u32::MAX, u32::MAX), 0);
}
#[test]
fn kv_bytes_for_request_overflow_saturates_at_u64_max() {
let mut info = golden_qwen35moe_info();
info.n_layers = u32::MAX;
info.n_key_value_heads = u32::MAX;
info.head_dim = u32::MAX;
let needed = info.kv_bytes_for_request(1, 1);
assert_eq!(
needed,
u64::MAX,
"saturating-mul must surface u64::MAX (caller's scheduler \
check rejects as SlotBudgetExceeded)"
);
}
fn canonical_gemma4_27b_config() -> crate::serve::config::Gemma4Config {
use crate::serve::config::{Gemma4Config, LayerType};
let layer_types: Vec<LayerType> = (0..30)
.map(|i| {
if (i + 1) % 6 == 0 {
LayerType::Full
} else {
LayerType::Sliding
}
})
.collect();
Gemma4Config {
vocab_size: 262_144,
hidden_size: 5376,
intermediate_size: 21_504,
moe_intermediate_size: 0,
num_hidden_layers: 30,
num_attention_heads: 16,
num_key_value_heads: 8,
num_global_key_value_heads: 2,
head_dim: 256,
global_head_dim: 512,
rms_norm_eps: 1e-6,
rope_theta_sliding: 10_000.0,
rope_theta_global: 1_000_000.0,
sliding_window: 1024,
max_position_embeddings: 262_144,
final_logit_softcapping: None,
attention_bias: false,
attention_k_eq_v: true,
tie_word_embeddings: true,
num_experts: 0,
top_k_experts: 0,
layer_types,
}
}
fn canonical_qwen36_27b_config() -> crate::inference::models::qwen35::Qwen35Config {
use crate::inference::models::qwen35::{default_layer_types, Qwen35Config, Qwen35Variant};
Qwen35Config {
variant: Qwen35Variant::Dense,
hidden_size: 5_120,
num_hidden_layers: 64,
num_attention_heads: 24,
num_key_value_heads: 4,
head_dim: 256,
linear_num_key_heads: 16,
linear_num_value_heads: 48,
linear_key_head_dim: 128,
linear_value_head_dim: 128,
linear_conv_kernel_dim: 4,
full_attention_interval: 4,
layer_types: default_layer_types(64, 4),
partial_rotary_factor: 0.25,
rope_theta: 1e7,
rotary_dim: 64,
mrope_section: [11, 11, 10, 0],
mrope_interleaved: true,
rms_norm_eps: 1e-6,
max_position_embeddings: 262_144,
vocab_size: 248_320,
attn_output_gate: true,
mtp_num_hidden_layers: 0,
mtp_use_dedicated_embeddings: false,
intermediate_size: Some(17_408),
moe: None,
}
}
fn canonical_qwen36_apex_40_config() -> crate::inference::models::qwen35::Qwen35Config {
use crate::inference::models::qwen35::{
default_layer_types, Qwen35Config, Qwen35MoeConfig, Qwen35Variant,
};
Qwen35Config {
variant: Qwen35Variant::Moe,
hidden_size: 2_048,
num_hidden_layers: 40,
num_attention_heads: 16,
num_key_value_heads: 2,
head_dim: 256,
linear_num_key_heads: 16,
linear_num_value_heads: 32,
linear_key_head_dim: 128,
linear_value_head_dim: 128,
linear_conv_kernel_dim: 4,
full_attention_interval: 4,
layer_types: default_layer_types(40, 4),
partial_rotary_factor: 0.25,
rope_theta: 1e7,
rotary_dim: 64,
mrope_section: [11, 11, 10, 0],
mrope_interleaved: true,
rms_norm_eps: 1e-6,
max_position_embeddings: 262_144,
vocab_size: 248_320,
attn_output_gate: true,
mtp_num_hidden_layers: 0,
mtp_use_dedicated_embeddings: false,
intermediate_size: None,
moe: Some(Qwen35MoeConfig {
moe_intermediate_size: 512,
num_experts: 256,
num_experts_per_tok: 8,
shared_expert_intermediate_size: 512,
}),
}
}
#[test]
fn qwen36_slot_kv_bytes_per_token_counts_only_full_attention_tq_rows() {
let cfg = canonical_qwen36_27b_config();
assert_eq!(super::qwen35_slot_kv_bytes_per_token(&cfg, true), 33_280);
assert_eq!(super::qwen35_slot_kv_bytes_per_token(&cfg, false), 131_072);
assert!(
(cfg.max_position_embeddings as u64 + 8_192)
* super::qwen35_slot_kv_bytes_per_token(&cfg, true)
< 9 * 1024 * 1024 * 1024,
"one full Qwen TQ slot must fit the canonical shared budget"
);
}
#[test]
fn qwen36_apex_full_context_np4_and_np8_fit_shared_budget() {
let cfg = canonical_qwen36_apex_40_config();
let linear = super::qwen35_slot_kv_bytes_per_token(&cfg, true);
let fixed = super::qwen35_fixed_kv_bytes_per_slot(&cfg);
let full_slot =
fixed.saturating_add(u64::from(cfg.max_position_embeddings).saturating_mul(linear));
let budget = 48 * 1024 * 1024 * 1024_u64;
assert_eq!(linear, 10_400);
assert_eq!(fixed, 256 * 1024 * 1024);
assert_eq!(full_slot, 2_994_733_056);
assert!(full_slot.saturating_mul(4) < budget);
assert!(full_slot.saturating_mul(8) < budget);
}
#[test]
fn gemma4_slot_kv_bytes_per_token_matches_hybrid_full_layers() {
let cfg = canonical_gemma4_27b_config();
let exact = super::gemma4_slot_kv_bytes_per_token(&cfg);
let expected: u64 = 5 * 3_088;
assert_eq!(
exact, expected,
"Gemma hybrid token-linear cost must include only five full layers",
);
assert_eq!(exact, 15_440);
let full_request_tokens = cfg.max_position_embeddings as u64 + 8_192;
assert!(
full_request_tokens * exact < 4 * 1024 * 1024 * 1024,
"a full logical slot must not be rejected using all-layer F32 fiction"
);
let fixed = super::gemma4_fixed_kv_bytes_per_slot(&cfg);
assert_eq!(fixed, 560 * 1024 * 1024);
let full_slot = fixed.saturating_add(full_request_tokens.saturating_mul(exact));
assert!(
full_slot.saturating_mul(8) < 48 * 1024 * 1024 * 1024,
"eight full logical Gemma slots fit the canonical shared physical budget"
);
}
#[test]
fn a5c_load_info_kv_bytes_per_token_uses_override_when_present() {
let cfg = canonical_gemma4_27b_config();
let exact = super::gemma4_slot_kv_bytes_per_token(&cfg);
let info = LoadInfo {
model_id: "gemma-4-27b-it-canonical".to_string(),
arch_str: "gemma4".to_string(),
arch_family: ArchFamily::Gemma4,
model_path: PathBuf::from("/canonical/gemma4-27b.gguf"),
on_disk_bytes: 0,
backend_chip: "test-gpu".to_string(),
backend: "mlx-native",
n_layers: cfg.num_hidden_layers as u32,
hidden_size: cfg.hidden_size as u32,
vocab_size: cfg.vocab_size as u32,
n_attention_heads: cfg.num_attention_heads as u32,
n_key_value_heads: cfg.num_key_value_heads as u32,
head_dim: cfg.head_dim as u32,
sliding_window: Some(cfg.sliding_window as u32),
full_attention_interval: cfg.full_attention_interval(),
max_context_length: Some(cfg.max_position_embeddings as u32),
moe: None,
quant_label: None,
quant_bpw: None,
tokenizer_source: TokenizerSource::HfTokenizerJson {
path: PathBuf::from("/canonical/tokenizer.json"),
},
eos_token_ids: vec![1, 106],
bos_token_id: Some(2),
chat_template_source: ChatTemplateSource::GgufEmbedded,
provenance: Provenance::External,
vision_projector: None,
load_wall_clock: Duration::ZERO,
resident_weight_bytes: None,
kv_cache_budget_bytes: None,
kv_spill_active: false,
tq_kv_active: false,
kv_bytes_per_token_override: Some(exact),
kv_fixed_bytes_per_slot_override: Some(super::gemma4_fixed_kv_bytes_per_slot(&cfg)),
};
assert_eq!(
info.kv_bytes_per_token(),
exact,
"kv_bytes_per_token MUST honour the override when present"
);
let flat: u64 = 30 * 8 * 256 * 4 * 2;
assert_ne!(
exact, flat,
"exact and flat MUST differ — otherwise the test could pass even \
if `kv_bytes_per_token` ignored the override"
);
assert_eq!(flat, 491_520, "canonical flat formula sanity");
assert!(
info.kv_bytes_per_token() < flat,
"exact override MUST be < flattened over-count (proves override \
is being honoured; not just a coincidence of identical values)"
);
}
#[test]
fn a5c_load_info_kv_bytes_per_token_falls_back_to_flat_when_no_override() {
let info = golden_qwen35moe_info();
assert!(
info.kv_bytes_per_token_override.is_none(),
"golden legacy fixture intentionally exercises the fallback"
);
let flat: u64 = 64 * 4 * 128 * 4 * 2;
assert_eq!(
info.kv_bytes_per_token(),
flat,
"no override ⇒ flat formula path (homogeneous arch)"
);
}
#[test]
fn mixed_family_shared_budget_banner_omits_false_token_quotient() {
let mut info = golden_qwen35moe_info();
info.kv_bytes_per_token_override = Some(10_400);
info.kv_fixed_bytes_per_slot_override = Some(256 * 1024 * 1024);
let mut output = Vec::new();
print_banner(&info, &mut output, false).expect("banner");
let output = String::from_utf8(output).expect("utf8");
assert!(output.contains("kv_budget = 4.00 GiB shared"));
assert!(!output.contains("~32768 tokens"));
}
#[test]
fn a5c_load_info_override_distinct_from_flat_falsifies_regression() {
let cfg = canonical_gemma4_27b_config();
let exact = super::gemma4_slot_kv_bytes_per_token(&cfg);
let mut info = golden_qwen35moe_info();
info.arch_family = ArchFamily::Gemma4;
info.kv_bytes_per_token_override = Some(exact);
assert_eq!(
info.kv_bytes_per_token(),
exact,
"override MUST short-circuit the flat formula"
);
}
}