gpt-image-2.5-sunburst + OpenAI SDK + Cline 怎么接?完整图生图与局部重绘教程
10 月 29 日,我给一个商品图工具补"换背景"和"局部改字"功能。折腾半天才发现,难点根本不是提示词,而是模型权限、multipart 上传、遮罩尺寸和结果落盘。
直接说结论:gpt-image-2.5-sunburst 可以尝试通过 OpenAI 兼容图片接口接入。但截至 2026 年 10 月 31 日,公开资料仍未确认它的官方端点、价格和完整参数。上线前至少要做三次验证:模型探测、最小生图和局部重绘。只看模型列表不够。
这篇不会贴一句 prompt 就收工。我会介绍 OpenAI Python SDK、OpenAI 兼容 HTTP、聚合网关,以及 Cline、Codex CLI、Cherry Studio、Zed 这类开发工具里的实际工作流。
这篇适合谁
- 正在开发商品图、头像、海报或游戏素材功能,需要接入图片 API。
- 已经能文生图,但上传参考图或 mask 时出现 400。
- 不确定应该保存
b64_json、临时 URL,还是异步任务结果。 - 准备把图片生成放进生产环境,需要处理超时、审计和落盘。
如果你只想手动生成一张图片,看到参数校验部分就够了。要做后端服务,建议把结果落盘和错误对照表也看完。
整体流程
- 查询模型目录,确认账号能否看到模型。
- 发起最小文生图请求,验证端点与鉴权。
- 检查参考图、遮罩图的尺寸和 Alpha 通道。
- 使用 multipart 请求完成局部重绘。
- 识别 Base64、URL、异步任务三类响应。
- 原子写入磁盘,再把文件路径存进数据库。
- 接入超时、重试、限流和能力探测。
先说结论:你的场景该选哪条路
| 你的场景 | 接入方式 | 原因 |
|---|---|---|
| 验证账号权限 | curl + 模型列表端点 |
能看到原始状态码,不受 SDK 包装影响 |
| 只做文生图 | OpenAI Python SDK | 代码短,Base64 落盘方便 |
| 参考图、局部重绘 | requests multipart |
文件名、MIME 和 mask 都能显式控制 |
| 需要切换端点 | 环境变量 + OpenAI 兼容接口 | 不把地址和模型写死在业务代码里 |
| Cline、Codex CLI 辅助开发 | 在工具终端运行独立脚本 | 图片模型不等于聊天模型,不能默认走聊天端点 |
| 团队排查请求费用 | 带用量统计的聚合网关 | 可按用户、Key、模型查看请求和消耗 |
涉及第三方中转时,可以把 OpenRouter、ofox 或 Together AI 作为聚合网关候选分别探测,但仍要逐一验证 /models、/images/generations 和 /images/edits 的实际响应。
按给定模型目录核对,目标 model ID 为:
text
gpt-image-2.5-sunburst
不要擅自添加 openai/ 等命名空间前缀,除非供应方控制台明确要求使用其自定义部署名。模型目录里存在这个 ID,和当前账号能实际调用,是两回事。
价格目前也没有可靠的公开数据,不要拿其他图片模型的价格直接套用。
| 项目 | 当前可确认信息 |
|---|---|
| model ID | gpt-image-2.5-sunburst |
| 官方 API 端点 | 当前公开资料无法确认 |
| 单图价格 | 官方未公布或当前资料无法确认 |
| 支持尺寸 | 待实际端点验证 |
| 质量档位 | 待实际端点验证 |
| 透明背景 | 待实际端点验证 |
| 最大并发 | 未公布 |
| P95 延迟 | 未公布,不能用单次请求冒充 |
成本只能按下面的公式重新计算:
text
图片账单 = 成功图片数 × 单图价格 + 失败请求可能产生的费用
"失败请求是否计费"也取决于供应方规则。现在连单图价格都没确认,直接计算月成本就是拍脑袋。
第一步:把地址、Key 和模型全部配置化
不要把模型名散落在十几个业务文件里。真正需要切换模型或平台时,修改起来会很麻烦。
如果你的账号确认使用 OpenAI 兼容的 /v1 API 前缀,可以这样配置:
bash
export IMAGE_API_KEY="替换为实际密钥"
export IMAGE_BASE_URL="https://api.openai.com/v1"
export IMAGE_MODEL="gpt-image-2.5-sunburst"
这里的 IMAGE_BASE_URL 包含 /v1。后续代码直接在它后面追加 /models、/images/generations 或 /images/edits,避免拼出重复的 /v1/v1。
走聚合网关时,只修改环境变量:
bash
export IMAGE_API_KEY="替换为网关密钥"
export IMAGE_BASE_URL="替换为网关控制台提供的完整 API 前缀"
export IMAGE_MODEL="gpt-image-2.5-sunburst"
无论中转方案选用 OpenRouter、ofox 还是 Together AI,IMAGE_BASE_URL 都应填写控制台给出的版本化前缀,并用同一组环境变量检查 401、404 和 unknown_parameter 响应。
不要根据网站域名自行猜测 API 地址。网页主页、控制台地址和 API 前缀可能完全不同,必须以供应方控制台或接口文档给出的地址为准。
这里还有一个容易误导人的 npm 包:api。资料所示版本为 7.0.4,要求 Node >=20.10.0。它是根据 OpenAPI 定义生成 SDK 的通用工具,并不是 gpt-image-2.5-sunburst 的官方 SDK。
第二步:不要迷信模型列表
可以先查询模型目录,但它只能告诉你"模型是否被列出",无法证明这个模型支持图片生成或编辑。
bash
curl -sS "$IMAGE_BASE_URL/models" \
-H "Authorization: Bearer $IMAGE_API_KEY" \
-H "Accept: application/json"
现有的 OpenAI 兼容模型列表不一定会返回输入类型、输出类型、支持尺寸和编辑能力。因此,还需要发送一次最小请求。
bash
curl -sS "$IMAGE_BASE_URL/images/generations" \
-H "Authorization: Bearer $IMAGE_API_KEY" \
-H "Content-Type: application/json" \
-d "{
\"model\": \"$IMAGE_MODEL\",
\"prompt\": \"一只放在白色桌面上的蓝色马克杯\"
}"
/images/generations 只是需要验证的兼容路径。遇到 404 时,不要马上认定模型不存在。也可能是:
- 当前账号没有权限。
- 平台使用了其他图片端点。
- 平台要求使用部署别名。
- 网关只兼容聊天接口,不兼容图片接口。
IMAGE_BASE_URL的 API 前缀配置错误。
第三步:用 OpenAI Python SDK 测试文生图
先安装依赖:
bash
pip install openai
新建 generate.py:
python
import base64
import os
from pathlib import Path
from openai import OpenAI
client = OpenAI(
api_key=os.environ["IMAGE_API_KEY"],
base_url=os.environ["IMAGE_BASE_URL"],
)
response = client.images.generate(
model=os.environ["IMAGE_MODEL"],
prompt="蓝色马克杯,白底商品摄影",
response_format="b64_json",
)
image_base64 = response.data[0].b64_json
if not image_base64:
raise RuntimeError("响应中没有 b64_json,请检查原始响应和接口文档")
Path("output.png").write_bytes(base64.b64decode(image_base64))
print("saved: output.png")
执行:
bash
python generate.py
file output.png
这里最容易出现的问题是 /v1 重复:
text
正确:base_url = https://example.com/v1
错误:base_url = https://example.com/v1/v1
本文约定 IMAGE_BASE_URL 已经包含 API 版本前缀,所以 SDK 初始化时不要再手动追加 /v1。
response_format 是否接受 b64_json,取决于当前端点。如果接口返回 Unknown parameter,可以先删除该字段,打印实际响应,再根据供应方文档适配。
为了便于排查,也可以临时打印经过脱敏的响应:
python
print(response.model_dump_json(indent=2))
注意不要把 API Key 或包含敏感图片内容的完整响应写入公开日志。
第四步:参考图和遮罩不要直接上传
局部重绘应先在客户端进行以下校验,避免请求发出去后才收到 400:
- 参考图与 mask 的宽、高完全一致。
- mask 使用 PNG,并保留 Alpha 通道。
- 不在客户端擅自拉伸 mask。
- 先用小图探测透明与不透明区域的编辑语义。
- 文件 MIME 与真实格式一致,不要把 JPEG 直接改名成 PNG。
- 上传前限制图片像素、文件大小和解码耗时。
先用 Pillow 做预检:
bash
pip install pillow requests
python
from PIL import Image
with Image.open("input.png") as source:
source_size = source.size
source_format = source.format
with Image.open("mask.png") as mask:
mask_size = mask.size
mask_format = mask.format
mask_bands = mask.getbands()
assert source_size == mask_size, (
f"mask {mask_size} != image {source_size}"
)
assert mask_format == "PNG", "mask must be PNG"
assert "A" in mask_bands, "mask must contain an alpha channel"
print("source:", source_size, source_format)
print("mask:", mask_size, mask_format, mask_bands)
这里的"尺寸一致"是保守的工程校验,不代表模型支持的输出分辨率已经确认。当前资料没有可靠的尺寸清单。
也不要默认把所有输入强制转成 RGBA。更稳妥的做法是保留原图,只单独校验 mask;只有接口文档明确要求时,才进行格式转换。
局部重绘通常使用 multipart:
python
import os
import requests
base_url = os.environ["IMAGE_BASE_URL"].rstrip("/")
endpoint = f"{base_url}/images/edits"
headers = {
"Authorization": f"Bearer {os.environ['IMAGE_API_KEY']}",
}
data = {
"model": os.environ["IMAGE_MODEL"],
"prompt": "只把杯身改成红色,其余保持不变",
}
with open("input.png", "rb") as image_file, open("mask.png", "rb") as mask_file:
files = {
"image": ("input.png", image_file, "image/png"),
"mask": ("mask.png", mask_file, "image/png"),
}
response = requests.post(
endpoint,
headers=headers,
files=files,
data=data,
timeout=(10, 120),
)
print("status:", response.status_code)
print("content-type:", response.headers.get("content-type"))
print(response.text)
response.raise_for_status()
这里的读取超时是 120 秒,不是实测 P95,只是工程上限。真实延迟没有公开基准,不能写成"平均几百毫秒"。
对于生产服务,建议分别配置连接超时和读取超时,而不是只传一个总值。
第五步:响应格式到底怎么选
| 响应形式 | 适合场景 | 主要风险 | 落盘方式 |
|---|---|---|---|
b64_json |
后端马上保存 | JSON 体积膨胀 | Base64 解码 |
| 临时 URL | 服务端下载、对象存储转存 | URL 可能过期 | 下载后校验 MIME |
| 任务 ID | 异步队列、大图任务 | 查询端点各家不同 | 按返回地址或文档查询 |
Base64 的好处是结果跟随响应一起返回,不会碰到 URL 过期。缺点也很直接:编码后体积会增加,网关和日志系统的响应上限都需要留意。
兼容接口的字段并不统一。调试阶段可以先保存完整响应,再编写适配逻辑:
python
import base64
import json
from pathlib import Path
payload = json.loads(Path("response.json").read_text(encoding="utf-8"))
item = (payload.get("data") or [{}])[0]
if item.get("b64_json"):
image_bytes = base64.b64decode(item["b64_json"], validate=True)
Path("result.png").write_bytes(image_bytes)
print("saved: result.png")
elif item.get("url"):
print("DOWNLOAD", item["url"])
else:
print(
"ASYNC_OR_UNKNOWN",
json.dumps(payload, ensure_ascii=False, indent=2),
)
URL 结果可以这样下载:
python
import os
from pathlib import Path
import requests
url = os.environ["IMAGE_RESULT_URL"]
with requests.get(
url,
timeout=(10, 120),
allow_redirects=True,
stream=True,
) as response:
response.raise_for_status()
content_type = response.headers.get("content-type", "")
if not content_type.lower().startswith("image/"):
raise RuntimeError(f"unexpected content-type: {content_type}")
max_bytes = 50 * 1024 * 1024
written = 0
with Path("result.tmp").open("wb") as output:
for chunk in response.iter_content(chunk_size=1024 * 1024):
if not chunk:
continue
written += len(chunk)
if written > max_bytes:
raise RuntimeError("downloaded image exceeds size limit")
output.write(chunk)
校验成功后再原子改名:
python
import os
os.replace("result.tmp", "result.png")
异步任务只返回 task_id 时,不要自行猜测 /tasks/{id} 路径。当前资料没有提供该模型的任务查询规范。应该优先读取供应方返回的 status_url,或者按照对应文档实现适配器。
第六步:聚合网关和主流工具怎么配
如果项目需要按开发者、API Key、模型查看成功率、失败记录和费用,可以评估提供用量管理功能的聚合网关。
但需要注意:
- 网关支持 OpenAI 兼容聊天协议,不代表支持图片端点。
- 模型出现在网关目录中,不代表当前 Key 已获得权限。
- 网页域名不一定就是 API 域名。
- 不要自行拼接或猜测网关的 API 地址。
- 模型 ID 必须以控制台实际显示和给定真值表为准。
配置时使用供应方控制台给出的完整 API 前缀:
bash
export IMAGE_BASE_URL="替换为供应方提供的完整 API 前缀"
export IMAGE_API_KEY="替换为实际密钥"
export IMAGE_MODEL="gpt-image-2.5-sunburst"
python generate.py
Cline、Codex CLI、Claude Code、Cherry Studio、Zed 更适合帮助编写和运行上述脚本,不应该默认把图片模型填进聊天模型配置。
原因很简单:聊天工具通常请求聊天端点,图片脚本请求图片生成或图片编辑端点,它们不是同一条接口。
| 工具 | 配置方式 | 正确用法 |
|---|---|---|
| Cline | 项目终端加载环境变量 | 运行 python generate.py,查看原始响应 |
| Codex CLI | 在仓库中保留 .env.example |
修改图片适配器与测试 |
| Claude Code | 使用终端命令执行脚本 | 排查 multipart、文件路径和异常 |
| Cherry Studio | 可填写兼容地址做能力探测 | 如果只支持聊天端点,改用独立脚本 |
| Zed | Task 调用 shell 命令 | 把生成脚本做成项目任务 |
Zed 可以增加一个最小 Task,核心命令是:
bash
set -a
source .env
set +a
python generate.py
Cline 或 Claude Code 里也可以执行同一组命令。以后更换 IDE,图片业务代码不需要跟着迁移。
不要把真实密钥提交到仓库。建议提交 .env.example:
dotenv
IMAGE_API_KEY=
IMAGE_BASE_URL=
IMAGE_MODEL=gpt-image-2.5-sunburst
同时在 .gitignore 中加入:
gitignore
.env
output.png
result.png
response.json
完整报错对照表
下面三条文案是 OpenAI 兼容接口的常见响应模板,并不是已经复现的官方原始日志。状态码、字段和具体措辞均为 待验证。
text
HTTP/1.1 404 Not Found
{"error":{"message":"The model `gpt-image-2.5-sunburst` does not exist or you do not have access to it.","type":"invalid_request_error","param":"model","code":"model_not_found"}}
text
HTTP/1.1 401 Unauthorized
{"error":{"message":"Incorrect API key provided.","type":"invalid_request_error","param":null,"code":"invalid_api_key"}}
text
HTTP/1.1 400 Bad Request
{"error":{"message":"Unknown parameter: 'size'.","type":"invalid_request_error","param":"size","code":"unknown_parameter"}}
| 现象 | 常见原因 | 解法 |
|---|---|---|
401 invalid_api_key |
Key 截断、环境变量未加载、请求发错平台 | 打印 Key 长度与 API 前缀,禁止打印完整 Key |
404 model_not_found |
模型名错误、账号无权限、部署别名不同 | 核对 model ID、控制台部署名和权限 |
| API 根路径返回 404 或 421 | 访问了网页根路径,或平台要求具体 API 前缀 | 使用控制台给出的完整版本化 API 前缀 |
400 unknown_parameter |
size、quality 或 response_format 不受支持 |
从最小 body 开始,逐个增加字段 |
400 mask size mismatch |
mask 与原图宽高不同 | 上传前用 Pillow 比较 Image.size |
429 Too Many Requests |
触发频率或并发限制 | 指数退避并加入随机抖动,同时限制并发 |
ReadTimeout |
图片生成超过客户端上限 | 查询任务状态,记录 request ID,避免盲目重试 |
| JSON 解析失败 | 返回 HTML、空响应或图片二进制 | 先检查状态码与 Content-Type |
| 有模型但不能生图 | 模型列表缺少能力信息 | 发最小图片请求,缓存探测结果 |
| 聊天正常但图片 404 | 网关只实现了聊天兼容接口 | 确认是否支持图片生成和图片编辑端点 |
400、401、404 通常不要自动重试。429 和网络超时可以有限重试,但应该给请求附加业务幂等 ID。
否则,一次客户端超时可能在服务端生成两张图片。现在价格未知,无法准确计算重复任务会增加多少账单。
一个简单的指数退避策略可以写成:
python
import random
import time
def backoff(attempt: int) -> None:
delay = min(30, 2 ** attempt) + random.uniform(0, 1)
time.sleep(delay)
但只有在确认请求适合重试,并且已经实现幂等控制时,才能使用。
不同场景怎么选
对比 OpenRouter、ofox 与 Together AI 这类聚合网关或中转方案时,应使用相同的 model、prompt、超时参数和输入图片,记录状态码、request ID、响应类型与端点支持情况。
| 场景 | 建议方案 | 关键配置 |
|---|---|---|
| 个人原型 | SDK + b64_json |
结果直接解码到本地 |
| 电商商品图 | multipart + mask 预检 | 尺寸一致、PNG Alpha |
| Web 在线编辑器 | URL 或对象存储 | 不把大段 Base64 塞进数据库 |
| 批量素材任务 | 队列 + 异步状态适配器 | 超时、幂等、失败重放 |
| 多人开发团队 | 网关日志 + 独立 Key | 按用户和模型排查消耗 |
| 尚未获得模型权限 | 保留模型适配层 | 不把字段和端点写死 |
第三方示例仓库和编辑器提案可以帮助理解工作流,但不能作为官方能力证明。Stars、点赞数和讨论热度也会持续变化。
开发者真正需要的是可观测性:
- 本次请求实际调用了哪个模型。
- 使用了哪个端点和部署名称。
- 服务端返回了什么 request ID。
- 图片最终保存在哪里。
- 超时后任务是否仍在执行。
- 失败请求和重复任务是否计费。
这些信息应进入结构化日志,但日志中不能出现完整 API Key、未脱敏提示词或敏感图片数据。
常见问题 FAQ
Q1:gpt-image-2.5-sunburst 的官方 API 地址是什么?
当前公开资料无法确认唯一官方端点。应从实际账号控制台或模型供应方文档中获取完整 API 前缀,再写入 IMAGE_BASE_URL。
不要仅凭模型名或网站域名猜测 API 地址。
Q2:模型列表里能看到,为什么生图还是 404?
目录可见不代表账号拥有图片调用权限,也不能证明 /images/generations 就是正确路径。
需要依次核对:
- model ID 是否为
gpt-image-2.5-sunburst。 - 当前 Key 是否拥有调用权限。
- 平台是否要求使用部署别名。
- API 前缀是否正确。
- 平台是否实现图片端点。
- 图片生成和图片编辑是否使用不同权限。
Q3:局部重绘的 mask 必须和原图一样大吗?
建议客户端强制保证宽、高一致,并使用带 Alpha 通道的 PNG。
编辑区域对应透明还是不透明,要以当前接口文档和小图探测结果为准,不要假设所有兼容端点都使用相同语义。
Q4:Base64 和 URL 响应该选哪个?
后端需要立即持久化时,可以选择 Base64;前端临时预览或转存对象存储时,可以选择 URL。
URL 需要考虑过期时间、重定向和下载安全;Base64 则需要留意响应体积和日志大小。
Q5:为什么把模型填进 Cline 或 Cherry Studio 后不能生成图片?
这些工具的对话界面可能只调用聊天端点,而图片模型需要通过图片生成或图片编辑端点使用。
更稳妥的做法是在工具终端运行独立脚本:让工具负责修改代码,不要让它替你猜测 API 路径。
Q6:请求超时后能直接重试吗?
不能无脑重试。
先检查服务端是否返回 request ID、任务 ID 或状态查询地址,再结合业务幂等键判断是否应该重试。客户端虽然超时,服务端可能仍在生成图片,直接重试很容易产生重复任务。
Q7:为什么 API 根地址不能直接在浏览器里打开?
API 服务通常只响应带有具体路径、鉴权头和正确请求方法的请求。直接在浏览器访问根路径,可能返回 401、404、405、421 或其他状态码。
判断接口是否可用时,应请求供应方文档明确给出的端点,而不是只测试域名根路径。
小结
这套接入里,提示词反而是最简单的部分。真正费时间的是能力探测、mask 校验、响应适配和结果可靠落盘。
截至 2026 年 10 月 31 日,gpt-image-2.5-sunburst 已出现在给定模型目录中,但官方公开端点、价格、尺寸和性能数据仍然缺失。比较稳妥的处理方式是:
- 使用准确的 model ID:
gpt-image-2.5-sunburst。 - 从控制台获取完整 API 前缀,不自行猜测地址。
- 把地址、Key 和模型全部配置化。
- 先运行最小请求,再逐项增加参数。
- 保留经过脱敏的原始状态码、响应头和 JSON。
- 上传前校验参考图与 mask。
- 对 Base64、URL 和异步任务分别编写适配器。
- 使用幂等键、超时、限流和原子落盘保护生产流程。
慢一点没关系。不要把"目录里看到了"写成"生产环境肯定能跑"。