Spaces:
Running on Zero
fix(lora): point manifest at the actually-published ACE-Step LoRAs
Browse filesThe plan / D2 manifest used placeholder HF paths for RapMachine,
Chinese Rap, Lyric2Vocal, Text2Samples — three of which were
announced in the ACE-Step roadmap but never published as standalone
HuggingFace repos. Clicking any preset chip surfaced a 404 toast
from huggingface_hub.
What actually exists today (verified via huggingface.co/ACE-Step):
- ACE-Step/ACE-Step-v1-chinese-rap-LoRA
filename: pytorch_lora_weights.safetensors (524 MB)
- ACE-Step/ACE-Step-v1.5-chinese-new-year-LoRA
filename: adapter_model.safetensors (88 MB)
Note that the filenames differ between the two repos (Chinese Rap
uses the diffusers/PEFT pytorch_lora_weights name, New Year uses
the newer adapter_model name) — that's why manifest entries carry
an explicit ``filename`` field per preset.
Manifest pared to those two real LoRAs. ui.py's preset radio now
reads choices dynamically from lora_stack.load_presets() so future
manifest changes don't require code edits. Tests updated to verify
schema + the ACE-Step/ org guard instead of a hardcoded count.
For everything else (RapMachine when/if released, Text2Samples,
community LoRAs, the user's own psytrance v2), the Custom Upload
path in the LoRA accordion still works as before.
Commit fixes the user's 404 reproduced on the live app right after
M2 shipped.
- presets/manifest.json +6 -20
- tests/test_lora_presets.py +24 -5
- ui.py +6 -7
|
@@ -1,30 +1,16 @@
|
|
| 1 |
[
|
| 2 |
{
|
| 3 |
-
"name": "
|
| 4 |
-
"hf_id": "ACE-Step/ACE-Step-v1-
|
| 5 |
-
"filename": "
|
| 6 |
"kind": "genre",
|
| 7 |
"default_scale": 0.85
|
| 8 |
},
|
| 9 |
{
|
| 10 |
-
"name": "Chinese
|
| 11 |
-
"hf_id": "ACE-Step/ACE-Step-v1-
|
| 12 |
-
"filename": "
|
| 13 |
"kind": "genre",
|
| 14 |
"default_scale": 0.85
|
| 15 |
-
},
|
| 16 |
-
{
|
| 17 |
-
"name": "Lyric2Vocal",
|
| 18 |
-
"hf_id": "ACE-Step/ACE-Step-v1-Lyric2Vocal-LoRA",
|
| 19 |
-
"filename": "Lyric2Vocal.safetensors",
|
| 20 |
-
"kind": "voice",
|
| 21 |
-
"default_scale": 0.70
|
| 22 |
-
},
|
| 23 |
-
{
|
| 24 |
-
"name": "Text2Samples",
|
| 25 |
-
"hf_id": "ACE-Step/ACE-Step-v1-Text2Samples-LoRA",
|
| 26 |
-
"filename": "Text2Samples.safetensors",
|
| 27 |
-
"kind": "instrumental",
|
| 28 |
-
"default_scale": 0.80
|
| 29 |
}
|
| 30 |
]
|
|
|
|
| 1 |
[
|
| 2 |
{
|
| 3 |
+
"name": "Chinese Rap",
|
| 4 |
+
"hf_id": "ACE-Step/ACE-Step-v1-chinese-rap-LoRA",
|
| 5 |
+
"filename": "pytorch_lora_weights.safetensors",
|
| 6 |
"kind": "genre",
|
| 7 |
"default_scale": 0.85
|
| 8 |
},
|
| 9 |
{
|
| 10 |
+
"name": "Chinese New Year",
|
| 11 |
+
"hf_id": "ACE-Step/ACE-Step-v1.5-chinese-new-year-LoRA",
|
| 12 |
+
"filename": "adapter_model.safetensors",
|
| 13 |
"kind": "genre",
|
| 14 |
"default_scale": 0.85
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 15 |
}
|
| 16 |
]
|
|
@@ -1,16 +1,23 @@
|
|
| 1 |
-
"""L1 tests for the LoRA preset registry.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2 |
|
| 3 |
from __future__ import annotations
|
| 4 |
|
| 5 |
import lora_stack as ls
|
| 6 |
|
| 7 |
|
| 8 |
-
def
|
| 9 |
presets = ls.load_presets()
|
| 10 |
-
assert len(presets) =
|
|
|
|
|
|
|
|
|
|
| 11 |
names = [p["name"] for p in presets]
|
| 12 |
-
assert "
|
| 13 |
-
assert "Lyric2Vocal" in names
|
| 14 |
|
| 15 |
|
| 16 |
def test_preset_has_required_fields():
|
|
@@ -18,5 +25,17 @@ def test_preset_has_required_fields():
|
|
| 18 |
for p in presets:
|
| 19 |
assert "name" in p
|
| 20 |
assert "hf_id" in p
|
|
|
|
| 21 |
assert "default_scale" in p
|
| 22 |
assert 0 <= p["default_scale"] <= 1.5
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""L1 tests for the LoRA preset registry.
|
| 2 |
+
|
| 3 |
+
The preset list itself can grow / shrink as ACE-Step publishes (or
|
| 4 |
+
removes) official LoRAs on HuggingFace. These tests verify the
|
| 5 |
+
manifest schema is correct, not the exact preset count.
|
| 6 |
+
"""
|
| 7 |
|
| 8 |
from __future__ import annotations
|
| 9 |
|
| 10 |
import lora_stack as ls
|
| 11 |
|
| 12 |
|
| 13 |
+
def test_load_presets_returns_at_least_one():
|
| 14 |
presets = ls.load_presets()
|
| 15 |
+
assert len(presets) >= 1
|
| 16 |
+
# As of 2026-05, ACE-Step's chinese-rap is the only LoRA the org
|
| 17 |
+
# has actually published. If they later add RapMachine etc., the
|
| 18 |
+
# manifest is updated and this test still passes.
|
| 19 |
names = [p["name"] for p in presets]
|
| 20 |
+
assert "Chinese Rap" in names
|
|
|
|
| 21 |
|
| 22 |
|
| 23 |
def test_preset_has_required_fields():
|
|
|
|
| 25 |
for p in presets:
|
| 26 |
assert "name" in p
|
| 27 |
assert "hf_id" in p
|
| 28 |
+
assert "filename" in p
|
| 29 |
assert "default_scale" in p
|
| 30 |
assert 0 <= p["default_scale"] <= 1.5
|
| 31 |
+
|
| 32 |
+
|
| 33 |
+
def test_preset_hf_id_is_under_ace_step_org():
|
| 34 |
+
"""Every shipped preset must live under the official ACE-Step org so
|
| 35 |
+
we can trust the upstream quality. Community LoRAs go via the
|
| 36 |
+
custom-upload path, not the preset chip row."""
|
| 37 |
+
presets = ls.load_presets()
|
| 38 |
+
for p in presets:
|
| 39 |
+
assert p["hf_id"].startswith("ACE-Step/"), (
|
| 40 |
+
f"Preset {p['name']!r} hf_id {p['hf_id']!r} is not under the official ACE-Step org"
|
| 41 |
+
)
|
|
@@ -12,6 +12,7 @@ from __future__ import annotations
|
|
| 12 |
|
| 13 |
import gradio as gr
|
| 14 |
|
|
|
|
| 15 |
import tooltips
|
| 16 |
|
| 17 |
|
|
@@ -76,14 +77,12 @@ def build_generate_tab() -> dict[str, gr.components.Component]:
|
|
| 76 |
"replaces the active LoRA._",
|
| 77 |
elem_classes=["ams-lora-note"],
|
| 78 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
| 79 |
components["lora_preset"] = gr.Radio(
|
| 80 |
-
choices=
|
| 81 |
-
"None",
|
| 82 |
-
"RapMachine",
|
| 83 |
-
"Chinese Rap",
|
| 84 |
-
"Lyric2Vocal",
|
| 85 |
-
"Text2Samples",
|
| 86 |
-
],
|
| 87 |
value="None",
|
| 88 |
label="Preset",
|
| 89 |
elem_classes=["ams-lora-preset"],
|
|
|
|
| 12 |
|
| 13 |
import gradio as gr
|
| 14 |
|
| 15 |
+
import lora_stack
|
| 16 |
import tooltips
|
| 17 |
|
| 18 |
|
|
|
|
| 77 |
"replaces the active LoRA._",
|
| 78 |
elem_classes=["ams-lora-note"],
|
| 79 |
)
|
| 80 |
+
# Preset choices are read from presets/manifest.json so the
|
| 81 |
+
# radio stays in sync with whatever official ACE-Step LoRAs
|
| 82 |
+
# are actually published on HuggingFace.
|
| 83 |
+
_preset_names = ["None"] + [p["name"] for p in lora_stack.load_presets()]
|
| 84 |
components["lora_preset"] = gr.Radio(
|
| 85 |
+
choices=_preset_names,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 86 |
value="None",
|
| 87 |
label="Preset",
|
| 88 |
elem_classes=["ams-lora-preset"],
|