use std::sync::Arc;
use axum::extract::State;
use axum::http::StatusCode;
use axum::response::{IntoResponse, Json, Response};
use crate::openai::{ModelInfo, ModelListResponse};
use super::compact::openai_error_response;
pub async fn list_models(
State(host): State<Arc<crate::main_modules::model_host::ModelHost>>,
) -> Json<ModelListResponse> {
let Some(state) = host.current() else {
return Json(ModelListResponse {
object: "list".to_string(),
data: Vec::new(),
});
};
const MAX_ADVERTISED_MODELS: usize = 1024;
let advertised = state.adapter_names.len().min(MAX_ADVERTISED_MODELS);
let mut data = Vec::with_capacity(advertised.saturating_add(1));
for adapter in state.adapter_names.iter().take(MAX_ADVERTISED_MODELS) {
data.push(ModelInfo::advertise(adapter.clone(), state.max_seq_len));
}
for name in state
.lora_stageable
.keys()
.chain(state.lora_disk_stageable.keys())
.take(MAX_ADVERTISED_MODELS.saturating_sub(data.len()))
{
data.push(ModelInfo::advertise(name.clone(), state.max_seq_len));
}
data.push(ModelInfo::advertise(
state.model_name.clone(),
state.max_seq_len,
));
Json(ModelListResponse {
object: "list".to_string(),
data,
})
}
pub async fn get_model(
State(host): State<Arc<crate::main_modules::model_host::ModelHost>>,
axum::extract::Path(model_id): axum::extract::Path<String>,
) -> Response {
let Some(state) = host.current() else {
return (
axum::http::StatusCode::NOT_FOUND,
Json(serde_json::json!({
"error": {
"message": crate::error_hints::message_with_hint(
"no model is loaded",
"model_not_loaded",
),
"type": "model_not_loaded",
"hint": crate::error_hints::hint_for("model_not_loaded"),
}
})),
)
.into_response();
};
let known = model_id == state.model_name
|| state.adapter_names.iter().any(|n| n == &model_id)
|| state.is_stageable_name(&model_id);
if known {
Json(serde_json::json!({
"id": model_id,
"object": "model",
"created": crate::ids::unix_timestamp(),
"owned_by": crate::identity::OWNED_BY,
"max_model_len": state.max_seq_len,
}))
.into_response()
} else {
openai_error_response(
StatusCode::NOT_FOUND,
format!("The model '{model_id}' does not exist"),
)
}
}
pub async fn embeddings_stub() -> Response {
openai_error_response(
StatusCode::NOT_IMPLEMENTED,
"Embeddings are not supported by this model. Metrale Engine serves generative (chat/completion) models only.".into(),
)
}