linger_openai_sdk/
embeddings.rs1use crate::error::LingerError;
2use crate::RequestId;
3use serde::{Deserialize, Serialize};
4use serde_json::Value;
5use std::collections::BTreeMap;
6
7#[derive(Clone, Debug, Serialize, PartialEq)]
10#[non_exhaustive]
11pub struct CreateEmbeddingRequest {
12 pub model: String,
15 pub input: EmbeddingInput,
18 #[serde(skip_serializing_if = "Option::is_none")]
21 pub encoding_format: Option<EmbeddingEncodingFormat>,
22 #[serde(skip_serializing_if = "Option::is_none")]
25 pub dimensions: Option<u32>,
26 #[serde(skip_serializing_if = "Option::is_none")]
29 pub user: Option<String>,
30 #[serde(flatten)]
33 pub extra: BTreeMap<String, Value>,
34}
35
36impl CreateEmbeddingRequest {
37 pub fn builder() -> CreateEmbeddingRequestBuilder {
40 CreateEmbeddingRequestBuilder::default()
41 }
42}
43
44#[derive(Clone, Debug, Default)]
47#[non_exhaustive]
48pub struct CreateEmbeddingRequestBuilder {
49 model: Option<String>,
50 input: Option<EmbeddingInput>,
51 encoding_format: Option<EmbeddingEncodingFormat>,
52 dimensions: Option<u32>,
53 user: Option<String>,
54 extra: BTreeMap<String, Value>,
55}
56
57impl CreateEmbeddingRequestBuilder {
58 pub fn model(mut self, model: impl Into<String>) -> Self {
61 self.model = Some(model.into());
62 self
63 }
64
65 pub fn input(mut self, input: impl Into<EmbeddingInput>) -> Self {
68 self.input = Some(input.into());
69 self
70 }
71
72 pub fn encoding_format(mut self, encoding_format: EmbeddingEncodingFormat) -> Self {
75 self.encoding_format = Some(encoding_format);
76 self
77 }
78
79 pub fn dimensions(mut self, dimensions: u32) -> Self {
82 self.dimensions = Some(dimensions);
83 self
84 }
85
86 pub fn user(mut self, user: impl Into<String>) -> Self {
89 self.user = Some(user.into());
90 self
91 }
92
93 pub fn extra(mut self, name: impl Into<String>, value: Value) -> Self {
96 self.extra.insert(name.into(), value);
97 self
98 }
99
100 pub fn build(self) -> Result<CreateEmbeddingRequest, LingerError> {
103 let model = self
104 .model
105 .filter(|value| !value.trim().is_empty())
106 .ok_or_else(|| LingerError::invalid_config("model is required"))?;
107 let input = self
108 .input
109 .ok_or_else(|| LingerError::invalid_config("input is required"))?;
110 if input.is_empty() {
111 return Err(LingerError::invalid_config("input must not be empty"));
112 }
113 Ok(CreateEmbeddingRequest {
114 model,
115 input,
116 encoding_format: self.encoding_format,
117 dimensions: self.dimensions,
118 user: self.user,
119 extra: self.extra,
120 })
121 }
122}
123
124#[derive(Clone, Debug, Serialize, PartialEq, Eq)]
127#[serde(untagged)]
128#[non_exhaustive]
129pub enum EmbeddingInput {
130 Text(String),
133 Texts(Vec<String>),
136}
137
138impl EmbeddingInput {
139 fn is_empty(&self) -> bool {
140 match self {
141 Self::Text(value) => value.is_empty(),
142 Self::Texts(values) => values.is_empty() || values.iter().any(String::is_empty),
143 }
144 }
145}
146
147impl From<&str> for EmbeddingInput {
148 fn from(value: &str) -> Self {
149 Self::Text(value.to_string())
150 }
151}
152
153impl From<String> for EmbeddingInput {
154 fn from(value: String) -> Self {
155 Self::Text(value)
156 }
157}
158
159impl From<Vec<String>> for EmbeddingInput {
160 fn from(value: Vec<String>) -> Self {
161 Self::Texts(value)
162 }
163}
164
165#[derive(Clone, Copy, Debug, Serialize, PartialEq, Eq)]
168#[serde(rename_all = "snake_case")]
169#[non_exhaustive]
170pub enum EmbeddingEncodingFormat {
171 Float,
174 Base64,
177}
178
179#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
182#[non_exhaustive]
183pub struct EmbeddingResponse {
184 pub object: String,
187 #[serde(default)]
190 pub data: Vec<Embedding>,
191 pub model: String,
194 pub usage: EmbeddingUsage,
197 #[serde(skip)]
200 request_id: Option<RequestId>,
201}
202
203impl EmbeddingResponse {
204 pub(crate) fn with_request_id(mut self, request_id: Option<RequestId>) -> Self {
205 self.request_id = request_id;
206 self
207 }
208
209 pub fn request_id(&self) -> Option<&RequestId> {
212 self.request_id.as_ref()
213 }
214}
215
216#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
219#[non_exhaustive]
220pub struct Embedding {
221 pub object: String,
224 pub embedding: Vec<f32>,
227 pub index: u32,
230}
231
232#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
235#[non_exhaustive]
236pub struct EmbeddingUsage {
237 pub prompt_tokens: u64,
240 pub total_tokens: u64,
243}