llm/models/
mod.rs

1use crate::{builder::LLMBackend, error::LLMError};
2use async_trait::async_trait;
3use chrono::{DateTime, Utc};
4use serde::{Deserialize, Serialize};
5use serde_json::Value;
6use std::fmt::Debug;
7
8pub trait ModelListResponse: Send + Sync {
9    fn get_models(&self) -> Vec<String>;
10    fn get_models_raw(&self) -> Vec<Box<dyn ModelListRawEntry>>;
11    fn get_backend(&self) -> LLMBackend;
12}
13
14pub trait ModelListRawEntry: Debug {
15    fn get_id(&self) -> String;
16    fn get_created_at(&self) -> DateTime<Utc>;
17    fn get_raw(&self) -> serde_json::Value;
18}
19
20#[derive(Debug, Clone, Default)]
21pub struct ModelListRequest {
22    pub filter: Option<String>,
23}
24
25/// Standard model entry structure used by OpenAI-compatible providers
26#[derive(Clone, Debug, Deserialize, Serialize)]
27pub struct StandardModelEntry {
28    pub id: String,
29    pub created: Option<u64>,
30    #[serde(flatten)]
31    pub extra: Value,
32}
33
34impl ModelListRawEntry for StandardModelEntry {
35    fn get_id(&self) -> String {
36        self.id.clone()
37    }
38
39    fn get_created_at(&self) -> DateTime<Utc> {
40        self.created
41            .map(|t| DateTime::from_timestamp(t as i64, 0).unwrap_or_default())
42            .unwrap_or_default()
43    }
44
45    fn get_raw(&self) -> Value {
46        self.extra.clone()
47    }
48}
49
50/// Inner structure for model list response data (serializable)
51#[derive(Clone, Debug, Deserialize, Serialize)]
52pub struct StandardModelListResponseInner {
53    pub data: Vec<StandardModelEntry>,
54}
55
56/// Standard model list response structure used by OpenAI-compatible providers
57#[derive(Clone, Debug)]
58pub struct StandardModelListResponse {
59    pub inner: StandardModelListResponseInner,
60    pub backend: LLMBackend,
61}
62
63impl ModelListResponse for StandardModelListResponse {
64    fn get_models(&self) -> Vec<String> {
65        self.inner.data.iter().map(|e| e.id.clone()).collect()
66    }
67
68    fn get_models_raw(&self) -> Vec<Box<dyn ModelListRawEntry>> {
69        self.inner
70            .data
71            .iter()
72            .map(|e| Box::new(e.clone()) as Box<dyn ModelListRawEntry>)
73            .collect()
74    }
75
76    fn get_backend(&self) -> LLMBackend {
77        self.backend.clone()
78    }
79}
80
81/// Trait for providers that support listing and retrieving model information.
82#[async_trait]
83pub trait ModelsProvider {
84    /// Asynchronously retrieves the list of available models ID's from the provider.
85    ///
86    /// # Arguments
87    ///
88    /// * `_request` - Optional filter by model ID
89    ///
90    /// # Returns
91    ///
92    /// List of model ID's or error
93    async fn list_models(
94        &self,
95        _request: Option<&ModelListRequest>,
96    ) -> Result<Box<dyn ModelListResponse>, LLMError> {
97        Err(LLMError::ProviderError(
98            "List Models not supported".to_string(),
99        ))
100    }
101}