batch_mode_batch_client/language_model_client_interface.rs
1// ---------------- [ File: batch-mode-batch-client/src/language_model_client_interface.rs ]
2crate::ix!();
3
4/*
5 To make a trait object-safe, we cannot have any methods that use generics
6 (`impl Trait` or a type parameter in the method signature). Previously,
7 `UploadBatchFile` included `upload_batch_file<P>`, causing object safety issues.
8
9 The fix is to split the functionality into:
10
11 1) An object-safe "core" trait (no generic methods).
12 2) An optional "extension" trait that adds the generic convenience method.
13
14 Then our aggregator trait references only the *core* trait, ensuring no
15 generic methods are included, which makes it object-safe.
16*/
17
18/* ================================
19 Sub-traits: object-safe methods
20 ================================
21*/
22
23#[async_trait]
24pub trait RetrieveBatchById: Send + Sync {
25 type Error;
26 async fn retrieve_batch(&self, batch_id: &str) -> Result<Batch, Self::Error>;
27}
28
29#[async_trait]
30pub trait GetBatchFileContent: Send + Sync {
31 type Error;
32 async fn file_content(&self, file_id: &str) -> Result<Bytes, Self::Error>;
33}
34
35/*
36 "Core" trait for uploading a file, object-safe:
37 no generic parameters or `impl Trait` in the signature.
38*/
39#[async_trait]
40pub trait UploadBatchFileCore: Send + Sync {
41 type Error;
42
43 async fn upload_batch_file_path(
44 &self,
45 file_path: &Path
46 ) -> Result<OpenAIFile, Self::Error>;
47}
48
49/*
50 OPTIONAL "extension" trait that provides a convenience
51 generic method. This trait is NOT object-safe, but doesn't
52 need to be used as a trait object. It is purely for convenience.
53*/
54#[async_trait]
55pub trait UploadBatchFileExt: UploadBatchFileCore {
56 async fn upload_batch_file<P>(
57 &self,
58 file_path: P
59 ) -> Result<OpenAIFile, Self::Error>
60 where
61 P: AsRef<Path> + Send + Sync,
62 {
63 // Default implementation simply calls the object-safe method
64 self.upload_batch_file_path(file_path.as_ref()).await
65 }
66}
67
68#[async_trait]
69pub trait CreateBatch: Send + Sync {
70 type Error;
71 async fn create_batch(
72 &self,
73 input_file_id: &str,
74 ) -> Result<Batch, Self::Error>;
75}
76
77#[async_trait]
78pub trait WaitForBatchCompletion: Send + Sync {
79 type Error;
80 async fn wait_for_batch_completion(
81 &self,
82 batch_id: &str,
83 ) -> Result<Batch, Self::Error>;
84}
85
86/*
87 =========================================================
88 Aggregator trait referencing ONLY the object-safe methods
89 =========================================================
90
91 Critically, we only inherit from `UploadBatchFileCore`
92 (NOT from the extension trait). This ensures we do NOT
93 pull in the generic method into the aggregator, keeping
94 it object-safe.
95*/
96#[async_trait]
97pub trait LanguageModelClientInterface<E: Debug>:
98 RetrieveBatchById<Error = E>
99 + GetBatchFileContent<Error = E>
100 + UploadBatchFileCore<Error = E>
101 + CreateBatch<Error = E>
102 + WaitForBatchCompletion<Error = E>
103 + Send
104 + Sync
105 + Debug
106{
107 // No generic methods here => object safe
108}
109
110/*
111 Finally, the trait to fetch an LM client object as a trait object:
112 This is now possible because we only reference the aggregator
113 (which is object-safe).
114*/
115pub trait GetLanguageModelClient<E> {
116 fn language_model_client(&self) -> Arc<dyn LanguageModelClientInterface<E>>;
117}