系列导语
本文是【大模型API中转站】系列篇。本系列致力于用最低的成本、最清晰的方法,帮你打通多模型 API 的任督二脉。建议先收藏,随用随查。
上一篇我们用 WorkBuddy 零代码接入了 gpt-image-2,这一篇进阶到代码层:用 Python 直接调用 gpt-image-2 生图接口。给你两种写法——OpenAI 官方 SDK (最省心)和原生 HTTP (最透明),都走 4SAPI 中转,复制即可跑。
1. 开篇:我为什么需要这个方案
痛点 :界面工具适合手动出图,但一旦要批量生成、接进自己的应用、做自动化流水线 ,就必须用代码调用 API。而直连官方依旧卡在注册、网络、外卡那几关,调试时一个超时就能耗掉你半天。
场景 :你是一个国内开发者,想在自己的脚本或后端服务里调用 GPT 生图能力——比如电商批量出图、给文章自动配图、做一个生图小工具——需要一段稳定、能跑通的代码。
本文目标 :给你一条"Python 代码 → 中转(4SAPI) → gpt-image-2"的可行通路,提供 SDK 与 HTTP 两套完整可运行代码,附响应解析、存图和错误处理。
2. 原理速览
请求流向:
你的 Python 代码
│ POST /v1/images/generations
│ (OpenAI 兼容格式 + Bearer 鉴权)
▼
中转服务 4SAPI(国内可达)
│ 转发 + 鉴权 + 计费
▼
gpt-image-2 生图模型
│ 返回图片(URL 或 base64)
▼
原路回传 → 你的代码保存/使用 Copy
关键认知:生图走的是专用端点。 和对话接口(/v1/chat/completions)不同,生图用的是 /v1/images/generations 。请求体的核心字段:
字段 含义 示例 model模型名称 gpt-image-2prompt生图提示词 "a cat sitting on wooden floor"n生成张数 1size图片尺寸(可选) "1024x1024"
因为 4SAPI 提供 OpenAI 兼容协议 ,所以你既可以直接用官方 openai SDK(只改 base_url),也可以用原生 HTTP 自己拼请求。下面两种都给。
3. 接入方案
准备工作 :到 4SAPI 官网注册并获取 API Key。下面代码里所有 YOUR_4SAPI_KEY 都替换成你的真实密钥。强烈建议用环境变量存放,不要硬编码进代码。
bash
# 先把 Key 放进环境变量(推荐)
# Windows PowerShell:
setx OPENAI_API_KEY "你的4sapi密钥"
# macOS / Linux:
export OPENAI_API_KEY = "你的4sapi密钥" Copy
方案一:OpenAI 官方 SDK(推荐,最省心)
SDK 帮你处理了鉴权头、序列化、重试等细节,代码最干净。只需把 base_url 指向 4SAPI。
安装依赖:
完整代码:
python
import os
import base64
from openai import OpenAI
# base_url 指向 4SAPI 中转,api_key 从环境变量读取
client = OpenAI(
api_key = os.getenv( "OPENAI_API_KEY" ), # 你的 4SAPI 密钥
base_url = "https://4sapi.com/v1" ,
)
resp = client.images.generate(
model = "gpt-image-2" ,
prompt = "a cat sitting on a wooden floor, warm light" ,
n = 1 ,
size = "1024x1024" ,
)
# 响应可能返回 url,也可能返回 base64(b64_json),两种都兼容处理
item = resp.data[ 0 ]
if getattr (item, "url" , None ):
print ( "图片 URL:" , item.url)
elif getattr (item, "b64_json" , None ):
img_bytes = base64.b64decode(item.b64_json)
with open ( "gpt_image_sdk.png" , "wb" ) as f:
f.write(img_bytes)
print ( "已保存为 gpt_image_sdk.png" ) Copy
说明 :images.generate 返回的 data 是一个列表,n 设为几就有几张。不同模型/参数下,结果可能是图片 url,也可能是 b64_json(base64 编码的图片),上面代码两种都做了兼容。
方案二:原生 HTTP 调用(最透明,无需 SDK)
不想装 SDK,或想完全掌控请求时用这种。这就是你给的那段代码,我补全了鉴权和说明:
python
import http.client
import json
conn = http.client.HTTPSConnection( "4sapi.com" )
payload = json.dumps({
"model" : "gpt-image-2" ,
"prompt" : "cat" ,
"n" : 1
})
headers = {
'Accept' : 'application/json' ,
'Authorization' : 'Bearer YOUR_4SAPI_KEY' , # 注意 Bearer 前缀,换成你的真实密钥
'Content-Type' : 'application/json'
}
conn.request( "POST" , "/v1/images/generations" , payload, headers)
res = conn.getresponse()
data = res.read()
text = data.decode( "utf-8" )
print (text)
# 把原始响应存成 json,方便后续解析/排查
with open ( "gpt_image_response.json" , "w" , encoding = "utf-8" ) as f:
f.write(text) Copy
关键修正 :你原代码里 'Authorization': '' 是空的,调用会直接返回 401。鉴权头必须是 Bearer + 你的密钥 (Bearer 后有个空格),这是最容易踩的坑。
进阶:从 HTTP 响应里把图片真正存下来
上面只是存了原始 JSON。要拿到图片本体,再加一段解析:
python
import base64
import urllib.request
result = json.loads(text)
item = result[ "data" ][ 0 ]
if "url" in item and item[ "url" ]:
# 返回的是图片链接,下载下来
urllib.request.urlretrieve(item[ "url" ], "gpt_image_http.png" )
print ( "已下载为 gpt_image_http.png" )
elif "b64_json" in item and item[ "b64_json" ]:
# 返回的是 base64,解码写文件
with open ( "gpt_image_http.png" , "wb" ) as f:
f.write(base64.b64decode(item[ "b64_json" ]))
print ( "已保存为 gpt_image_http.png" ) Copy
第 4 步:运行并验证
把密钥填好后直接运行脚本。跑通的标志:
控制台打印出图片 URL 或一段 JSON。
当前目录生成了 gpt_image_sdk.png / gpt_image_http.png(或 gpt_image_response.json)。
打开图片,能看到一只猫——整条链路就通了。
3.5 两种写法怎么选?常见报错排查
选型对比:
维度 OpenAI SDK 原生 HTTP 上手难度 低,几行搞定 中,要自己拼请求 依赖 需 pip install openai 仅标准库,零依赖 可控性 一般 高,请求全透明 适合场景 业务开发、快速集成 调试、嵌入受限环境、学习原理
一句话建议 :日常开发用 SDK,排查问题或环境装不了依赖时用 HTTP。
常见报错:
现象 原因 解法 401 Unauthorized Authorization 为空、漏了 Bearer 前缀、Key 错 头部填 Bearer 你的密钥,核对 Key 404 Not Found 端点写错(用了 chat 路径)、模型名错 生图用 /v1/images/generations,模型名 gpt-image-2 429 限流 调用太频繁 / 额度耗尽 加重试与退避,检查 4SAPI 余额 KeyError: 'data' 响应是错误体而非正常结果 先打印 text 看返回内容,按报错信息定位 图片打不开 把 base64 当 URL 处理(或反之) 用上文 url / b64_json 兼容写法 超时 网络波动 / 中转排队 设置超时与重试,持续异常联系中转站
排查口诀:先看 401(鉴权)、再看 404(端点/模型名)、最后看响应体 。
3.6 其他语言怎么调?(cURL / Node.js / Go)
协议是统一的,换语言只是换"拼请求"的写法。下面三段都走同一个端点 https://4sapi.com/v1/images/generations、同样的 Bearer 鉴权。
cURL(最快验证,先用它确认 Key 和端点没问题):
bash
curl https://4sapi.com/v1/images/generations \
-H "Authorization: Bearer YOUR_4SAPI_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-image-2",
"prompt": "a cat sitting on a wooden floor",
"n": 1
}' Copy
Node.js(用官方 openai SDK,和 Python 同款思路):
javascript
import OpenAI from "openai";
import fs from "fs";
const client = new OpenAI({
apiKey: process.env.OPENAI_API_KEY, // 你的 4SAPI 密钥
baseURL: "https://4sapi.com/v1",
});
const resp = await client.images.generate({
model: "gpt-image-2",
prompt: "a cat sitting on a wooden floor, warm light",
n: 1,
size: "1024x1024",
});
const item = resp.data[0];
if (item.url) {
console.log("图片 URL:", item.url);
} else if (item.b64_json) {
fs.writeFileSync("gpt_image_node.png", Buffer.from(item.b64_json, "base64"));
console.log("已保存为 gpt_image_node.png");
} Copy
Go(标准库,零第三方依赖):
go
package main
import (
" bytes "
" fmt "
" io "
" net/http "
)
func main () {
payload := [] byte ( `{"model":"gpt-image-2","prompt":"a cat","n":1}` )
req, _ := http. NewRequest ( "POST" ,
"https://4sapi.com/v1/images/generations" ,
bytes. NewBuffer (payload))
req.Header. Set ( "Authorization" , "Bearer YOUR_4SAPI_KEY" )
req.Header. Set ( "Content-Type" , "application/json" )
resp, err := http.DefaultClient. Do (req)
if err != nil {
panic (err)
}
defer resp.Body. Close ()
body, _ := io. ReadAll (resp.Body)
fmt. Println ( string (body))
} Copy
记住:无论哪种语言,端点、鉴权头、请求体字段都一样 。换语言只是换语法外壳,协议层是同一套。
3.7 进阶:能上生产的批量生成(重试 + 退避 + 限流)
前面的代码是"能跑通",真要批量出图还得加三件套:超时、重试退避、并发限流 。下面是一个可直接复用的 Python 封装,循环出图时单张失败不会拖垮整批。
python
import os
import time
import base64
import random
from openai import OpenAI
client = OpenAI(
api_key = os.getenv( "OPENAI_API_KEY" ),
base_url = "https://4sapi.com/v1" ,
timeout = 60 , # 单次请求超时(秒)
)
def generate_one (prompt, filename, max_retries = 4 ):
"""生成单张图,带指数退避重试。成功返回 True。"""
for attempt in range (max_retries):
try :
resp = client.images.generate(
model = "gpt-image-2" ,
prompt = prompt,
n = 1 ,
size = "1024x1024" ,
)
item = resp.data[ 0 ]
if getattr (item, "b64_json" , None ):
with open (filename, "wb" ) as f:
f.write(base64.b64decode(item.b64_json))
elif getattr (item, "url" , None ):
import urllib.request
urllib.request.urlretrieve(item.url, filename)
print ( f "[OK] { filename } " )
return True
except Exception as e:
# 指数退避 + 随机抖动,避免被限流时一起重试
wait = ( 2 ** attempt) + random.random()
print ( f "[重试 { attempt + 1} / { max_retries } ] { e } , { wait :.1f } s 后再试" )
time.sleep(wait)
print ( f "[FAIL] { filename } 最终失败" )
return False
# 批量任务:提示词 → 文件名
tasks = [
( "a cat sitting on a wooden floor" , "cat_01.png" ),
( "a dog running on grass" , "dog_01.png" ),
( "a cup of coffee on a desk" , "coffee_01.png" ),
]
ok = 0
for prompt, filename in tasks:
if generate_one(prompt, filename):
ok += 1
time.sleep( 1 ) # 简单限流:每张之间停 1 秒,按额度调整
print ( f "完成 { ok } / {len (tasks) } 张" ) Copy
这段代码做对了几件事:
超时 :timeout=60 防止单次卡死无限等待。
指数退避 :失败后等待 2^n + 抖动 秒,遇到 429 限流时尤其有用。
随机抖动 :避免多任务"同时重试"再次撞限流。
批次容错 :单张失败只影响那一张,整批继续;最后汇总成功数。
简单限流 :每张之间 sleep,按你的额度调节,避免一上来就触顶。
想再快可以上并发(concurrent.futures 线程池),但务必同时配合限流和退避,否则很容易被中转或上游限流挡回来。
3.8 提示词怎么写,出图才稳
同样的模型,提示词差一点,出图质量天差地别。几条实用经验:
主体 + 细节 + 风格 + 光线 四件套:a cat(主体)→ orange tabby cat on a wooden floor(细节)→ photorealistic(风格)→ warm afternoon light(光线)。
用英文写提示词 :生图模型对英文提示词通常更敏感、更稳定。
负向描述放进 prompt :不想要的元素直接写明,如 no text, no watermark。
固定风格做产品图 :把品牌色、构图、背景写成模板,只替换主体,保证一批图风格统一。
先小图快试,再大图定稿 :低分辨率快速验证提示词方向,满意了再出高清,省钱省时。
对比示例:
text
弱提示词:cat
强提示词:a fluffy orange tabby cat sitting on a light wooden floor,
photorealistic, warm afternoon light, shallow depth of field,
no text, no watermark Copy
后者出图的可控性和成品率明显更高。
3.9 真实落地场景
这套调用能力接进业务后,常见的三类用法:
批量商品图 / 配图 :电商或内容平台,按商品/文章标题批量生成配图,用 3.7 的批量封装跑一个列表即可。
应用内"一键生图"功能 :把调用封装成后端接口,前端传 prompt、后端返图片,做成你 App 里的生图按钮。
自动化内容流水线 :和定时任务结合,比如每天为新发布的文章自动配一张题图,全程无人工。
接进后端时记得:Key 只放服务端 ,绝不下发到前端;前端调你自己的接口,由后端去调中转,这样既安全又能统一做限流和计费。
3.10 调用参数速查表
参数 必填 说明 model是 模型名,固定 gpt-image-2 prompt是 生图提示词,建议英文 + 细节 n否 生成张数,默认 1 size否 尺寸,如 1024x1024,以模型支持为准 response_format否 部分实现支持指定 url 或 b64_json
不同中转/模型版本支持的参数略有差异,拿不准时先用 cURL 打一发,看返回里有哪些字段最直接。
4. 成本与风险提示
费用构成 :中转调用费(4SAPI 侧,按用量/套餐)+ gpt-image-2 生成费(一般按张数 × 分辨率计价)。批量调用前务必做小批量测算 ,循环里一不小心就是一笔大账单。
代码安全 :
API Key 绝不硬编码 进源码,用环境变量或密钥管理服务,提交前检查别把 Key 带进 Git。
.gitignore 加上含密钥的本地配置文件。
数据隐私 :请求经中转转发,敏感内容(个人信息、内部资料)不建议直接发往第三方通路。
合规提醒 :遵守模型官方使用条款与内容政策,不用于违规绕过或滥用。
生产环境建议 :批量场景务必加超时、重试(指数退避)、限流控制 ;关键业务准备降级通路,不要把单一中转作为唯一依赖。
5. 总结与系列导航
一句话总结 :想用代码调用 gpt-image-2 生图,记住三件事——
端点 :POST https://4sapi.com/v1/images/generations
鉴权 :请求头 Authorization: Bearer 你的密钥(别忘了 Bearer 和那个空格)
两种写法 :要省心用 OpenAI SDK(改 base_url 即可),要透明用原生 HTTP
SDK 适合快速集成进业务,HTTP 适合调试和受限环境。两套代码都已给全,复制改 Key 即可跑。
常见疑问(FAQ)
Q:能一次生成多张吗? 能,把 n 调大即可,响应 data 会返回对应数量;批量更多图建议用 3.7 的重试封装。
Q:怎么控制图片尺寸? 加 size 字段,如 "1024x1024",具体支持的尺寸以模型为准。
Q:其他语言能调吗? 能,见 3.6 的 cURL / Node.js / Go 示例。只要支持 HTTP,端点和 Bearer 鉴权都一样。
Q:批量出图老被限流怎么办? 用 3.7 的指数退避 + 随机抖动 + 每张间隔,按额度调节并发与间隔。
Q:出图质量不稳定? 看 3.8,把提示词写成"主体+细节+风格+光线",并用英文描述。
如果你有更优雅的封装或批量调用姿势,欢迎在评论区分享,我会挑选优质思路补充进系列。