use std::sync::OnceLock;
use serde::Deserialize;
use sha2::{Digest, Sha256};
use super::error::ApexError;
use super::rules::ApexTier;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct FingerprintHParams {
pub model_type: String,
pub num_hidden_layers: u32,
pub hidden_size: u32,
pub num_experts: u32,
pub num_attention_heads: u32,
pub num_key_value_heads: u32,
pub intermediate_size: u32,
pub moe_intermediate_size: u32,
pub mtp_num_hidden_layers: u32,
}
impl FingerprintHParams {
pub fn from_config(config: &serde_json::Value) -> Option<Self> {
let model_type = config.get("model_type")?.as_str()?.to_string();
let num_hidden_layers = config.get("num_hidden_layers")?.as_u64()? as u32;
let hidden_size = config.get("hidden_size")?.as_u64()? as u32;
let num_experts = config
.get("num_experts")
.or_else(|| config.get("num_local_experts"))
.and_then(|v| v.as_u64())
.unwrap_or(0) as u32;
let num_attention_heads = config.get("num_attention_heads")?.as_u64()? as u32;
let num_key_value_heads = config
.get("num_key_value_heads")
.and_then(|v| v.as_u64())
.map(|x| x as u32)
.unwrap_or(num_attention_heads);
let intermediate_size = config
.get("intermediate_size")
.and_then(|v| v.as_u64())
.map(|x| x as u32)
.unwrap_or(0);
let moe_intermediate_size = config
.get("moe_intermediate_size")
.and_then(|v| v.as_u64())
.map(|x| x as u32)
.unwrap_or(0);
let mtp_num_hidden_layers = config
.get("mtp_num_hidden_layers")
.and_then(|v| v.as_u64())
.map(|x| x as u32)
.unwrap_or(0);
Some(Self {
model_type,
num_hidden_layers,
hidden_size,
num_experts,
num_attention_heads,
num_key_value_heads,
intermediate_size,
moe_intermediate_size,
mtp_num_hidden_layers,
})
}
pub fn fingerprint(&self) -> String {
let canonical = format!(
"{{\
\"hidden_size\":{hs},\
\"intermediate_size\":{is_},\
\"model_type\":\"{mt}\",\
\"moe_intermediate_size\":{mis},\
\"mtp_num_hidden_layers\":{mtp},\
\"num_attention_heads\":{nah},\
\"num_experts\":{ne},\
\"num_hidden_layers\":{nhl},\
\"num_key_value_heads\":{nkv}\
}}",
hs = self.hidden_size,
is_ = self.intermediate_size,
mt = self.model_type,
mis = self.moe_intermediate_size,
mtp = self.mtp_num_hidden_layers,
nah = self.num_attention_heads,
ne = self.num_experts,
nhl = self.num_hidden_layers,
nkv = self.num_key_value_heads,
);
let mut h = Sha256::new();
h.update(canonical.as_bytes());
format!("{:x}", h.finalize())
}
}
#[derive(Debug, Clone, Deserialize)]
pub struct ApexConfigRef {
pub fingerprint: String,
pub model_id_pattern: String,
pub arch: String,
pub tier: String,
pub mudler_config_path: String,
pub expected_hparams: serde_json::Value,
}
#[derive(Debug, Deserialize)]
struct ManifestEnvelope {
entries: Vec<ApexConfigRef>,
}
const MANIFEST_JSON: &str = include_str!("../../../../data/apex-references/manifest.json");
fn manifest() -> &'static [ApexConfigRef] {
static CACHE: OnceLock<Vec<ApexConfigRef>> = OnceLock::new();
CACHE
.get_or_init(|| {
let env: ManifestEnvelope = serde_json::from_str(MANIFEST_JSON).expect(
"apex manifest JSON is malformed — check data/apex-references/manifest.json",
);
env.entries
})
.as_slice()
}
pub const VENDOR_CONFIGS: &[(&str, &str)] = &[
(
"vendor/apex-quant/configs/gemma4_26b_quality.txt",
include_str!("../../../../data/apex-references/configs/gemma4_26b_quality.txt"),
),
(
"vendor/apex-quant/configs/gemma4_26b_balanced.txt",
include_str!("../../../../data/apex-references/configs/gemma4_26b_balanced.txt"),
),
(
"vendor/apex-quant/configs/gemma4_26b_compact.txt",
include_str!("../../../../data/apex-references/configs/gemma4_26b_compact.txt"),
),
(
"vendor/apex-quant/configs/gemma4_26b_mini.txt",
include_str!("../../../../data/apex-references/configs/gemma4_26b_mini.txt"),
),
(
"vendor/apex-quant/configs/qwen35a3b_quality.txt",
include_str!("../../../../data/apex-references/configs/qwen35a3b_quality.txt"),
),
(
"vendor/apex-quant/configs/qwen35a3b_balanced.txt",
include_str!("../../../../data/apex-references/configs/qwen35a3b_balanced.txt"),
),
(
"vendor/apex-quant/configs/qwen35a3b_compact.txt",
include_str!("../../../../data/apex-references/configs/qwen35a3b_compact.txt"),
),
(
"vendor/apex-quant/configs/qwen35a3b_mini.txt",
include_str!("../../../../data/apex-references/configs/qwen35a3b_mini.txt"),
),
(
"vendor/apex-quant/configs/carnice_qwen36_mtp_quality.txt",
include_str!("../../../../data/apex-references/configs/carnice_qwen36_mtp_quality.txt"),
),
(
"vendor/apex-quant/configs/carnice_qwen36_mtp_balanced.txt",
include_str!("../../../../data/apex-references/configs/carnice_qwen36_mtp_balanced.txt"),
),
(
"vendor/apex-quant/configs/carnice_qwen36_mtp_compact.txt",
include_str!("../../../../data/apex-references/configs/carnice_qwen36_mtp_compact.txt"),
),
(
"vendor/apex-quant/configs/carnice_qwen36_mtp_mini.txt",
include_str!("../../../../data/apex-references/configs/carnice_qwen36_mtp_mini.txt"),
),
];
pub fn vendor_config_content(path: &str) -> Option<&'static str> {
VENDOR_CONFIGS
.iter()
.find(|(p, _)| *p == path)
.map(|(_, c)| *c)
}
fn tier_label(tier: ApexTier) -> &'static str {
match tier {
ApexTier::Quality => "quality",
ApexTier::IQuality => "i-quality",
ApexTier::Balanced => "balanced",
ApexTier::IBalanced => "i-balanced",
ApexTier::Compact => "compact",
ApexTier::ICompact => "i-compact",
ApexTier::Mini => "mini",
}
}
pub fn detect_apex_config(
hparams: &FingerprintHParams,
tier: ApexTier,
) -> Option<&'static ApexConfigRef> {
let fp = hparams.fingerprint();
let want_tier = tier_label(tier);
manifest()
.iter()
.find(|e| e.fingerprint == fp && e.tier == want_tier)
}
pub fn manifest_entry_count() -> usize {
manifest().len()
}
pub fn manifest_entries() -> &'static [ApexConfigRef] {
manifest()
}
#[cfg(test)]
mod tests {
use super::*;
fn gemma4_26b_hparams() -> FingerprintHParams {
FingerprintHParams {
model_type: "gemma4_text".into(),
num_hidden_layers: 30,
hidden_size: 2816,
num_experts: 128,
num_attention_heads: 16,
num_key_value_heads: 8,
intermediate_size: 2112,
moe_intermediate_size: 704,
mtp_num_hidden_layers: 0,
}
}
fn qwen35a3b_hparams() -> FingerprintHParams {
FingerprintHParams {
model_type: "qwen3_5_moe_text".into(),
num_hidden_layers: 40,
hidden_size: 2048,
num_experts: 256,
num_attention_heads: 16,
num_key_value_heads: 2,
intermediate_size: 0,
moe_intermediate_size: 512,
mtp_num_hidden_layers: 0,
}
}
fn carnice_mtp_hparams() -> FingerprintHParams {
FingerprintHParams {
mtp_num_hidden_layers: 1,
..qwen35a3b_hparams()
}
}
#[test]
fn gemma4_26b_fingerprint_matches_manifest() {
let fp = gemma4_26b_hparams().fingerprint();
assert_eq!(
fp, "79ce3481c1eaf4ebdc833b01e9e970fca7c08824c080abc0f5f735dd97c440a1",
"Gemma 4 26B-A4B-IT canonical fingerprint drifted; manifest needs regen"
);
}
#[test]
fn qwen35a3b_fingerprint_matches_manifest() {
let fp = qwen35a3b_hparams().fingerprint();
assert_eq!(
fp,
"9676b7abea7495049a8d6432a71caeac394fc7c4cbeb950b6ec0d27cd8c5c223"
);
}
#[test]
fn carnice_mtp_fingerprint_differs_from_base() {
let base = qwen35a3b_hparams().fingerprint();
let mtp = carnice_mtp_hparams().fingerprint();
assert_ne!(base, mtp, "mtp flag must produce distinct fingerprint");
assert_eq!(
mtp,
"4d1512c7ae74ee2782901c568a6d0d848fe84dfe5f80e308863cb9ebd95919ee"
);
}
#[test]
fn manifest_entry_count_meets_adr_floor() {
let n = manifest_entry_count();
assert!(
n >= 10,
"ADR-033 P-1 requires ≥5 manifest entries; operator-set floor is 10; got {n}"
);
}
#[test]
fn detect_gemma4_26b_balanced_dispatch() {
let entry = detect_apex_config(&gemma4_26b_hparams(), ApexTier::Balanced)
.expect("gemma4-26b-a4b-it@balanced must resolve to a manifest entry");
assert_eq!(
entry.mudler_config_path,
"vendor/apex-quant/configs/gemma4_26b_balanced.txt"
);
assert_eq!(entry.tier, "balanced");
assert_eq!(entry.arch, "gemma4");
}
#[test]
fn detect_gemma4_26b_i_balanced_aliases_balanced_txt() {
let entry = detect_apex_config(&gemma4_26b_hparams(), ApexTier::IBalanced)
.expect("i-balanced must resolve");
assert_eq!(
entry.mudler_config_path,
"vendor/apex-quant/configs/gemma4_26b_balanced.txt"
);
}
#[test]
fn detect_mtp_vs_base_resolve_to_different_configs() {
let base = detect_apex_config(&qwen35a3b_hparams(), ApexTier::Balanced).unwrap();
let mtp = detect_apex_config(&carnice_mtp_hparams(), ApexTier::Balanced).unwrap();
assert_ne!(base.mudler_config_path, mtp.mudler_config_path);
assert_eq!(
base.mudler_config_path,
"vendor/apex-quant/configs/qwen35a3b_balanced.txt"
);
assert_eq!(
mtp.mudler_config_path,
"vendor/apex-quant/configs/carnice_qwen36_mtp_balanced.txt"
);
}
#[test]
fn unknown_hparams_return_none() {
let h = FingerprintHParams {
model_type: "llama".into(),
num_hidden_layers: 32,
hidden_size: 4096,
num_experts: 0,
num_attention_heads: 32,
num_key_value_heads: 8,
intermediate_size: 14336,
moe_intermediate_size: 0,
mtp_num_hidden_layers: 0,
};
assert!(detect_apex_config(&h, ApexTier::Balanced).is_none());
}
#[test]
fn every_manifest_entry_has_baked_vendor_content() {
for entry in manifest() {
assert!(
vendor_config_content(&entry.mudler_config_path).is_some(),
"manifest entry {:?} references unbaked path {:?} \
— add it to VENDOR_CONFIGS in fingerprint.rs",
entry.fingerprint,
entry.mudler_config_path
);
}
}
#[test]
fn from_config_extracts_gemma4_hparams() {
let cfg: serde_json::Value = serde_json::from_str(
r#"{
"model_type": "gemma4_text",
"num_hidden_layers": 30,
"hidden_size": 2816,
"num_experts": 128,
"num_attention_heads": 16,
"num_key_value_heads": 8,
"intermediate_size": 2112,
"moe_intermediate_size": 704
}"#,
)
.unwrap();
let h = FingerprintHParams::from_config(&cfg).unwrap();
assert_eq!(h, gemma4_26b_hparams());
}
}
#[allow(dead_code)]
fn _ensure_apex_error_path() -> Option<ApexError> {
None
}