rig/embeddings/
embedding.rs1use crate::{
10 http_client,
11 wasm_compat::{WasmCompatSend, WasmCompatSync},
12};
13use serde::{Deserialize, Serialize};
14
15#[derive(Debug, thiserror::Error)]
16pub enum EmbeddingError {
17 #[error("HttpError: {0}")]
19 HttpError(#[from] http_client::Error),
20
21 #[error("JsonError: {0}")]
23 JsonError(#[from] serde_json::Error),
24
25 #[error("UrlError: {0}")]
26 UrlError(#[from] url::ParseError),
27
28 #[cfg(not(target_family = "wasm"))]
29 #[error("DocumentError: {0}")]
31 DocumentError(Box<dyn std::error::Error + Send + Sync + 'static>),
32
33 #[cfg(target_family = "wasm")]
34 #[error("DocumentError: {0}")]
36 DocumentError(Box<dyn std::error::Error + 'static>),
37
38 #[error("ResponseError: {0}")]
40 ResponseError(String),
41
42 #[error("ProviderError: {0}")]
44 ProviderError(String),
45}
46
47pub trait EmbeddingModel: WasmCompatSend + WasmCompatSync {
49 const MAX_DOCUMENTS: usize;
51
52 type Client;
53
54 fn make(client: &Self::Client, model: impl Into<String>, dims: Option<usize>) -> Self;
55
56 fn ndims(&self) -> usize;
58
59 fn embed_texts(
61 &self,
62 texts: impl IntoIterator<Item = String> + WasmCompatSend,
63 ) -> impl std::future::Future<Output = Result<Vec<Embedding>, EmbeddingError>> + WasmCompatSend;
64
65 fn embed_text(
67 &self,
68 text: &str,
69 ) -> impl std::future::Future<Output = Result<Embedding, EmbeddingError>> + WasmCompatSend {
70 async {
71 let mut embeddings = self.embed_texts(vec![text.to_string()]).await?;
72 embeddings.pop().ok_or_else(|| {
73 EmbeddingError::ResponseError(
74 "embedding provider returned an empty response for embed_text".to_string(),
75 )
76 })
77 }
78 }
79}
80
81pub trait ImageEmbeddingModel: Clone + WasmCompatSend + WasmCompatSync {
83 const MAX_DOCUMENTS: usize;
85
86 fn ndims(&self) -> usize;
88
89 fn embed_images(
91 &self,
92 images: impl IntoIterator<Item = Vec<u8>> + WasmCompatSend,
93 ) -> impl std::future::Future<Output = Result<Vec<Embedding>, EmbeddingError>> + Send;
94
95 fn embed_image<'a>(
97 &'a self,
98 bytes: &'a [u8],
99 ) -> impl std::future::Future<Output = Result<Embedding, EmbeddingError>> + WasmCompatSend {
100 async move {
101 let mut embeddings = self.embed_images(vec![bytes.to_owned()]).await?;
102 embeddings.pop().ok_or_else(|| {
103 EmbeddingError::ResponseError(
104 "embedding provider returned an empty response for embed_image".to_string(),
105 )
106 })
107 }
108 }
109}
110
111#[derive(Clone, Default, Deserialize, Serialize, Debug)]
113pub struct Embedding {
114 pub document: String,
116 pub vec: Vec<f64>,
118}
119
120impl PartialEq for Embedding {
121 fn eq(&self, other: &Self) -> bool {
122 self.document == other.document
123 }
124}
125
126impl Eq for Embedding {}