rigspark-core 2.3.0

Deterministic, offline LLM memory and VRAM sizing, KV-cache estimation, hardware-fit scoring and model catalog for rigspark.
Documentation
use crate::{
    catalog::{Catalog, GgufSource, MlxSource, parse_document},
    enrich::{Mode, RawModel, enrich},
    sizing::{ValidationError, parse_param_count},
};
use serde::Deserialize;
use std::collections::BTreeMap;

pub const BOOTSTRAP_CLOCK: &str = "2026-08-04T00:00:00.000Z";

#[derive(Deserialize)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
struct Metadata {
    kv_bytes_per_token: Option<f64>,
    gguf: Option<GgufSource>,
    mlx: Option<MlxSource>,
}

pub fn build_catalog(candidates: &[RawModel], now: &str) -> Result<Catalog, ValidationError> {
    let seed = Catalog {
        schema_version: 2,
        generated_at: BOOTSTRAP_CLOCK.into(),
        models: Vec::new(),
    };
    let mut catalog = enrich(&seed, candidates, Mode::Backfill, now, None)?.catalog;
    let metadata: BTreeMap<String, Metadata> =
        parse_document(include_str!("../fixtures/bootstrap-metadata.json"))?;
    for model in &mut catalog.models {
        if let Some(entry) = metadata.get(&model.id) {
            model.kv_bytes_per_token = entry.kv_bytes_per_token;
            model.source.gguf = entry.gguf.clone();
            model.source.mlx = entry.mlx.clone();
        }
        model.benchmark_proxy = family_quality_offset(&model.family)
            .map(|_| derive_benchmark_proxy(&model.family, &model.params))
            .transpose()?;
    }
    let encoded =
        serde_json::to_string(&catalog).map_err(|error| ValidationError(error.to_string()))?;
    Catalog::parse(&encoded)
}

pub fn family_quality_offset(family: &str) -> Option<f64> {
    let offset = match family {
        "kimi-k2" | "deepseek-r1" | "phi4" => 0.12,
        "kimi-k2-thinking" => 0.14,
        "kimi-vl" | "qwen2.5" | "gemma3n" | "gemma3" | "phi3" => 0.06,
        "kimi-dev" | "kimi-linear" | "llama3.3" | "qwen2.5-coder" | "gemma4" | "phi3.5" => 0.08,
        "llama3.1" | "gemma2" => 0.04,
        "qwen3" | "deepseek-v3" | "phi4-mini" => 0.1,
        "mixtral" | "mistral-small" | "glm4" => 0.05,
        "mistral-nemo" | "yi" | "granite3.1" => 0.03,
        "mistral" | "olmo2" | "granite3-moe" => 0.02,
        "llama3.2" | "smollm2" => 0.0,
        _ => return None,
    };
    Some(offset)
}

pub fn derive_benchmark_proxy(family: &str, params: &str) -> Result<f64, ValidationError> {
    let offset = family_quality_offset(family).unwrap_or(0.0);
    let billions = parse_param_count(params)? / 1e9;
    let base = [
        (0.5, 0.05),
        (1.0, 0.12),
        (2.0, 0.2),
        (4.0, 0.28),
        (7.0, 0.36),
        (10.0, 0.44),
        (15.0, 0.52),
        (25.0, 0.58),
        (40.0, 0.64),
        (80.0, 0.7),
        (200.0, 0.78),
    ]
    .into_iter()
    .find_map(|(ceiling, score)| (billions < ceiling).then_some(score))
    .unwrap_or(0.85_f64);
    Ok(((base + offset).clamp(0.05, 0.99) * 100.0).round() / 100.0)
}