Parse the standard embedding API response format (shared by OpenAI and Voyage).
(json: &serde_json::Value)
| 267 | |
| 268 | /// Parse the standard embedding API response format (shared by OpenAI and Voyage). |
| 269 | fn parse_embedding_response(json: &serde_json::Value) -> Result<Vec<Vec<f32>>, AiError> { |
| 270 | let data = json["data"] |
| 271 | .as_array() |
| 272 | .ok_or_else(|| AiError::ParseError("missing 'data' array".to_string()))?; |
| 273 | |
| 274 | let mut vectors = Vec::with_capacity(data.len()); |
| 275 | for item in data { |
| 276 | let embedding = item["embedding"] |
| 277 | .as_array() |
| 278 | .ok_or_else(|| AiError::ParseError("missing 'embedding' array".to_string()))?; |
| 279 | let vec: Vec<f32> = embedding |
| 280 | .iter() |
| 281 | .filter_map(|v| v.as_f64().map(|f| f as f32)) |
| 282 | .collect(); |
| 283 | if vec.is_empty() { |
| 284 | return Err(AiError::ParseError("empty embedding vector".to_string())); |
| 285 | } |
| 286 | vectors.push(vec); |
| 287 | } |
| 288 | Ok(vectors) |
| 289 | } |
| 290 | |
| 291 | // ── LLM API Calls ─────────────────────────────────────────────── |
| 292 |