runImageEditFlow 统一处理 /v1/images/edits 和 /v1/images/variations。 asVariation=true 时,即便客户端没有传 prompt,也会注入一条默认指令。
(c *gin.Context, asVariation bool)
| 1264 | // runImageEditFlow 统一处理 /v1/images/edits 和 /v1/images/variations。 |
| 1265 | // asVariation=true 时,即便客户端没有传 prompt,也会注入一条默认指令。 |
| 1266 | func (h *Handler) runImageEditFlow(c *gin.Context, asVariation bool) { |
| 1267 | contentType := strings.Split(c.GetHeader("Content-Type"), ";")[0] |
| 1268 | contentType = strings.ToLower(strings.TrimSpace(contentType)) |
| 1269 | |
| 1270 | var imageSources []editImageInput |
| 1271 | var prompt, model, responseFormat string |
| 1272 | var n int |
| 1273 | var stream bool |
| 1274 | |
| 1275 | parseFormFields := func(promptVal, modelVal, nVal, responseFormatVal, streamVal string) { |
| 1276 | prompt = strings.TrimSpace(promptVal) |
| 1277 | model = strings.TrimSpace(modelVal) |
| 1278 | responseFormat = strings.TrimSpace(responseFormatVal) |
| 1279 | if nVal != "" { |
| 1280 | if v, err := strconv.Atoi(nVal); err == nil { |
| 1281 | n = v |
| 1282 | } |
| 1283 | } |
| 1284 | stream = isStreamTrue(streamVal) |
| 1285 | } |
| 1286 | |
| 1287 | if contentType == "application/json" { |
| 1288 | // JSON 形态:对齐 OpenAI 官方 image edit 请求, |
| 1289 | // 同时支持 Responses API 风格的 content 数组([{type:"input_image", image_url:"..."}, ...]) |
| 1290 | var body struct { |
| 1291 | Prompt string `json:"prompt"` |
| 1292 | Model string `json:"model"` |
| 1293 | N int `json:"n"` |
| 1294 | Size string `json:"size"` |
| 1295 | ResponseFormat string `json:"response_format"` |
| 1296 | Stream bool `json:"stream"` |
| 1297 | Images []officialtypes.ImageEditSource `json:"images,omitempty"` |
| 1298 | Image *officialtypes.ImageEditSource `json:"image,omitempty"` |
| 1299 | ImageURL interface{} `json:"image_url,omitempty"` |
| 1300 | // Responses API 风格字段: |
| 1301 | // input: 字符串 / 对象 / 数组(每项是 {role, content:[...]} 或单独的 part) |
| 1302 | // content: 数组(顶层 content,有时用于 chat completions) |
| 1303 | // messages: 标准 chat 风格 [{role, content:[...]}] |
| 1304 | Input interface{} `json:"input,omitempty"` |
| 1305 | Content interface{} `json:"content,omitempty"` |
| 1306 | Messages interface{} `json:"messages,omitempty"` |
| 1307 | } |
| 1308 | if err := c.BindJSON(&body); err != nil { |
| 1309 | c.JSON(400, gin.H{"error": gin.H{ |
| 1310 | "message": "Request must be proper JSON", |
| 1311 | "type": "invalid_request_error", |
| 1312 | "param": nil, |
| 1313 | "code": err.Error(), |
| 1314 | }}) |
| 1315 | return |
| 1316 | } |
| 1317 | prompt = strings.TrimSpace(body.Prompt) |
| 1318 | model = body.Model |
| 1319 | n = body.N |
| 1320 | responseFormat = body.ResponseFormat |
| 1321 | stream = body.Stream |
| 1322 | |
| 1323 | client := bogdanfinn.NewStdClient() |
no test coverage detected