Skip to content

yue2: continue a song from given semantic tokens - #641

Merged
0xShug0 merged 1 commit into
0xShug0:mainfrom
engival:yue2-semantic-prefix
Sep 22, 2026
Merged

0xShug0 merged 1 commit into
0xShug0:mainfrom
engival:yue2-semantic-prefix

Conversation

@engival

@engival engival commented Sep 22, 2026

Copy link
Copy Markdown
Contributor

What it enables: changing a song's style part-way through, by editing the token history the model continues from. Demo: https://youtu.be/gMS2Ko7s97o

What it adds

semantic_prefix (inline JSON array) and semantic_prefix_file: the first N semantic frames are given instead of sampled. The AR stage prefills them behind the prompt and samples from frame N. They use the same format export_semantic writes.

  • The forced frames count toward semantic_min_tokens and semantic_max_tokens. Setting both to T stops at an exact length, and N = T renders the given tokens without sampling. No new option is needed for either.
  • With cot=melody/full, a prefix requires abc/abc_file. Otherwise a new score would be planned that the frames don't belong to.
  • The runtime change is small: generate/generate_cfg take the forced ids and reuse the existing prefill path. No new stage is added. Requests without the option are untouched.

Example

examples/yue2_style_change/ is the whole workflow with audiocpp_cli and the Python standard library only. It renders one score in two styles (stop_after=semantic, export_semantic), splices the token lists, continues from the edited history, and renders the result. It ships a score and lyric so the default run is reproducible. Happy to move it out of the repo if you'd rather not carry it.

Validation (Intel Arc B70, Vulkan)

  • No new options: WAV byte-identical to main.
  • N = T round trip: byte-identical WAV to the render the tokens came from.
  • N = 300, T = 640: the first 300 frames are kept exactly, and the same request twice gives identical output.
  • The CFG path (cot=off) works, and the validation errors fire.
  • Path tests: yue2_semantic_prefix_continue plus the three existing YuE2 cases pass.
  • The example runs end to end (191 s song, 226 s wall).

Notes

Deterministic for a given request, but not the same draws as an uninterrupted run (the RNG starts at the first sampled frame). With guidance ≠ 1.0 the prefix prefills through host K/V, so memory grows with N. The default cot=full route is single-stream on device.

@engival
engival force-pushed the yue2-semantic-prefix branch 2 times, most recently from b7ddc3e to 4ee81d1 Compare September 22, 2026 01:47
@engival
engival marked this pull request as ready for review September 22, 2026 02:52
@0xShug0

0xShug0 commented Sep 22, 2026

Copy link
Copy Markdown
Owner

@engival I think there’s some overhead when

semantic_min_tokens = N
semantic_max_tokens = N
semantic_prefix contains N tokens
  • With stop_after=audio (the default), AR is needed later for NAR conditioning, but the semantic-stage prefill and logits are redundant.
  • If guidance_scale == 1, one redundant prefill.
  • If guidance_scale != 1, two redundant CFG prefills plus batched decode setup.
  • Technically valid, but not practically useful: stop_after=semantic, In this case, the supplied tokens can be returned directly. AR initialization, prefill, logits computation, and decode setup are all unnecessary.

semantic_prefix (inline JSON array) and semantic_prefix_file force the first N semantic frames: the AR stage prefills them behind the prompt and samples from frame N. The forced frames count toward semantic_min_tokens, semantic_max_tokens and the repetition penalty window, so min = max = T stops at an exact length and N = T renders the given tokens without sampling. With cot=melody or cot=full a prefix requires abc or abc_file. Requests without the option render as before.

When the prefix already fills the window (N = semantic_max_tokens) the AR stage is skipped: the given frames are the stream, stop_after=semantic returns them as they came, and stop_after=audio prefills them once in the NAR stage for its conditioning.

examples/yue2_style_change uses it, with stop_after and export_semantic, to change a song's style part-way through from audiocpp_cli alone.
@engival
engival force-pushed the yue2-semantic-prefix branch from 4ee81d1 to f409158 Compare September 22, 2026 13:23
@engival

engival commented Sep 22, 2026

Copy link
Copy Markdown
Contributor Author

@0xShug0

Yeah, that was an oversight. It now short-circuits to skip the AR phase in that case.

@0xShug0
0xShug0 merged commit d32a6a0 into 0xShug0:main Sep 22, 2026
6 checks passed
@0xShug0

0xShug0 commented Sep 22, 2026

Copy link
Copy Markdown
Owner

@engival Thanks! PR merged.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants