Skip to main content

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

1use crate::openai::count_tokens::types as ot;
2use crate::openai::create_image::request::{
3    OpenAiCreateImageRequest, RequestBody as CreateImageRequestBody,
4};
5use crate::openai::create_image::types as it;
6use crate::openai::create_response::request::{
7    OpenAiCreateResponseRequest, RequestBody as ResponseRequestBody,
8};
9use crate::transform::openai::create_image::utils::{
10    create_image_model_to_string, image_tool_choice, response_image_background_from_request,
11    response_image_model_from_create_image_model, response_image_moderation_from_request,
12    response_image_output_format_from_request, response_image_quality_from_create_image_request,
13    response_image_size_from_create_image_request, user_message_from_parts,
14};
15use crate::transform::utils::TransformError;
16
17impl TryFrom<OpenAiCreateImageRequest> for OpenAiCreateResponseRequest {
18    type Error = TransformError;
19
20    fn try_from(value: OpenAiCreateImageRequest) -> Result<Self, TransformError> {
21        OpenAiCreateResponseRequest::try_from(&value)
22    }
23}
24
25impl TryFrom<&OpenAiCreateImageRequest> for OpenAiCreateResponseRequest {
26    type Error = TransformError;
27
28    fn try_from(value: &OpenAiCreateImageRequest) -> Result<Self, TransformError> {
29        create_image_to_response_request(&value.body)
30    }
31}
32
33fn create_image_to_response_request(
34    body: &CreateImageRequestBody,
35) -> Result<OpenAiCreateResponseRequest, TransformError> {
36    // Validate unsupported fields
37    if matches!(
38        body.response_format,
39        Some(it::OpenAiImageResponseFormat::Url)
40    ) {
41        return Err(TransformError::not_implemented(
42            "cannot convert OpenAI image request with response_format=url to responses.create request",
43        ));
44    }
45
46    // Build the image_generation tool with all config from the create image request
47    let image_tool = ot::ResponseImageGenerationTool {
48        type_: ot::ResponseImageGenerationToolType::ImageGeneration,
49        action: Some(ot::ResponseImageGenerationAction::Generate),
50        background: response_image_background_from_request(body.background.clone()),
51        input_fidelity: None,
52        input_image_mask: None,
53        model: body
54            .model
55            .as_ref()
56            .map(|m| response_image_model_from_create_image_model(m.clone())),
57        moderation: response_image_moderation_from_request(body.moderation.clone()),
58        output_compression: body.output_compression.map(|c| c as u64),
59        output_format: response_image_output_format_from_request(body.output_format.clone()),
60        partial_images: body.partial_images,
61        quality: response_image_quality_from_create_image_request(body.quality.clone()),
62        size: response_image_size_from_create_image_request(body.size.clone())?,
63    };
64
65    // Build input: user message with text content
66    let input = user_message_from_parts(vec![ot::ResponseInputContent::Text(
67        ot::ResponseInputText {
68            text: body.prompt.clone(),
69            type_: ot::ResponseInputTextType::InputText,
70        },
71    )]);
72
73    // Determine model name for the response request
74    let model = body
75        .model
76        .as_ref()
77        .map(create_image_model_to_string)
78        .unwrap_or_else(|| "gpt-image-1".to_string());
79
80    Ok(OpenAiCreateResponseRequest {
81        body: ResponseRequestBody {
82            model: Some(model),
83            input: Some(input),
84            tools: Some(vec![
85                crate::openai::create_response::types::ResponseTool::ImageGeneration(image_tool),
86            ]),
87            tool_choice: Some(image_tool_choice()),
88            stream: body.stream,
89            user: body.user.clone(),
90            ..ResponseRequestBody::default()
91        },
92        ..OpenAiCreateResponseRequest::default()
93    })
94}