Files
gpt-image-2-generator/references/api.md
2026-04-27 14:33:50 +08:00

316 lines
7.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# GPT Image 2 示例文档
本文档基于用户站 `https://apicodex.xyz` 的接入方式整理,包含:
- 文生图示例
- 带参考图示例
- 支持的比例列表
- 实测返回结构
- 同步返回与异步轮询的兼容写法
## 接口地址
```text
POST https://apicodex.xyz/v1/images/generations
```
## 鉴权
请求头使用 Bearer Token
```python
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json",
}
```
## 支持的比例
当前整理到的 `size` 比例共有 13 种:
- `1:1`
- `16:9`
- `9:16`
- `4:3`
- `3:4`
- `3:2`
- `2:3`
- `5:4`
- `4:5`
- `2:1`
- `1:2`
- `21:9`
- `9:21`
说明:
- 上述 13 种比例按你提供的接口说明整理
- 本文档里实际请求验证过的是 `16:9`
建议只通过 `size` 传比例,不要在 `prompt` 里重复写比例。
## 文生图示例
```python
import requests
url = "https://apicodex.xyz/v1/images/generations"
payload = {
"model": "gpt-image-2",
"prompt": "一只橘猫坐在窗台上看夕阳,水彩画风格",
"n": 1,
"size": "16:9",
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json",
}
response = requests.post(url, json=payload, headers=headers, timeout=300)
print(response.json())
```
## 带参考图示例
注意:不要把参考图放进 `/v1/images/generations``image_urls` 字段。当前实测该字段会被忽略,返回 usage 中 `input_tokens_details.image_tokens` 仍为 `0`。带图请求应走:
```text
POST https://apicodex.xyz/v1/images/edits
```
### 参考图为 URL
```python
import requests
image_url = "https://example.com/photo.jpg"
image_resp = requests.get(image_url, timeout=60)
image_resp.raise_for_status()
url = "https://apicodex.xyz/v1/images/edits"
data = {
"model": "gpt-image-2",
"prompt": "把这张照片变成水彩画风格",
"size": "1:1",
}
files = [
("image[]", ("photo.jpg", image_resp.content, image_resp.headers.get("Content-Type") or "image/jpeg")),
]
headers = {
"Authorization": "Bearer <token>",
}
response = requests.post(url, data=data, files=files, headers=headers, timeout=300)
print(response.json())
```
### 参考图为 base64
```python
import requests
import base64
url = "https://apicodex.xyz/v1/images/edits"
data = {
"model": "gpt-image-2",
"prompt": "把这张照片变成水彩画风格",
"size": "1:1",
}
image_bytes = base64.b64decode("iVBORw0KGgoAAAANSUhEUgAA...")
files = [
("image[]", ("reference.png", image_bytes, "image/png")),
]
headers = {
"Authorization": "Bearer <token>",
}
response = requests.post(url, data=data, files=files, headers=headers, timeout=300)
print(response.json())
```
### 多张参考图
```python
import requests
url = "https://apicodex.xyz/v1/images/edits"
data = {
"model": "gpt-image-2",
"prompt": "把这两张照片融合成一张海报",
"size": "4:3",
}
files = [
("image[]", ("photo-a.jpg", open("photo-a.jpg", "rb"), "image/jpeg")),
("image[]", ("photo-b.png", open("photo-b.png", "rb"), "image/png")),
]
headers = {
"Authorization": "Bearer <token>",
}
try:
response = requests.post(url, data=data, files=files, headers=headers, timeout=300)
print(response.json())
finally:
for _, file_tuple in files:
file_tuple[1].close()
```
## 实测结果
本仓库在 `2026-04-22`America/Los_Angeles对以下请求做了真实测试
```json
{
"model": "gpt-image-2",
"prompt": "一只橘猫坐在窗台上看夕阳,水彩画风格",
"n": 1,
"size": "16:9"
}
```
实测结论:
- 请求返回 `HTTP 200`
- `size: "16:9"` 被接口接受
- 当前实测返回是“同步结果”,不是 `task_id`
- 顶层字段为 `created``data`
- `data[0]` 中包含 `b64_json``revised_prompt`
- 本次实测的 `revised_prompt``黄昏里的橘猫窗台景`
- 本次解码后的样例图尺寸为 `1196x1315`,没有严格匹配 `16:9`
实测返回结构可概括为:
```json
{
"created": 1776919131,
"data": [
{
"b64_json": "<base64 image data>",
"revised_prompt": "黄昏里的橘猫窗台景"
}
]
}
```
本次测试产物已保存到仓库临时目录:
- `tmp/imagegen/gpt-image-2-16-9-response.json`
- `tmp/imagegen/gpt-image-2-16-9-sample.png`
## 同步返回时的取图方式
如果接口直接返回 `b64_json`,可以这样保存图片:
```python
import base64
import requests
url = "https://apicodex.xyz/v1/images/generations"
payload = {
"model": "gpt-image-2",
"prompt": "一只橘猫坐在窗台上看夕阳,水彩画风格",
"n": 1,
"size": "16:9",
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json",
}
response = requests.post(url, json=payload, headers=headers, timeout=300)
data = response.json()
img_b64 = data["data"][0]["b64_json"]
with open("output.png", "wb") as f:
f.write(base64.b64decode(img_b64))
```
## 异步轮询写法
你提供的说明里写的是“提交后返回 `task_id`,再轮询 `/v1/tasks/{task_id}`”。如果后续该上游切回异步模式,可以用下面这种兼容写法:
```python
import base64
import time
import requests
url = "https://apicodex.xyz/v1/images/generations"
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json",
}
payload = {
"model": "gpt-image-2",
"prompt": "a corgi astronaut on the moon, cinematic, 8k",
"size": "16:9",
"n": 1,
}
resp = requests.post(url, json=payload, headers=headers, timeout=300)
resp.raise_for_status()
data = resp.json()
# 情况 1直接同步返回 base64
if isinstance(data, dict) and data.get("data") and data["data"][0].get("b64_json"):
with open("output.png", "wb") as f:
f.write(base64.b64decode(data["data"][0]["b64_json"]))
print("saved output.png")
# 情况 2返回 task_id需要轮询
elif isinstance(data, dict) and data.get("data", {}).get("id"):
task_id = data["data"]["id"]
task_url = f"https://apicodex.xyz/v1/tasks/{task_id}"
time.sleep(10)
while True:
task_resp = requests.get(task_url, headers=headers, timeout=60)
task_resp.raise_for_status()
task = task_resp.json()
status = task["data"]["status"]
if status == "completed":
print(task["data"]["result"]["images"][0]["url"][0])
break
if status == "failed":
raise RuntimeError(task["data"]["error"]["message"])
time.sleep(5)
else:
raise RuntimeError(f"unexpected response: {data}")
```
## 如果是异步结果,取图字段
如果接口返回的是任务模式,则最终图片 URL 取值为:
```text
data.result.images[0].url[0]
```
任务状态说明:
- `pending`: 已提交或排队中
- `processing`: 上游处理中
- `completed`: 成功
- `failed`: 失败
## 注意事项
- 单张图接口耗时可能较长,建议客户端超时至少设到 `300s`
- 本次实测中,`size: "16:9"` 虽然被接口接受,但返回图片尺寸并未严格命中 `16:9`;如果你的业务依赖固定画幅,建议在下载后自行校验并按需裁切
- 如果使用异步模式,首次轮询建议在提交后等待 `10~20`
- 轮询间隔建议 `3~5` 秒,不要毫秒级高频轮询
- 建议失败时做有限次重试,尤其是 TLS 或上游网络抖动场景
- 如果服务端返回的是 `b64_json`,说明当前是同步模式,不需要再调 `/v1/tasks/{task_id}`