use std::io::Read as _;
use std::path::Path;
use anyhow::{Context, Result};
use metrale_circuit::ir::Circuit;
use metrale_circuit::venn::Repo;
use super::circuit_hw::{CheckpointTexts, FsTree};
use super::circuit_memory_serve::Behavior;
pub(crate) fn behavior(tree: &FsTree, class: &str, target: &str) -> Result<Behavior> {
let rel = format!("kernels/{class}/{target}/MODEL.toml");
match tree.read(&rel) {
Ok(text) => Behavior::parse(&text, rel),
Err(_) => Ok(Behavior {
source: format!("{rel} absent: engine defaults"),
..Behavior::default()
}),
}
}
fn bound(pattern: &str, module: &str) -> bool {
pattern
.split('.')
.zip(module.split('.'))
.all(|(p, m)| p == "*" || p == m)
}
fn bindings(c: &Circuit) -> Vec<&str> {
c.nodes
.iter()
.filter(|n| n.weight.is_some() || n.op == metrale_circuit::OpKind::Embed)
.flat_map(|n| n.binding.iter().map(String::as_str))
.collect()
}
fn header_tensors(path: &Path) -> Result<Vec<(String, u64)>> {
let mut f = std::fs::File::open(path).with_context(|| format!("{}", path.display()))?;
let mut len = [0u8; 8];
f.read_exact(&mut len)?;
let mut json = vec![0u8; u64::from_le_bytes(len) as usize];
f.read_exact(&mut json)?;
let h: serde_json::Map<String, serde_json::Value> = serde_json::from_slice(&json)?;
Ok(h.into_iter()
.filter(|(k, _)| k != "__metadata__")
.filter_map(|(k, v)| {
let o = v.get("data_offsets")?.as_array()?;
Some((k, o.get(1)?.as_u64()? - o.first()?.as_u64()?))
})
.collect())
}
pub(crate) fn outside_bytes(texts: &CheckpointTexts, c: &Circuit) -> Result<Option<u64>> {
let Some(dir) = &texts.dir else {
return Ok(None);
};
let mut files: Vec<_> = std::fs::read_dir(dir)?
.filter_map(|e| e.ok().map(|e| e.path()))
.filter(|p| p.extension().is_some_and(|x| x == "safetensors"))
.collect();
if files.is_empty() {
return Ok(None);
}
files.sort();
let pats = bindings(c);
let mut out = 0;
for f in files {
for (name, bytes) in header_tensors(&f)? {
let module = name.rsplit_once('.').map_or(name.as_str(), |(m, _)| m);
if !pats.iter().any(|p| bound(p, module)) {
out += bytes;
}
}
}
Ok(Some(out))
}
#[cfg(test)]
#[path = "circuit_memory_weights_tests.rs"]
mod circuit_memory_weights_tests;