Skip to main content

gproxy_protocol/adapt/embeddings/
mod.rs

1//! Explicit embedding split/batch calls over one selected upstream target.
2
3mod gemini_openai;
4mod openai_gemini;
5mod openai_packing;
6mod packing;
7mod single;
8
9use crate::{
10    HttpBody, WireResponse,
11    codec::CodecLimits,
12    transform::{Converted, TransformError, embeddings::OpenAiUsageFacts},
13};
14
15pub use gemini_openai::gemini_batch_to_openai;
16pub use openai_gemini::openai_to_gemini_batch;
17pub use single::{gemini_single_to_openai, openai_to_gemini_single};
18
19#[derive(Debug, Clone)]
20pub struct EmbeddingBatchOptions {
21    /// Bounds each HTTP call and the aggregate encoded successful output.
22    pub codec: CodecLimits,
23    /// Optional actual usage for each planned call, used only where the target
24    /// does not return it. Empty means no supplements; otherwise length must
25    /// equal the number of calls after packing by encoded bytes.
26    pub usage_per_call: Vec<Option<OpenAiUsageFacts>>,
27}
28
29#[derive(Debug)]
30pub struct EmbeddingBatchResult<T> {
31    pub output: Converted<T>,
32    pub completed_calls: usize,
33}
34
35#[derive(Debug)]
36pub enum EmbeddingFailure {
37    Transform(TransformError),
38    Rejected(Box<WireResponse<HttpBody>>),
39}
40
41/// Failure never presents completed partial vectors as a successful batch.
42/// `completed_calls` counts 2xx calls whose JSON was decoded, including one
43/// whose typed data proved invalid. A transport/body failure can have an
44/// unknown upstream outcome; this counter is not a retry authorization.
45/// `completed_items` counts only vectors validated before the failed call.
46#[derive(Debug)]
47pub struct EmbeddingBatchError {
48    pub completed_calls: usize,
49    pub completed_items: usize,
50    pub failure: EmbeddingFailure,
51}
52
53impl std::fmt::Display for EmbeddingBatchError {
54    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
55        write!(
56            f,
57            "embedding batch failed after {} completed calls and {} validated items: ",
58            self.completed_calls, self.completed_items
59        )?;
60        match &self.failure {
61            EmbeddingFailure::Transform(error) => error.fmt(f),
62            EmbeddingFailure::Rejected(response) => write!(f, "upstream HTTP {}", response.status),
63        }
64    }
65}
66
67impl std::error::Error for EmbeddingBatchError {
68    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
69        match &self.failure {
70            EmbeddingFailure::Transform(error) => Some(error),
71            EmbeddingFailure::Rejected(_) => None,
72        }
73    }
74}
75
76impl From<TransformError> for EmbeddingBatchError {
77    fn from(error: TransformError) -> Self {
78        Self {
79            completed_calls: 0,
80            completed_items: 0,
81            failure: EmbeddingFailure::Transform(error),
82        }
83    }
84}
85
86fn at(error: TransformError, calls: usize, items: usize) -> EmbeddingBatchError {
87    EmbeddingBatchError {
88        completed_calls: calls,
89        completed_items: items,
90        failure: EmbeddingFailure::Transform(error),
91    }
92}