use serde::Deserialize;
use serde::Serialize;
use crate::shared::ModelId;
use crate::shared::ProviderId;
use crate::shared::ProviderReference;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "kebab-case")]
#[non_exhaustive]
pub enum ModelKind {
Language,
Embedding,
Image,
Transcription,
Speech,
Reranking,
Video,
SpeechTranslation,
Realtime,
}
impl ModelKind {
#[must_use]
pub fn as_str(self) -> &'static str {
match self {
Self::Language => "language model",
Self::Embedding => "embedding model",
Self::Image => "image model",
Self::Transcription => "transcription model",
Self::Speech => "speech model",
Self::Reranking => "reranking model",
Self::Video => "video model",
Self::SpeechTranslation => "speech translation model",
Self::Realtime => "realtime model",
}
}
}
impl std::fmt::Display for ModelKind {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str(self.as_str())
}
}
#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
#[error("{message}")]
pub struct NoSuchModelError {
pub provider: Option<ProviderId>,
pub model_id: String,
pub model_kind: ModelKind,
pub message: String,
}
impl NoSuchModelError {
#[must_use]
pub fn new(model_id: impl Into<String>, model_kind: ModelKind) -> Self {
let model_id = model_id.into();
Self {
provider: None,
message: format!("no such {model_kind}: {model_id}"),
model_id,
model_kind,
}
}
#[must_use]
pub fn with_provider(mut self, provider: &ProviderId) -> Self {
self.provider = Some(provider.clone());
self.message = format!(
"no such {}: {} (provider {provider})",
self.model_kind, self.model_id
);
self
}
#[must_use]
pub fn unsupported_kind(provider: &ProviderId, model_id: &str, model_kind: ModelKind) -> Self {
Self {
provider: Some(provider.clone()),
model_id: model_id.to_owned(),
model_kind,
message: format!(
"provider {provider} does not expose {model_kind}s (requested {model_id})"
),
}
}
#[must_use]
pub fn with_message(mut self, message: impl Into<String>) -> Self {
self.message = message.into();
self
}
}
#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
#[error("{message}")]
pub struct NoSuchProviderReferenceError {
pub provider: String,
pub reference: ProviderReference,
pub message: String,
}
impl NoSuchProviderReferenceError {
#[must_use]
pub fn new(provider: impl Into<String>, reference: ProviderReference) -> Self {
let provider = provider.into();
let available: Vec<&str> = reference.keys().map(String::as_str).collect();
Self {
message: format!(
"no provider reference found for provider `{provider}`; available providers: {}",
available.join(", ")
),
provider,
reference,
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
#[error(
"too many values for a single embedding call: {provider} model `{model_id}` accepts up to \
{max_embeddings_per_call} values per call, got {value_count}"
)]
pub struct TooManyEmbeddingValuesForCallError {
pub provider: ProviderId,
pub model_id: ModelId,
pub max_embeddings_per_call: usize,
pub value_count: usize,
}
#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
#[error("{message}")]
pub struct UnsupportedFunctionalityError {
pub functionality: String,
pub message: String,
}
impl UnsupportedFunctionalityError {
#[must_use]
pub fn new(functionality: impl Into<String>) -> Self {
let functionality = functionality.into();
Self {
message: format!("`{functionality}` functionality not supported"),
functionality,
}
}
#[must_use]
pub fn with_message(functionality: impl Into<String>, message: impl Into<String>) -> Self {
Self {
functionality: functionality.into(),
message: message.into(),
}
}
}