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}