Skip to main content

gproxy_protocol/transform/openai/create_image/gemini/
request.rs

1use crate::gemini::count_tokens::types as gt;
2use crate::gemini::generate_content::request::{
3    GeminiGenerateContentRequest, PathParameters, QueryParameters, RequestBody, RequestHeaders,
4};
5use crate::gemini::stream_generate_content::request::{
6    GeminiStreamGenerateContentRequest,
7    PathParameters as GeminiStreamGenerateContentPathParameters,
8    QueryParameters as GeminiStreamGenerateContentQueryParameters,
9    RequestHeaders as GeminiStreamGenerateContentRequestHeaders,
10};
11use crate::gemini::types::HttpMethod as GeminiHttpMethod;
12use crate::openai::create_image::request::{
13    OpenAiCreateImageRequest, RequestBody as CreateImageRequestBody,
14};
15use crate::openai::create_image::types as it;
16use crate::transform::gemini::model_get::utils::ensure_models_prefix;
17use crate::transform::openai::create_image::gemini::utils::gemini_image_config_from_create_image_size;
18use crate::transform::openai::create_image::utils::create_image_model_to_string;
19use crate::transform::utils::TransformError;
20
21fn validate_create_image_request(body: &CreateImageRequestBody) -> Result<(), TransformError> {
22    if matches!(
23        body.response_format,
24        Some(it::OpenAiImageResponseFormat::Url)
25    ) {
26        return Err(TransformError::not_implemented(
27            "cannot convert OpenAI image request with response_format=url to Gemini generateContent request",
28        ));
29    }
30
31    Ok(())
32}
33
34impl TryFrom<OpenAiCreateImageRequest> for GeminiGenerateContentRequest {
35    type Error = TransformError;
36
37    fn try_from(value: OpenAiCreateImageRequest) -> Result<Self, TransformError> {
38        let headers = RequestHeaders {
39            extra: value.headers.extra,
40        };
41        let body = value.body;
42        validate_create_image_request(&body)?;
43
44        let image_config = gemini_image_config_from_create_image_size(body.size)?;
45        let model = ensure_models_prefix(
46            &body
47                .model
48                .as_ref()
49                .map(create_image_model_to_string)
50                .unwrap_or_default(),
51        );
52
53        Ok(GeminiGenerateContentRequest {
54            method: GeminiHttpMethod::Post,
55            path: PathParameters { model },
56            query: QueryParameters::default(),
57            headers,
58            body: RequestBody {
59                contents: vec![gt::GeminiContent {
60                    parts: vec![gt::GeminiPart {
61                        text: Some(body.prompt),
62                        ..gt::GeminiPart::default()
63                    }],
64                    role: Some(gt::GeminiContentRole::User),
65                }],
66                tools: None,
67                tool_config: None,
68                safety_settings: None,
69                system_instruction: None,
70                generation_config: Some(gt::GeminiGenerationConfig {
71                    response_modalities: Some(vec![gt::GeminiModality::Image]),
72                    candidate_count: body.n,
73                    image_config,
74                    ..gt::GeminiGenerationConfig::default()
75                }),
76                cached_content: None,
77                store: None,
78            },
79        })
80    }
81}
82
83impl TryFrom<&OpenAiCreateImageRequest> for GeminiStreamGenerateContentRequest {
84    type Error = TransformError;
85
86    fn try_from(value: &OpenAiCreateImageRequest) -> Result<Self, TransformError> {
87        let output = GeminiGenerateContentRequest::try_from(value.clone())?;
88
89        Ok(Self {
90            method: GeminiHttpMethod::Post,
91            path: GeminiStreamGenerateContentPathParameters {
92                model: output.path.model,
93            },
94            query: GeminiStreamGenerateContentQueryParameters::default(),
95            headers: GeminiStreamGenerateContentRequestHeaders {
96                extra: output.headers.extra,
97            },
98            body: output.body,
99        })
100    }
101}
102
103impl TryFrom<OpenAiCreateImageRequest> for GeminiStreamGenerateContentRequest {
104    type Error = TransformError;
105
106    fn try_from(value: OpenAiCreateImageRequest) -> Result<Self, TransformError> {
107        GeminiStreamGenerateContentRequest::try_from(&value)
108    }
109}