Spaces:
Running on Zero
Running on Zero
Multi-user concurrency: compose outside the GPU queue, parallel assists/examples/videos
Browse filesSimple mode ran the composer LLM call inside the concurrency_id="gpu" (limit 1) event, so after clicking Generate the LLM request did not even START until every queued song from other users finished — the delay users are reporting. Also, Gradio's default concurrency limit is 1 per function, so one user's assist/example/video blocked everyone else's.
- Simple flow split: simple_compose (limit 8, starts immediately) -> .success -> studio_generate on the GPU queue. Status shows 'waiting for a GPU slot' between the two.
- compose_assist: limit 8. render_video: limit 4. load_example (cached files): unlimited.
- player.stop cancels the compose step too.
API note: the /simple_generate endpoint is replaced by /simple_compose + the chained sing step.
app.py
CHANGED
|
@@ -1533,19 +1533,21 @@ def compose_assist(raw_state, duration):
|
|
| 1533 |
return state, "Lyrics & structured prompt ready — review and tweak them, then press Generate."
|
| 1534 |
|
| 1535 |
|
| 1536 |
-
def
|
| 1537 |
-
#
|
|
|
|
| 1538 |
state = _normalize_state(state)
|
| 1539 |
description = _composed_description(state)
|
| 1540 |
title = state["title"] or state["description"]
|
| 1541 |
-
yield gr.skip(), "writing lyrics & structured prompt...", gr.skip(),
|
| 1542 |
lyr, gm, vd, arr = compose_song(description, duration)
|
| 1543 |
state.update(lyrics=lyr, global_meta=gm, vocals=vd, arrangement=arr)
|
| 1544 |
-
yield
|
| 1545 |
-
|
| 1546 |
-
|
| 1547 |
-
|
| 1548 |
-
|
|
|
|
| 1549 |
|
| 1550 |
|
| 1551 |
def studio_generate(state, duration, seed, randomize_seed, headroom, steps, guidance):
|
|
@@ -1618,12 +1620,17 @@ with gr.Blocks(theme=gr.themes.Citrus(), css=CSS) as demo:
|
|
| 1618 |
|
| 1619 |
_knobs = [duration, seed, randomize_seed, headroom, steps, guidance]
|
| 1620 |
|
| 1621 |
-
|
| 1622 |
-
|
| 1623 |
-
[player, stats,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1624 |
concurrency_limit=1, concurrency_id="gpu", show_progress="minimal",
|
| 1625 |
)
|
| 1626 |
-
ev_simple.then(render_video, [wav_state, video_title], video_out).then(
|
| 1627 |
lambda s: s.replace(" — rendering share video...", " — share video ready."), stats, stats
|
| 1628 |
)
|
| 1629 |
|
|
@@ -1632,18 +1639,18 @@ with gr.Blocks(theme=gr.themes.Citrus(), css=CSS) as demo:
|
|
| 1632 |
[player, stats, wav_state, seed, video_title],
|
| 1633 |
concurrency_limit=1, concurrency_id="gpu", show_progress="minimal",
|
| 1634 |
)
|
| 1635 |
-
ev_studio.then(render_video, [wav_state, video_title], video_out).then(
|
| 1636 |
lambda s: s.replace(" — rendering share video...", " — share video ready."), stats, stats
|
| 1637 |
)
|
| 1638 |
|
| 1639 |
player.stop(
|
| 1640 |
lambda: "stopped — kept the part that was already streamed.", None, stats,
|
| 1641 |
-
cancels=[ev_simple, ev_studio], show_progress="hidden",
|
| 1642 |
)
|
| 1643 |
|
| 1644 |
-
composer.edit(compose_assist, [composer, duration], [composer, stats], show_progress="minimal")
|
| 1645 |
|
| 1646 |
-
composer.apply(load_example, [composer], [composer, player, stats, video_out, wav_state, video_title], show_progress="minimal")
|
| 1647 |
|
| 1648 |
if __name__ == "__main__":
|
| 1649 |
demo.launch()
|
|
|
|
| 1533 |
return state, "Lyrics & structured prompt ready — review and tweak them, then press Generate."
|
| 1534 |
|
| 1535 |
|
| 1536 |
+
def simple_compose(state, duration):
|
| 1537 |
+
# Composing is a plain LLM API call, so it runs OUTSIDE the GPU queue: it starts the moment the user
|
| 1538 |
+
# clicks instead of waiting behind every queued song. The singing step chains after it on the GPU queue.
|
| 1539 |
state = _normalize_state(state)
|
| 1540 |
description = _composed_description(state)
|
| 1541 |
title = state["title"] or state["description"]
|
| 1542 |
+
yield gr.skip(), "writing lyrics & structured prompt...", gr.skip(), title
|
| 1543 |
lyr, gm, vd, arr = compose_song(description, duration)
|
| 1544 |
state.update(lyrics=lyr, global_meta=gm, vocals=vd, arrangement=arr)
|
| 1545 |
+
yield (
|
| 1546 |
+
{"cmd": "status", "text": "Lyrics ready — waiting for a GPU slot..."},
|
| 1547 |
+
"lyrics ready — waiting for a GPU slot...",
|
| 1548 |
+
state,
|
| 1549 |
+
gr.skip(),
|
| 1550 |
+
)
|
| 1551 |
|
| 1552 |
|
| 1553 |
def studio_generate(state, duration, seed, randomize_seed, headroom, steps, guidance):
|
|
|
|
| 1620 |
|
| 1621 |
_knobs = [duration, seed, randomize_seed, headroom, steps, guidance]
|
| 1622 |
|
| 1623 |
+
ev_compose = composer.submit(lambda: ({"cmd": "reset", "loader": True, "status": "Writing lyrics & structured prompt with MiniMax-M3...", "nonce": random.random()}, None), None, [player, video_out]).then(
|
| 1624 |
+
simple_compose, [composer, duration],
|
| 1625 |
+
[player, stats, composer, video_title],
|
| 1626 |
+
concurrency_limit=8, show_progress="minimal",
|
| 1627 |
+
)
|
| 1628 |
+
ev_simple = ev_compose.success(
|
| 1629 |
+
studio_generate, [composer] + _knobs,
|
| 1630 |
+
[player, stats, wav_state, seed, video_title],
|
| 1631 |
concurrency_limit=1, concurrency_id="gpu", show_progress="minimal",
|
| 1632 |
)
|
| 1633 |
+
ev_simple.then(render_video, [wav_state, video_title], video_out, concurrency_limit=4).then(
|
| 1634 |
lambda s: s.replace(" — rendering share video...", " — share video ready."), stats, stats
|
| 1635 |
)
|
| 1636 |
|
|
|
|
| 1639 |
[player, stats, wav_state, seed, video_title],
|
| 1640 |
concurrency_limit=1, concurrency_id="gpu", show_progress="minimal",
|
| 1641 |
)
|
| 1642 |
+
ev_studio.then(render_video, [wav_state, video_title], video_out, concurrency_limit=4).then(
|
| 1643 |
lambda s: s.replace(" — rendering share video...", " — share video ready."), stats, stats
|
| 1644 |
)
|
| 1645 |
|
| 1646 |
player.stop(
|
| 1647 |
lambda: "stopped — kept the part that was already streamed.", None, stats,
|
| 1648 |
+
cancels=[ev_compose, ev_simple, ev_studio], show_progress="hidden",
|
| 1649 |
)
|
| 1650 |
|
| 1651 |
+
composer.edit(compose_assist, [composer, duration], [composer, stats], concurrency_limit=8, show_progress="minimal")
|
| 1652 |
|
| 1653 |
+
composer.apply(load_example, [composer], [composer, player, stats, video_out, wav_state, video_title], concurrency_limit=None, show_progress="minimal")
|
| 1654 |
|
| 1655 |
if __name__ == "__main__":
|
| 1656 |
demo.launch()
|