1use crate::agent::AgentBuilder;
2use crate::client::{AsCompletion, ProviderClient};
3use crate::completion::{
4 CompletionError, CompletionModel, CompletionModelDyn, CompletionRequest, CompletionResponse,
5};
6use crate::extractor::ExtractorBuilder;
7use crate::streaming::StreamingCompletionResponse;
8use schemars::JsonSchema;
9use serde::{Deserialize, Serialize};
10use std::future::Future;
11use std::sync::Arc;
12
13pub trait CompletionClient: ProviderClient + Clone {
16 type CompletionModel: CompletionModel;
18
19 fn completion_model(&self, model: &str) -> Self::CompletionModel;
32
33 fn agent(&self, model: &str) -> AgentBuilder<Self::CompletionModel> {
49 AgentBuilder::new(self.completion_model(model))
50 }
51
52 fn extractor<T: JsonSchema + for<'a> Deserialize<'a> + Serialize + Send + Sync>(
54 &self,
55 model: &str,
56 ) -> ExtractorBuilder<T, Self::CompletionModel> {
57 ExtractorBuilder::new(self.completion_model(model))
58 }
59}
60
61#[derive(Clone)]
63pub struct CompletionModelHandle<'a> {
64 pub inner: Arc<dyn CompletionModelDyn + 'a>,
65}
66
67impl CompletionModel for CompletionModelHandle<'_> {
68 type Response = ();
69 type StreamingResponse = ();
70
71 fn completion(
72 &self,
73 request: CompletionRequest,
74 ) -> impl Future<Output = Result<CompletionResponse<Self::Response>, CompletionError>> + Send
75 {
76 self.inner.completion(request)
77 }
78
79 fn stream(
80 &self,
81 request: CompletionRequest,
82 ) -> impl Future<
83 Output = Result<StreamingCompletionResponse<Self::StreamingResponse>, CompletionError>,
84 > + Send {
85 self.inner.stream(request)
86 }
87}
88
89pub trait CompletionClientDyn: ProviderClient {
90 fn completion_model<'a>(&self, model: &str) -> Box<dyn CompletionModelDyn + 'a>;
92
93 fn agent<'a>(&self, model: &str) -> AgentBuilder<CompletionModelHandle<'a>>;
95}
96
97impl<
98 T: CompletionClient<CompletionModel = M>,
99 M: CompletionModel<StreamingResponse = R> + 'static,
100 R: Clone + Unpin + 'static,
101 > CompletionClientDyn for T
102{
103 fn completion_model<'a>(&self, model: &str) -> Box<dyn CompletionModelDyn + 'a> {
104 Box::new(self.completion_model(model))
105 }
106
107 fn agent<'a>(&self, model: &str) -> AgentBuilder<CompletionModelHandle<'a>> {
108 AgentBuilder::new(CompletionModelHandle {
109 inner: Arc::new(self.completion_model(model)),
110 })
111 }
112}
113
114impl<T: CompletionClientDyn + Clone + 'static> AsCompletion for T {
115 fn as_completion(&self) -> Option<Box<dyn CompletionClientDyn>> {
116 Some(Box::new(self.clone()))
117 }
118}