Parse Structured Music LLM Output
Turning an LLM's rambling reply into four clean song fields
- caption
- lyrics
- title
- image_prompt
- source_name
- generation_seed
- run_index
- variant_count
- source_path
- prompt_origin
- prompt_provenance_json
Anyone who's wired a chat LLM into a generation graph knows the pain: the model gives you exactly what you asked for, wrapped in "Here is your enhanced prompt!" and a closing paragraph, and you have to scrape the good parts out of the chat-shaped noise. That's failure mode one from the local-LLM playbook, and it's exactly what this node exists to kill. Parse Structured Music LLM Output takes the assistant's text, extracts the [Caption], [Lyrics], [Title], and [Image_Prompt] sections, validates that the required music sections are present, and emits each one as a clean STRING - plus per-song seeds and provenance.
The bundled system prompt demands the canonical [Caption] → [Lyrics] → [Title] → [Image_Prompt] order, but the parser is deliberately order-tolerant: an LLM that shuffles the sections won't nuke an otherwise usable result. What it won't tolerate is missing or empty required sections - it raises an error rather than silently generating a song with no caption. Silent failure is worse than a loud one here.
Inputs
structured_llm_output- the full assistant text from your LLM node.song_count- how many song variants to emit from this source (1–100). More songs = more downstream generation time, obviously.seed_mode-random_each_song(fresh seed per variant) orincrement_from_base(reproducible sequential seeds frombase_seed). For reproducible batches, increment is the one you want.base_seed- only meaningful in increment mode.user_prompt- stored with the parsed result for provenance.source_name_override- replaces the auto-derived source identifier when non-empty.fallback_title- used only when no usable[Title]survives parsing; it never replaces a valid LLM title.
Outputs
Every output is a list (is_list), so ComfyUI maps them across your batch: caption, lyrics, title, image_prompt, source_name, generation_seed, run_index, variant_count, source_path, prompt_origin, and prompt_provenance_json. Wire caption + lyrics into the MiniMax Music 3 node, image_prompt into the artwork branch, and the provenance outputs into MiniMax Song Metadata.
Installing it
Pack install via ComfyUI Manager (search "MiniMax Music Production Toolkit") or:
cd ComfyUI/custom_nodes
git clone https://github.com/jplenio/ComfyUI-MiniMax-Music-Production-Toolkit.git
cd ComfyUI-MiniMax-Music-Production-Toolkit
python -m pip install -r requirements.txt
Dependencies: scipy, soundfile, imageio-ffmpeg, mutagen, Pillow. Restart ComfyUI and hard-refresh once.
Gotchas
If you get a hard parse error, the LLM probably skipped a required section or mangled the tags - the README's honest caveat applies: "the example LLM stage depends on the quality and instruction-following ability of the GGUF model you choose." A small or heavily-quantized model that truncates its output mid-[Lyrics] will trip this node on purpose. And the cache-buster rule applies upstream: if the LLM output looks identical every run, the LLM node is caching - wire in the LLM Session ID node, not the parser.
Inputs (20)
| Name | Type | Default | Description |
|---|---|---|---|
| song_count | INT | 11–100 | Number of song variants to emit from the selected source. Higher values repeat the downstream workflow for additional variants and therefore increase total generation time. |
| seed_mode | COMBO | random_each_song | Controls how generation seeds are created for multiple songs. random_each_song chooses a fresh seed per item; increment_from_base produces reproducible sequential seeds starting from base_seed. |
| base_seed | INT | 10–9223372036854776000 | Base integer used when deterministic/incrementing seed generation is selected. With random_each_song it is not the source of the random values; with increment_from_base each variant is derived from this value. |
| user_prompt | STRING | Instrumental Progressive House with melodic and subtle trance influences, highly atmospheric and spacious, driven by memorable signature motifs and distinctive recurring synth riffs. Emotional, smooth, modern, with strong progression and evolving layers. create a 4–5 minutes long melodic story in the track. | Short user/music request sent to the external LLM or stored with the parsed result. This is the concise creative request that the long system prompt expands into MiniMax fields. |
| source_name_override | STRING | Optional explicit source name. When non-empty it replaces the automatically derived source identifier used for filenames/provenance. | |
| fallback_title | STRING | llm-song | Title used when the LLM answer and the manual fields contain none. A cover still takes its title from the source filename. |
| structured_llm_outputopt | STRING | Raw text answer from the LLM chat node, with the [Style], [Lyrics], [Title] and [Image_Prompt] sections the parser expects. | |
| manual_captionopt | STRING | Manual MiniMax Music caption used when manual source mode is selected. Put musical/production instructions here, not structural Lyrics tags. | |
| manual_lyricsopt | STRING | Manual MiniMax Music Lyrics field. Use supported section tags and lyric text only; instrumental tracks should contain structural tags rather than prose production instructions. | |
| manual_titleopt | STRING | Fallback/manual song title used in manual source mode. It may later be replaced by an LLM-generated title depending on the workflow branch. | |
| manual_image_promptopt | STRING | Artwork prompt used when the LLM answer contains none. The text-free prohibition is appended automatically when it is missing. | |
| model_check_reportopt | STRING | Text report from the model preflight: which artifacts are present, already downloaded or missing. Recorded for the log and the production JSON only. | |
| llm_statusopt | STRING | Status line from the LLM node, kept in the provenance so a run can be traced back to the model and provider that produced it. | |
| max_prompt_tokensopt | INT | 4500500–4800 | Token budget for the combined Caption+Lyrics sent to MiniMax Music 3. The MiniMax text encoder hard-rejects prompts over 5000 tokens, so the default 4500 keeps a safety margin for the estimation error. The estimate is conservative (calibrated against the real MiniMax tokenizer). |
| trim_long_promptopt | BOOLEAN | true | When the estimated prompt exceeds the budget: ON trims softly (whole lines from the end of the lyrics, orphan section tags removed, caption intact) and logs a warning; OFF raises a clear error instead so the MiniMax encoder never fails cryptically. |
| model_profile_jsonopt | STRING | JSON profile of the selected song model: which model is active, its duration window, prompt hard limit and capabilities. This node adapts its behaviour to that profile; it comes from the song model profile node. | |
| cover_source_jsonopt | STRING | Source audio identity and shared transcription mode from Cover song / Source audio. Used only for YuE2 Cover; the filename owns the final title. | |
| structured_summary_jsonopt | STRING | Summary JSON from the structured prompt node (template, fields, requested length). Used for provenance and to honour a requested song length. | |
| cover_lyricsopt | STRING | Cover-only: source transcript with timestamps. Original words are placed in measured score sections, restored after LLM rewrites, then checked for complete word order including repetitions. New lyrics use the timing as guidance. | |
| cover_lyrics_lockopt | STRING | Cover Studio only, and empty by default. A deliberately locked lyrics block: when connected and non-empty it replaces the LLM's words verbatim and marks them as intentional, so the 'new lyrics' copy guard does not mistake a user lock for a lazy model answer. Leave it empty to keep the previous behaviour. |
Outputs (11)
| Name | Type | Description |
|---|---|---|
| caption | STRING | — |
| lyrics | STRING | — |
| title | STRING | — |
| image_prompt | STRING | — |
| source_name | STRING | — |
| generation_seed | INT | — |
| run_index | INT | — |
| variant_count | INT | — |
| source_path | STRING | — |
| prompt_origin | STRING | — |
| prompt_provenance_json | STRING | — |