Spaces:
Running on Zero
Running on Zero
feat(lora): add preset registry with hf-download helper
Browse files- lora_stack.py +29 -0
- presets/manifest.json +30 -0
- tests/test_lora_presets.py +22 -0
lora_stack.py
CHANGED
|
@@ -120,3 +120,32 @@ def sniff(path: Path | str) -> LoRAInfo:
|
|
| 120 |
diagnostic=diagnostic,
|
| 121 |
file_size=file_size,
|
| 122 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 120 |
diagnostic=diagnostic,
|
| 121 |
file_size=file_size,
|
| 122 |
)
|
| 123 |
+
|
| 124 |
+
|
| 125 |
+
_PRESETS_PATH = Path(__file__).resolve().parent / "presets" / "manifest.json"
|
| 126 |
+
|
| 127 |
+
|
| 128 |
+
def load_presets() -> list[dict]:
|
| 129 |
+
"""Load the bundled LoRA preset manifest."""
|
| 130 |
+
return json.loads(_PRESETS_PATH.read_text())
|
| 131 |
+
|
| 132 |
+
|
| 133 |
+
def download_preset(name: str) -> Path:
|
| 134 |
+
"""Download a preset LoRA from HF if not already cached.
|
| 135 |
+
|
| 136 |
+
Returns the local path on success. Raises LoRAValidationError if the
|
| 137 |
+
preset name is unknown OR the HF download fails (network, 404, etc.).
|
| 138 |
+
"""
|
| 139 |
+
from huggingface_hub import hf_hub_download
|
| 140 |
+
from huggingface_hub.utils import HfHubHTTPError
|
| 141 |
+
|
| 142 |
+
for p in load_presets():
|
| 143 |
+
if p["name"] == name:
|
| 144 |
+
try:
|
| 145 |
+
local = hf_hub_download(repo_id=p["hf_id"], filename=p["filename"])
|
| 146 |
+
return Path(local)
|
| 147 |
+
except HfHubHTTPError as e:
|
| 148 |
+
raise LoRAValidationError(
|
| 149 |
+
f"Could not download preset {name!r} from {p['hf_id']!r}: {e}"
|
| 150 |
+
) from e
|
| 151 |
+
raise LoRAValidationError(f"Unknown preset: {name}")
|
presets/manifest.json
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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 |
+
]
|
tests/test_lora_presets.py
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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():
|
| 17 |
+
presets = ls.load_presets()
|
| 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
|