主题
NovelAI OpenAI 兼容 API
本文档说明本站 NovelAI 绘图模型的 OpenAI 兼容接口,以及基于 Chat Completions 定义的自定义绘图请求规范。
协议边界
本文档中的 characters、i2i、inpaint 等字段是本站 OpenAI Chat 自定义绘图参数,不是 NovelAI 官方原生请求体(payload)。调用 NovelAI 原生格式接口时,请使用原生 API 文档。
如需在普通 OpenAI 兼容客户端中使用,请阅读 客户端使用说明。
调用前需要准备好你在本站生成的 sk-... API Key。本文以站点直连地址 https://api.taleapi.asia/v1 为例,也可以根据网络环境从线路与接口中选择其他线路,并在地址末尾加上 /v1。
1. 请求头
所有接口都使用 Bearer 鉴权,即在 Authorization 请求头中提交 API Key。JSON 请求示例:
http
Authorization: Bearer 你在本站生成的 API Key
Content-Type: application/jsonChat Completions 和 Images generations 使用 JSON 请求体;Images edits 使用 multipart/form-data,应由上传库生成包含分隔符的请求头,不要套用上面的 JSON 内容类型。GET /v1/models 没有请求体。
对于 OpenAI 兼容端点,缺少 Bearer 密钥或密钥为空会返回 401 AUTH_REQUIRED。非空密钥被拒绝时可能返回 401 AUTH_INVALID 或 424 UPSTREAM_AUTH_FAILED。客户端应同时依据 HTTP 状态码和响应中的 error.code 处理。
Authorization 的 Bearer 前缀区分大小写,必须按上面的格式发送。
2. OpenAI 兼容接口
本站同时提供以下 OpenAI 兼容接口:
http
GET https://api.taleapi.asia/v1/models
POST https://api.taleapi.asia/v1/chat/completions
POST https://api.taleapi.asia/v1/images/generations
POST https://api.taleapi.asia/v1/images/edits- Models:返回 OpenAI Models API 风格的模型列表。
- Chat Completions:在聊天消息中提交本站自定义绘图参数,支持文生图、图生图和局部重绘;回复用 Markdown 图片语法嵌入 Data URI(包含图片内容的文本地址)。
- Images generations:基础文生图接口,返回 Base64(图片字节的文本编码)或 SSE(Server-Sent Events,服务器发送事件)流。
- Images edits:通过 multipart 表单上传单张原图,重绘整张图;返回 Base64 或 SSE 流。
生图费用包含基础费用和 Anlas(NovelAI 点数)费用,0 Anlas 仍收基础费用。Chat 可设置额外点数预算,但 Vibe Transfer(氛围转移参考图)请求不受该预算限制;Images 不提供单次费用上限。具体换算见费用说明。
3. 获取模型列表
请求:
http
GET https://api.taleapi.asia/v1/modelscurl 示例:
bash
curl "https://api.taleapi.asia/v1/models" \
-H "Authorization: Bearer 你在本站生成的 API Key"响应示例:
json
{
"object": "list",
"data": [
{
"id": "nai-diffusion-4-5-full",
"object": "model",
"created": 1700000000,
"owned_by": "novelai"
}
]
}使用 data[].id 作为绘图请求中的 model。
常用模型:
text
nai-diffusion-5-full
nai-diffusion-5-curated
nai-diffusion-4-5-full
nai-diffusion-4-5-curated
nai-diffusion-4-full4. Chat Completions 请求体规则
本节适用于 POST /v1/chat/completions。请求体外层使用 OpenAI Chat Completions 格式,绘图参数则写为 content 中的 JSON 文本,下文称为“内层 JSON”。这两层参数不能混放。
服务端从 messages 尾部向前查找,使用最后一条 role: "user" 消息的 content。后续的 assistant 或 system 消息不影响该选择。
- 外层
model是模型名的唯一来源。 content可以是字符串,或恰好包含一个type: "text"项的 content part 数组。- 数组中出现
image_url、其他 part 类型或多个 text part,均返回 400。 - 没有包含非空文本的 user 消息时返回 400。
4.1 content 解析规则
最后一条 user 消息的文本按以下规则解析:
- 合法 JSON object:作为本站自定义绘图参数对象。
- JSON 语法无效:原始文本作为正向
prompt,响应内容会追加格式警告。 - 合法 JSON 但结果为 string、array、number、boolean 或 null:返回 400,不做纯文本回退。
jsonc
{ "role": "user", "content": "1girl, white dress" } // ✅ 作为 prompt
{ "role": "user", "content": "{\"prompt\":\"1girl\"}" } // ✅
{ "role": "user", "content": "[\"1girl\"]" } // ❌ 合法 JSON arraycontent part 数组示例:
json
{
"role": "user",
"content": [
{ "type": "text", "text": "{\"prompt\":\"1girl\"}" }
]
}4.2 最小请求示例
json
{
"model": "nai-diffusion-4-5-full",
"messages": [
{
"role": "user",
"content": "{\"prompt\":\"1girl, solo, masterpiece, best quality\",\"negative_prompt\":\"lowres, bad anatomy\"}"
}
],
"stream": false
}代码里不要手写转义字符串,应该用语言自带的 JSON 序列化(Python 的 json.dumps):
python
import json
draw_params = {
"prompt": "1girl, solo, masterpiece, best quality",
"negative_prompt": "lowres, bad anatomy",
}
request_body = {
"model": "nai-diffusion-4-5-full",
"messages": [
{"role": "user", "content": json.dumps(draw_params)},
],
"stream": False,
}5. Chat 自定义绘图参数
最后一条 user 消息的内层 JSON 支持以下主要字段(不需要的字段全部省略即可):
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
prompt | string | 是 | 正向提示词;语言要求见提示词限制。 |
negative_prompt | string | 否 | 负向提示词;语言规则同正向提示词。 |
size | [width, height] | 否 | 长度为 2 的数组,缺省或 null 使用 [1216, 832]。两个元素必须是 JSON integer;字符串、浮点数和 boolean 均无效。 |
steps | integer | 否 | 迭代步数,全部模型范围 1~50,缺省 28。 |
scale | number | 否 | 提示词引导强度,输入范围 0.0~20.0,缺省 5.0。大于 10.0 的输入按 10.0 生效。 |
sampler | string | 否 | 采样器,缺省 k_euler_ancestral。 |
seed | integer | 否 | 随机种子;省略表示随机,显式 null 返回 400。 |
n_samples | integer | 否 | 缺省使用 1。只允许整数 1;null、浮点数、boolean、字符串和其他整数均返回 400。建议直接省略。 |
quality | boolean | 否 | 缺省使用 true;启用时自动追加质量标签。显式 null 返回 400。 |
uc_preset | string | 否 | Undesired Content(不希望出现的内容)预设,缺省 light;可选 strong、light、furry_focus、human_focus、none。 |
variety_boost | boolean | 否 | Variety+(增加生成多样性)开关,默认 false;V5 不支持开启。 |
cfg_rescale | number | 否 | Prompt Guidance Rescale(提示词引导重缩放),范围 0 ~ 1。 |
noise_schedule | string | 否 | Noise Schedule(采样过程的噪声调度方式),例如 karras。 |
characters | array | 否 | 为角色分别设置提示词,见多角色。 |
use_coords | boolean | 否 | 多角色坐标模式开关,见顶层开关。缺省使用自动布局;显式 null 或非 boolean 值返回 400。 |
controlnet | object | 否 | 氛围转移参考图,V4 / V4.5 最多 4 张,见 Vibe Transfer。 |
character_references | array | 否 | 精准参考图,仅 V4.5 最多 4 张,与氛围转移互斥,见 Precise Reference。 |
输出图片格式
image_format是内层 JSON 字段,与prompt/size平级,详见输出格式字段。
quality、use_coords、n_samples、size 和 image_format 使用严格类型校验。scale 会先校验输入范围,再确定实际生效值;例如传入 15 时实际按 10 处理。
完整绘图参数示例:
json
{
"prompt": "1girl, solo, masterpiece, best quality, detailed eyes",
"negative_prompt": "lowres, bad anatomy, bad hands, text, watermark",
"size": [1216, 832],
"steps": 28,
"scale": 5,
"sampler": "k_euler_ancestral",
"seed": 123456789,
"variety_boost": true,
"cfg_rescale": 0.5,
"noise_schedule": "karras"
}6. Chat 自定义尺寸字段
size 必须传长度为 2 的数组 [width, height]:
json
{ "size": [832, 1216] }字符串写法(包括 "832x1216"、"portrait" 等预设名)一律返回 400,错误信息会提示使用 [832, 1216]。
| 用途 | 数组值 |
|---|---|
| 竖图 | [832, 1216] |
| 横图 | [1216, 832] |
| 方图 | [1024, 1024] |
数组元素必须是 JSON integer,不能使用字符串、浮点数或 boolean。服务端会归一化最终尺寸,规则和示例见通用生成规则。
7. 多角色(characters)
本站五个 NovelAI 模型均支持在同一张图中定义多个角色,每个角色有独立的正向 / 负向提示词和位置。
适用模型:V4 Full、V4.5 Full / Curated、V5 Full / Curated。最多支持 6 个角色。
7.1 顶层开关
| 字段 | 类型 | 含义 |
|---|---|---|
use_coords | boolean | true = 使用 position 手动定位;false(默认)= 由模型自动安排。 |
7.2 characters[i] 字段
| 字段 | 类型 | 默认 | 说明 |
|---|---|---|---|
prompt | string | 必填 | 该角色正向提示词;语言要求见提示词限制。 |
negative_prompt | string | "" | 该角色负向提示词,语言规则同正向提示词。 |
position | string | "C3" | 5×5 网格预设字符串,格式 [A-E][1-5]:字母列 A→E 由左到右,数字行 1→5 由上到下,中心 = "C3"。只接受字符串。 |
position 网格直观对照(横轴 = 字母 A→E 表示左右,纵轴 = 数字 1→5 表示上下):
A B C D E ← 字母列(左 → 右)
┌──────┬──────┬──────┬──────┬──────┐
1 │ A1 │ B1 │ C1 │ D1 │ E1 │ 上
2 │ A2 │ B2 │ C2 │ D2 │ E2 │
3 │ A3 │ B3 │ C3 │ D3 │ E3 │ 中
4 │ A4 │ B4 │ C4 │ D4 │ E4 │
5 │ A5 │ B5 │ C5 │ D5 │ E5 │ 下
└──────┴──────┴──────┴──────┴──────┘
↑
数字行(上 → 下)常用:左 = B3,右 = D3,中 = C3,左上 = B2,右下 = D4。
7.3 示例:左蓝右白双猫娘
下面这个 payload 用对角错位构图把两个角色分别钉在 B2(左上)和 D4(右下),并通过各自的 negative_prompt 互斥发色,方便肉眼判定多角色绑定与坐标定位是否生效。
json
{
"prompt": "2girls, cat girls, standing side by side, looking at viewer, masterpiece, best quality, detailed background, indoor, simple background",
"negative_prompt": "lowres, bad anatomy, bad hands, text, watermark, blurry, extra fingers, deformed, jpeg artifacts, multiple views",
"size": [1216, 832],
"steps": 28,
"scale": 5,
"sampler": "k_euler_ancestral",
"seed": 424242,
"noise_schedule": "karras",
"image_format": "png",
"use_coords": true,
"characters": [
{
"prompt": "1girl, cat girl, blue hair, long blue hair, blue cat ears, blue tail, blue eyes, blue ribbon, blue dress, holding a blue rose, on the left side",
"negative_prompt": "white hair, pink hair, red hair",
"position": "B2"
},
{
"prompt": "1girl, cat girl, white hair, long white hair, white cat ears, white tail, red eyes, white kimono, holding a white fan, on the right side",
"negative_prompt": "blue hair, pink hair, black hair",
"position": "D4"
}
]
}生效路径与判定:
- 顶层
prompt描述全局画面(场景、构图、画质),不写任何角色专属特征。 - 每个
characters[i].prompt单独绑定该角色专属特征(发色、眼色、服装、手持物)。 use_coords: true+ 每个角色的position把"哪个角色的特征落到画面的哪个区域"显式钉死;本例B2落在画面左上、D4落在画面右下,故意拉开纵向距离来检验上下定位。- 各角色
negative_prompt把对方的颜色列为禁止项,避免特征互相污染。
预期构图是左上蓝发角色、右下白发角色。生成结果具有随机性,局部偏差不能单独证明参数未生效。
8. 图生图(Image2Image)
i2i 是内层 payload 字段,与 prompt、size 平级。它基于一张源图重绘整张图,由 strength 控制原图结构的保留程度。
i2i 与 inpaint 互斥,同一请求只能使用其中一个,同时传入会直接返回 400。
| 字段 | 类型 | 范围 / 默认 | 说明 |
|---|---|---|---|
i2i.image | string(base64 / data URI) | 必填 | 源图。 |
i2i.strength | number | 0.01 ~ 0.99,默认 0.7 | 变换强度,越小越像原图。 |
i2i.noise | number | 0.0 ~ 0.99,默认 0.0 | 注入噪声量。 |
i2i.seed | integer | 默认随机 | i2i 噪声种子。 |
图片约束:
- 接受纯 Base64 字符串或
data:image/<subtype>;base64,...形式的 Data URI,实际字节必须能被解码为图片。 - 图片宽高必须符合平台尺寸上限。
- 图片宽高必须与内层 payload 归一化后的
size严格相等,不一致直接返回 400。Chat 内层 i2i 不会自动缩放源图。 - 省略
size时使用默认[1216, 832],因此源图也必须是1216×832;竖图请求应显式传对应尺寸。
示例:
json
{
"prompt": "1girl, white dress",
"size": [832, 1216],
"i2i": {
"image": "data:image/png;base64,iVBORw0KGgo...",
"strength": 0.5,
"noise": 0
}
}9. 局部重绘(Inpaint)
inpaint 是内层 payload 字段,与 prompt、size 平级。它基于遮罩图,只重绘原图中的指定区域。
| 字段 | 类型 | 范围 / 默认 | 说明 |
|---|---|---|---|
inpaint.image | string(base64 / data URI) | 必填 | 原图。 |
inpaint.mask | string(base64 / data URI) | 必填 | 遮罩图:白色 = 需要重绘的区域,黑色 = 保留原图。 |
inpaint.strength | number | 0.01 ~ 1.0,默认 1.0 | 重绘强度。 |
inpaint.seed | integer | 默认随机 | 噪声种子。 |
图片约束:
image与mask均接受纯 Base64 字符串或data:image/<subtype>;base64,...形式的 Data URI,实际字节必须能被解码为图片。image与mask的宽高必须是 64 的倍数,且不超过平台尺寸上限。image、mask、内层 payload 归一化后的size三者宽高必须完全相等,任一不一致都会返回 400。- 省略
size时使用默认[1216, 832],因此原图与遮罩也必须是1216×832。
示例:
json
{
"prompt": "1girl, red dress",
"size": [832, 1216],
"inpaint": {
"image": "data:image/png;base64,iVBORw0KGgo...",
"mask": "data:image/png;base64,iVBORw0KGgo...",
"strength": 1.0
}
}10. 点数费用上限(max_tokens)
本节适用于 POST /v1/chat/completions 的单次点数控制。Anlas 是 NovelAI 的点数单位;预算只限制额外点数,不是回复长度,也不是包含基础费用的总金额上限。
在外层 Chat 请求中,max_completion_tokens 优先于 max_tokens。只接受非负整数;未传或选中的字段为 null 时不设置预算。
预算换算为 floor(tokens / 10000) Anlas。例如 50000 表示最多 5 Anlas,19999 表示最多 1 Anlas,0 或 2 都表示不允许消耗额外 Anlas。预算不足返回 402 MAX_TOKENS_EXCEEDED。如果客户端默认设置 2048,实际上只允许 0 Anlas;需要付费生成时应调整或移除预算。
Chat 氛围转移请求不受此预算约束
内层 controlnet 非空时,服务会忽略外层 max_tokens 和 max_completion_tokens,包括值为 0 的情况。该请求涉及编码和生成两段成本,不能用这两个字段限制总费用。提交前应确认接受相应费用。
费用换算见通用生成规则。Images 端点不提供单次费用上限设置。
10.1 Vibe Transfer(氛围转移)
通过 Chat 参考图片的风格与氛围时,使用内层 controlnet.images,最多 4 项,支持 V4 Full 和 V4.5 Full / Curated;V5 不支持。不能同时使用精准参考字段 character_references。只要 controlnet 非空,外层点数预算就会被忽略,上传原图或复用缓存均如此。
上传原图时,每项包含:
| 字段 | 范围 / 默认 | 说明 |
|---|---|---|
image | 必填 | 图片 Base64 或 Data URI,不是图片 URL。 |
info_extracted | 0.01~1,默认 0.7 | 信息提取程度;与模型、原图共同决定编码缓存。 |
strength | 0.01~1,默认 0.6 | 单张参考强度。 |
controlnet.strength 是整体参考强度,范围 0~1,默认 1。以下是内层 JSON 示例,图片占位符必须替换为真实内容:
json
{
"prompt": "a quiet garden, soft light",
"controlnet": {
"images": [
{ "image": "data:image/png;base64,...", "info_extracted": 0.7, "strength": 0.6 }
]
}
}需要新编码时,每张图编码消耗 2 Anlas,另计实际生图费用。成功响应中可包含以下注释,index 对应提交时的参考图下标:
html
<!-- vibe_cache_ids:[{"index":0,"cache_id":"返回的缓存标识"}] -->复用时,对应项只允许 cache_id 和可选 strength,不能再混入 image、info_extracted 等字段:
json
{
"prompt": "a quiet garden, sunset",
"controlnet": {
"images": [{ "cache_id": "返回的缓存标识", "strength": 0.6 }]
}
}缓存绑定生成模型,不能跨模型复用。cache_id 可分享给其他调用方,持有者可以复用该编码;不要公开不希望他人复用的标识。缓存不是永久存储,失效或缺失时应重新上传原图。缓存命中时不额外收取编码费,生图费用按基础费用和实际点数费用计算;上述预算例外同样适用。这里的 cache_id 必须来自 Chat 响应的 vibe_cache_ids 注释,不能用其他接口返回的二进制编码替代。
10.2 Precise Reference(精准参考)
通过 Chat 用图片参考角色或风格时,使用内层 character_references。仅适用于 V4.5 Full / Curated,最多 4 项,与 Vibe Transfer 互斥。它使用图片,不同于多角色的文字提示词;V4 Full 和 V5 不支持精准参考。
| 字段 | 范围 / 默认 | 说明 |
|---|---|---|
image | 必填 | 图片 Base64 或 Data URI。 |
type | 默认 character&style | character(角色)、style(风格)、character&style(角色与风格)。 |
fidelity | 0~1,默认 1 | 参考保真度。 |
strength | 0~1,默认 1 | 参考强度。 |
json
{
"prompt": "1girl, standing in a garden",
"character_references": [
{ "image": "data:image/png;base64,...", "type": "character", "fidelity": 0.8, "strength": 1 }
]
}精准参考会产生相应点数费用,不使用 Vibe 的 cache_id;不含 controlnet 时,外层 Chat 点数预算仍然生效。
11. 采样器与 Noise Schedule
可选采样器:
text
k_euler
k_euler_ancestral
k_dpm_2
k_dpm_2_ancestral
k_dpmpp_2m
k_dpmpp_2s_ancestral
k_dpmpp_sde
ddim采样器决定生成过程的采样算法。V5 不支持 k_dpm_2_ancestral,传入会返回 400;不确定如何选择时,使用以下适用于五个模型的默认值:
json
{ "sampler": "k_euler_ancestral" }Noise Schedule 可选值:
text
karras
exponential
polyexponential12. Chat 自定义输出格式字段
在内层 payload 里设置 image_format,与 prompt / size / use_coords 平级:
json
{
"prompt": "1girl, white dress",
"size": [832, 1216],
"image_format": "png"
}| 字段 | 类型 | 默认 | 说明 |
|---|---|---|---|
image_format | string | "png" | 缺省或 null 使用 "png";只接受 "png",其他值返回 400。 |
约束:
- 取值不是
"png"直接返回 400,不会静默回退。 - 该字段只在内层 payload 里读取;放在外层 OpenAI body 等其他位置都不会被识别,会按缺省值
"png"处理。
13. Chat Completions 响应格式
非流式响应示例:
json
{
"id": "bestnai-0123456789abcdef0123456789abcdef",
"object": "chat.completion",
"created": 1710000000,
"model": "nai-diffusion-4-5-full",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": "\n<!-- seeds:[123456789] -->"
},
"finish_reason": "stop"
}
],
"usage": {
"prompt_tokens": 100000,
"completion_tokens": 2,
"total_tokens": 100002
}
}图片在:
text
response["choices"][0]["message"]["content"]内容格式是 Markdown 图片,URL 是 data:image/png;base64,<...>。每次请求只返回 1 张图。
usage 是本次请求的最终计费信息。生图固定 prompt_tokens=100000,completion_tokens=max(2, billed_anlas × 10000),其中 billed_anlas 表示实际结算的 Anlas。0 Anlas 对应输入、输出、总 Token 数 100000/2/100002,仍有基础费用。费用说明见通用生成规则。
至少成功解析到一个图片 seed 时,末尾会包含 seed 信息。若所有图片的元数据解析均失败,则不输出该注释:
html
<!-- seeds:[123456789] -->如果最后一条 user 消息不是合法 JSON,并按 content 解析规则作为正向提示词处理,响应内容会额外追加格式警告。该警告在非流式响应和 Chat 流式响应中都会出现;合法 JSON object 不会附加警告。如果同一次请求还有其他运行警告,该警告不保证是最后一行。
14. 解析 Chat 图片
python
import re
import json
_IMG_RE = re.compile(r"!\[[^\]]*\]\((data:image/[^;)]+;base64,[^)]+)\)")
_SEED_RE = re.compile(r"<!--\s*seeds:(\[.*?\])\s*-->")
def extract_image_data_uris(content: str) -> list[str]:
"""从响应消息中提取图片 Data URI 列表。"""
return _IMG_RE.findall(content)
def extract_seeds(content: str) -> list[int | None]:
"""从响应消息的 HTML 注释中提取随机种子列表。"""
m = _SEED_RE.search(content)
if not m:
return []
return json.loads(m.group(1))把 data URI 落盘成 PNG:
python
import base64
from pathlib import Path
def save_data_uri(data_uri: str, out_path: Path) -> None:
"""解码 PNG Data URI,并写入指定路径。"""
# data:image/png;base64,xxxx... → 拆 header / payload
header, _, payload = data_uri.partition(",")
out_path.with_suffix(".png").write_bytes(base64.b64decode(payload))15. Chat curl 示例
bash
curl "https://api.taleapi.asia/v1/chat/completions" \
-H "Authorization: Bearer 你在本站生成的 API Key" \
-H "Content-Type: application/json" \
-d '{
"model": "nai-diffusion-4-5-full",
"messages": [
{
"role": "user",
"content": "{\"prompt\":\"1girl, solo, masterpiece, best quality, detailed eyes\",\"negative_prompt\":\"lowres, bad anatomy, bad hands, text, watermark\",\"size\":[1216,832],\"steps\":28,\"scale\":5,\"sampler\":\"k_euler_ancestral\",\"image_format\":\"png\"}"
}
],
"stream": false
}'16. Chat Python 示例
依赖:pip install openai(或 uv add openai)。SDK 版本 ≥ 1.0。
python
import json
import re
from openai import OpenAI
OPENAI_BASE_URL = "https://api.taleapi.asia/v1"
OPENAI_API_KEY = "你在本站生成的 sk-... Key"
_IMG_RE = re.compile(r"!\[[^\]]*\]\((data:image/[^;)]+;base64,[^)]+)\)")
_SEED_RE = re.compile(r"<!--\s*seeds:(\[.*?\])\s*-->")
client = OpenAI(base_url=OPENAI_BASE_URL, api_key=OPENAI_API_KEY)
def generate_image() -> dict:
"""调用 Chat Completions 绘图,并返回图片 Data URI 与随机种子。"""
draw_params = {
"prompt": "1girl, solo, masterpiece, best quality, detailed eyes",
"negative_prompt": "lowres, bad anatomy, bad hands, text, watermark",
"size": [1216, 832],
"steps": 28,
"scale": 5,
"sampler": "k_euler_ancestral",
"image_format": "png",
}
# 使用 JSON 序列化传递本站自定义绘图参数,避免手写转义字符串
resp = client.chat.completions.create(
model="nai-diffusion-4-5-full",
messages=[
{"role": "user", "content": json.dumps(draw_params)},
],
stream=False,
timeout=180,
)
content = resp.choices[0].message.content or ""
seed_match = _SEED_RE.search(content)
return {
"images": _IMG_RE.findall(content),
"seeds": json.loads(seed_match.group(1)) if seed_match else [],
}错误处理:接口错误响应会被 openai SDK 包装成 openai.APIStatusError,其 .status_code 与 .response.json()["error"] 分别对应 OpenAI 错误格式中的 HTTP 状态码与错误对象。
17. Chat Completions 流式响应
如需流式响应:
json
{ "stream": true }如果传 stream: true,服务端会按 OpenAI SSE(服务器发送事件)格式返回 text/event-stream。此接口的 流式响应不是逐步预览:完整图片内容会在某一个 delta.content 中一次性返回。 响应依次包含角色 chunk、完整内容 chunk、带 finish_reason: "stop" 的结束 chunk,最后发送 data: [DONE]。 没有特殊需求时不建议使用流式。
18. OpenAI Images 接口
18.1 Images generations 请求
基础文生图可直接调用:
http
POST https://api.taleapi.asia/v1/images/generations最小请求:
json
{
"model": "nai-diffusion-4-5-full",
"prompt": "1girl, white dress"
}该端点支持的字段:
| 字段 | 类型 | 默认 | 行为 |
|---|---|---|---|
model | string | 无 | 必填非空字符串,且必须精确匹配 /v1/models 返回的 ID。 |
prompt | string | 无 | 必填非空字符串,进入与 Chat 相同的提示词清洗和校验。 |
n | integer | 1 | 只接受 1;布尔值和其他整数返回 400。显式 null 等同省略。 |
size | string | "1216x832" | 接受不区分大小写的 auto,或小写 x 分隔的 宽x高。 |
response_format | string | "b64_json" | 取值为 b64_json;显式 null 等同省略。 |
stream | boolean | false | 只接受布尔;显式 null 等同省略。 |
quality、background、moderation、output_format、output_compression、partial_images、style、user 及其他扩展字段不会改变处理结果。即使请求携带 partial_images,流式响应也只返回最终图片。
Images generations 和 edits 不提供单次费用上限设置,添加 max_tokens / max_completion_tokens 不能限制费用。需要点数预算或参考图参数时,查阅 Chat 预算与参考图;其中氛围转移请求不受预算限制。
size: "auto" 固定使用默认尺寸 1216×832。具体尺寸必须使用小写 x,例如 "1024x1024";"1024X1024"、数组和 "1024*1024" 均返回 400。最终尺寸仍按通用生成规则归一化。
需要负向提示词、采样器、步数、图生图或局部重绘等扩展能力时,使用 Chat Completions 的内层 payload。Images generations 固定单张生成和 PNG 响应。
完整请求示例:
json
{
"model": "nai-diffusion-4-5-full",
"prompt": "1girl, white dress, soft light",
"n": 1,
"size": "1024x1024",
"response_format": "b64_json",
"stream": false
}18.2 Images generations 非流式响应
json
{
"created": 1710000000,
"data": [
{
"b64_json": "iVBORw0KGgo..."
}
]
}b64_json 是纯 Base64,不含 data:image/...;base64, 前缀,且正常只有一项。
OpenAI Python 包示例:
python
import base64
from pathlib import Path
from openai import OpenAI
client = OpenAI(
base_url="https://api.taleapi.asia/v1",
api_key="你在本站生成的 sk-... Key",
)
response = client.images.generate(
model="nai-diffusion-4-5-full",
prompt="1girl, white dress, soft light",
n=1,
size="1024x1024",
response_format="b64_json",
)
Path("output.png").write_bytes(base64.b64decode(response.data[0].b64_json))18.3 Images generations 流式响应
stream: true 返回 text/event-stream。每张最终图片发送一个 completed 事件:
text
event: image_generation.completed
data: {"type":"image_generation.completed","b64_json":"iVBORw0KGgo...","background":"auto","created_at":1710000000,"output_format":"png","quality":"auto","size":"1216x832"}只发送最终 image_generation.completed,不发送中间图片,也不发送 Chat 专用的 [DONE];客户端读取到 EOF(响应流结束)即完成接收。
18.4 Images edits
http
POST https://api.taleapi.asia/v1/images/editsImages edits 使用 multipart/form-data,不是 JSON 请求体。
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
image | file | 是 | 单张原图,文件大小不超过 10 MiB。 |
prompt | string | 是 | 正向提示词;语言要求见提示词限制。 |
model | string | 是 | 必须精确匹配 /v1/models 返回的模型 ID。 |
size | string | 否 | auto 或 宽x高。省略或传 auto 时根据原图尺寸归一化。 |
stream | string | 否 | 只能传表单文本 true 或 false,缺省为 false。 |
服务端固定使用 strength=0.7、noise=0.2。其他表单字段不会改变处理结果;该端点固定生成一张 PNG 图片,执行整图图生图。
原图尺寸处理规则:
- 原图尺寸与归一化目标尺寸一致:直接使用原图。
- 尺寸不同但宽高比例一致:等比缩放原图到目标尺寸。
- 宽高比例不一致:返回 400。
服务端不会裁剪、补边或旋转原图。
非流式请求示例:
bash
curl "https://api.taleapi.asia/v1/images/edits" \
-H "Authorization: Bearer 你在本站生成的 API Key" \
-F "[email protected]" \
-F "prompt=1girl, white dress" \
-F "model=nai-diffusion-4-5-full" \
-F "size=832x1216"非流式响应与 Images generations 相同,返回纯 Base64。stream=true 返回 text/event-stream,只发送最终 image_edit.completed 事件,不发送中间预览或 [DONE],由 EOF 结束事件流。
19. OpenAI 错误格式
OpenAI 兼容端点的错误响应是 OpenAI 风格:
json
{
"error": {
"message": "请求参数校验失败,请检查字段类型和必填字段。",
"type": "invalid_request_error",
"param": "",
"code": "REQUEST_VALIDATION_ERROR"
}
}param 用于定位首个无效字段,嵌套字段会保留完整路径。
常见错误:
| HTTP | code | 常见原因 |
|---|---|---|
400 | MODEL_REQUIRED | 缺少外层 model。 |
400 | MODEL_NOT_SUPPORTED | 模型 ID 不在支持列表中。 |
400 | REQUEST_VALIDATION_ERROR | prompt、尺寸、步数、图片或 Images 字段无效。 |
400 | UPSTREAM_INVALID_REQUEST | 图像服务拒绝了当前参数。 |
402 | MAX_TOKENS_EXCEEDED | 所需 Anlas 超过本次请求预算;提高或移除预算,或降低尺寸、步数等参数。 |
401 | AUTH_REQUIRED / AUTH_INVALID | 密钥缺失、错误、禁用或失效。 |
403 | AUTH_INVALID | 密钥无权执行本次请求。 |
403 | NAI5_NOT_ALLOWED / ANLAS_NOT_ALLOWED | 当前请求身份无权使用 V5 或付费能力,请联系管理员。 |
424 | UPSTREAM_AUTH_FAILED / UPSTREAM_SERVER_ERROR / UPSTREAM_ERROR | 依赖的 NovelAI 鉴权、生成或服务执行失败,或上游未返回最终图片。 |
429 | SERVICE_BUSY / UPSTREAM_RATE_LIMITED | 客户端请求频率、并发限制或图像服务限流。 |
429 | DRAW_BUSY / QUEUE_FULL / REQUEST_RETRY_REQUIRED | 已有任务、队列已满或需要稍后重新提交。 |
500 | INTERNAL_ERROR / UPSTREAM_API_KEY_MISSING | 服务内部错误或服务凭据未配置。 |
503 | SERVICE_BUSY / SERVICE_NOT_READY / UPSTREAM_NETWORK_ERROR | 服务繁忙、尚未就绪或暂时无法连接图像服务。 |
503 | NAI5_UNAVAILABLE / NO_PAID_CREDIT | 当前缺少可用 V5 资源或可用点数,不等于调用方钱包余额不足。 |
502 | MISSING_ANLAS_COST | 缺少有效计费凭据,服务拒绝返回图片;请联系管理员。 |
HTTP 424 表示请求已被 API 接受,但依赖的图像操作失败;错误信封中的 type 为 upstream_error。
参数错误通常返回 400 或 422。客户端应先检查 HTTP 状态码,再读取 error.code、error.message 和 error.param。原生接口的错误处理方式见NovelAI 原生 API 文档。
