Qwen Image 2.0 Pro
qwen-image-2.0-pro 文生图接口、参数、响应、下载与计费说明
qwen-image-2.0-pro 是同步文生图模型,擅长中英文文字渲染、海报、图表、PPT 视觉稿、写实材质和复杂图文布局。
能力矩阵
| 能力 | 支持情况 | 说明 |
|---|---|---|
| 文本生成图片 | 支持 | 中英文提示词,单次输出 1-6 张 PNG |
| 中英文文字渲染 | 支持 | 适合海报、信息图和演示文稿视觉稿 |
| 自定义尺寸 | 支持 | 使用 parameters.size |
| 反向提示词、提示词改写、水印、种子 | 支持 | 均为可选参数 |
| 参考图片、图片编辑、multipart 上传 | 不在稳定范围 | 此页面的请求只接受一个文本内容项 |
顶层 prompt | 不支持 | 文本必须位于 input.messages |
| 流式响应 | 不在稳定范围 | 使用同步 HTTP 请求并等待完整 JSON 响应 |
接口
- Endpoint:
POST /v1/images/generations - Base URL:
https://api.vibelab.me Authorization: Bearer <your-api-key>Content-Type: application/json
请求采用多模态消息 JSON:input.messages 保存提示词,parameters 保存生成选项。不要发送 multipart 表单。
参数
| 参数 | 类型 | 必填 | 默认值 | 范围或格式 | 适用性与依赖 |
|---|---|---|---|---|---|
model | string | 是 | - | 固定为 qwen-image-2.0-pro | 所有请求 |
input | object | 是 | - | 包含 messages | 所有请求 |
input.messages | array | 是 | - | 数组内恰好 1 个元素 | 仅支持单轮 |
input.messages[0].role | string | 是 | - | 固定为 user | 所有请求 |
input.messages[0].content | array | 是 | - | 数组内恰好 1 个元素 | 只允许文本内容 |
input.messages[0].content[0].text | string | 是 | - | 中英文,最多 1300 Token;超出部分可能被截断 | 正向提示词 |
parameters | object | 否 | {} | 见下列字段 | 省略时使用模型默认值 |
parameters.negative_prompt | string | 否 | 空 | 最多 500 个字符;超出部分可能被截断 | 描述不希望出现的内容 |
parameters.size | string | 否 | 2048*2048 | 宽*高;总像素在 512*512 至 2048*2048 之间 | 宽高可自由组合,需满足总像素范围 |
parameters.n | integer | 否 | 1 | 1-6 | 期望输出图片数 |
parameters.prompt_extend | boolean | 否 | true | true 或 false | 开启时会改写正向提示词,可能增加耗时 |
parameters.watermark | boolean | 否 | false | true 或 false | 开启后在右下角添加模型水印 |
parameters.seed | integer | 否 | 随机 | 0-2147483647 | 相同值仅提高相对稳定性,不保证结果完全一致 |
尺寸限制按总像素计算,不表示宽和高必须分别落在 512-2048。以下是官方推荐的常用比例:
| 比例 | 推荐尺寸 |
|---|---|
| 1:1 | 2048*2048 |
| 16:9 | 2688*1536 |
| 9:16 | 1536*2688 |
| 4:3 | 2368*1728 |
| 3:4 | 1728*2368 |
请求结构
最小请求:
{
"model": "qwen-image-2.0-pro",
"input": {
"messages": [
{
"role": "user",
"content": [{"text": "白底上的蓝色圆形图标"}]
}
]
}
}完整参数:
{
"model": "qwen-image-2.0-pro",
"input": {
"messages": [
{
"role": "user",
"content": [{"text": "雨夜城市街角的咖啡店,写实摄影,玻璃窗上有清晰中文招牌"}]
}
]
},
"parameters": {
"negative_prompt": "模糊,低画质,文字扭曲",
"size": "2048*2048",
"n": 1,
"prompt_extend": false,
"watermark": false,
"seed": 20260712
}
}显式尺寸:
{
"model": "qwen-image-2.0-pro",
"input": {"messages": [{"role": "user", "content": [{"text": "海边日落,全景摄影"}]}]},
"parameters": {"size": "2688*1536"}
}显式张数:
{
"model": "qwen-image-2.0-pro",
"input": {"messages": [{"role": "user", "content": [{"text": "极简风格的应用图标"}]}]},
"parameters": {"n": 3}
}中文海报:
{
"model": "qwen-image-2.0-pro",
"input": {
"messages": [
{
"role": "user",
"content": [{"text": "竖版夏日音乐节海报,主标题写‘向海而歌’,副标题写‘7月20日 18:00’,蓝白配色,现代排版"}]
}
]
},
"parameters": {"size": "1536*2688", "prompt_extend": false}
}固定种子:
{
"model": "qwen-image-2.0-pro",
"input": {"messages": [{"role": "user", "content": [{"text": "红色陶瓷杯,产品摄影,白色背景"}]}]},
"parameters": {"seed": 42, "prompt_extend": false}
}cURL
curl --fail-with-body https://api.vibelab.me/v1/images/generations \
-H "Authorization: Bearer $LOOPTOKEN_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "qwen-image-2.0-pro",
"input": {
"messages": [
{"role": "user", "content": [{"text": "白底上的蓝色圆形图标"}]}
]
},
"parameters": {"n": 1}
}'Python
需要 Python 3.9+ 与 requests。脚本会检查状态码、解析结构化错误、遍历并下载所有图片,并从响应头或 URL 推断扩展名。
import mimetypes
import os
from pathlib import Path
from urllib.parse import urlparse
import requests
API_URL = "https://api.vibelab.me/v1/images/generations"
api_key = os.environ["LOOPTOKEN_API_KEY"]
payload = {
"model": "qwen-image-2.0-pro",
"input": {
"messages": [{"role": "user", "content": [{"text": "白底上的蓝色圆形图标"}]}]
},
"parameters": {"n": 2},
}
response = requests.post(
API_URL,
headers={"Authorization": f"Bearer {api_key}"},
json=payload,
timeout=300,
)
try:
body = response.json()
except ValueError:
body = {"error": {"type": "invalid_response", "message": response.text}}
if not response.ok:
error = body.get("error", body)
raise RuntimeError(f"HTTP {response.status_code}: {error}")
items = [
item
for choice in body.get("output", {}).get("choices", [])
for item in choice.get("message", {}).get("content", [])
if item.get("image")
]
if not items:
raise RuntimeError("response contained no output image URL")
for index, item in enumerate(items, start=1):
image_response = requests.get(item["image"], timeout=120)
image_response.raise_for_status()
content_type = image_response.headers.get("content-type", "").split(";", 1)[0]
extension = mimetypes.guess_extension(content_type) or Path(urlparse(item["image"]).path).suffix or ".png"
path = Path(f"qwen-image-{index}{extension}")
path.write_bytes(image_response.content)
print(path)Node.js
需要 Node.js 18+。脚本使用内置 fetch,无需额外依赖。
import { writeFile } from 'node:fs/promises';
import path from 'node:path';
const apiKey = process.env.LOOPTOKEN_API_KEY;
if (!apiKey) throw new Error('LOOPTOKEN_API_KEY is required');
const response = await fetch('https://api.vibelab.me/v1/images/generations', {
method: 'POST',
headers: {
Authorization: `Bearer ${apiKey}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
model: 'qwen-image-2.0-pro',
input: {
messages: [{ role: 'user', content: [{ text: '白底上的蓝色圆形图标' }] }],
},
parameters: { n: 2 },
}),
});
const text = await response.text();
let body;
try {
body = JSON.parse(text);
} catch {
body = { error: { type: 'invalid_response', message: text } };
}
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${JSON.stringify(body.error ?? body)}`);
}
const items = (body.output?.choices ?? []).flatMap((choice) =>
(choice.message?.content ?? []).filter((item) => item.image),
);
if (items.length === 0) throw new Error('response contained no output image URL');
const extensionFor = (contentType, url) => {
const known = { 'image/png': '.png', 'image/jpeg': '.jpg', 'image/webp': '.webp', 'image/gif': '.gif' };
return known[contentType.split(';', 1)[0]] ?? (path.extname(new URL(url).pathname) || '.png');
};
for (const [index, item] of items.entries()) {
const imageResponse = await fetch(item.image);
if (!imageResponse.ok) throw new Error(`download failed: HTTP ${imageResponse.status}`);
const extension = extensionFor(imageResponse.headers.get('content-type') ?? '', item.image);
const filename = `qwen-image-${index + 1}${extension}`;
await writeFile(filename, Buffer.from(await imageResponse.arrayBuffer()));
console.log(filename);
}响应
成功响应示例:
{
"output": {
"choices": [
{
"finish_reason": "stop",
"message": {
"role": "assistant",
"content": [
{"image": "https://example.invalid/generated/image.png?Expires=0"}
]
}
}
]
},
"usage": {
"image_count": 1,
"width": 2048,
"height": 2048
}
}| 字段 | 类型 | 说明 |
|---|---|---|
output | object | 模型输出容器 |
output.choices | array | 同步调用通常只有一个 choice |
output.choices[].finish_reason | string | 正常完成时通常为 stop |
output.choices[].message.role | string | 模型消息角色,通常为 assistant |
output.choices[].message.content | array | 生成内容数组;n 张图片可位于同一数组中 |
output.choices[].message.content[].image | string | PNG 图片的临时 HTTPS URL |
usage.image_count | integer | 成功生成的图片数 |
usage.width | integer | 输出宽度,像素 |
usage.height | integer | 输出高度,像素 |
图片 URL 是临时资源。收到响应后应立即下载并转存;下载域名和具体有效期都不属于稳定合同,不应依赖固定域名白名单或长期可恢复性。
LoopToken 请求 ID 位于 HTTP 响应头 X-Request-Id,不会由 LoopToken 注入成功响应体。排查时应同时保存该响应头。
错误处理
LoopToken 本地错误采用统一结构:
{
"error": {
"message": "invalid image generation request",
"type": "invalid_request",
"code": "invalid_request",
"request_id": "req_example"
}
}| HTTP 状态 | error.type | 常见原因 |
|---|---|---|
| 400 | invalid_request | LoopToken 本地无法读取或解析请求,例如 JSON 无效或缺少 model |
| 401 | 鉴权错误 | API Key 缺失或无效 |
| 402 | insufficient_credits | 余额不足以预扣本次请求 |
| 403 | model_not_allowed | 当前 Key 无权使用该模型 |
| 404 | model_not_found | 模型名不存在 |
| 502 | upstream_error | 模型服务拒绝提示词、尺寸、其他参数或内容安全校验,或生成失败 |
| 503 | no_available_channel | 当前没有可处理该模型的服务资源;也可能在可重试失败后返回 |
error.code 当前与 error.type 相同。模型服务的非 2xx 响应会由 LoopToken 统一转换为 HTTP 502 和 upstream_error,不透出上游错误类型或文案。错误响应应同时记录 HTTP 状态、error.code、error.message 和 error.request_id。当前环境未提供可安全使用的 API 凭据,因此这些错误场景的实际响应尚未进行在线验证。
计费
按最终识别到的输出图片张数计费。请求开始时按正整数 parameters.n 预扣;省略、零或负数时按 1 张。成功响应能识别图片时按实际图片数结算;若模型服务返回 2xx,但无法识别 output.choices[].message.content[].image 而得到 Count=0,则按上述本地提交数量结算。非 2xx、没有可用服务资源或重试全部失败会全额退款。usage 仅是模型服务返回的用量信息,不是 LoopToken 的计费金额。尺寸价格键未命中时使用 default 单价。最终价格以模型列表为准。
边界
- 只发送 JSON 文生图请求;参考图片、图片修改和 multipart 文件上传不属于此接口的稳定能力。
- 不要使用顶层
prompt;必须使用input.messages[0].content[0].text。 - 不要假设流式返回、异步任务 ID、Base64 图片或 OpenAI
data[]响应可用。 - LoopToken 当前只读取
model、parameters.n和parameters.size做路由与计费,其余字段会转发给模型服务校验;参数越界可能表现为502 upstream_error。