use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::path::{Path, PathBuf};
use std::sync::{Arc, Mutex};
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
pub struct ModelMetadata {
pub id: String,
pub name: String,
pub architecture: String,
pub total_layers: usize,
pub parameter_count: u64,
pub precision: String,
pub vram_required_gb: f32,
pub local_path: PathBuf,
}
#[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq, Eq)]
pub enum ModelStatus {
Downloaded,
Loading,
Loaded,
Unloading,
}
pub struct ModelRegistry {
models: Arc<Mutex<HashMap<String, ModelMetadata>>>,
status: Arc<Mutex<HashMap<String, ModelStatus>>>,
base_dir: PathBuf,
}
impl ModelRegistry {
pub fn new<P: AsRef<Path>>(base_dir: P) -> Self {
Self {
models: Arc::new(Mutex::new(HashMap::new())),
status: Arc::new(Mutex::new(HashMap::new())),
base_dir: base_dir.as_ref().to_path_buf(),
}
}
pub fn register(&self, metadata: ModelMetadata) {
let mut models = self.models.lock().unwrap();
models.insert(metadata.id.clone(), metadata);
}
pub fn get_metadata(&self, id: &str) -> Option<ModelMetadata> {
let models = self.models.lock().unwrap();
models.get(id).cloned()
}
pub fn list_models(&self) -> Vec<ModelMetadata> {
let models = self.models.lock().unwrap();
models.values().cloned().collect()
}
pub fn set_status(&self, id: &str, status: ModelStatus) {
let mut statuses = self.status.lock().unwrap();
statuses.insert(id.to_string(), status);
}
pub fn get_status(&self, id: &str) -> ModelStatus {
let statuses = self.status.lock().unwrap();
statuses.get(id).copied().unwrap_or(ModelStatus::Downloaded)
}
pub fn base_dir(&self) -> &Path {
&self.base_dir
}
}
#[cfg(test)]
mod tests {
use super::*;
use tempfile::tempdir;
#[test]
fn test_model_registration() {
let dir = tempdir().unwrap();
let registry = ModelRegistry::new(dir.path());
let meta = ModelMetadata {
id: "llama3-8b".to_string(),
name: "Llama 3 8B".to_string(),
architecture: "llama".to_string(),
total_layers: 32,
parameter_count: 8_000_000_000,
precision: "f16".to_string(),
vram_required_gb: 16.0,
local_path: dir.path().join("llama3-8b"),
};
registry.register(meta.clone());
assert_eq!(registry.get_metadata("llama3-8b"), Some(meta));
assert_eq!(registry.get_status("llama3-8b"), ModelStatus::Downloaded);
registry.set_status("llama3-8b", ModelStatus::Loaded);
assert_eq!(registry.get_status("llama3-8b"), ModelStatus::Loaded);
}
}