Appearance
图片生成 POST /v1/images/generations
异步图片生成端点。兼容 OpenAI Images API 规范,支持文生图(txt2img)与图生图(img2img / image edit)统一入口。
兼容入口:
POST /v1/images/edits是图生图编辑的传统 OpenAI 入口(2026-09-07 合并改造保留),JSON 模式跟本接口完全等价,multipart 模式只支持image/mask文件上传。所有图片生成的 Base64 自动落库能力(下文)在两个入口同样生效。
端点
POST https://api.imodel.space/v1/images/generations
Authorization: Bearer YOUR_API_KEY
Content-Type: application/json请求参数
| 字段 | 位置 | 类型 | 必传 | 默认 | 说明 |
|---|---|---|---|---|---|
model | body | string | ✅ | — | 模型代号(如 gpt-image-2 / dall-e-3 / dall-e-2),决定调用的上游实现与计费档位 |
prompt | body | string | ✅ | — | 文本提示词。无 image / image_urls 时为文生图;有参考图时为图生图编辑 |
n | body | integer | ❌ | 1 | 生成数量,部分模型(如 dall-e-3)仅支持 n=1 |
quality | body | string | ❌ | — | standard / hd (dall-e-3);low / medium / high (gpt-image-2)。具体取值范围以模型 cost_config 为准 |
size | body | string | ❌ | — | 比例或像素字符串。优先使用 resolution + aspect(见下方「size 与 resolution/aspect」章节),此字段保留 OpenAI 协议兼容 |
style | body | string | ❌ | — | vivid / natural,仅 dall-e-3 支持 |
response_format | body | string | ❌ | url | url / b64_json,异步模式下忽略(始终走 outputs[] 轮询) |
user | body | string | ❌ | — | 透传用户标识,用于风控审计 |
background | body | string | ❌ | — | transparent / opaque / auto,仅 gpt-image-2 |
output_format | body | string | ❌ | — | png / jpeg / webp,仅 gpt-image-2 |
output_compression | body | integer | ❌ | — | 0-100,仅 jpeg / webp 模式生效 |
moderation | body | string | ❌ | auto | auto / low,仅 gpt-image-2 |
image | body | string | ❌ | — | 单张参考图 URL。传值即视为图生图编辑,与 image_urls 二选一 |
image_urls | body | string[] | ❌ | — | 多张参考图 URL 数组,上限 10 张(超过返回 too_many_images) |
mask | body | string | ❌ | — | 蒙版 URL,JSON 模式局部编辑场景 |
resolution | body | string | ❌ | — | 网关扩展字段。清晰度档位(1K / 2K / 4K),按档位查 cost_config.rates 计费。详见下方「size 与 resolution/aspect」章节 |
aspect | body | string | ❌ | — | 网关扩展字段。画面比例(1:1 / 16:9 / 9:16 / 4:3 / 3:4),与 resolution 共同决定实际像素 |
请求示例
文生图(无参考图)
json
{
"model": "gpt-image-2",
"prompt": "一只猫在花园里晒太阳",
"resolution": "1K",
"aspect": "16:9",
"n": 1
}图生图编辑(多张参考图融合)
json
{
"model": "gpt-image-2",
"prompt": "将参考图 1 的主体与参考图 2 的背景融合,生成黄昏氛围的合成图",
"image_urls": [
"https://cdn.example.com/ref_subject.jpg",
"https://cdn.example.com/ref_background.jpg"
],
"resolution": "2K",
"aspect": "16:9"
}局部编辑(蒙版)
json
{
"model": "gpt-image-2",
"prompt": "把蒙版区域内的椅子替换为盆栽",
"image": "https://cdn.example.com/room.jpg",
"mask": "https://cdn.example.com/room_mask.png",
"resolution": "1K",
"aspect": "16:9"
}图生图编辑(base64 内嵌图 + URL 混传)
json
{
"model": "gpt-image-2",
"prompt": "将参考图 1 的人物换到参考图 2 的场景里",
"image_urls": [
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUg...用户拍照的 base64",
"https://cdn.example.com/ref_background.jpg"
],
"resolution": "2K",
"aspect": "16:9"
}服务端会把 base64 自动上传到 COS + 落素材表,image_urls[0] 在落库前替换为 CDN 公开直链;image_urls[1] 是公网 URL 原样保留,worker 直接 GET 拉取。
参考图来源
image / image_urls 字段不强制使用本平台素材上传。任何公网可访问的 URL 都行(不限域名)。四种典型来源:
- 本平台素材库:API Key 上传 后用返回的
cdn_url—— 自动入库、可在素材管理页查/改/删、跨任务复用 - 自有图床:阿里云 OSS / 腾讯云 COS / 七牛 / 又拍云 / 自建 nginx 等任何公网可访问的存储
- 公共 CDN:Unsplash / 公司 CDN / 图床服务等
- Base64 内嵌图(
data:image/png;base64,...,2026-09-11 新增支持):见下方「Base64 内嵌图自动落库」章节
只要 URL 返回 200 且能识别扩展名(Content-Type 或 URL 后缀),后端 worker 直接 GET 拉取。
Base64 内嵌图自动落库(2026-09-11 新增)
背景
靓仔要求支持客户端把参考图以 base64 内嵌在请求 body 里(避免前端先上传 COS 再发请求的两步流程,比如移动端拍照后立刻编辑的场景)。
image / image_urls / mask 三个字段都接受 data:image/<sub>;base64,<payload> 形式的字符串,与公网 URL 混传也支持(比如 image_urls 数组里前 3 张是 base64、后 2 张是 https URL)。
后端处理流程
- 解码校验:服务端拿到 base64 后,先
base64.StdEncoding.DecodeString解码字节,再做image.DecodeConfig校验是否是合法图片(png/jpeg/gif)。任一步失败 → 返回 400image_materialize_failed - 大小限制:单张 base64 解码后 ≤ 16 MB(防止恶意大文件撑爆 COS / DB)
- 上传 COS:用现有
pkg/cos走 server 端永久密钥,文件 key 遵循users/{group}/{userId}/images/{timestamp}_{hex8}.{ext}命名规范(跟POST /api/asset/upload_cos一致) - 入素材表:
assets表新增一条source_type=local/file_type=image记录,用户在素材管理页可见这张图(后续跨任务复用、重新生成都可) - 替换 URL:原始
image_urls[i]字符串替换为 CDN 公开直链(https://<CDN_BASE_URL>/<file_key>或 COS 默认域名)。/v1/images/edits同步路径直接把替换后的 URL 调上游;异步路径落库tasks.request_params.image_urls也是替换后的 URL,绝不会让 base64 进 DB
失败语义
任一环节失败(解码失败 / 非合法图 / COS 没配置 / 上传失败 / 素材落库失败),任务整体不入库,直接返回 400:
json
{
"error": {
"code": "image_materialize_failed",
"message": "decoded image too large: 18874368 bytes (max 16777216)"
}
}这样设计的理由:不让脏数据进 DB 是关键。2026-09-11 admin_task_search 列表接口超时的根因就是 base64 进 tasks.request_params 撑到 7MB+,列表一次拉 20 条响应体 14MB+。自动 materialize 后这个隐患被堵在 controller 入口。
配置要求
服务端必须配置 configs/tencent.yaml 的 cos 段(SecretID / SecretKey / BucketName / Region)。未配置时 base64 入参会返回 400 cos not configured。
历史兼容
存量 tasks 表里如果有 base64 残留在 request_params(2026-09-11 之前的脏数据),/api/server/schedule/admin_task_search 列表接口做了字段白名单剥离,默认不返回 request_params 列,详情接口(/api/server/schedule/admin_task_search?task_no=xxx,后续补)按需返回。已对云端 2 条 7MB 记录做了一次清理(UPDATE id IN (930, 931) → {"_cleaned":{"reason":"2026-09-11 admin_task_search 性能清理"}})。
size 与 resolution / aspect
三类写法
靓仔要求图片生成支持以下三种参数写法,优先级依次为:
| 优先级 | 写法 | 示例 | 说明 |
|---|---|---|---|
| 1 | 比例 + 档位 | { "size": "16:9", "resolution": "2K" } | 推荐。size 传比例,resolution 传档位,后端按模型映射表查实际像素 |
| 2 | 显式像素 | { "size": "1376x768" } | 仅 size,按 W×H 直查模型 cost_config.rates;miss 时按 height 反推 P 数 |
| 3 | 预设名 + 档位 | { "size": "landscape_16_9", "resolution": "2K" } | 预设名走模型侧映射(各模型不同),resolution 用于计费档位 |
resolution 档位(2026-09-07 按档位计价)
resolution 是网关扩展字段,OpenAI Images API 标准未定义。本系统对齐模型 cost_config.rates 的键:
- 档位典型取值:
1K/2K/4K(具体由模型管理员在 管理后台计费配置 配置) - 计费逻辑:优先按
rates[resolution]查单价;miss 时回退fixed_price兜底 - 单位:每次请求(
unit=request,按次计费),与duration/size无关 - 前端
useGenerationPricecomposable 会按当前模型meta.rates自动计算价格
aspect 比例
仅支持白名单内的取值,具体由各模型的 meta.aspect_whitelist 配置决定。常见白名单:1:1 / 16:9 / 9:16 / 4:3 / 3:4。
响应
异步端点,不会同步返回图片。响应 202 Accepted,客户端用返回的 task_id 调 任务查询 GET /v1/tasks/{task_no} 拿产物。
http
HTTP/1.1 202 Accepted
Content-Type: application/json
{
"id": "TASK-7f9c1d3a-1b2c-4d5e-8a9f-0c1d2e3f4a5b",
"status": "running",
"created_at": 1763692800,
"poll_url": "/v1/tasks/TASK-7f9c1d3a-1b2c-4d5e-8a9f-0c1d2e3f4a5b"
}| 字段 | 类型 | 说明 |
|---|---|---|
id | string | 任务编号(task_no),后续轮询用 |
status | string | 任务状态。提交成功即返回 running(2026-09-08 靓仔要求:三方平台已提交即视为生成中,不再走 queued);终态为 succeeded / failed / cancelled / timeout(完整枚举见 任务查询) |
created_at | integer | 任务创建时间(Unix 秒) |
poll_url | string | 轮询路径,模板为 /v1/tasks/{id} |
任务列表
按模型分页拉取当前用户的图片任务历史,用于前端 omni-generate 工作台历史展示。
GET https://api.imodel.space/v1/images/generations/list?model=gpt-image-2&page=1&page_size=6&status=active
Authorization: Bearer YOUR_API_KEY| 参数 | 位置 | 类型 | 必传 | 默认 | 说明 |
|---|---|---|---|---|---|
model | query | string | ✅ | — | 模型代号(过滤该模型下的任务) |
page | query | integer | ❌ | 1 | 页码,从 1 开始 |
page_size | query | integer | ❌ | 6 | 单页条数,最大 100 |
status | query | string | ❌ | — | 状态过滤:active(进行中,含 queued/scaling/running)/ done(已成功)/ failed(已失败/取消/超时)。省略时返回全部 |
响应
json
{
"data": [
{
"id": "TASK-7f9c1d3a-1b2c-4d5e-8a9f-0c1d2e3f4a5b",
"task_id": 644,
"status": "succeeded",
"progress": 100,
"created_at": 1763692800,
"started_at": 1763692800,
"finished_at": 1763692850,
"outputs": [
"/api/asset/image/TASK-7f9c1d3a-1b2c-4d5e-8a9f-0c1d2e3f4a5b?index=0"
],
"params": {
"prompt": "一只猫在花园里晒太阳",
"size": "16:9",
"resolution": "1K",
"n": 1,
"task_kind": "txt2img"
},
"cost_lingshi": 8,
"billing_state": "consumed"
}
],
"page": 1,
"page_size": 6,
"total": 1
}| 字段 | 类型 | 说明 |
|---|---|---|
data[].id | string | 任务编号(task_no) |
data[].task_id | integer | 数据库数字主键,任务详情弹窗展示用 |
data[].status | string | OpenAI 风格状态字符串:queued / scaling / running / succeeded / failed / cancelled / timeout |
data[].progress | integer | 进度百分比(0-100),仅 running 时实时更新 |
data[].created_at / started_at / finished_at | integer | 各阶段 Unix 时间戳,前端用于计算排队/生成耗时 |
data[].outputs[] | string[] | 产物 URL 数组(每张图一项),路径走 gapi 代理(不会暴露上游 ComfyUI 地址) |
data[].params | object | 任务参数快照(提交时的 prompt / size / resolution / n / task_kind) |
data[].cost_lingshi | integer | 实际消费灵石数 |
data[].billing_state | string | 账单状态:frozen(冻结中)/ consumed(已扣除)/ refunded(已退还) |
total | integer | 满足过滤条件的总条数,前端 el-pagination 总页数计算用 |
文档更新记录
| 日期 | 更新内容 |
|---|---|
| 2026-09-11 | 新增「Base64 内嵌图自动落库」章节(image / image_urls / mask 支持 data:image/...;base64,... 自动落 COS + 素材表 + 替换为 CDN URL,2026-09-11 修复 admin_task_search 列表超时的根因);错误码表加 image_materialize_failed |
| 2026-09-08 | 新增图片生成接口文档。补充 resolution / aspect 网关扩展字段、三类写法、按档位计费说明、status 直接返回 running 而非 queued 的改造说明 |
错误码表
4xx — 客户端请求问题
| HTTP | code | 说明 | 解决建议 |
|---|---|---|---|
| 400 | invalid_request_error | 参数错误:检查 prompt(必填)/ model(必填)/ image_urls(≤10)等 | 对照「请求参数表」逐字段核验必传项与上限 |
| 400 | too_many_images | image_urls 数量超 10 张上限 | 减少参考图数量至 ≤10 张 |
| 400 | image_materialize_failed | image / image_urls / mask 含 base64 内嵌图,但解码失败 / 非合法图 / COS 没配 / 上传失败 | 见「Base64 内嵌图自动落库」章节的「失败语义」段落;服务端需要配 cos,客户端需要保证 base64 是合法 png/jpeg/gif |
| 400 | estimate_failed | 计费配置校验失败(如 unit=request 但 rates 与 fixed_price 都为 0) | 管理员在 管理后台计费配置 配置 rates 或 fixed_price |
| 400 | model_not_allowed | API Key 无权访问该模型(权限管控) | 在 API Key 管理页添加该模型权限 |
| 402 | insufficient_quota | 账户灵石不足,无法生成 | 在控制台「灵石充值」购买后重试 |
| 402 | daily_cost_limit_exceeded | API Key 单日消费上限 | 调高 Key 日限额,或等待次日重置 |
| 500 | freeze_failed | 余额冻结失败 | 重试;持续失败请检查账户状态 |
| 502 | upstream_error | 三方上游服务异常(网络/超时/上游 5xx) | 稍后重试 |
| 502 | submit_failed | 上游任务提交失败(签名/鉴权/上游拒收) | 检查 API Key 权限与上游账号状态 |
5xx — 服务端问题
| HTTP | code | 说明 | 解决建议 |
|---|---|---|---|
| 500 | internal_error | 网关内部异常(落库失败等) | 重试;持续失败请附 task_no 联系客服 |
通用 4xx/5xx 见 错误码总表。