Skip to main content

gproxy_protocol/transform/gemini/embeddings/openai/
response.rs

1use crate::gemini::embeddings::response::{GeminiEmbedContentResponse, ResponseBody};
2use crate::gemini::embeddings::types::GeminiContentEmbedding;
3use crate::gemini::types::{GeminiApiError, GeminiApiErrorResponse, GeminiResponseHeaders};
4use crate::openai::embeddings::response::OpenAiEmbeddingsResponse;
5use crate::openai::embeddings::types::OpenAiEmbeddingVector;
6use crate::transform::utils::TransformError;
7
8fn google_status_from_http(status_code: http::StatusCode) -> Option<String> {
9    let status = match status_code.as_u16() {
10        400 => "INVALID_ARGUMENT",
11        401 => "UNAUTHENTICATED",
12        403 => "PERMISSION_DENIED",
13        404 => "NOT_FOUND",
14        409 => "ABORTED",
15        429 => "RESOURCE_EXHAUSTED",
16        500 => "INTERNAL",
17        503 | 529 => "UNAVAILABLE",
18        504 => "DEADLINE_EXCEEDED",
19        _ => return None,
20    };
21    Some(status.to_string())
22}
23
24impl TryFrom<OpenAiEmbeddingsResponse> for GeminiEmbedContentResponse {
25    type Error = TransformError;
26
27    fn try_from(value: OpenAiEmbeddingsResponse) -> Result<Self, TransformError> {
28        Ok(match value {
29            OpenAiEmbeddingsResponse::Success {
30                stats_code,
31                headers,
32                body,
33            } => {
34                let values = body
35                    .data
36                    .into_iter()
37                    .next()
38                    .map(|item| match item.embedding {
39                        OpenAiEmbeddingVector::FloatArray(values) => values,
40                        OpenAiEmbeddingVector::Base64(_) => Vec::new(),
41                    })
42                    .unwrap_or_default();
43
44                GeminiEmbedContentResponse::Success {
45                    stats_code,
46                    headers: GeminiResponseHeaders {
47                        extra: headers.extra,
48                    },
49                    body: ResponseBody {
50                        embedding: GeminiContentEmbedding {
51                            values,
52                            shape: None,
53                        },
54                    },
55                }
56            }
57            OpenAiEmbeddingsResponse::Error {
58                stats_code,
59                headers,
60                body,
61            } => GeminiEmbedContentResponse::Error {
62                stats_code,
63                headers: GeminiResponseHeaders {
64                    extra: headers.extra,
65                },
66                body: GeminiApiErrorResponse {
67                    error: GeminiApiError {
68                        code: i32::from(stats_code.as_u16()),
69                        message: body.error.message,
70                        status: google_status_from_http(stats_code),
71                        details: None,
72                    },
73                },
74            },
75        })
76    }
77}