use crate::error::{DbError, Result};
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct ModelName(String);
const MAX_MODEL_NAME: usize = 48;
impl ModelName {
pub fn new(raw: impl AsRef<str>) -> Result<Self> {
let raw = raw.as_ref();
let invalid = || DbError::InvalidModelName(raw.to_string());
if raw.is_empty() || raw.len() > MAX_MODEL_NAME {
return Err(invalid());
}
let mut chars = raw.chars();
match chars.next() {
Some(c) if c.is_ascii_lowercase() => {}
_ => return Err(invalid()),
}
if !chars.all(|c| c.is_ascii_lowercase() || c.is_ascii_digit() || c == '_') {
return Err(invalid());
}
Ok(Self(raw.to_string()))
}
pub fn as_str(&self) -> &str {
&self.0
}
pub fn table(&self) -> String {
format!("embeddings_{}", self.0)
}
pub fn index(&self) -> String {
format!("idx_embeddings_{}_vec", self.0)
}
}
impl std::fmt::Display for ModelName {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str(&self.0)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn accepts_the_names_the_document_uses() {
for ok in ["nomic_v1", "e5", "bge_m3", "all_minilm_l6_v2", "m1"] {
assert_eq!(ModelName::new(ok).unwrap().as_str(), ok);
}
}
#[test]
fn rejects_anything_that_is_not_a_bare_identifier() {
for bad in [
"",
"nomic-v1", "Nomic", "1nomic", "_nomic", "nomic v1", "nomic\"; DROP TABLE links; --",
"nomic'",
"nomic;",
"nomic(1)",
"concepts\" --",
"näh", ] {
assert!(
matches!(ModelName::new(bad), Err(DbError::InvalidModelName(_))),
"{bad:?} was accepted as a model name"
);
}
assert!(ModelName::new("a".repeat(MAX_MODEL_NAME + 1)).is_err());
assert!(ModelName::new("a".repeat(MAX_MODEL_NAME)).is_ok());
}
#[test]
fn derives_the_table_and_index_identifiers() {
let m = ModelName::new("nomic_v1").unwrap();
assert_eq!(m.table(), "embeddings_nomic_v1");
assert_eq!(m.index(), "idx_embeddings_nomic_v1_vec");
}
#[test]
fn no_model_name_can_collide_with_a_ledger_table() {
for ledger in ["concepts", "links", "links_current", "transaction_log"] {
assert!(
ModelName::new(ledger).unwrap().table() != ledger,
"model {ledger:?} produced a ledger table name"
);
}
}
}