(&self, texts: &[String])
| 194 | } |
| 195 | |
| 196 | async fn embed_voyage(&self, texts: &[String]) -> Result<Vec<Vec<f32>>, AiError> { |
| 197 | let api_key = self.api_key.as_ref().ok_or(AiError::NoApiKey)?; |
| 198 | |
| 199 | let body = serde_json::json!({ |
| 200 | "model": self.model, |
| 201 | "input": texts, |
| 202 | "input_type": "document" |
| 203 | }); |
| 204 | |
| 205 | let client = reqwest::Client::new(); |
| 206 | let resp = client |
| 207 | .post("https://api.voyageai.com/v1/embeddings") |
| 208 | .header("Authorization", format!("Bearer {}", api_key)) |
| 209 | .header("content-type", "application/json") |
| 210 | .json(&body) |
| 211 | .send() |
| 212 | .await |
| 213 | .map_err(|e| AiError::Http(e.to_string()))?; |
| 214 | |
| 215 | if !resp.status().is_success() { |
| 216 | let status = resp.status(); |
| 217 | let text = resp.text().await.unwrap_or_default(); |
| 218 | return Err(AiError::ApiError { |
| 219 | status: status.as_u16(), |
| 220 | body: text, |
| 221 | }); |
| 222 | } |
| 223 | |
| 224 | let json: serde_json::Value = resp |
| 225 | .json() |
| 226 | .await |
| 227 | .map_err(|e| AiError::Http(e.to_string()))?; |
| 228 | |
| 229 | parse_embedding_response(&json) |
| 230 | } |
| 231 | |
| 232 | async fn embed_openai(&self, texts: &[String]) -> Result<Vec<Vec<f32>>, AiError> { |
| 233 | let api_key = self.api_key.as_ref().ok_or(AiError::NoApiKey)?; |
no test coverage detected