Skip to main content

newt_core/
model_id.rs

1use serde::{Deserialize, Serialize};
2use std::fmt;
3
4/// Strongly-typed model identifier for audit trail purposes.
5/// Every inference response must carry a ModelId so the arbiter and scorecard
6/// can attribute the work to a specific model.
7#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
8#[serde(transparent)]
9pub struct ModelId(String);
10
11impl ModelId {
12    pub fn new(id: impl Into<String>) -> Self {
13        Self(id.into())
14    }
15
16    pub fn as_str(&self) -> &str {
17        &self.0
18    }
19}
20
21impl fmt::Display for ModelId {
22    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
23        self.0.fmt(f)
24    }
25}
26
27impl From<String> for ModelId {
28    fn from(s: String) -> Self {
29        Self(s)
30    }
31}
32
33impl From<&str> for ModelId {
34    fn from(s: &str) -> Self {
35        Self(s.to_string())
36    }
37}
38
39#[cfg(test)]
40mod tests {
41    use super::*;
42
43    #[test]
44    fn new_and_display() {
45        let id = ModelId::new("llama3.1:8b");
46        assert_eq!(id.to_string(), "llama3.1:8b");
47    }
48
49    #[test]
50    fn as_str() {
51        let id = ModelId::new("gpt-4o");
52        assert_eq!(id.as_str(), "gpt-4o");
53    }
54
55    #[test]
56    fn from_string() {
57        let id: ModelId = "test-model".into();
58        assert_eq!(id.as_str(), "test-model");
59    }
60
61    #[test]
62    fn serde_roundtrip() {
63        let id = ModelId::new("claude-3");
64        let json = serde_json::to_string(&id).unwrap();
65        assert_eq!(json, "\"claude-3\"");
66        let back: ModelId = serde_json::from_str(&json).unwrap();
67        assert_eq!(id, back);
68    }
69
70    #[test]
71    fn equality() {
72        assert_eq!(ModelId::new("a"), ModelId::new("a"));
73        assert_ne!(ModelId::new("a"), ModelId::new("b"));
74    }
75}