#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "serde", serde(rename_all = "snake_case"))]
pub enum Provider {
OpenAi,
Anthropic,
Cohere,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "serde", serde(rename_all = "snake_case"))]
pub enum Model {
Gpt4o,
Gpt4,
Gpt35Turbo,
Claude3Opus,
Claude3Sonnet,
Claude3Haiku,
CommandRPlus,
CommandR,
}
impl Model {
pub fn infer_from_name(name: &str) -> Option<(Provider, Self)> {
let n = name.to_ascii_lowercase();
if n.contains("gpt-4o") || n.contains("gpt4o") {
Some((Provider::OpenAi, Model::Gpt4o))
} else if n.contains("gpt-3.5") || n.contains("gpt35") || n.contains("gpt-35") {
Some((Provider::OpenAi, Model::Gpt35Turbo))
} else if n.contains("gpt-4") || n.contains("gpt4") {
Some((Provider::OpenAi, Model::Gpt4))
} else if n.contains("opus") {
Some((Provider::Anthropic, Model::Claude3Opus))
} else if n.contains("sonnet") {
Some((Provider::Anthropic, Model::Claude3Sonnet))
} else if n.contains("haiku") {
Some((Provider::Anthropic, Model::Claude3Haiku))
} else if n.contains("command-r-plus") || n.contains("command-r+") {
Some((Provider::Cohere, Model::CommandRPlus))
} else if n.contains("command-r") {
Some((Provider::Cohere, Model::CommandR))
} else {
None
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn provider_variants_are_distinct() {
assert_eq!(Provider::OpenAi, Provider::OpenAi);
assert_ne!(Provider::OpenAi, Provider::Anthropic);
assert_ne!(Provider::OpenAi, Provider::Cohere);
assert_ne!(Provider::Anthropic, Provider::Cohere);
}
#[test]
fn model_variants_are_distinct() {
assert_eq!(Model::Gpt4o, Model::Gpt4o);
assert_ne!(Model::Gpt4o, Model::Gpt4);
assert_ne!(Model::Claude3Opus, Model::Claude3Haiku);
assert_ne!(Model::CommandRPlus, Model::CommandR);
}
#[test]
fn infer_openai_gpt4o_most_specific() {
assert_eq!(
Model::infer_from_name("gpt-4o-2024-08-06"),
Some((Provider::OpenAi, Model::Gpt4o))
);
assert_eq!(Model::infer_from_name("GPT4O"), Some((Provider::OpenAi, Model::Gpt4o)));
}
#[test]
fn infer_openai_gpt35_before_gpt4() {
assert_eq!(
Model::infer_from_name("gpt-3.5-turbo"),
Some((Provider::OpenAi, Model::Gpt35Turbo))
);
}
#[test]
fn infer_openai_gpt4() {
assert_eq!(Model::infer_from_name("gpt-4"), Some((Provider::OpenAi, Model::Gpt4)));
}
#[test]
fn infer_anthropic_family() {
assert_eq!(
Model::infer_from_name("claude-3-opus-20240229"),
Some((Provider::Anthropic, Model::Claude3Opus))
);
assert_eq!(
Model::infer_from_name("claude-3-5-sonnet"),
Some((Provider::Anthropic, Model::Claude3Sonnet))
);
assert_eq!(
Model::infer_from_name("claude-3-haiku"),
Some((Provider::Anthropic, Model::Claude3Haiku))
);
}
#[test]
fn infer_cohere_command_r_plus_before_command_r() {
assert_eq!(
Model::infer_from_name("command-r-plus"),
Some((Provider::Cohere, Model::CommandRPlus))
);
assert_eq!(
Model::infer_from_name("command-r"),
Some((Provider::Cohere, Model::CommandR))
);
}
#[test]
fn infer_unknown_returns_none() {
assert_eq!(Model::infer_from_name("mystery-model-v9"), None);
assert_eq!(Model::infer_from_name(""), None);
}
}