Integrate pinned YuE2 community WebUI

This commit is contained in:
Mikei386
2026-09-10 22:13:32 +02:00
parent 72c9d8c485
commit af25425aee
4 changed files with 165 additions and 17 deletions
+15
View File
@@ -1,6 +1,7 @@
FROM python:3.12-slim-bookworm
ARG YUE2_COMMIT=9c6c4b349be978b06a9d0d958471a07a6cdeff4d
ARG YUE2_WEBUI_COMMIT=8fc05609bde5dcd345d7c6d57fff3da0839164c5
RUN apt-get update \
&& apt-get install -y --no-install-recommends ca-certificates git libsndfile1 \
@@ -10,6 +11,20 @@ RUN git clone https://github.com/multimodal-art-projection/YuE.git /opt/yue2 \
&& git -C /opt/yue2 checkout "${YUE2_COMMIT}" \
&& python -m pip install --no-cache-dir /opt/yue2
# The community console is intentionally layered onto the already verified,
# pinned YuE2 runtime. We use only its webui/ directory; its bundled YuE2 fork
# and Windows installers never become part of the Athena image.
RUN git clone https://github.com/Ladypoly/YuE2_WebUI.git /tmp/yue2-webui \
&& git -C /tmp/yue2-webui checkout "${YUE2_WEBUI_COMMIT}" \
&& cp -a /tmp/yue2-webui/webui /opt/yue2/webui \
&& cp /tmp/yue2-webui/LICENSE /opt/yue2/YuE2_WebUI-LICENSE \
&& python -m pip install --no-cache-dir -r /opt/yue2/webui/requirements.txt \
&& rm -rf /tmp/yue2-webui
COPY community-webui-patches /tmp/community-webui-patches
RUN python /tmp/community-webui-patches/patch_webui.py /opt/yue2/webui \
&& rm -rf /tmp/community-webui-patches
COPY ui /opt/yue2-playground
WORKDIR /workspace
+22 -8
View File
@@ -30,19 +30,33 @@ image is built, but no YuE2 container has been created or started.
The initial control request is a true empty-lyrics instrumental request. No
invented `[Instrumental]` lyrics marker is used.
## Temporary playground
## Community WebUI
The optional `playground` profile provides a small German web interface for
new-song generation. It lists persistent results, streams FLAC files with HTTP
range support and permits explicit deletion. It is bound only to Athena's
localhost on port 8014 and is not integrated into the profile router yet. The
web process itself does not load the model; a click on **Song generieren**
starts one exclusive offline generation job.
The `community-ui` profile runs Ladypoly's YuE2 WebUI at the pinned commit
`8fc05609bde5dcd345d7c6d57fff3da0839164c5`. Only the WebUI layer is copied
from that repository. Athena continues to use the verified official YuE2
`0.1.6` runtime and the existing model cache; the WebUI fork's bundled model
code and Windows installers are not used.
The UI is bound only to Athena's localhost on port 8014 and stores complete
takes below `/data/music/yue2`. Optional Windows-only installers for llama.cpp
and stable-diffusion.cpp are not part of the Athena setup. Manual composition,
generation, result playback, score editing and the take library work without
those optional components.
The small integration patch under `community-webui-patches/` fixes the
community release's missing `refreshArt()` function on Linux and permits the
native YuE2 empty-lyrics request for true instrumentals. It deliberately does
not modify the model runtime.
```sh
docker compose --profile playground up -d yue2-ui
docker compose --profile community-ui up -d yue2-ui
```
The original small German playground remains available as a stopped fallback
on localhost port 8016 through the `playground-fallback` profile. Do not run
both frontends concurrently because both can submit work to the same GPU.
## Manual test (only after GPU availability was checked)
From `/opt/mike-ai/yue2-3b` on Athena:
@@ -0,0 +1,83 @@
"""Small Linux integration fixes for the pinned community WebUI.
Keep these transformations explicit and fail the image build if upstream moves
the expected code. That prevents a future upstream update from silently
producing a half-patched console.
"""
from pathlib import Path
import sys
root = Path(sys.argv[1])
app_js = root / "static" / "app.js"
index_html = root / "static" / "index.html"
server_py = root / "server.py"
def replace_once(path: Path, old: str, new: str) -> None:
text = path.read_text(encoding="utf-8")
if text.count(old) != 1:
raise RuntimeError(f"expected exactly one patch marker in {path}: {old[:80]!r}")
path.write_text(text.replace(old, new, 1), encoding="utf-8")
# The published UI calls refreshArt() during startup, but does not define it.
# Athena does not install the Windows-only stable-diffusion.cpp helper, so show
# that state honestly and keep the optional controls inert instead of crashing
# the whole page.
art_marker = ''' $("artDirAdd").addEventListener("click", function () {
'''
art_fix = ''' function refreshArt() {
return api("/api/art/status").then(function (data) {
STATE.art = data;
var installed = !!data.installed;
var supported = !!data.supported;
$("artState").textContent = data.busy || (installed ? "installed" :
(supported ? "not installed" : "not available on Linux"));
$("artState").dataset.s = data.busy ? "busy" : (installed ? "ready" : "missing");
$("artInstall").disabled = !!data.busy || !supported;
$("artInstall").textContent = installed ? "Reinstall" : "Install";
$("setArtAuto").checked = !!data.auto;
$("setArtAuto").disabled = !installed;
$("setArtModel").innerHTML = (data.models || []).length
? data.models.map(function (m) {
return '<option value="' + escape(m.path) + '">' + escape(m.name || m.file) + '</option>';
}).join("")
: '<option value="">no art model available</option>';
if (data.selected) $("setArtModel").value = data.selected;
$("setArtModel").disabled = !installed;
$("artDir").disabled = !supported;
$("artDirAdd").disabled = !supported;
$("artDirs").textContent = supported
? ((data.dirs || []).length ? "Also scanning: " + data.dirs.join(" · ") : "No extra folders configured.")
: "The community release only provides the cover-art installer for Windows; song generation is unaffected.";
$("artCatalog").innerHTML = "";
return data;
}).catch(function (error) {
$("artState").textContent = "unavailable";
$("artInstall").disabled = true;
$("artDirs").textContent = error.message;
});
}
$("artDirAdd").addEventListener("click", function () {
'''
replace_once(app_js, art_marker, art_fix)
# YuE2 natively supports an empty lyric string for true instrumentals. The
# community server rejected that valid request even though the browser did not.
replace_once(
server_py,
''' if not body.style.strip() or not body.lyrics.strip():
raise HTTPException(400, "A style prompt and lyrics are both required")
''',
''' if not body.style.strip():
raise HTTPException(400, "A style prompt is required")
''',
)
replace_once(
index_html,
'''<span class="label">Lyrics <em>section tags on their own line</em></span>''',
'''<span class="label">Lyrics <em>section tags on their own line · leave empty for a true instrumental</em></span>''',
)
+45 -9
View File
@@ -5,6 +5,7 @@ services:
context: .
args:
YUE2_COMMIT: 9c6c4b349be978b06a9d0d958471a07a6cdeff4d
YUE2_WEBUI_COMMIT: 8fc05609bde5dcd345d7c6d57fff3da0839164c5
image: mike-ai/yue2:3b-0.1.6
restart: "no"
environment:
@@ -23,22 +24,63 @@ services:
capabilities: [gpu]
yue2-ui:
profiles: ["playground"]
profiles: ["community-ui"]
build:
context: .
args:
YUE2_COMMIT: 9c6c4b349be978b06a9d0d958471a07a6cdeff4d
YUE2_WEBUI_COMMIT: 8fc05609bde5dcd345d7c6d57fff3da0839164c5
image: mike-ai/yue2:3b-0.1.6
container_name: mike-ai-yue2-playground
restart: "no"
entrypoint: ["python", "/opt/yue2/webui/server.py"]
environment:
NVIDIA_VISIBLE_DEVICES: "GPU-8ad38c6c-5a01-9d8e-1dfa-ed662ad78fbe"
NVIDIA_DRIVER_CAPABILITIES: compute,utility
YUE2_HOST: "0.0.0.0"
YUE2_PORT: "8014"
YUE2_OUTPUTS: "/workspace/runs"
HF_HUB_OFFLINE: "1"
TRANSFORMERS_OFFLINE: "1"
ports:
- "127.0.0.1:8014:8014"
volumes:
- /data/models/yue2:/opt/yue2/models:ro
- /data/music/yue2:/workspace/runs
deploy:
resources:
reservations:
devices:
- driver: nvidia
device_ids: ["GPU-8ad38c6c-5a01-9d8e-1dfa-ed662ad78fbe"]
capabilities: [gpu]
healthcheck:
test: ["CMD", "python", "-c", "import urllib.request; urllib.request.urlopen('http://127.0.0.1:8014/api/state', timeout=2)"]
interval: 5s
timeout: 3s
retries: 12
start_period: 5s
# Kept as a deliberately non-default fallback until the community console
# has completed a real generation on Athena.
yue2-playground-fallback:
profiles: ["playground-fallback"]
build:
context: .
args:
YUE2_COMMIT: 9c6c4b349be978b06a9d0d958471a07a6cdeff4d
YUE2_WEBUI_COMMIT: 8fc05609bde5dcd345d7c6d57fff3da0839164c5
image: mike-ai/yue2:3b-0.1.6
container_name: mike-ai-yue2-playground-fallback
restart: "no"
entrypoint: ["python", "/opt/yue2-playground/server.py"]
environment:
NVIDIA_VISIBLE_DEVICES: "GPU-8ad38c6c-5a01-9d8e-1dfa-ed662ad78fbe"
NVIDIA_DRIVER_CAPABILITIES: compute,utility
YUE2_UI_HOST: "0.0.0.0"
YUE2_UI_PORT: "8014"
YUE2_UI_PORT: "8016"
ports:
- "127.0.0.1:8014:8014"
- "127.0.0.1:8016:8016"
volumes:
- /data/models/yue2:/workspace/models:ro
- /data/music/yue2:/workspace/runs
@@ -49,9 +91,3 @@ services:
- driver: nvidia
device_ids: ["GPU-8ad38c6c-5a01-9d8e-1dfa-ed662ad78fbe"]
capabilities: [gpu]
healthcheck:
test: ["CMD", "python", "-c", "import urllib.request; urllib.request.urlopen('http://127.0.0.1:8014/health', timeout=2)"]
interval: 5s
timeout: 3s
retries: 12
start_period: 5s