add support for openwebui (#487)

This commit is contained in:
Adil Hafeez 2025-05-28 19:08:00 -07:00 committed by GitHub
parent 4899117876
commit 9c4733590f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 150 additions and 24 deletions

View file

@ -3,7 +3,6 @@ use std::sync::Arc;
use bytes::Bytes;
use common::api::open_ai::ChatCompletionsRequest;
use common::consts::ARCH_PROVIDER_HINT_HEADER;
use common::utils::shorten_string;
use http_body_util::combinators::BoxBody;
use http_body_util::{BodyExt, Full, StreamBody};
use hyper::body::Frame;
@ -39,7 +38,7 @@ pub async fn chat_completions(
let v: Value = serde_json::from_slice(&chat_request_bytes).unwrap();
let err_msg = format!("Failed to parse request body: {}", err);
warn!("{}", err_msg);
warn!("request body: {}", v.to_string());
warn!("arch-router request body: {}", v.to_string());
let mut bad_request = Response::new(full(err_msg));
*bad_request.status_mut() = StatusCode::BAD_REQUEST;
return Ok(bad_request);
@ -47,8 +46,8 @@ pub async fn chat_completions(
};
debug!(
"request body: {}",
shorten_string(&serde_json::to_string(&chat_completion_request).unwrap())
"arch-router request body: {}",
&serde_json::to_string(&chat_completion_request).unwrap()
);
let trace_parent = request_headers
@ -56,7 +55,7 @@ pub async fn chat_completions(
.find(|(ty, _)| ty.as_str() == "traceparent")
.map(|(_, value)| value.to_str().unwrap_or_default().to_string());
let selected_llm = match router_service
let mut selected_llm = match router_service
.determine_route(&chat_completion_request.messages, trace_parent.clone())
.await
{
@ -69,6 +68,11 @@ pub async fn chat_completions(
}
};
if selected_llm.is_none() {
debug!("No LLM model selected, using default from request");
selected_llm = Some(chat_completion_request.model.clone());
}
info!(
"sending request to llm provider: {} with llm model: {:?}",
llm_provider_endpoint, selected_llm

View file

@ -1 +1,2 @@
pub mod chat_completions;
pub mod models;

View file

@ -0,0 +1,40 @@
use bytes::Bytes;
use common::api::open_ai::Models;
use common::configuration::LlmProvider;
use http_body_util::{combinators::BoxBody, BodyExt, Full};
use hyper::{Response, StatusCode};
use serde_json;
use std::sync::Arc;
pub async fn list_models(
llm_providers: Arc<Vec<LlmProvider>>,
) -> Response<BoxBody<Bytes, hyper::Error>> {
let prov = llm_providers.clone();
let providers = (*prov).clone();
let openai_models = Models::from(providers);
match serde_json::to_string(&openai_models) {
Ok(json) => {
let body = Full::new(Bytes::from(json))
.map_err(|never| match never {})
.boxed();
Response::builder()
.status(StatusCode::OK)
.header("Content-Type", "application/json")
.body(body)
.unwrap()
}
Err(_) => {
let body = Full::new(Bytes::from_static(
b"{\"error\":\"Failed to serialize models\"}",
))
.map_err(|never| match never {})
.boxed();
Response::builder()
.status(StatusCode::INTERNAL_SERVER_ERROR)
.header("Content-Type", "application/json")
.body(body)
.unwrap()
}
}
}

View file

@ -1,4 +1,5 @@
use brightstaff::handlers::chat_completions::chat_completions;
use brightstaff::handlers::models::list_models;
use brightstaff::router::llm_router::RouterService;
use brightstaff::utils::tracing::init_tracer;
use bytes::Bytes;
@ -52,6 +53,8 @@ async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
let arch_config = Arc::new(config);
let llm_providers = Arc::new(arch_config.llm_providers.clone());
debug!(
"arch_config: {:?}",
&serde_json::to_string(arch_config.as_ref()).unwrap()
@ -84,10 +87,12 @@ async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
let router_service = Arc::clone(&router_service);
let llm_provider_endpoint = llm_provider_endpoint.clone();
let llm_providers = llm_providers.clone();
let service = service_fn(move |req| {
let router_service = Arc::clone(&router_service);
let parent_cx = extract_context_from_request(&req);
let llm_provider_endpoint = llm_provider_endpoint.clone();
let llm_providers = llm_providers.clone();
async move {
match (req.method(), req.uri().path()) {
@ -96,6 +101,35 @@ async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
.with_context(parent_cx)
.await
}
(&Method::GET, "/v1/models") => {
Ok(list_models(llm_providers).await)
}
(&Method::OPTIONS, "/v1/models") => {
let mut response = Response::new(empty());
*response.status_mut() = StatusCode::NO_CONTENT;
response.headers_mut().insert(
"Allow",
"GET, OPTIONS".parse().unwrap(),
);
response.headers_mut().insert(
"Access-Control-Allow-Origin",
"*".parse().unwrap(),
);
response.headers_mut().insert(
"Access-Control-Allow-Headers",
"Authorization, Content-Type".parse().unwrap(),
);
response.headers_mut().insert(
"Access-Control-Allow-Methods",
"GET, POST, OPTIONS".parse().unwrap(),
);
response.headers_mut().insert(
"Content-Type",
"application/json".parse().unwrap(),
);
Ok(response)
}
_ => {
let mut not_found = Response::new(empty());
*not_found.status_mut() = StatusCode::NOT_FOUND;