rig/client/
embeddings.rs

1use crate::Embed;
2use crate::client::{AsEmbeddings, ProviderClient};
3use crate::embeddings::embedding::EmbeddingModelDyn;
4use crate::embeddings::{EmbeddingModel, EmbeddingsBuilder};
5
6/// A provider client with embedding capabilities.
7/// Clone is required for conversions between client types.
8pub trait EmbeddingsClient: ProviderClient + Clone {
9    /// The type of EmbeddingModel used by the Client
10    type EmbeddingModel: EmbeddingModel;
11
12    /// Create an embedding model with the given name.
13    /// Note: default embedding dimension of 0 will be used if model is not known.
14    /// If this is the case, it's better to use function `embedding_model_with_ndims`
15    ///
16    /// # Example
17    /// ```
18    /// use rig::prelude::*;
19    /// use rig::providers::openai::{Client, self};
20    ///
21    /// // Initialize the OpenAI client
22    /// let openai = Client::new("your-open-ai-api-key");
23    ///
24    /// let embedding_model = openai.embedding_model(openai::TEXT_EMBEDDING_3_LARGE);
25    /// ```
26    fn embedding_model(&self, model: &str) -> Self::EmbeddingModel;
27
28    /// Create an embedding model with the given name and the number of dimensions in the embedding generated by the model.
29    ///
30    /// # Example with OpenAI
31    /// ```
32    /// use rig::prelude::*;
33    /// use rig::providers::openai::{Client, self};
34    ///
35    /// // Initialize the OpenAI client
36    /// let openai = Client::new("your-open-ai-api-key");
37    ///
38    /// let embedding_model = openai.embedding_model("model-unknown-to-rig", 3072);
39    /// ```
40    fn embedding_model_with_ndims(&self, model: &str, ndims: usize) -> Self::EmbeddingModel;
41
42    /// Create an embedding builder with the given embedding model.
43    ///
44    /// # Example with OpenAI
45    /// ```
46    /// use rig::prelude::*;
47    /// use rig::providers::openai::{Client, self};
48    ///
49    /// // Initialize the OpenAI client
50    /// let openai = Client::new("your-open-ai-api-key");
51    ///
52    /// let embeddings = openai.embeddings(openai::TEXT_EMBEDDING_3_LARGE)
53    ///     .simple_document("doc0", "Hello, world!")
54    ///     .simple_document("doc1", "Goodbye, world!")
55    ///     .build()
56    ///     .await
57    ///     .expect("Failed to embed documents");
58    /// ```
59    fn embeddings<D: Embed>(&self, model: &str) -> EmbeddingsBuilder<Self::EmbeddingModel, D> {
60        EmbeddingsBuilder::new(self.embedding_model(model))
61    }
62
63    /// Create an embedding builder with the given name and the number of dimensions in the embedding generated by the model.
64    ///
65    /// # Example with OpenAI
66    /// ```
67    /// use rig::prelude::*;
68    /// use rig::providers::openai::{Client, self};
69    ///
70    /// // Initialize the OpenAI client
71    /// let openai = Client::new("your-open-ai-api-key");
72    ///
73    /// let embeddings = openai.embeddings_with_ndims(openai::TEXT_EMBEDDING_3_LARGE, 3072)
74    ///     .simple_document("doc0", "Hello, world!")
75    ///     .simple_document("doc1", "Goodbye, world!")
76    ///     .build()
77    ///     .await
78    ///     .expect("Failed to embed documents");
79    /// ```
80    fn embeddings_with_ndims<D: Embed>(
81        &self,
82        model: &str,
83        ndims: usize,
84    ) -> EmbeddingsBuilder<Self::EmbeddingModel, D> {
85        EmbeddingsBuilder::new(self.embedding_model_with_ndims(model, ndims))
86    }
87}
88
89pub trait EmbeddingsClientDyn: ProviderClient {
90    /// Create an embedding model with the given name.
91    /// Note: default embedding dimension of 0 will be used if model is not known.
92    /// If this is the case, it's better to use function `embedding_model_with_ndims`
93    fn embedding_model<'a>(&self, model: &str) -> Box<dyn EmbeddingModelDyn + 'a>;
94
95    /// Create an embedding model with the given name and the number of dimensions in the embedding generated by the model.
96    fn embedding_model_with_ndims<'a>(
97        &self,
98        model: &str,
99        ndims: usize,
100    ) -> Box<dyn EmbeddingModelDyn + 'a>;
101}
102
103impl<T: EmbeddingsClient<EmbeddingModel = M>, M: EmbeddingModel + 'static> EmbeddingsClientDyn
104    for T
105{
106    fn embedding_model<'a>(&self, model: &str) -> Box<dyn EmbeddingModelDyn + 'a> {
107        Box::new(self.embedding_model(model))
108    }
109
110    fn embedding_model_with_ndims<'a>(
111        &self,
112        model: &str,
113        ndims: usize,
114    ) -> Box<dyn EmbeddingModelDyn + 'a> {
115        Box::new(self.embedding_model_with_ndims(model, ndims))
116    }
117}
118
119impl<T: EmbeddingsClientDyn + Clone + 'static> AsEmbeddings for T {
120    fn as_embeddings(&self) -> Option<Box<dyn EmbeddingsClientDyn>> {
121        Some(Box::new(self.clone()))
122    }
123}