feat(image): add gpt-image-2 single and multi-image workflows

This commit is contained in:
zhangheng
2026-05-15 19:30:07 +08:00
commit 1e61d7c806
12 changed files with 1716 additions and 0 deletions

316
docs/usage.md Normal file
View File

@@ -0,0 +1,316 @@
# 图片生成接口指南
## 1. 环境准备
Windows PowerShell
```powershell
py -m pip install requests pillow
```
Mac / Linux Terminal
```bash
python3 -m pip install requests pillow
```
## 2. 接口地址
`POST https://api.toskaxy.xyz/v1/images/generations`
## 3. 鉴权方式
```http
Authorization: Bearer pk_live_xxx
Content-Type: application/json
```
## 4. 支持的图片模型
- `gpt-image-1`
- `gpt-image-1.5`
- `gpt-image-2`
## 5. 文生图最小字段
- `model`:图片模型名称,例如 `gpt-image-2`
- `prompt`:图片提示词
- `size`:输出尺寸。推荐直接传像素尺寸,例如 `4096x4096``4096x2304``2304x4096`
- `resolution`:兼容字段。使用比例写法时传 `1K``2K``4K`,网关会转换成实际像素尺寸
## 6. `gpt-image-2` 的 4K 尺寸规则
推荐写法:直接传像素。
```json
{ "model": "gpt-image-2", "prompt": "draw a clean product poster", "size": "4096x4096" }
{ "model": "gpt-image-2", "prompt": "draw a clean product poster", "size": "4096x2304" }
{ "model": "gpt-image-2", "prompt": "draw a clean product poster", "size": "2304x4096" }
```
兼容写法:比例 + `resolution`
```json
{ "model": "gpt-image-2", "prompt": "draw a clean product poster", "size": "1:1", "resolution": "4K" }
{ "model": "gpt-image-2", "prompt": "draw a clean product poster", "size": "16:9", "resolution": "4K" }
{ "model": "gpt-image-2", "prompt": "draw a clean product poster", "size": "9:16", "resolution": "4K" }
```
## 7. 比例转换示例
- `1:1` + `4K` -> `4096x4096`
- `16:9` + `4K` -> `4096x2304`
- `9:16` + `4K` -> `2304x4096`
- `3:4` + `4K` -> `3072x4096`
- `4:3` + `4K` -> `4096x3072`
## 8. 旧图片模型的 4K 降级规则
`gpt-image-1``gpt-image-1.5` 不支持真正 4K。如果用户传 `resolution: "4K"`,网关会自动降级成上游支持的最大尺寸。
- 横图比例:`1536x1024`
- 竖图比例:`1024x1536`
- 方图比例:`1024x1024`
## 9. 支持的比例
`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`
建议只通过 `size` 传比例,不要在 `prompt` 里重复写比例。
## 10. 4K 文生图完整 Python 示例
`API_KEY` 改成自己的密钥,保存为 `gpt_image2_generate.py` 后运行。
```python
import base64
import requests
API_KEY = "pk_live_xxx"
BASE_URL = "https://api.toskaxy.xyz"
payload = {
"model": "gpt-image-2",
"prompt": "高端香水产品海报,玻璃瓶,干净背景,商业摄影,细节清晰",
"n": 1,
"size": "4096x4096",
"quality": "high",
"response_format": "b64_json",
}
headers = {
"Authorization": f"Bearer {API_KEY}",
"Content-Type": "application/json",
}
resp = requests.post(
f"{BASE_URL}/v1/images/generations",
json=payload,
headers=headers,
timeout=240,
)
resp.raise_for_status()
data = resp.json()
img_b64 = data["data"][0]["b64_json"]
with open("output.png", "wb") as f:
f.write(base64.b64decode(img_b64))
print("已保存 output.png")
```
## 11. 图生图:参考图为公开 URL
```python
import base64
import requests
API_KEY = "pk_live_xxx"
BASE_URL = "https://api.toskaxy.xyz"
payload = {
"model": "gpt-image-2",
"prompt": "把参考图变成水彩画风格,保留主体结构",
"n": 1,
"size": "2048x2048",
"quality": "high",
"response_format": "b64_json",
"image_urls": [
"https://example.com/reference.jpg"
],
}
headers = {
"Authorization": f"Bearer {API_KEY}",
"Content-Type": "application/json",
}
resp = requests.post(
f"{BASE_URL}/v1/images/generations",
json=payload,
headers=headers,
timeout=240,
)
resp.raise_for_status()
data = resp.json()
img_b64 = data["data"][0]["b64_json"]
with open("output.png", "wb") as f:
f.write(base64.b64decode(img_b64))
print("已保存 output.png")
```
## 12. 图生图:参考图为本地文件 base64
`reference.png` 放到脚本同一个文件夹,脚本会把它转成 data URL 再提交。
```python
import base64
import requests
API_KEY = "pk_live_xxx"
BASE_URL = "https://api.toskaxy.xyz"
REFERENCE_FILE = "reference.png"
with open(REFERENCE_FILE, "rb") as f:
reference_b64 = base64.b64encode(f.read()).decode("utf-8")
payload = {
"model": "gpt-image-2",
"prompt": "基于参考图生成一张高端产品海报,干净构图,中文界面可用",
"n": 1,
"size": "4096x2304",
"quality": "high",
"response_format": "b64_json",
"image_urls": [
f"data:image/png;base64,{reference_b64}"
],
}
headers = {
"Authorization": f"Bearer {API_KEY}",
"Content-Type": "application/json",
}
resp = requests.post(
f"{BASE_URL}/v1/images/generations",
json=payload,
headers=headers,
timeout=240,
)
resp.raise_for_status()
data = resp.json()
img_b64 = data["data"][0]["b64_json"]
with open("output.png", "wb") as f:
f.write(base64.b64decode(img_b64))
print("已保存 output.png")
```
## 13. 下载后校验是否为 4K
```python
from io import BytesIO
from PIL import Image
import requests
image_url = "<接口返回的图片URL>"
img_bytes = requests.get(image_url, timeout=120).content
img = Image.open(BytesIO(img_bytes))
print(img.size)
width, height = img.size
assert max(width, height) >= 3840, f"not 4K enough: {img.size}"
```
## 14. 同步返回与异步轮询兼容写法
```python
import base64
import time
import requests
API_KEY = "pk_live_xxx"
BASE_URL = "https://api.toskaxy.xyz"
headers = {
"Authorization": f"Bearer {API_KEY}",
"Content-Type": "application/json",
}
payload = {
"model": "gpt-image-2",
"prompt": "a corgi astronaut on the moon, cinematic, 8k",
"size": "16:9",
"resolution": "4K",
"n": 1,
"response_format": "b64_json",
}
resp = requests.post(
f"{BASE_URL}/v1/images/generations",
json=payload,
headers=headers,
timeout=240,
)
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("已保存 output.png")
# 情况 2异步任务返回 task_id
elif isinstance(data, dict) and isinstance(data.get("data"), dict) and data["data"].get("id"):
task_id = data["data"]["id"]
task_url = f"{BASE_URL}/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}")
```
## 15. 图片接口常见问题
- 只传 `size: "16:9"` 不能保证一定是 4K要 4K推荐直接传 `4096x2304` 等像素尺寸。
- `gpt-image-1``gpt-image-1.5` 不支持真正 4K网关会自动降级。
- `gpt-image-2` 的图生图不要把参考图塞进 `/v1/images/generations` 的 JSON。应改走 `/v1/images/edits`,并用 `multipart/form-data` 上传 `image``image[]`
- 单张图可能耗时较长,客户端 `timeout` 建议至少 120 秒4K 建议 240 秒。
- 如果返回 `b64_json`,说明当前是同步模式,不需要再轮询 `task_id`
## 16. 直连测试命令
- 运行 `scripts/run_figma_direct_test.sh` 会先读取当前 `.env`,再临时清空本地代理并直连 `vip.auto-code.net`
- 它只强制 `IMAGE_REQUEST_STYLE=apicodex``IMAGE_SIZE=3840x2160` 和长超时,其余参数继续沿用 `.env``gpt_image2_generate.py` 的默认值。
- 每次请求会落到 `outputs/image-demo-runs/<时间戳>/`
- 直接运行:`bash scripts/run_figma_direct_test.sh`
- 只测 `https://api.aoixx.com/v1/images/generations` 时,运行 `bash scripts/run_aoixx_direct_test.sh`
- 如果要走 OpenAI-compatible 的 `gpt-image-2` 图生图,运行 `bash scripts/run_openai_gpt_image2_edit.sh`
- 如果要走多图参考生成多图,运行 `bash scripts/run_openai_gpt_image2_multi.sh`
- 图生图可通过环境变量传参考图:
`REFERENCE_IMAGE=./input.png`,或 `REFERENCE_IMAGE_URL=https://example.com/input.png`
- 如需 mask可额外传
`MASK_IMAGE=./mask.png`,或 `MASK_IMAGE_URL=https://example.com/mask.png`
- 多图参考推荐两种写法:
`REFERENCE_IMAGE_1=./a.png``REFERENCE_IMAGE_2=./b.png`,或
`REFERENCE_IMAGES='["./a.png","./b.png","./c.png"]'`
- 多图输出用 `IMAGE_N=3` 控制,未设置时默认等于参考图数量。
- 示例:
`REFERENCE_IMAGE=./input.png IMAGE_PROMPT="改成极简白底产品海报" bash scripts/run_openai_gpt_image2_edit.sh`