Nodes/AQnodes for ComfyUI/AQ_openai_compatible
ComfyUI Node

AQ_openai_compatible

Run the acestep music-metadata flow against any OpenAI-compatible API

By 2frames·Created about a year ago·Updated 7 months ago· 1
AQ_openai_compatible
  • image
  • response_json
  • tags
  • lyrics
  • seed
  • bpm
  • duration
  • timesignature
  • language
  • keyscale
  • coverImage
  • title
  • tagline
  • headline
  • yt_description
  • yt_tags
  • yt_title
  • instruction
◄openai_api_key►
◄modelgpt-5-nano►
◄custom_model►
◄prompt►
◄system_messageYou are a helpful assistant.►
◄temperature1.00►
◄top_p0.95►
◄seed0►
◄verbositymedium►
◄reasoning_effortmedium►
◄api_endpointhttps://api.openai.com/v1/chat/completions►

The flexible one in the acestep family. Same fixed song-metadata schema - tags, lyrics, bpm, duration, keyscale, cover art, YouTube text - but instead of OpenAI's Responses API it posts to whatever endpoint you give it, defaulting to OpenAI's chat-completions URL. Point it at Ollama, vLLM, LM Studio, Together, Groq, or any local OpenAI-compatible server, and you get the same structured output without the cloud dependency.

Why you'd pick this over the others

If you want the whole song-metadata pipeline but refuse to send your lyrics prompts to a cloud API - or you just already run a local LLM - this is the bridge. It uses chat completions with a strict JSON-schema response_format, which most OpenAI-compatible servers support these days. The trade-off is real: strict schema enforcement (additionalProperties: false) is only as good as the server, and weaker local models won't always honor it, so expect the occasional retry.

How it works

Same coerce-and-split as the siblings: it sends temperature/top_p/seed (omitted when negative), parses the JSON, and splits it into typed outputs with defaults (bpm→120, duration→120s, keyscale→C major). An optional image becomes a data:image/png;base64 URL in the message. The schema descriptions carry the full ACE-Step flavor - tags as a music style prompt, lyrics with [verse]/[chorus]/[inst] structure tags and language codes, BPM ranges by genre - so the model is being instructed on the exact pipeline it feeds.

Inputs

openai_api_key, model (9 choices, gpt-5-nano default), custom_model, prompt, system_message, temperature, top_p, seed, verbosity, reasoning_effort, api_endpoint (default https://api.openai.com/v1/chat/completions), and an optional image.

Outputs

The 17-slot acestep set: response_json, tags, lyrics, seed, bpm, duration, timesignature, language, keyscale, coverImage, title, tagline, headline, yt_description, yt_tags, yt_title, instruction.

Install

Part of AQnodes:

cd ComfyUI/custom_nodes
git clone https://github.com/2frames/ComfyUI-AQnodes
cd ComfyUI-AQnodes
pip install -r requirements.txt

or search "AQnodes" in ComfyUI Manager and restart.

Gotchas

Not every local server honors strict JSON schema - Ollama and vLLM do; older ones return markdown-wrapped JSON and the node raises when parsing fails, so keep an eye on the console. The verbosity/reasoning_effort controls inherited from the OpenAI twin map loosely to the chat-completions payload and may be ignored by local models. And note the default endpoint is OpenAI's chat completions URL - it works if you want OpenAI after all, just with a different API shape than AQ_OpenAI_acstep15's Responses API.

CategoryAquasite/LLM

Inputs (12)

NameTypeDefaultDescription
openai_api_keySTRING—
modelCOMBOgpt-5-nano9 options: gpt-5.2, gpt-5-nano, gpt-5-mini, gpt-5, gpt-4.1-mini, gpt-4.1, +3
custom_modelSTRING—
promptSTRING—
system_messageSTRINGYou are a helpful assistant.—
temperatureFLOAT1.00-1–2—
top_pFLOAT0.95-1–1—
seedINT00–18446744073709550000—
verbosityCOMBOmedium4 options: none, low, medium, high
reasoning_effortCOMBOmedium5 options: none, minimal, low, medium, high
api_endpointSTRINGhttps://api.openai.com/v1/chat/completions—
imageoptIMAGE—

Outputs (17)

NameTypeDescription
response_jsonSTRING—
tagsSTRING—
lyricsSTRING—
seedINT—
bpmINT—
durationFLOAT—
timesignatureCOMBO—
languageCOMBO—
keyscaleCOMBO—
coverImageSTRING—
titleSTRING—
taglineSTRING—
headlineSTRING—
yt_descriptionSTRING—
yt_tagsSTRING—
yt_titleSTRING—
instructionSTRING—