外观
生图接入指南
适合需要通过 API 或 SDK 生成、编辑图片的用户。选一条协议路径,生成或编辑一张图片,保存后再核对使用记录。
先看结论
| 模型 | 请求地址 | 认证头 | 图片通常在哪里 |
|---|---|---|---|
gpt-image-2 | 生成:https://api.bestai.chat/v1/images/generations编辑: https://api.bestai.chat/v1/images/edits | Authorization: Bearer <BestAI Key> | data[].b64_json,有些上游也会返回 data[].url |
gemini-3.1-flash-image | https://api.bestai.chat/v1beta/models/gemini-3.1-flash-image:generateContent | x-goog-api-key: <BestAI Key> | candidates[].content.parts[].inlineData |
gemini-3-pro-image | 同上,把 URL 中的模型名替换掉 | x-goog-api-key: <BestAI Key> | candidates[].content.parts[].inlineData |
几点需要先分清:
- 这里的
<BestAI Key>是你在 BestAI 控制台创建的 Key,不是 Google AI Studio Key,也不是 OpenAI 官方 Key。 - OpenAI 生成和编辑使用两个 endpoint;Gemini 没有单独的编辑 endpoint,在同一个
generateContent请求中附上原图即可。 - 模型、分组、尺寸和价格属于运营配置,以控制台当前显示为准。文档中的模型名只用于示例。
gemini-3-pro-image和gemini-3.1-flash-image是两种模型 ID。BestAI 的可用性和上游映射由当前分组决定,不凭模型名推断路由或能力。- 下面的验证请求会产生用量。OpenAI 示例用
1024x1024和n=1;Gemini 示例用imageSize="1K",不使用n字段。输出规格不代表固定价格。
开始前准备
在当前终端设置 Key。不要把真实值写进代码仓库、截图或聊天记录:
bash
export BESTAI_API_KEY="sk-你的Key"建议先在仪表盘确认余额和 Key 额度,再开始测试。
以下 curl 和 heredoc 命令适用于 Bash / Zsh / WSL,保存脚本需要 Python 3。Windows PowerShell 用户可选用 OpenAI Python SDK 示例;Bash 的 <<'PY' 语法不能直接用于 PowerShell。每次只执行选中的生成或编辑路径,不必逐条运行全文。
curl -sS 收到 HTTP 错误时也可能正常退出。先确认输出的 HTTP 状态,再解析保存的 JSON;失败后先读错误,不直接重试生成。示例响应文件会被同名的新响应覆盖,重跑前保留需要的旧 JSON。
OpenAI:gpt-image-2
1. 发出最小请求
OpenAI 图片接口的 Base URL 是 https://api.bestai.chat/v1,完整 endpoint 是 /images/generations。请求体先只保留模型、提示词、尺寸和数量:
bash
curl -sS \
"https://api.bestai.chat/v1/images/generations" \
-H "Authorization: Bearer $BESTAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-image-2",
"prompt": "一张简洁的蓝色几何海报,纯色背景,居中构图",
"size": "1024x1024",
"n": 1
}' \
-o openai-image-response.json \
-w "HTTP %{http_code}\n"注意:这里把响应保存成 JSON 文件。不要把整个 JSON 直接重命名成 .png,图片数据还需要解码。
2. 读取并保存图片
OpenAI 返回的常见结构是 data[0].b64_json。部分兼容上游会返回 data[0].url,下面脚本也支持下载。脚本只使用 Python 标准库;第二个参数指定输出文件前缀,已有图片不会被覆盖:
bash
python3 - openai-image-response.json bestai-image <<'PY'
import base64
import json
import sys
import urllib.request
import urllib.parse
with open(sys.argv[1], encoding="utf-8") as f:
response = json.load(f)
if response.get("error"):
raise SystemExit(response["error"])
item = (response.get("data") or [None])[0]
if not item:
raise SystemExit("响应中没有 data[0]")
if item.get("b64_json"):
image = base64.b64decode(item["b64_json"], validate=True)
elif item.get("url"):
# URL 可能有有效期,拿到后立即下载,不要把完整 URL 写入日志。
if urllib.parse.urlsplit(item["url"]).scheme not in ("https", "http"):
raise SystemExit("图片 URL 必须是 HTTP 或 HTTPS 地址")
with urllib.request.urlopen(item["url"], timeout=120) as source:
image = source.read()
else:
raise SystemExit("data[0] 中没有 b64_json 或 url")
if image.startswith(b"\x89PNG\r\n\x1a\n"):
suffix = ".png"
elif image.startswith(b"\xff\xd8"):
suffix = ".jpg"
elif image.startswith(b"RIFF") and image[8:12] == b"WEBP":
suffix = ".webp"
else:
raise SystemExit("返回内容不是可识别的 PNG、JPEG 或 WebP,请检查响应")
output = sys.argv[2] + suffix
with open(output, "xb") as f:
f.write(image)
print(f"已保存 {output} ({len(image)} bytes)")
PY出现 FileExistsError 时换一个输出前缀,不要删除尚需保留的图片。脚本识别实际格式后选择后缀;仍应使用图片查看器打开确认文件完整。
3. 使用原图编辑图片
编辑接口是 POST /v1/images/edits。这里使用 multipart/form-data 上传本地原图,先准备一张 PNG、JPEG 或 WebP 图片:
bash
export SOURCE_IMAGE="./source.png"
curl -sS \
"https://api.bestai.chat/v1/images/edits" \
-H "Authorization: Bearer $BESTAI_API_KEY" \
-F "image=@${SOURCE_IMAGE}" \
-F "model=gpt-image-2" \
-F "prompt=保留主体和构图,只把白色背景改为浅蓝色" \
-F "size=1024x1024" \
-F "n=1" \
-o openai-image-edit-response.json \
-w "HTTP %{http_code}\n"curl -F 会自动生成包含 boundary 的 Content-Type,不要手动填写该请求头。首次使用较小的原图,按不超过 20 MiB(20 × 1024 × 1024 字节)的单文件大小准备;站点总请求大小和所选上游可能有更低限制。
编辑响应与生成响应的取图方式相同。复用上面脚本,将输入文件名改为 openai-image-edit-response.json,输出前缀改为 bestai-image-edit。
4. OpenAI SDK 的最小写法
在自己的 Python 环境先运行 python -m pip install openai。下例保存为 .py,用同一环境运行,读取已设置的 BESTAI_API_KEY。SDK 响应先存成 JSON,再复用前面的取图脚本;不把未知格式的数据直接命名为 PNG:
python
import os
from pathlib import Path
from openai import OpenAI
client = OpenAI(
base_url="https://api.bestai.chat/v1",
api_key=os.environ["BESTAI_API_KEY"],
)
output_path = Path("openai-image-response.json")
if output_path.exists():
raise SystemExit("响应文件已存在,请先更换 output_path 再调用")
result = client.images.generate(
model="gpt-image-2",
prompt="一张简洁的蓝色几何海报,纯色背景,居中构图",
size="1024x1024",
n=1,
)
with output_path.open("x", encoding="utf-8") as output:
output.write(result.model_dump_json())
print("已保存 openai-image-response.json,请继续执行取图脚本")要编辑时,保留上面的 import 与 client 初始化,用下面代码替换生成调用及保存步骤,不需要先生成一张新图:
python
output_path = Path("openai-image-edit-response.json")
if output_path.exists():
raise SystemExit("响应文件已存在,请先更换 output_path 再调用")
with open("source.png", "rb") as source:
result = client.images.edit(
model="gpt-image-2",
image=source,
prompt="保留主体和构图,只把白色背景改为浅蓝色",
size="1024x1024",
n=1,
)
with output_path.open("x", encoding="utf-8") as output:
output.write(result.model_dump_json())
print("已保存 openai-image-edit-response.json,请继续执行取图脚本")SDK 示例也使用不覆盖模式保存 JSON;再次调用前换一个文件名。PowerShell 下取图时,将前面两个 PY 标记之间的 Python 代码保存为 save_openai_image.py,运行 python save_openai_image.py openai-image-response.json bestai-image。
某些客户端会把 gpt-image-2 作为 Responses API 的 image_generation 工具调用。那是另一条协议路径;本文的最小验证使用 Images API。如果客户端报“不支持 /v1/responses”,请在客户端切换到图片接口,或按该客户端的 Responses 配置说明处理。
Gemini:gemini-3.1-flash-image
1. 发出原生 Gemini 请求
Gemini 原生兼容接口的 Base URL 是 https://api.bestai.chat/v1beta。generateContent 是 endpoint 的动作名,不能省略:
bash
export GEMINI_IMAGE_MODEL="gemini-3.1-flash-image"
curl -sS \
"https://api.bestai.chat/v1beta/models/${GEMINI_IMAGE_MODEL}:generateContent" \
-H "x-goog-api-key: $BESTAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"contents": [
{
"role": "user",
"parts": [
{"text": "生成一个简单的绿色圆形,纯色背景,仅用于接口验证"}
]
}
],
"generationConfig": {
"responseModalities": ["TEXT", "IMAGE"],
"imageConfig": {
"aspectRatio": "1:1",
"imageSize": "1K"
}
}
}' \
-o gemini-image-response.json \
-w "HTTP %{http_code}\n"本例用 responseModalities: ["TEXT", "IMAGE"] 请求文本和图片,不将模态限制为只有 TEXT。aspectRatio 和 imageSize 是生成配置,不要放在 contents 里。常见比例包括 1:1、16:9、9:16、4:3 和 3:4;1K、2K、4K 是否可用,以当前模型和分组为准。
2. 从 inlineData 保存图片
Gemini 的图片通常位于 candidates[].content.parts[] 中,字段名是大小写敏感的 inlineData,其中:
mimeType是图片类型,例如image/png或image/jpeg。data是不带data:image/...;base64,前缀的 Base64 字符串。
下面脚本保存最终响应中的图片 part,跳过标记为思考过程的内容。第二个参数是输出前缀,文件已存在时会停止:
bash
python3 - gemini-image-response.json bestai-gemini <<'PY'
import base64
import json
import sys
with open(sys.argv[1], encoding="utf-8") as f:
response = json.load(f)
if response.get("error"):
raise SystemExit(response["error"])
count = 0
for candidate in response.get("candidates", []):
for part in (candidate.get("content") or {}).get("parts", []):
if part.get("thought"):
continue
inline = part.get("inlineData") or part.get("inline_data")
if not inline or not inline.get("data"):
continue
mime = inline.get("mimeType") or inline.get("mime_type") or ""
if not mime.startswith("image/"):
continue
raw = base64.b64decode(inline["data"], validate=True)
if raw.startswith(b"\x89PNG\r\n\x1a\n"):
suffix = ".png"
elif raw.startswith(b"\xff\xd8"):
suffix = ".jpg"
elif raw.startswith(b"RIFF") and raw[8:12] == b"WEBP":
suffix = ".webp"
else:
raise SystemExit("图片 part 不是可识别的 PNG、JPEG 或 WebP")
count += 1
output = f"{sys.argv[2]}-{count:02d}{suffix}"
with open(output, "xb") as f:
f.write(raw)
print(f"已保存 {output} ({len(raw)} bytes)")
if count == 0:
raise SystemExit("响应中没有 inlineData 图片 part")
PY3. 使用原图编辑图片
Gemini 编辑仍请求 generateContent。区别是 parts 中必须同时包含修改要求和原图 inlineData。下面的 Python 只使用标准库,用来构造请求 JSON:
bash
export SOURCE_IMAGE="./source.png"
python3 - "$SOURCE_IMAGE" > gemini-image-edit-request.json <<'PY'
import base64
import json
import pathlib
import sys
source = pathlib.Path(sys.argv[1]).read_bytes()
if source.startswith(b"\x89PNG\r\n\x1a\n"):
mime_type = "image/png"
elif source.startswith(b"\xff\xd8"):
mime_type = "image/jpeg"
elif source.startswith(b"RIFF") and source[8:12] == b"WEBP":
mime_type = "image/webp"
else:
raise SystemExit("原图应为 PNG、JPEG 或 WebP")
request = {
"contents": [
{
"role": "user",
"parts": [
{"text": "保留主体和构图,只把白色背景改为浅蓝色"},
{
"inlineData": {
"mimeType": mime_type,
"data": base64.b64encode(source).decode("ascii"),
}
},
],
}
],
"generationConfig": {
"responseModalities": ["TEXT", "IMAGE"],
"imageConfig": {"aspectRatio": "1:1", "imageSize": "1K"},
},
}
json.dump(request, sys.stdout, ensure_ascii=False)
PY确认生成 JSON 的步骤没有报错后,再发送请求;GEMINI_IMAGE_MODEL 使用本节前面设置的模型:
bash
curl -sS \
"https://api.bestai.chat/v1beta/models/${GEMINI_IMAGE_MODEL}:generateContent" \
-H "x-goog-api-key: $BESTAI_API_KEY" \
-H "Content-Type: application/json" \
--data-binary @gemini-image-edit-request.json \
-o gemini-image-edit-response.json \
-w "HTTP %{http_code}\n"脚本按原图内容识别 MIME 类型。复用“从 inlineData 保存图片”的脚本,将输入文件名改为 gemini-image-edit-response.json,第二个参数改为 bestai-gemini-edit。重跑时换一个输出前缀,避免与旧图片重名。
4. 使用 gemini-3-pro-image
只需要替换模型 ID:
bash
export GEMINI_IMAGE_MODEL="gemini-3-pro-image"请求体和保存方式不变,但要先确认 Key 的分组确实提供这个模型。模型不可用、余额不足和上游拒绝是不同问题,按错误正文分别检查,不通过反复换模型重试来处理额度问题。
批量生成多张图片
如果你要处理多条提示词,或希望集中查看、下载批量任务结果,可以直接使用 BestAI 批量生图。页面已包含 Key、模型、提示词和结果下载的操作说明,不需要手工组装 API 请求。
批量生图只会显示已开通该能力的 Key 和模型,以页面实际可选内容为准。单张生成或图片编辑继续使用本文上面的 API 方式。
如何判断图片真的生成成功
一次图片生成或编辑验证同时满足下面三点,才算接入完成:
- HTTP 请求成功,并且响应中确实找到
b64_json、url或inlineData图片数据。 - 脚本能把图片写入本地,且文件能被图片查看器打开。
- 在使用记录中找到同一时间的请求,核对模型、状态和实际扣费。
只有 HTTP 200、但没有图片字段时,不要直接把响应当成图片;先保存 JSON 并检查是否返回了文本、错误或安全拦截信息。图片 URL 可能有有效期,拿到后立即下载;Base64 图片很大时也不要把完整响应打印到终端日志。
常见错误
| 现象 | 第一检查项 |
|---|---|
401 / 403 | Key 是否完整、认证头是否正确、Key 所属分组是否开放生图、余额和额度是否足够 |
404 | 对照本文完整请求地址,确认没有重复路径,Gemini 没漏 /v1beta/models/ 或 :generateContent |
| 模型不存在 / 不在白名单 | 使用控制台当前显示的模型 ID;不要把其他分组的模型名直接照抄过来 |
| 余额不足相关错误 | 先查自己的账户、订阅和 Key 额度;均正常时提供脱敏错误正文排查上游,不能只凭一句错误确定是哪一层余额不足 |
image file is required | OpenAI 编辑请求是否使用 -F "image=@...",并确认文件存在 |
image_endpoint_required | 核对客户端是否把图片模型发到了文字接口;切到本文对应的图片协议,仍失败时保留完整错误代码排查分组能力 |
| 返回成功但没有图片 | 检查 data[].b64_json、data[].url 或 Gemini 的 inlineData,并确认请求包含图片模态 |
| 有图片但没有使用记录 | 先刷新并检查日期、Key 和模型筛选,再核对客户端 Base URL 和 Key |
生图请求通常比短文本验证更贵。排查时保留请求时间、模型 ID、HTTP 状态和使用记录即可,不要提交完整 API Key、Cookie 或完整响应内容。
返回通用 SDK 接入指南查看其他协议,或回到文档中心选择下一项任务。
协议依据
核对日期:2026-10-03。参考 OpenAI 图片接口说明、GPT Image 2 模型页及 Gemini generateContent 生图说明。
本文使用 BestAI 的 Images / generateContent 兼容路径。Google 当前示例中的 responseFormat.image 与本页的 generationConfig.imageConfig 不是同一字段;本页沿用 BestAI 已有的 imageConfig 配置,不直接混用。上游官方能力不等同于每个 BestAI 分组都已开通。
