diff --git a/docs/technical/【技术方案】Raw GPT Image 2图片编辑代理-2026-09-07.md b/docs/technical/【技术方案】Raw GPT Image 2图片编辑代理-2026-09-07.md index 4c319b003..f8696987b 100644 --- a/docs/technical/【技术方案】Raw GPT Image 2图片编辑代理-2026-09-07.md +++ b/docs/technical/【技术方案】Raw GPT Image 2图片编辑代理-2026-09-07.md @@ -35,7 +35,7 @@ POST /api/raw/v1/images/edit } ``` -`image` 是必填的单图结构 `{ data, mimeType }`;`mask` 可选并使用相同结构。`image` 和 `mask` 的 `mimeType` 必须为 `image/png`,base64 解码后必须是可完整解码的有效 PNG 文件,提供 mask 时其宽高必须与 image 完全一致;空数据、非 PNG 字节、MIME 不匹配或尺寸不一致均在扣费前返回 400。服务端不把输入格式另建成请求参数。`prompt` 必填,UTF-8 原始字节长度不得超过 `16 KiB`;超限在扣费前返回 400。`quality`、`background` 和 `output_format` 采用 GPT Image 模型支持的值。 +`image` 是必填的单图结构 `{ data, mimeType }`;`mask` 可选并使用相同结构。`image` 和 `mask` 的 `mimeType` 必须为 `image/png`,base64 解码后必须是可完整解码的有效 PNG 文件,提供 mask 时其宽高必须与 image 完全一致;空数据、非 PNG 字节、MIME 不匹配或尺寸不一致均在扣费前返回 400。服务端不把输入格式另建成请求参数。`prompt` 必填,UTF-8 原始字节长度不得超过 `4 KiB`;超限在扣费前返回 400。`quality`、`background` 和 `output_format` 采用 GPT Image 模型支持的值。 `width`、`height` 使用严格输出尺寸规则,均在扣费前校验: diff --git a/server-rs/crates/api-server/src/raw_image.rs b/server-rs/crates/api-server/src/raw_image.rs index 1c46e7fbc..9dc066ae1 100644 --- a/server-rs/crates/api-server/src/raw_image.rs +++ b/server-rs/crates/api-server/src/raw_image.rs @@ -59,7 +59,7 @@ pub(crate) struct RawImageEditResponse { pub(crate) data: Vec, } -const RAW_IMAGE_MAX_PROMPT_BYTES: usize = 16 * 1024; +const RAW_IMAGE_MAX_PROMPT_BYTES: usize = 4 * 1024; pub(crate) async fn edit_raw_image( State(state): State, @@ -109,7 +109,6 @@ pub(crate) async fn edit_raw_image( return Err(map_platform_image_error(error)); } }; - let task_id = generated.task_id.clone(); let data: Vec = generated .b64_images .into_iter() @@ -125,7 +124,7 @@ pub(crate) async fn edit_raw_image( started_at_micros, true, None, - Some(task_id), + Some("raw-image-edit".to_string()), Some(json!({ "imageCount": data.len() })), ) .await; @@ -452,6 +451,6 @@ mod tests { Err(error) => error, }; - assert!(format!("{error:?}").contains("prompt 不能超过 16384 字节")); + assert!(format!("{error:?}").contains("prompt 不能超过 4096 字节")); } } diff --git a/server-rs/crates/platform-image/src/vector_engine/raw_edit.rs b/server-rs/crates/platform-image/src/vector_engine/raw_edit.rs index 13f41e7e6..77c386322 100644 --- a/server-rs/crates/platform-image/src/vector_engine/raw_edit.rs +++ b/server-rs/crates/platform-image/src/vector_engine/raw_edit.rs @@ -28,13 +28,12 @@ pub struct RawImageEditOptions { #[derive(Debug, Deserialize)] struct RawImageEditResponsePayload { - id: Option, - data: Option>, + data: Vec, } #[derive(Debug, Deserialize)] struct RawImageEditResponseEntry { - b64_json: Option, + b64_json: String, } pub const RAW_IMAGE_MAX_EDGE: u32 = GPT_IMAGE_2_MAX_EDGE; @@ -262,9 +261,8 @@ pub async fn create_vector_engine_raw_image_edit( }; let b64_images = payload .data - .unwrap_or_default() .into_iter() - .filter_map(|entry| entry.b64_json) + .map(|entry| entry.b64_json) .collect::>(); if b64_images.is_empty() { let message = format!("{failure_context}:上游未返回 b64_json 图片"); @@ -291,7 +289,6 @@ pub async fn create_vector_engine_raw_image_edit( }); } Ok(RawImageEditResult { - task_id: payload.id.unwrap_or_else(|| "raw-image-edit".to_string()), b64_images, recovered_failure_audits: Vec::new(), }) @@ -387,7 +384,6 @@ fn status_class(status: u16) -> &'static str { #[cfg(test)] mod tests { use super::*; - use serde_json::json; #[test] fn raw_result_forwards_b64_without_decoding_or_using_output_format() { @@ -401,14 +397,19 @@ mod tests { assert_eq!( payload .data - .unwrap_or_default() .into_iter() - .filter_map(|entry| entry.b64_json) + .map(|entry| entry.b64_json) .collect::>(), vec!["not-base64-but-forwarded".to_string()] ); } + #[test] + fn raw_success_response_requires_typed_data_and_b64_json_fields() { + assert!(serde_json::from_str::(r#"{}"#).is_err()); + assert!(serde_json::from_str::(r#"{"data":[{}]}"#).is_err()); + } + #[test] fn raw_image_edit_dimensions_enforce_strict_contract() { assert!(validate_raw_image_edit_dimensions(1024, 640).is_ok()); diff --git a/server-rs/crates/platform-image/src/vector_engine/types.rs b/server-rs/crates/platform-image/src/vector_engine/types.rs index 82a69bb4a..d25ad5c12 100644 --- a/server-rs/crates/platform-image/src/vector_engine/types.rs +++ b/server-rs/crates/platform-image/src/vector_engine/types.rs @@ -18,7 +18,6 @@ pub struct GeneratedImages { #[derive(Clone, Debug)] pub struct RawImageEditResult { - pub task_id: String, pub b64_images: Vec, pub recovered_failure_audits: Vec, }