feat(api): 移除gpt-image-2参考图强制验证并优化图像处理逻辑

移除对gpt-image-2模型的参考图上传强制验证,支持无参考图时调用生成接口,
同时优化图像URL提取和处理逻辑以支持不同响应格式

BREAKING CHANGE: gpt-image-2不再强制要求上传参考图
```
This commit is contained in:
公司git 2026-04-26 09:49:31 +08:00
parent 3610bedb39
commit 3df902963d
6 changed files with 46 additions and 25 deletions

View File

@ -91,17 +91,15 @@ def generate():
image_data = data.get("image_data", [])
if model_value == "gpt-image-2":
if not image_data:
return jsonify({"error": "gpt-image-2 编辑模式至少需要上传 1 张参考图"}), 400
payload = {
"prompt": prompt,
"model": model_value,
"images": [{"image_url": img} for img in image_data],
"size": data.get("size") or "2048x2048",
"quality": "high",
"output_format": "png",
}
if image_data:
payload["images"] = [{"image_url": img} for img in image_data]
else:
payload = {
"prompt": prompt,

View File

@ -37,6 +37,7 @@ class Config:
CHAT_API = f"{AI_BASE_URL}/v1/chat/completions"
VIDEO_GEN_API = f"{AI_BASE_URL}/v2/videos/generations"
VIDEO_POLL_API = f"{AI_BASE_URL}/v2/videos/generations/{{task_id}}"
GPT_IMAGE_GENERATION_API = "https://nas.4x4g.com:8317/v1/images/generations"
GPT_IMAGE_EDIT_API = "https://nas.4x4g.com:8317/v1/images/edits"
GPT_IMAGE_EDIT_KEY = "sk-vDmmYNzoe7UjWskKx"

View File

@ -34,12 +34,18 @@ def validate_generation_request(user, data):
model_value = data.get("model")
is_gemini_flash_image_preview = model_value == "gemini-3.1-flash-image-preview"
is_gpt_image_edit = model_value == "gpt-image-2"
image_data = data.get("image_data", [])
has_reference_images = bool(image_data)
if isinstance(is_premium, str):
is_premium = is_premium.lower() in ("1", "true", "yes", "on")
# gpt-image-2 走独立的 edits 接口,其余模型沿用现有 generations 接口
target_api = Config.GPT_IMAGE_EDIT_API if is_gpt_image_edit else Config.AI_API
# gpt-image-2 有参考图走 edits无参考图走 generations其它模型沿用现有 generations 接口
target_api = (
(Config.GPT_IMAGE_EDIT_API if has_reference_images else Config.GPT_IMAGE_GENERATION_API)
if is_gpt_image_edit
else Config.AI_API
)
api_key = None
use_trial = False
@ -70,7 +76,11 @@ def validate_generation_request(user, data):
else:
api_key = Config.TRIAL_KEY
target_api = Config.GPT_IMAGE_EDIT_API if is_gpt_image_edit else Config.TRIAL_API
target_api = (
(Config.GPT_IMAGE_EDIT_API if has_reference_images else Config.GPT_IMAGE_GENERATION_API)
if is_gpt_image_edit
else Config.TRIAL_API
)
use_trial = True
# 计算本次任务消耗

View File

@ -150,6 +150,14 @@ def _extract_b64_images(result):
return images
def _extract_image_urls(result):
urls = []
for item in result.get("data", []) or []:
if isinstance(item, dict) and item.get("url"):
urls.append(item["url"])
return urls
def _process_gpt_image_edit(app, user_id, task_id, payload, api_key, target_api, cost, use_trial):
headers = {
"Authorization": f"Bearer {api_key}",
@ -173,7 +181,28 @@ def _process_gpt_image_edit(app, user_id, task_id, payload, api_key, target_api,
result = response.json()
b64_images = _extract_b64_images(result)
if not b64_images:
raise Exception("gpt-image-2 未返回可用图片数据")
url_images = _extract_image_urls(result)
if not url_images:
raise Exception("gpt-image-2 未返回可用图片数据")
processed_data = [{"url": image_url, "thumb": image_url} for image_url in url_images]
new_record = GenerationRecord(
user_id=user_id,
prompt=payload.get("prompt"),
model=payload.get("model"),
cost=cost,
image_urls=json.dumps(processed_data),
)
db.session.add(new_record)
db.session.commit()
system_logger.info("gpt-image-2 生图任务完成", user_id=user_id, task_id=task_id, model=payload.get("model"))
redis_client.setex(
f"task:{task_id}",
3600,
json.dumps({"status": "complete", "urls": url_images, "record_id": new_record.id}),
)
return
processed_data = []
final_urls = []

View File

@ -552,18 +552,6 @@ document.getElementById('submitBtn').onclick = async () => {
}
// UI 锁定
if (document.getElementById('modelSelect').value === GPT_IMAGE_EDIT_MODEL && uploadedFiles.length === 0) {
return showToast('gpt-image-2 requires a reference image', 'warning');
}
if (document.getElementById('modelSelect').value === GPT_IMAGE_EDIT_MODEL && uploadedFiles.length === 0) {
return showToast('gpt-image-2 妯″瀷蹇呴』涓婁紶鍙傝€冨浘', 'warning');
}
if (document.getElementById('modelSelect').value === GPT_IMAGE_EDIT_MODEL && uploadedFiles.length === 0) {
return showToast('gpt-image-2 requires a reference image', 'warning');
}
btn.disabled = true;
const btnText = btn.querySelector('span');
btnText.innerText = uploadedFiles.length > 0 ? "正在同步参考图..." : "正在开启 AI 引擎...";

View File

@ -664,11 +664,6 @@
const num = parseInt(document.getElementById('numSelect').value);
const isPremium = document.getElementById('isPremium').checked;
if (model === GPT_IMAGE_EDIT_MODEL && uploadedFiles.length === 0) {
showToast('gpt-image-2 模型必须上传参考图', 'warning');
return;
}
// 显示加载状态
document.getElementById('placeholder').classList.add('hidden');
document.getElementById('placeholder').classList.add('hidden');