use std::{future::Future, pin::Pin, sync::Arc};
use crate::{
error::Result,
generic::GenericChatCompletionResponse,
provider::{
ChatCompleteParameters, ChatCompletionProvider, PromptExecutionProvider,
StreamingChatProvider,
},
template::{IntoPrompt, PromptTemplate},
};
#[derive(Debug, Clone)]
pub struct ArtificialClient<B> {
backend: Arc<B>,
}
impl<B> ArtificialClient<B>
where
B: PromptExecutionProvider,
{
pub fn new(backend: B) -> Self {
Self {
backend: Arc::new(backend),
}
}
pub fn backend(&self) -> &B {
&self.backend
}
}
impl<B: PromptExecutionProvider> PromptExecutionProvider for ArtificialClient<B> {
type Message = B::Message;
fn prompt_execute<'a, 'p, P>(
&'a self,
prompt: P,
) -> Pin<Box<dyn Future<Output = Result<GenericChatCompletionResponse<P::Output>>> + Send + 'p>>
where
'a: 'p,
P: PromptTemplate + Send + Sync + 'p,
<P as IntoPrompt>::Message: Into<Self::Message>,
{
let backend = Arc::clone(&self.backend);
Box::pin(async move { backend.prompt_execute(prompt).await })
}
}
impl<B: ChatCompletionProvider> ChatCompletionProvider for ArtificialClient<B> {
type Message = B::Message;
fn chat_complete<'p, M>(
&self,
params: ChatCompleteParameters<M>,
) -> Pin<
Box<
dyn Future<
Output = Result<GenericChatCompletionResponse<crate::generic::GenericMessage>>,
> + Send
+ 'p,
>,
>
where
M: Into<Self::Message> + Send + Sync + 'p,
{
self.backend.chat_complete(params)
}
}
impl<B: StreamingChatProvider> StreamingChatProvider for ArtificialClient<B> {
type Delta<'s>
= B::Delta<'s>
where
Self: 's;
fn chat_complete_stream<'p, M>(&self, params: ChatCompleteParameters<M>) -> Self::Delta<'p>
where
M: Into<Self::Message> + Send + Sync + 'p,
{
self.backend.chat_complete_stream(params)
}
}