RuAPI 提供两个系列的图像生成模型:Gemini Image(也就是俗称的 Nano Banana)和 GPT Image。它们的调用方式完全不同,这是动手之前必须先搞清楚的一点。USDT 计费,无需外币卡。
Gemini 图像模型不走 /v1/images/generations。 它们走普通的聊天端点 /v1/chat/completions,生成的图片直接夹在回复正文里。详见「方式一」。
可用模型
| 模型 ID | 端点 | 计费方式 | 什么时候用 |
|---|
gemini-2.5-flash-image | chat | 按次 | 最便宜。改图能力尤其强 |
gemini-3.1-flash-image-preview | chat | 按次 | 更快,画质好于 2.5 |
gemini-3-pro-image-preview | chat | 按次 | 画质最高(Nano Banana Pro) |
gpt-image-2 | /v1/images/generations | 按 token | 兼容 OpenAI 生态 |
准确的价格见主站 价格页面。Gemini 系列按次计费(一张图一口价),gpt-image-2 按 token 计费(图越大、质量越高越贵)。
接口地址与鉴权
- Base URL:
https://www.ruapi.ai/v1
- 鉴权:请求头带
Authorization: Bearer sk-你的KEY(在控制台「令牌」页创建)
方式一:Gemini Image —— 走聊天端点
Gemini 图像模型挂在聊天端点上。你像调文本模型一样发请求,回来的是图片。
图片是以 Markdown data URI 的形式内联在 choices[0].message.content 里的 —— 没有单独的图片字段。响应长这样:这是一只穿着宇航服、以土星为背景的橘猫!

你得自己把 base64 从正文里抠出来。下面是现成的代码。
文生图
curl https://www.ruapi.ai/v1/chat/completions \
-H "Authorization: Bearer sk-你的KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gemini-2.5-flash-image",
"messages": [
{ "role": "user", "content": "画一只穿着宇航服、以土星为背景的橘猫" }
]
}'
import base64
import re
import requests
resp = requests.post(
"https://www.ruapi.ai/v1/chat/completions",
headers={"Authorization": "Bearer sk-你的KEY"},
json={
"model": "gemini-2.5-flash-image",
"messages": [
{"role": "user", "content": "画一只穿着宇航服、以土星为背景的橘猫"}
],
},
)
content = resp.json()["choices"][0]["message"]["content"]
# 把所有 Markdown data URI 里的图片抠出来
images = re.findall(r"!\[image\]\(data:(image/[^;]+);base64,([^)]+)\)", content)
for i, (mime, b64) in enumerate(images):
ext = mime.split("/")[-1]
with open(f"image_{i}.{ext}", "wb") as f:
f.write(base64.b64decode(b64))
# 模型在图片旁边写的那句话
caption = re.sub(r"!\[image\]\([^)]*\)", "", content).strip()
print(caption, f"—— 共保存 {len(images)} 张图")
一次响应里可能有多张图,所以例子里用的是 findall 而不是 search。模型几乎总会在图片旁边附一句简短的文字说明。
图生图(编辑)
要改一张已有的图,按 vision 模型的格式传进去即可:content 用数组,里面放 text 和 image_url 两部分。url 既可以是公网链接,也可以是 data URI。
curl https://www.ruapi.ai/v1/chat/completions \
-H "Authorization: Bearer sk-你的KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gemini-2.5-flash-image",
"messages": [
{
"role": "user",
"content": [
{ "type": "text", "text": "把这张图改成黑白的,其他什么都别动。" },
{ "type": "image_url", "image_url": { "url": "https://example.com/photo.jpg" } }
]
}
]
}'
import base64
import re
from pathlib import Path
import requests
# 方案 A —— 公网图片链接
source = {"url": "https://example.com/photo.jpg"}
# 方案 B —— 本地文件走 data URI
# raw = Path("photo.jpg").read_bytes()
# source = {"url": "data:image/jpeg;base64," + base64.b64encode(raw).decode()}
resp = requests.post(
"https://www.ruapi.ai/v1/chat/completions",
headers={"Authorization": "Bearer sk-你的KEY"},
json={
"model": "gemini-2.5-flash-image",
"messages": [
{
"role": "user",
"content": [
{"type": "text", "text": "把这张图改成黑白的,其他什么都别动。"},
{"type": "image_url", "image_url": source},
],
}
],
},
)
content = resp.json()["choices"][0]["message"]["content"]
mime, b64 = re.findall(r"!\[image\]\(data:(image/[^;]+);base64,([^)]+)\)", content)[0]
Path("edited.png").write_bytes(base64.b64decode(b64))
多轮连续修图
模型的回复可以原样塞回 messages 里当作 assistant 消息 —— 其中的 Markdown data URI 会被识别,图片将作为下一轮的输入。这样就能做「改成黑白」→「再加个白边」这种连续编辑。
messages = [{"role": "user", "content": "画一只橘猫"}]
for instruction in ["把图片改成黑白的", "加一圈白色边框"]:
resp = requests.post(URL, headers=HEADERS, json={"model": MODEL, "messages": messages}).json()
reply = resp["choices"][0]["message"]["content"]
messages.append({"role": "assistant", "content": reply}) # 图片留在上下文里
messages.append({"role": "user", "content": instruction})
每一轮都是一次独立的付费调用。另外,带 base64 图片的历史会让请求体迅速膨胀,别把超过两三张的历史图都塞进上下文。
支持的输入图片格式
image/png、image/jpeg、image/webp、image/heic、image/heif。其他格式会被拒绝,报 mime type is not supported by Gemini。
原生 Gemini 端点
如果你本来就在用 Google GenAI SDK,同一个密钥也能走原生格式:
curl "https://www.ruapi.ai/v1beta/models/gemini-2.5-flash-image:generateContent" \
-H "Authorization: Bearer sk-你的KEY" \
-H "Content-Type: application/json" \
-d '{ "contents": [{ "parts": [{ "text": "画一只穿着宇航服的橘猫" }] }] }'
这条路径下图片是结构化返回的 —— 在 candidates[0].content.parts[].inlineData.data(base64),不用解析 Markdown。如果你不需要兼容 OpenAI SDK,这个方式更省事。
方式二:GPT Image —— 走 /v1/images/generations
gpt-image-2 就是 OpenAI 那套经典的图像生成端点。没有 messages,只有 prompt。
curl https://www.ruapi.ai/v1/images/generations \
-H "Authorization: Bearer sk-你的KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-image-2",
"prompt": "一只穿着宇航服、以土星为背景的橘猫",
"size": "1024x1024",
"quality": "low",
"n": 1
}'
import base64
from openai import OpenAI
client = OpenAI(api_key="sk-你的KEY", base_url="https://www.ruapi.ai/v1")
result = client.images.generate(
model="gpt-image-2",
prompt="一只穿着宇航服、以土星为背景的橘猫",
size="1024x1024",
quality="low",
n=1,
)
with open("image.png", "wb") as f:
f.write(base64.b64decode(result.data[0].b64_json))
| 参数 | 取值 | 说明 |
|---|
size | 1024x1024、1536x1024、1024x1536… | 两边长度都必须是 16 的倍数 |
quality | low、medium、high | 决定输出 token 数,也就是直接决定价格 |
n | 1 或更多 | 每张图单独计费 |
{
"data": [
{
"b64_json": "iVBORw0KGgoAAAANSUhEUg...",
"url": "https://.../image.png",
"revised_prompt": "一只穿着宇航服、以土星为背景的橘猫"
}
],
"usage": { "input_tokens": 17, "output_tokens": 425, "total_tokens": 442 }
}
请用 b64_json,不要用 url。 url 指向的是外部存储,链接有效期没有保证,随时可能打不开。b64_json 就是图片本身,拿到手就永久属于你。
usage.output_tokens 是图片 token,价格就按它算。把 quality 降到 low 能让它成倍减少,适合出草稿和做测试。
常见问题
为什么 gemini-2.5-flash-image 走 /v1/images/generations 不通?
因为按 OpenAI 的口径它不是「图像生成模型」,而是一个能吐图片的多模态聊天模型。请用 /v1/chat/completions 调用,见「方式一」。
content 里那一大坨 base64 是什么?
那就是图片。通过 OpenAI 兼容的聊天端点返回时,图片被拼成  塞进正文。用上面的正则抠出来即可;或者改走原生 Gemini 端点,那里图片是独立字段。
gemini-2.5-flash-image 性价比最高。要极致细节就用 gemini-3-pro-image-preview。gpt-image-2 也能改图,但走的是另一个端点 /v1/images/edits。
Gemini 系列什么都不存,base64 直接在响应里。gpt-image-2 的响应带一个 url 字段,但不要依赖它 —— 把 b64_json 存下来。
Gemini 的响应里有 usage 和 token 数,会按这个扣费吗?
不会。Gemini 图像模型按次计费,一张图一口价。usage 只是参考信息,不参与扣费。只有 gpt-image-2 是按 token 计费的。