最新资讯
bloomberg.com Nvidia 加强东南亚芯片追踪以打击走私 thestack.technology 模型路由需求升温,Agent Router 推出开源替代方案 www.youtube.com Google DeepMind 的 Philipp Schmid:AI 同事需要具备的七个要素 unite.ai Cashfree 为 AI Agent 的托管结账加入 WebMCP 工具 dev.to 我们在 DolphinBench 上测试记忆检索:纯关键词搜索暴露了自身回归 dev.to 别再把 Agent 写成 while 循环,把它建模为状态机 analyticsindiamag.com 小语言模型可能重塑企业 AI 部署方式 bloomberg.com Rightmove 与 Scout24 借 AI 产品应对低迷房市并上调展望 stackoverflow.blog 欢迎来到芯片时代:半导体制造、AI 数据中心与芯片设计的未来 www.youtube.com AI Agent 总犯同样的错:CentralAgent AI 将记忆重构为经验系统 pub.towardsai.net Netflix 科学家建议重采样 LLM 评判:5 次仅将误差棒缩小 13% pub.towardsai.net Jev 作为 LLM 前的静默层:构建提示感知的模型路由器
多元动态
登录 注册
行业动态 dev.to · @Ilan Kim

直接调用 NovelAI V5 API:请求体、params_version 与常见报错实测

原文 我的收藏

作者在 macOS 上用 Node 直接调用 NovelAI V5 的 nai-diffusion-5-full 接口,发现其请求体骨架与 V4 相同,params_version 传 4/3/1/0 出图结果一致,JSON 与 multipart 请求体结果也相同。缺失 v4_prompt 或 v4_negative_prompt 会返回 500 而非 400;对 FormData 手动设置 Content-Type 会因缺少 multipart boundary 报 400;使用旧域名会报 model 枚举值无效。内容面向自行编写脚本调用该 API 的开发者。

AI推荐理由 作者在 macOS 上实测 NovelAI V5 图像 API,给出可复现的请求体结构、params_version 取值不影响出图、缺失 v4_prompt/v4_negative_prompt 返回 500、FormData 手设 Content-Type 报 multipart boundary 错误、旧域名报 model 枚举错误等具体结论。对直接调用该 API 的开发者有实用价值,但属个人实测,样本为六张图,结论适用范围有限。

72

正文

nai-diffusion-5-full takes the same body skeleton V4 took, posted to https://image.novelai.net/ai/generate-image, and params_version — the one field every third-party tool fills in differently — returns a pixel-for-pixel identical image whether you send 4, 3, 1, or 0 with this body skeleton. JSON and multipart bodies gave the same result too. What does break it: drop either v4_prompt or v4_negative_prompt and you get 500 Internal Server Error rather than a 400, set Content-Type by hand on a FormData body and you get a missing multipart boundary 400, and post to the old host and you get a model must be a valid enum value 400. This is for people calling NovelAI V5 from their own scripts rather than through a ComfyUI node or a GUI like NAIA (a community-built desktop front end for NovelAI). On 2026-09-14, on macOS 26.5.2 with Node v22.22.3 and an Opus account (tier: 3), I generated six images inside the free band and compared request formats, error responses, and balance changes; I also read the strings out of the official web client bundle the same day. Two terms if NovelAI is new to you: Anlas is NovelAI's generation credit, and Opus is the top subscription tier, which generates one image at a time at the common sizes and up to 28 steps without spending any, as long as no base image is involved and the allowance has not run out. The policy and the per-size cost table are in the earlier post, the measurements through a ComfyUI node are in the one after it, and this post covers only the request contract. The problem If you look at third-party tools' request bodies to work out how to call V5 yourself, the params_version value is different in every one of them. ComfyUI_NAIDGenerator, a ComfyUI node for NovelAI, sends 1. The README of ComfyUI_RS_NAI_API_Request, another ComfyUI node, says "V5 requests use params_version: 4 while older models keep params_version: 3". The changelog of NAIWeaver, a standalone NovelAI client, says "send params_version: 4" (all checked 2026-09-14). The official OpenAPI document has no required array and no nai-diffusion-5 string, so it cannot settle which one is right. From there, nudging the body around gets you three responses. All three are verbatim from this round of testing: POST https://api.novelai.net/ai/generate-image (old host) 400 {"statusCode":400,"message":"model must be a valid enum value"} POST https://image.novelai.net/ai/generate-image (v4_prompt or v4_negative_prompt omitted) 500 {"statusCode":500,"message":"Internal Server Error"} POST https://image.novelai.net/ai/generate-image (FormData + Content-Type: multipart/form-data set by hand) 400 {"statusCode":400,"message":"missing multipart boundary"} Enter fullscreen mode Exit fullscreen mode The first one has different wording from the "update to the image URL" 400 the balance lookup returns. The old host accepts the generation request itself but does not know the V5 model ID, so from the message alone it looks like you typed the model ID wrong. The second is the confusing one. It is a 500 rather than a 400-class validation error, so it reads like a server outage, but the cause is your request body. The third one appears when you hand Node's fetch a FormData body and set the header yourself, because the boundary undici would have attached automatically disappears. What the measurements show params_version does not change the result with this body skeleton. Same prompt, seed 1234567890, 832×1216, 28 steps, one image per value: params_version Response Response time PNG Source Anlas 4 (official web client) 200 2.5 s NovelAI Diffusion V5 0ADF9AB7 9,930 → 9,930 3 (the value said to be for older models) 200 1.8 s same no change 1 (ComfyUI_NAIDGenerator) 200 1.9 s same no change 0 (a value no tool uses) 200 1.8 s same no change Comparing the four images pixel by pixel with Pillow gives a mean absolute difference of 0 and 0% of pixels changed, so they are completely identical. The Comment metadata of the returned PNGs has no params_version field either. If the value were read and acted on, 0 should at least have been rejected, so with this skeleton it has to be treated as ignored. Whether that also holds for other field combinations — character prompts, inpainting and so on — I did not check. So where does 4 come from? In the novelai.net bundle I pulled on 2026-09-14 (_app-b7172cc1a6a0b340.js), the default parameters in the nai-diffusion-5-full branch start with params_version:4, and there is migration code that raises stored settings to 4 if params_version got me a 200 and an image_0.png whose pixels match the table above: // node nai-v5-direct.mjs — the key file has a pst- token on the line after the "novelai" label import { readFile, writeFile } from 'node:fs/promises'; const lines = (await readFile(process.argv[2], 'utf8')).split(/\r?\n/).map((l) => l.trim()); const token = lines[lines.findIndex((l) => /novelai/i.test(l)) + 1]; const body = JSON.parse(await readFile('body.json', 'utf8')); const r = await fetch('https://image.novelai.net/ai/generate-image', { method: 'POST', headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify(body), }); console.log(r.status, r.headers.get('content-type')); if (r.ok) await writeFile('out.zip', Buffer.from(await r.arrayBuffer())); // image_0.png is inside else console.log(await r.text()); Enter fullscreen mode Exit fullscreen mode For transport, set Content-Type: application/json explicitly if you send JSON, and do not set a Content-Type header yourself if you use FormData. Node 22's fetch builds the header with the boundary on its own for a FormData body. The response is a binary/octet-stream zip with image_0.png inside. Check the model from the Source value in the PNG's tEXt chunk (NovelAI Diffusion V5 0ADF9AB7). To stay at 0 Anlas, keep all of it: Opus, one image (n_samples: 1), no base image, a pixel product of 1,048,576 or less, and 28 steps or fewer — then read /user/subscription before and after the generation and compare the sum trainingStepsLeft.fixedTrainingStepsLeft + trainingStepsLeft.purchasedTrainingSteps. trainingStepsLeft is an object rather than an integer, so you cannot subtract it directly. usage.percent is too coarse to use for per-image checks. Respect the API document's "all generation requests must be initiated by a human action" and its 429 note ("API clients should not attempt to retry") by sending human-initiated requests one at a time with a gap between them. This round of measurements ran with 6 seconds between requests and a concurrency of 1. Image: the sample outputs in this post are AI images generated with NovelAI Diffusion V5. Takeaways With this body skeleton, params_version is ignored — 4, 3, 1, and 0 all return the same pixels — and JSON and multipart bodies produced the same image. The parts that actually matter are the host, image.novelai.net, and keeping both v4_prompt and v4_negative_prompt in the body, since dropping either one returns a 500 rather than a validation 400. Unverified How a 429 behaves: the API document explicitly forbids retrying, so I didn't provoke one on purpose. 429 isn't even documented for the image endpoints, so I don't know the actual message. What happens when director_reference_* fields are sent to V5: V5 doesn't support Precise Reference, but the schema doesn't block these fields. Whether that is a 400 or "ignored and billed", I didn't run, because of the billing risk. The actual charge for a 29-step or 2-image request: that is the paid band, so I didn't generate it. The price lookup path I tried was a 404, so the only figure I have is the 45 Anlas for the large size from the earlier post. The absolute capacity of the Opus battery (allowance): usage.percent stayed fixed at 87 across six images, so I couldn't work backwards to a per-image draw. How params_version behaves with other body skeletons: I didn't run it with character-prompt, inpainting, or img2img bodies. Large values such as 9 also fell outside the generation budget. Changelog Version Description 1.0 2026-09-14 first version (macOS 26.5.2 · Node v22.22.3 · Opus, 6 free-tier generations)

来源报道 · 1 篇 · 以下链接均前往原始媒体

← 返回精选动态 原文

更多内容