Skip to main content
本文档面向接入方,说明如何通过 OpenAI Responses API 的 background=true 模式调用生图模型, 异步生成图片。内容包含完整示例代码,并重点演示如何传入多张参考图片以及如何传入多份提示词文档

1. 概述

生图通常需要 30 秒到 5 分钟。如果用同步方式调用,客户端必须一直保持 HTTP 连接等待,网络抖动或网关 超时都可能导致请求失败。 background=true 模式把”等待完成”拆成三步:
1) 提交任务  → 立即拿到 resp_xxx(status=queued),连接随即关闭
2) 轮询状态  → status 在 queued / in_progress 之间流转
3) 取回结果  → status=completed,output 中带回图片
适用场景:
  • 高分辨率图片生成(耗时长)
  • 客户端网络不稳定,需要避免长连接超时
  • 批量提交、稍后统一取结果
兼容性:本服务完全兼容 OpenAI Responses API 的 background 语义。直接使用官方 OpenAI SDK, 只需把 base_url 指向本服务即可,responses.create / retrieve / cancel 均可正常使用。

2. 前置条件

创建密钥时务必选择OpenAI-IMG分组
Base URLhttps://your-sub2api-domain.com/v1
API Keysk-your-api-key
生图端点POST /v1/responses
轮询端点GET /v1/responses/{response_id}
取消端点POST /v1/responses/{response_id}/cancel
安装官方 SDK:
pip install openai
初始化客户端:
from openai import OpenAI

client = OpenAI(
    base_url="https://your-sub2api-domain.com/v1",
    api_key="sk-your-api-key",
)

3. 请求结构说明

生图在 Responses API 中是一个 工具调用(tool),不是独立的模型端点。标准结构是:
  • 顶层 model:文本模型(负责理解 prompt 并决定调用生图工具)
  • tools[]:包含一个 image_generation 工具,工具里的 model 才是图片模型
  • tool_choice:强制走生图工具
  • input:用户输入(文字 + 参考图片)
{
  "model": "gpt-5.5",
  "background": true,
  "tools": [
    {
      "type": "image_generation",
      "model": "gpt-image-2",
      "quality": "high",
      "size": "2560x1440",
      "output_format": "png"
    }
  ],
  "tool_choice": { "type": "image_generation" },
  "input": [
    {
      "role": "user",
      "content": [
        { "type": "input_text", "text": "Generate a beautiful sunset landscape" }
      ]
    }
  ]
}

关于简写形式(实测不可用,请勿使用)

有一种”偷懒”写法:把图片模型直接放在顶层 model、并在顶层写 size / output_format,不写 tools
{
  "model": "gpt-image-2",
  "background": true,
  "size": "2560x1440",
  "output_format": "png",
  "input": "Generate a beautiful sunset landscape"
}
这种写法经实测在本服务上不可用,请不要使用:
  • 官方 OpenAI SDK 直接拒绝——responses.create(size=...) 会报 unexpected keyword argument 'size',根本发不出去。
  • 即便用裸 HTTP 绕过 SDK 发出去,服务端虽然接受并返回 queued,但任务随后会变成 failed,上游报错 400: Unsupported parameter: size(顶层 size 未被并入生图工具, 被原样转发给上游)。
结论:始终使用第 3 节开头的标准结构——顶层 model 填文本模型(如 gpt-5.5), size / quality / output_format 等参数放在 tools[] 里的 image_generation 工具内。 这是唯一经端到端验证可用的写法。

4. 快速开始(三步)

第 1 步:提交任务

response = client.responses.create(
    model="gpt-5.5",
    background=True,
    tools=[{
        "type": "image_generation",
        "model": "gpt-image-2",
        "quality": "high",
        "size": "2560x1440",
        "output_format": "png",
    }],
    tool_choice={"type": "image_generation"},
    input=[{
        "role": "user",
        "content": [
            {"type": "input_text", "text": "Generate a beautiful sunset landscape"},
        ],
    }],
)

print(response.id)      # resp_xxxxxxxx
print(response.status)  # queued
提交后立即返回(通常 < 100ms):
{
  "id": "resp_xxxxxxxx",
  "object": "response",
  "status": "queued",
  "created_at": 1748600000,
  "model": "gpt-5.5",
  "output": []
}

第 2 步:轮询状态

import time

while True:
    result = client.responses.retrieve(response.id)
    print(result.status)

    if result.status == "completed":
        break
    if result.status in ("failed", "cancelled"):
        print("生成未成功:", getattr(result, "error", result.status))
        break

    time.sleep(10)  # 生图建议每 10-15 秒轮询一次
轮询过程中可能看到:
{ "id": "resp_xxxxxxxx", "object": "response", "status": "in_progress" }

第 3 步:取回图片

完成后 output 中会包含一个或多个 image_generation_call,图片数据在 result 字段(base64):
import base64

for item in result.output:
    if item.type == "image_generation_call":
        with open("output.png", "wb") as f:
            f.write(base64.b64decode(item.result))
        print("已保存 output.png")

5. 使用多个参考图片

参考图片通过 inputcontent 数组中的多个 input_image 部分传入。 每张参考图是一个 input_imageimage_urlbase64 data URL,配 detail 控制参考精细度。 按你传入的顺序排列,数量不限,与文字提示放在同一个 user 消息里。
下面的写法对应项目内实际使用的参考脚本 base64 data URL,detail="high",单条 user 消息,background=True
import base64
import mimetypes
from pathlib import Path

def to_data_url(path: str) -> str:
    """把本地图片编码成 base64 data URL(与参考脚本一致)。"""
    mime, _ = mimetypes.guess_type(path)
    mime = mime or "image/png"
    data = Path(path).read_bytes()
    return f"data:{mime};base64,{base64.b64encode(data).decode('ascii')}"

# 多张本地参考图
content = [
    {"type": "input_text",  "text": "参考这几张图的构图与配色,生成一张电影感分镜图"},
    {"type": "input_image", "image_url": to_data_url("ref_pose.jpg"),  "detail": "high"},
    {"type": "input_image", "image_url": to_data_url("ref_style.png"), "detail": "high"},
    {"type": "input_image", "image_url": to_data_url("ref_bg.jpg"),    "detail": "high"},
]

response = client.responses.create(
    model="gpt-5.5",
    background=True,
    tools=[{
        "type": "image_generation",
        "model": "gpt-image-2",
        "quality": "high",
        "size": "2560x1440",
        "output_format": "png",
    }],
    tool_choice={"type": "image_generation"},
    input=[{"role": "user", "content": content}],
)
print("已提交:", response.id)
要点:
  • input_image 的数量不限,按数组顺序传给模型。
  • image_url 可以用 base64 data URLdata:image/...;base64,...),也可以用 https 公网链接——两种都经端到端实测可用(见下)。
  • 参考图片与文字提示放在同一个 user 消息content 数组里即可。
实测结论(已端到端验证):
  • base64 data URL 多图:通过。3 张本地图编码后同条消息传入,成功生成图片。
  • https 公网链接:通过。用一个公开可访问的 https 图片 URL 作参考图,约 54 秒成功生成图片。 注意链接必须是上游可公开访问的稳定 URL(会被原样转发给上游抓取)。
  • detail 字段实测用的是 high;其余取值(low / auto)未单独验证。

6. 使用多个提示词文档

当你有多份提示词(例如:角色设定文档、场景描述文档、风格指南文档),有两种传法, 两种都会被原样转发给模型。

方式 A:同一条消息里放多个 input_text(推荐)

把每份文档作为一个独立的 input_text 部分,按逻辑顺序排列,最后再放参考图片:
character_doc = Path("character.md").read_text(encoding="utf-8")
scene_doc     = Path("scene.md").read_text(encoding="utf-8")
style_doc     = Path("style_guide.md").read_text(encoding="utf-8")

content = [
    {"type": "input_text", "text": f"【角色设定】\n{character_doc}"},
    {"type": "input_text", "text": f"【场景描述】\n{scene_doc}"},
    {"type": "input_text", "text": f"【风格指南】\n{style_doc}"},
    {"type": "input_text", "text": "请综合以上三份文档,生成一张符合设定的主视觉图。"},
    {"type": "input_image", "image_url": to_data_url("mood_ref.jpg"), "detail": "high"},
]

response = client.responses.create(
    model="gpt-5.5",
    background=True,
    tools=[{
        "type": "image_generation",
        "model": "gpt-image-2",
        "quality": "high",
        "size": "3072x1728",
        "output_format": "png",
    }],
    tool_choice={"type": "image_generation"},
    input=[{"role": "user", "content": content}],
)

方式 B:多条 user 消息

如果你想让文档在对话结构上彼此独立,也可以用多条消息:
input_messages = [
    {"role": "user", "content": [{"type": "input_text", "text": f"【角色设定】\n{character_doc}"}]},
    {"role": "user", "content": [{"type": "input_text", "text": f"【场景描述】\n{scene_doc}"}]},
    {"role": "user", "content": [{"type": "input_text", "text": f"【风格指南】\n{style_doc}"}]},
    {"role": "user", "content": [
        {"type": "input_text", "text": "请综合以上文档生成主视觉图。"},
        {"type": "input_image", "image_url": to_data_url("mood_ref.jpg"), "detail": "high"},
    ]},
]

response = client.responses.create(
    model="gpt-5.5",
    background=True,
    tools=[{"type": "image_generation", "model": "gpt-image-2", "size": "3072x1728"}],
    tool_choice={"type": "image_generation"},
    input=input_messages,
)
要点:
  • 只要 input结构化数组(如上两种写法),服务端会原样转发,不做改写。
  • 给每份文档加一个清晰的小标题(如 【角色设定】)有助于模型区分文档边界。
  • 文档与参考图片可以自由组合:在任意一条消息的 content 里同时放 input_textinput_image 即可。

7. 完整示例:多参考图 + 多文档 + 轮询保存

#!/usr/bin/env python3
import base64
import time
import mimetypes
from pathlib import Path
from openai import OpenAI

client = OpenAI(
    base_url="https://your-sub2api-domain.com/v1",
    api_key="sk-your-api-key",
)

def to_data_url(path: str) -> str:
    mime, _ = mimetypes.guess_type(path)
    mime = mime or "image/png"
    return f"data:{mime};base64,{base64.b64encode(Path(path).read_bytes()).decode('ascii')}"

# 多份提示词文档
character_doc = Path("character.md").read_text(encoding="utf-8")
style_doc     = Path("style_guide.md").read_text(encoding="utf-8")

# 一条 user 消息:多文档 + 指令 + 多参考图
content = [
    {"type": "input_text",  "text": f"【角色设定】\n{character_doc}"},
    {"type": "input_text",  "text": f"【风格指南】\n{style_doc}"},
    {"type": "input_text",  "text": "综合以上文档与参考图,生成一张高分辨率电影分镜图。"},
    {"type": "input_image", "image_url": to_data_url("ref1.jpg"), "detail": "high"},
    {"type": "input_image", "image_url": to_data_url("ref2.jpg"), "detail": "high"},
]

# 1) 提交 background 任务
response = client.responses.create(
    model="gpt-5.5",
    background=True,
    tools=[{
        "type": "image_generation",
        "model": "gpt-image-2",
        "quality": "high",
        "size": "3072x1728",
        "output_format": "png",
    }],
    tool_choice={"type": "image_generation"},
    input=[{"role": "user", "content": content}],
)
print("任务已提交:", response.id)

# 2) 轮询(带超时保护)
started = time.time()
TIMEOUT = 600  # 10 分钟
while True:
    elapsed = time.time() - started
    if elapsed > TIMEOUT:
        print("超时,放弃等待")
        break

    time.sleep(10)
    result = client.responses.retrieve(response.id)
    print(f"[{elapsed:.0f}s] {result.status}")

    if result.status == "completed":
        # 3) 保存所有图片
        idx = 0
        for item in result.output:
            if item.type == "image_generation_call":
                out = f"storyboard_{idx}.png"
                Path(out).write_bytes(base64.b64decode(item.result))
                print("已保存", out)
                idx += 1
        print(f"完成,用时 {elapsed:.0f}s")
        break

    if result.status in ("failed", "cancelled"):
        print("生成未成功:", getattr(result, "error", result.status))
        break

8. 使用 curl 测试

# 1) 提交任务(注意:input 用结构化数组传多图/多文档)
curl -X POST "https://your-sub2api-domain.com/v1/responses" \
  -H "Authorization: Bearer sk-your-api-key" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "gpt-5.5",
    "background": true,
    "tools": [{"type": "image_generation", "model": "gpt-image-2", "size": "2560x1440", "output_format": "png"}],
    "tool_choice": {"type": "image_generation"},
    "input": [{
      "role": "user",
      "content": [
        {"type": "input_text",  "text": "文档一:角色设定..."},
        {"type": "input_text",  "text": "文档二:风格指南..."},
        {"type": "input_text",  "text": "综合以上文档生成主视觉图"},
        {"type": "input_image", "image_url": "data:image/jpeg;base64,/9j/4AAQ...", "detail": "high"},
        {"type": "input_image", "image_url": "data:image/png;base64,iVBORw0KGgo...", "detail": "high"}
      ]
    }]
  }'
# → {"id":"resp_xxxx","object":"response","status":"queued","output":[]}

# 2) 轮询
curl "https://your-sub2api-domain.com/v1/responses/resp_xxxx" \
  -H "Authorization: Bearer sk-your-api-key"
# → {"status":"in_progress"}            生成中
# → {"status":"completed","output":[...]}  完成,output 中含 image_generation_call.result(base64)

# 3) 取消(可选)
curl -X POST "https://your-sub2api-domain.com/v1/responses/resp_xxxx/cancel" \
  -H "Authorization: Bearer sk-your-api-key"
# → {"id":"resp_xxxx","object":"response","status":"cancelled"}

9. 取消任务

cancelled = client.responses.cancel(response.id)
print(cancelled.status)  # cancelled
取消成功后该任务的结果映射会被立即清除,后续再 retrieve 将返回 404。

10. 状态流转

queued → in_progress → completed
                     → failed
                     → cancelled(用户主动取消)
状态含义
queued任务已接收,等待开始
in_progress正在生成中
completed生成完成,output 中包含结果
failed生成失败,error 字段含原因
cancelled用户主动取消

11. 支持的图片尺寸

尺寸像素数状态
1024x10241.0M支持
1920x10882.1M支持
2048x20484.2M支持
2560x14403.7M支持
3072x17285.3M支持
3840x21608.3M不支持
  • 标准结构下,出图尺寸与请求 size 精确一致(3072x1728、3840x2160 落地像素均吻合)。 注意:第 3 节那种”简写写法”会让 size 被上游忽略,尺寸不可控。
  • 大尺寸的失败多为可重试的偶发错误,不一定是”尺寸不支持”。实测中见过两类: 传输层 INTERNAL_ERROR、上游 server_error: You can retry。两者都建议重试后再判断。
耗时参考(1024 档约 15-30 秒;3072x1728 约 70-80 秒;3840x2160 约 80 秒)。

12. 注意事项

  1. 结果有效期 15 分钟
    • 生成完成后,结果在服务端保留 15 分钟,过期后再 retrieve 返回 404。
    • 建议尽快取走结果,不要拿到 completed 后长时间不读取。
  2. 轮询频率
    • 图片生成:每 10-15 秒轮询一次。
    • 不要高频轮询(< 1 秒),会增加服务器负载。
  3. 取走即清除
    • 一旦 retrieve 返回了 completed 的完整结果,该结果映射会被删除; 请在同一次轮询里就把图片保存下来,不要依赖二次拉取。
  4. 单实例限制
    • 取消(cancel)只对当前处理该任务的服务实例生效。
    • 若服务重启,进行中的任务会丢失(映射 15 分钟后过期返回 404)。
  5. 多图 / 多文档务必用结构化 input 数组
    • input_image、多个 input_text 时,input 必须是数组结构(见第 5、6 节)。
    • 仅当 input 是单条纯文本字符串时才适合用简写。
  6. 错误处理
    • 提交(POST)返回非 queued 状态,说明请求参数有问题。
    • 轮询返回 failed 时,查看 error.message:常见原因有上游临时错误(可重试)、 不支持的尺寸、内容审核拒绝(moderation_blocked)。
  7. response_id 格式
    • 形如 resp_ + 一串十六进制字符,请原样保存用于后续轮询 / 取消。