techfreakworm commited on
Commit
24b2854
·
unverified ·
1 Parent(s): a1d8cb5

fix(lora): point manifest at the actually-published ACE-Step LoRAs

Browse files

The 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.

Files changed (3) hide show
  1. presets/manifest.json +6 -20
  2. tests/test_lora_presets.py +24 -5
  3. ui.py +6 -7
presets/manifest.json CHANGED
@@ -1,30 +1,16 @@
1
  [
2
  {
3
- "name": "RapMachine",
4
- "hf_id": "ACE-Step/ACE-Step-v1-RapMachine-LoRA",
5
- "filename": "RapMachine.safetensors",
6
  "kind": "genre",
7
  "default_scale": 0.85
8
  },
9
  {
10
- "name": "Chinese Rap",
11
- "hf_id": "ACE-Step/ACE-Step-v1-Chinese-Rap-LoRA",
12
- "filename": "ChineseRap.safetensors",
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
  ]
tests/test_lora_presets.py CHANGED
@@ -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 test_load_presets_returns_four():
9
  presets = ls.load_presets()
10
- assert len(presets) == 4
 
 
 
11
  names = [p["name"] for p in presets]
12
- assert "RapMachine" in names
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
+ )
ui.py CHANGED
@@ -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"],