diff --git a/crates/tabby-common/src/config.rs b/crates/tabby-common/src/config.rs index 51ab892129f..32d5315ae55 100644 --- a/crates/tabby-common/src/config.rs +++ b/crates/tabby-common/src/config.rs @@ -252,6 +252,10 @@ pub struct HttpModelConfig { /// Used by Completion API to construct a chat model. #[builder(default)] pub chat_template: Option, + + /// Used by Chat/Completion API allowing users to get supported models info. + #[builder(default)] + pub supported_models: Option>, } #[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] diff --git a/crates/tabby/src/routes/mod.rs b/crates/tabby/src/routes/mod.rs index 87882854c20..9cf78e49ce6 100644 --- a/crates/tabby/src/routes/mod.rs +++ b/crates/tabby/src/routes/mod.rs @@ -56,10 +56,12 @@ mod chat; mod completions; mod events; mod health; +mod models; mod server_setting; pub use chat::*; pub use completions::*; pub use events::*; pub use health::*; +pub use models::*; pub use server_setting::*; diff --git a/crates/tabby/src/routes/models.rs b/crates/tabby/src/routes/models.rs new file mode 100644 index 00000000000..320984fba90 --- /dev/null +++ b/crates/tabby/src/routes/models.rs @@ -0,0 +1,53 @@ +use std::sync::Arc; + +use axum::{extract::State, Json}; +use serde::{Deserialize, Serialize}; +use utoipa::ToSchema; + +#[derive(Serialize, Deserialize, ToSchema, Clone, Debug)] +pub struct ModelInfo { + completion: Option>, + chat: Option>, +} + +impl From for ModelInfo { + fn from(value: tabby_common::config::Config) -> Self { + let models = value.model; + let mut http_model_configs: ModelInfo = ModelInfo { + completion: None, + chat: None, + }; + + if let Some(tabby_common::config::ModelConfig::Http(completion_http_config)) = + models.completion + { + if let Some(models) = completion_http_config.supported_models { + http_model_configs.completion = Some(models.clone()); + } + } + + if let Some(tabby_common::config::ModelConfig::Http(chat_http_config)) = models.chat { + if let Some(models) = chat_http_config.supported_models { + http_model_configs.chat = Some(models.clone()); + } + } + + http_model_configs + } +} + +#[utoipa::path( + get, + path = "/v1beta/models", + tag = "v1beta", + operation_id = "config", + responses( + (status = 200, description = "Success", body = ServerSetting, content_type = "application/json"), + ), + security( + ("token" = []) + ) +)] +pub async fn models(State(state): State>) -> Json { + Json(state.as_ref().clone()) +} diff --git a/crates/tabby/src/serve.rs b/crates/tabby/src/serve.rs index 7a0cfb02cd1..0a2014c4bad 100644 --- a/crates/tabby/src/serve.rs +++ b/crates/tabby/src/serve.rs @@ -257,6 +257,8 @@ async fn api_router( "/v1/health", routing::get(routes::health).with_state(health_state), ) + .route("/v1beta/models", routing::get(routes::models)) + .with_state(Arc::new(config.clone().into())) }); if let Some(completion_state) = completion_state {