pub mod error;
pub use error::*;
use futures::stream::BoxStream;
use serde::{Deserialize, Serialize};
use std::{borrow::Cow, future::Future, pin::Pin, sync::Arc};
pub type BoxFuture<'a, T> = Pin<Box<dyn Future<Output = T> + Send + 'a>>;
pub trait AiModel: AsRef<str> + Send + Sync + 'static {
fn as_any(&self) -> &dyn std::any::Any;
fn model_id(&self) -> ModelId<'_>;
}
impl dyn AiModel {
pub fn downcast<M: 'static + Clone>(&self) -> Option<M> {
self.as_any().downcast_ref::<M>().cloned()
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize)]
pub struct ModelId<'a> {
pub id: Cow<'a, str>,
pub name: Cow<'a, str>,
}
impl std::fmt::Display for ModelId<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.name)
}
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct AiRequest {
pub text: String,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct AiResponse {
pub text: String,
pub token_usage: TokenUsage,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)]
pub struct TokenUsage {
pub input_tokens: Option<u64>,
pub output_tokens: Option<u64>,
pub total_tokens: Option<u64>,
}
pub trait AiProvider: Send + Sync {
fn send_request(
&self,
model: &dyn AiModel,
request: AiRequest,
) -> BoxFuture<'_, Result<AiResponse>>;
fn send_streaming(
&self,
model: &dyn AiModel,
request: AiRequest,
) -> BoxStream<'_, Result<AiResponse>>;
}
impl<T> AiProvider for &T
where
T: AiProvider + ?Sized,
{
fn send_request(
&self,
model: &dyn AiModel,
request: AiRequest,
) -> BoxFuture<'_, Result<AiResponse>> {
(**self).send_request(model, request)
}
fn send_streaming(
&self,
model: &dyn AiModel,
request: AiRequest,
) -> BoxStream<'_, Result<AiResponse>> {
(**self).send_streaming(model, request)
}
}
impl<T> AiProvider for &mut T
where
T: AiProvider + ?Sized,
{
fn send_request(
&self,
model: &dyn AiModel,
request: AiRequest,
) -> BoxFuture<'_, Result<AiResponse>> {
(**self).send_request(model, request)
}
fn send_streaming(
&self,
model: &dyn AiModel,
request: AiRequest,
) -> BoxStream<'_, Result<AiResponse>> {
(**self).send_streaming(model, request)
}
}
impl<T> AiProvider for Box<T>
where
T: AiProvider + ?Sized,
{
fn send_request(
&self,
model: &dyn AiModel,
request: AiRequest,
) -> BoxFuture<'_, Result<AiResponse>> {
(**self).send_request(model, request)
}
fn send_streaming(
&self,
model: &dyn AiModel,
request: AiRequest,
) -> BoxStream<'_, Result<AiResponse>> {
(**self).send_streaming(model, request)
}
}
impl<T> AiProvider for Arc<T>
where
T: AiProvider + ?Sized,
{
fn send_request(
&self,
model: &dyn AiModel,
request: AiRequest,
) -> BoxFuture<'_, Result<AiResponse>> {
(**self).send_request(model, request)
}
fn send_streaming(
&self,
model: &dyn AiModel,
request: AiRequest,
) -> BoxStream<'_, Result<AiResponse>> {
(**self).send_streaming(model, request)
}
}