Skip to main content

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

1use crate::openai::count_tokens::types as ot;
2use crate::openai::create_image_edit::request::{
3    OpenAiCreateImageEditRequest, RequestBody as CreateImageEditRequestBody,
4};
5use crate::openai::create_image_edit::types as iet;
6use crate::openai::create_response::request::{
7    OpenAiCreateResponseRequest, RequestBody as ResponseRequestBody,
8};
9use crate::transform::openai::create_image::utils::{
10    create_image_edit_model_to_string, image_tool_choice, response_image_background_from_request,
11    response_image_model_from_create_image_edit_model, response_image_moderation_from_request,
12    response_image_output_format_from_request,
13    response_image_quality_from_create_image_edit_request,
14    response_image_size_from_create_image_edit_request, user_message_from_parts,
15};
16use crate::transform::utils::TransformError;
17
18impl TryFrom<OpenAiCreateImageEditRequest> for OpenAiCreateResponseRequest {
19    type Error = TransformError;
20
21    fn try_from(value: OpenAiCreateImageEditRequest) -> Result<Self, TransformError> {
22        OpenAiCreateResponseRequest::try_from(&value)
23    }
24}
25
26impl TryFrom<&OpenAiCreateImageEditRequest> for OpenAiCreateResponseRequest {
27    type Error = TransformError;
28
29    fn try_from(value: &OpenAiCreateImageEditRequest) -> Result<Self, TransformError> {
30        create_image_edit_to_response_request(&value.body)
31    }
32}
33
34fn create_image_edit_to_response_request(
35    body: &CreateImageEditRequestBody,
36) -> Result<OpenAiCreateResponseRequest, TransformError> {
37    // Build input: image references + text prompt
38    let mut parts = Vec::with_capacity(body.images.len() + 1);
39    for image in &body.images {
40        parts.push(ot::ResponseInputContent::Image(ot::ResponseInputImage {
41            type_: ot::ResponseInputImageType::InputImage,
42            detail: None,
43            file_id: image.file_id.clone(),
44            image_url: image.image_url.clone(),
45        }));
46    }
47    parts.push(ot::ResponseInputContent::Text(ot::ResponseInputText {
48        text: body.prompt.clone(),
49        type_: ot::ResponseInputTextType::InputText,
50    }));
51
52    let input = user_message_from_parts(parts);
53
54    // Build the image_generation tool with edit action
55    let image_tool = ot::ResponseImageGenerationTool {
56        type_: ot::ResponseImageGenerationToolType::ImageGeneration,
57        action: Some(ot::ResponseImageGenerationAction::Edit),
58        background: response_image_background_from_request(body.background.clone()),
59        input_fidelity: body.input_fidelity.as_ref().map(|f| match f {
60            iet::OpenAiImageEditInputFidelity::High => {
61                ot::ResponseImageGenerationInputFidelity::High
62            }
63            iet::OpenAiImageEditInputFidelity::Low => ot::ResponseImageGenerationInputFidelity::Low,
64        }),
65        input_image_mask: body
66            .mask
67            .as_ref()
68            .map(|m| ot::ResponseImageGenerationInputImageMask {
69                file_id: m.file_id.clone(),
70                image_url: m.image_url.clone(),
71            }),
72        model: body
73            .model
74            .as_ref()
75            .map(|m| response_image_model_from_create_image_edit_model(m.clone())),
76        moderation: response_image_moderation_from_request(body.moderation.clone()),
77        output_compression: body.output_compression.map(|c| c as u64),
78        output_format: response_image_output_format_from_request(body.output_format.clone()),
79        partial_images: body.partial_images,
80        quality: response_image_quality_from_create_image_edit_request(body.quality.clone()),
81        size: response_image_size_from_create_image_edit_request(body.size.clone()),
82    };
83
84    let model = body
85        .model
86        .as_ref()
87        .map(create_image_edit_model_to_string)
88        .unwrap_or_else(|| "gpt-image-1".to_string());
89
90    Ok(OpenAiCreateResponseRequest {
91        body: ResponseRequestBody {
92            model: Some(model),
93            input: Some(input),
94            tools: Some(vec![
95                crate::openai::create_response::types::ResponseTool::ImageGeneration(image_tool),
96            ]),
97            tool_choice: Some(image_tool_choice()),
98            stream: body.stream,
99            user: body.user.clone(),
100            ..ResponseRequestBody::default()
101        },
102        ..OpenAiCreateResponseRequest::default()
103    })
104}