use std::sync::Arc;
use async_trait::async_trait;
use crate::providers::{
AnthropicAdapter, AnthropicAdapterConfig, OpenAiAdapter, OpenAiAdapterConfig,
OpenAiCompatibleAdapter, OpenAiCompatibleAdapterConfig, ProviderChatRequest,
ProviderChatResponse, ProviderEmbedRequest, ProviderEmbeddingResponse, ProviderGenerateRequest,
ProviderGenerateResponse, ProviderKind, ProviderModel, ProviderRequestContext, ProviderResult,
ProviderStream, ProviderStreamEvent,
};
#[async_trait]
pub trait ProviderBackend: Send + Sync {
fn kind(&self) -> ProviderKind;
async fn list_models(&self) -> ProviderResult<Vec<ProviderModel>>;
async fn get_model(&self, model: &str) -> ProviderResult<ProviderModel>;
async fn chat(&self, req: ProviderChatRequest) -> ProviderResult<ProviderChatResponse>;
async fn chat_with_context(
&self,
_context: ProviderRequestContext,
req: ProviderChatRequest,
) -> ProviderResult<ProviderChatResponse> {
self.chat(req).await
}
async fn generate(
&self,
req: ProviderGenerateRequest,
) -> ProviderResult<ProviderGenerateResponse>;
async fn generate_with_context(
&self,
_context: ProviderRequestContext,
req: ProviderGenerateRequest,
) -> ProviderResult<ProviderGenerateResponse> {
self.generate(req).await
}
async fn stream_generate(
&self,
req: ProviderGenerateRequest,
) -> ProviderResult<ProviderStream<ProviderStreamEvent>>;
async fn stream_generate_with_context(
&self,
_context: ProviderRequestContext,
req: ProviderGenerateRequest,
) -> ProviderResult<ProviderStream<ProviderStreamEvent>> {
self.stream_generate(req).await
}
async fn embed(&self, req: ProviderEmbedRequest) -> ProviderResult<ProviderEmbeddingResponse>;
async fn embed_with_context(
&self,
_context: ProviderRequestContext,
req: ProviderEmbedRequest,
) -> ProviderResult<ProviderEmbeddingResponse> {
self.embed(req).await
}
async fn stream_chat(
&self,
req: ProviderChatRequest,
) -> ProviderResult<ProviderStream<ProviderStreamEvent>>;
async fn stream_chat_with_context(
&self,
_context: ProviderRequestContext,
req: ProviderChatRequest,
) -> ProviderResult<ProviderStream<ProviderStreamEvent>> {
self.stream_chat(req).await
}
}
#[derive(Clone)]
pub struct ProviderTransport {
backend: Arc<dyn ProviderBackend>,
}
impl ProviderTransport {
pub fn from_backend(backend: Arc<dyn ProviderBackend>) -> Self {
Self { backend }
}
pub fn openai_compatible(config: OpenAiCompatibleAdapterConfig) -> ProviderResult<Self> {
Ok(Self::from_backend(Arc::new(OpenAiCompatibleAdapter::new(
config,
)?)))
}
pub fn openai(config: OpenAiAdapterConfig) -> ProviderResult<Self> {
Ok(Self::from_backend(Arc::new(OpenAiAdapter::new(config)?)))
}
pub fn anthropic(config: AnthropicAdapterConfig) -> ProviderResult<Self> {
Ok(Self::from_backend(Arc::new(AnthropicAdapter::new(config)?)))
}
pub fn kind(&self) -> ProviderKind {
self.backend.kind()
}
pub async fn list_models(&self) -> ProviderResult<Vec<ProviderModel>> {
self.backend.list_models().await
}
pub async fn get_model(&self, model: &str) -> ProviderResult<ProviderModel> {
self.backend.get_model(model).await
}
pub async fn chat(&self, req: ProviderChatRequest) -> ProviderResult<ProviderChatResponse> {
self.backend.chat(req).await
}
pub async fn chat_with_context(
&self,
context: ProviderRequestContext,
req: ProviderChatRequest,
) -> ProviderResult<ProviderChatResponse> {
self.backend.chat_with_context(context, req).await
}
pub async fn generate(
&self,
req: ProviderGenerateRequest,
) -> ProviderResult<ProviderGenerateResponse> {
self.backend.generate(req).await
}
pub async fn generate_with_context(
&self,
context: ProviderRequestContext,
req: ProviderGenerateRequest,
) -> ProviderResult<ProviderGenerateResponse> {
self.backend.generate_with_context(context, req).await
}
pub async fn stream_generate(
&self,
req: ProviderGenerateRequest,
) -> ProviderResult<ProviderStream<ProviderStreamEvent>> {
self.backend.stream_generate(req).await
}
pub async fn stream_generate_with_context(
&self,
context: ProviderRequestContext,
req: ProviderGenerateRequest,
) -> ProviderResult<ProviderStream<ProviderStreamEvent>> {
self.backend
.stream_generate_with_context(context, req)
.await
}
pub async fn embed(
&self,
req: ProviderEmbedRequest,
) -> ProviderResult<ProviderEmbeddingResponse> {
self.backend.embed(req).await
}
pub async fn embed_with_context(
&self,
context: ProviderRequestContext,
req: ProviderEmbedRequest,
) -> ProviderResult<ProviderEmbeddingResponse> {
self.backend.embed_with_context(context, req).await
}
pub async fn stream_chat(
&self,
req: ProviderChatRequest,
) -> ProviderResult<ProviderStream<ProviderStreamEvent>> {
self.backend.stream_chat(req).await
}
pub async fn stream_chat_with_context(
&self,
context: ProviderRequestContext,
req: ProviderChatRequest,
) -> ProviderResult<ProviderStream<ProviderStreamEvent>> {
self.backend.stream_chat_with_context(context, req).await
}
}