Nekochu commited on
Commit
c5c37c1
·
verified ·
1 Parent(s): 3c29213

Upload folder using huggingface_hub

Browse files
Files changed (4) hide show
  1. .gitignore +1 -0
  2. README.md +11 -6
  3. app.py +556 -0
  4. requirements.txt +17 -0
.gitignore ADDED
@@ -0,0 +1 @@
 
 
1
+ __pycache__/
README.md CHANGED
@@ -1,12 +1,17 @@
1
  ---
2
- title: ACE Step CPU
3
- emoji: 🐢
4
- colorFrom: purple
5
- colorTo: blue
6
  sdk: gradio
7
- sdk_version: 6.10.0
8
  app_file: app.py
9
  pinned: false
 
 
 
10
  ---
11
 
12
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
1
  ---
2
+ title: ACE-Step CPU
3
+ emoji: 🎵
4
+ colorFrom: blue
5
+ colorTo: purple
6
  sdk: gradio
7
+ sdk_version: 5.50.0
8
  app_file: app.py
9
  pinned: false
10
+ license: mit
11
+ startup_duration_timeout: 3600
12
+ python_version: 3.11
13
  ---
14
 
15
+ # ACE-Step 1.5 Music Generation (CPU)
16
+
17
+ Generate music from text descriptions and train LoRA adapters, all on CPU.
app.py ADDED
@@ -0,0 +1,556 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ ACE-Step 1.5 Music Generation + LoRA Training (CPU)
3
+ Runs on HuggingFace Spaces free CPU tier.
4
+ """
5
+
6
+ import os
7
+ import sys
8
+ import gc
9
+ import time
10
+ import tempfile
11
+ import shutil
12
+ from pathlib import Path
13
+
14
+ # Force CPU, no CUDA
15
+ os.environ["CUDA_VISIBLE_DEVICES"] = ""
16
+ os.environ["TOKENIZERS_PARALLELISM"] = "false"
17
+ os.environ["TORCHAUDIO_USE_BACKEND"] = "ffmpeg"
18
+ os.environ["ACESTEP_DISABLE_TQDM"] = "1"
19
+
20
+ import torch
21
+ torch.set_default_dtype(torch.float32)
22
+
23
+ import numpy as np
24
+ import gradio as gr
25
+ import soundfile as sf
26
+
27
+ # ---------------------------------------------------------------------------
28
+ # Clone ACE-Step repo if not present
29
+ # ---------------------------------------------------------------------------
30
+ REPO_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), "ace-step-source")
31
+ if not os.path.isdir(REPO_DIR):
32
+ print("[Setup] Cloning ACE-Step 1.5 repository...")
33
+ os.system(f"git clone --depth 1 https://github.com/ace-step/ACE-Step-1.5 {REPO_DIR}")
34
+
35
+ # Add repo to path
36
+ if REPO_DIR not in sys.path:
37
+ sys.path.insert(0, REPO_DIR)
38
+
39
+ # ---------------------------------------------------------------------------
40
+ # Lazy-load handler (downloads model on first use)
41
+ # ---------------------------------------------------------------------------
42
+ _dit_handler = None
43
+ _init_status = None
44
+
45
+ CHECKPOINT_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), "checkpoints")
46
+ LORA_OUTPUT_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), "lora_output")
47
+ CURRENT_LM_SIZE = "1.7B" # Track current LM size
48
+
49
+
50
+ def get_handler():
51
+ """Get or initialize the ACE-Step handler (lazy, first call downloads model)."""
52
+ global _dit_handler, _init_status
53
+
54
+ if _dit_handler is not None and _dit_handler.model is not None:
55
+ return _dit_handler, _init_status
56
+
57
+ from acestep.handler import AceStepHandler
58
+ from acestep.model_downloader import ensure_main_model
59
+
60
+ print("[Init] Ensuring model is downloaded...")
61
+ success, msg = ensure_main_model(
62
+ checkpoints_dir=Path(CHECKPOINT_DIR),
63
+ prefer_source="huggingface",
64
+ )
65
+ print(f"[Init] Model download: {msg}")
66
+
67
+ if not success:
68
+ _init_status = f"Model download failed: {msg}"
69
+ return None, _init_status
70
+
71
+ _dit_handler = AceStepHandler()
72
+ project_root = os.path.dirname(os.path.abspath(__file__))
73
+
74
+ os.environ["ACESTEP_PROJECT_ROOT"] = project_root
75
+
76
+ status, ok = _dit_handler.initialize_service(
77
+ project_root=project_root,
78
+ config_path="acestep-v15-turbo",
79
+ device="cpu",
80
+ use_flash_attention=False,
81
+ compile_model=False,
82
+ offload_to_cpu=False,
83
+ offload_dit_to_cpu=False,
84
+ quantization=None,
85
+ use_mlx_dit=False,
86
+ )
87
+
88
+ _init_status = status
89
+ if not ok:
90
+ print(f"[Init] FAILED: {status}")
91
+ _dit_handler = None
92
+ return None, _init_status
93
+
94
+ # Force float32 on everything
95
+ _dit_handler.dtype = torch.float32
96
+ if _dit_handler.model is not None:
97
+ _dit_handler.model = _dit_handler.model.float().to("cpu")
98
+ if _dit_handler.vae is not None:
99
+ _dit_handler.vae = _dit_handler.vae.float().to("cpu")
100
+ if _dit_handler.text_encoder is not None:
101
+ _dit_handler.text_encoder = _dit_handler.text_encoder.float().to("cpu")
102
+
103
+ print(f"[Init] OK: {status}")
104
+ return _dit_handler, _init_status
105
+
106
+
107
+ def get_trained_loras():
108
+ """List available trained LoRAs."""
109
+ loras = ["None (no LoRA)"]
110
+ if os.path.isdir(LORA_OUTPUT_DIR):
111
+ for name in sorted(os.listdir(LORA_OUTPUT_DIR)):
112
+ lora_dir = os.path.join(LORA_OUTPUT_DIR, name)
113
+ if os.path.isdir(lora_dir):
114
+ # Check for any .safetensors or .pt files
115
+ for f in os.listdir(lora_dir):
116
+ if f.endswith((".safetensors", ".pt", ".bin")):
117
+ loras.append(name)
118
+ break
119
+ return loras
120
+
121
+
122
+ # ---------------------------------------------------------------------------
123
+ # Generate Tab
124
+ # ---------------------------------------------------------------------------
125
+ def generate_music(
126
+ caption,
127
+ lyrics,
128
+ instrumental,
129
+ bpm,
130
+ duration,
131
+ seed,
132
+ inference_steps,
133
+ lm_size,
134
+ lora_choice,
135
+ progress=gr.Progress(track_tqdm=True),
136
+ ):
137
+ """Generate music from text prompt on CPU."""
138
+ t0 = time.time()
139
+
140
+ handler, status = get_handler()
141
+ if handler is None:
142
+ return None, f"Model not ready: {status}"
143
+
144
+ # Apply trained LoRA if selected
145
+ if lora_choice and lora_choice != "None (no LoRA)":
146
+ lora_dir = os.path.join(LORA_OUTPUT_DIR, lora_choice)
147
+ if os.path.isdir(lora_dir):
148
+ try:
149
+ handler.load_lora(lora_dir)
150
+ print(f"[Gen] Loaded LoRA: {lora_choice}")
151
+ except Exception as e:
152
+ print(f"[Gen] LoRA load failed: {e}")
153
+
154
+ # TODO: LM size switching requires re-downloading the LM model
155
+ # For now, log the selected size
156
+ if lm_size != CURRENT_LM_SIZE:
157
+ print(f"[Gen] LM size {lm_size} requested (current: {CURRENT_LM_SIZE})")
158
+
159
+ # Clamp values
160
+ duration = max(10, min(float(duration), 120)) # cap at 120s for CPU
161
+ inference_steps = max(1, min(int(inference_steps), 32))
162
+ bpm_val = int(bpm) if bpm and int(bpm) > 0 else None
163
+ seed_val = int(seed) if seed and int(seed) >= 0 else -1
164
+
165
+ try:
166
+ result = handler.generate_music(
167
+ captions=caption or "upbeat electronic dance music",
168
+ lyrics=lyrics or "[Instrumental]",
169
+ bpm=bpm_val,
170
+ audio_duration=duration,
171
+ inference_steps=inference_steps,
172
+ guidance_scale=1.0, # turbo model, no CFG needed
173
+ use_random_seed=(seed_val < 0),
174
+ seed=str(seed_val) if seed_val >= 0 else "",
175
+ batch_size=1,
176
+ task_type="text2music",
177
+ vocal_language="en",
178
+ shift=1.0,
179
+ infer_method="ode",
180
+ progress=None,
181
+ )
182
+
183
+ elapsed = time.time() - t0
184
+
185
+ if not result.get("success", False):
186
+ error = result.get("error", result.get("status_message", "Unknown error"))
187
+ return None, f"Generation failed: {error}"
188
+
189
+ audios = result.get("audios", [])
190
+ if not audios:
191
+ return None, "No audio generated"
192
+
193
+ audio_tensor = audios[0].get("tensor")
194
+ sample_rate = audios[0].get("sample_rate", 48000)
195
+
196
+ if audio_tensor is None:
197
+ return None, "Audio tensor is None"
198
+
199
+ # Convert to numpy
200
+ if isinstance(audio_tensor, torch.Tensor):
201
+ audio_np = audio_tensor.cpu().float().numpy()
202
+ else:
203
+ audio_np = np.array(audio_tensor, dtype=np.float32)
204
+
205
+ # Save to temp file
206
+ tmp = tempfile.NamedTemporaryFile(suffix=".wav", delete=False)
207
+ # soundfile expects (samples, channels)
208
+ if audio_np.ndim == 2:
209
+ audio_np = audio_np.T # (channels, samples) -> (samples, channels)
210
+ sf.write(tmp.name, audio_np, sample_rate)
211
+
212
+ status_msg = (
213
+ f"Generated in {elapsed:.1f}s | "
214
+ f"Duration: {duration}s | Steps: {inference_steps} | "
215
+ f"Seed: {seed_val}"
216
+ )
217
+ return tmp.name, status_msg
218
+
219
+ except Exception as e:
220
+ import traceback
221
+ return None, f"Error: {e}\n{traceback.format_exc()}"
222
+ finally:
223
+ gc.collect()
224
+
225
+
226
+ # ---------------------------------------------------------------------------
227
+ # Train LoRA Tab
228
+ # ---------------------------------------------------------------------------
229
+ def train_lora(
230
+ audio_files,
231
+ lora_name,
232
+ epochs,
233
+ learning_rate,
234
+ lora_rank,
235
+ progress=gr.Progress(track_tqdm=True),
236
+ ):
237
+ """Train a LoRA adapter from uploaded audio files on CPU."""
238
+ if not audio_files:
239
+ return "No audio files uploaded."
240
+
241
+ handler, status = get_handler()
242
+ if handler is None:
243
+ return f"Model not ready: {status}"
244
+
245
+ lora_name = lora_name.strip() or "my_lora"
246
+ epochs = max(1, min(int(epochs), 10))
247
+ lr = float(learning_rate)
248
+ rank = max(1, min(int(lora_rank), 64))
249
+
250
+ output_dir = os.path.join(
251
+ os.path.dirname(os.path.abspath(__file__)), "lora_output", lora_name
252
+ )
253
+ os.makedirs(output_dir, exist_ok=True)
254
+
255
+ # Create a temp directory for audio files
256
+ audio_dir = os.path.join(output_dir, "audio_input")
257
+ os.makedirs(audio_dir, exist_ok=True)
258
+
259
+ # Copy uploaded files
260
+ for f in audio_files:
261
+ src = f.name if hasattr(f, "name") else str(f)
262
+ dst = os.path.join(audio_dir, os.path.basename(src))
263
+ shutil.copy2(src, dst)
264
+
265
+ log_lines = []
266
+ log_lines.append(f"LoRA Training: '{lora_name}'")
267
+ log_lines.append(f"Audio files: {len(audio_files)}")
268
+ log_lines.append(f"Epochs: {epochs}, LR: {lr}, Rank: {rank}")
269
+ log_lines.append(f"Output: {output_dir}")
270
+ log_lines.append("")
271
+
272
+ try:
273
+ # Preprocessing step: encode audio files to tensors
274
+ log_lines.append("[Step 1/2] Preprocessing audio files...")
275
+
276
+ tensor_dir = os.path.join(output_dir, "preprocessed_tensors")
277
+ os.makedirs(tensor_dir, exist_ok=True)
278
+
279
+ from acestep.training_v2.preprocess import preprocess_audio_files
280
+
281
+ preprocess_result = preprocess_audio_files(
282
+ audio_dir=audio_dir,
283
+ output_dir=tensor_dir,
284
+ checkpoint_dir=CHECKPOINT_DIR,
285
+ variant="turbo",
286
+ max_duration=60.0,
287
+ device="cpu",
288
+ precision="float32",
289
+ )
290
+
291
+ processed = preprocess_result.get("processed", 0)
292
+ total = preprocess_result.get("total", 0)
293
+ failed = preprocess_result.get("failed", 0)
294
+ log_lines.append(f" Preprocessed: {processed}/{total} (failed: {failed})")
295
+
296
+ if processed == 0:
297
+ log_lines.append("ERROR: No files were preprocessed successfully.")
298
+ return "\n".join(log_lines)
299
+
300
+ # Training step
301
+ log_lines.append("[Step 2/2] Training LoRA adapter...")
302
+
303
+ from acestep.training_v2.model_loader import load_decoder_for_training
304
+ from acestep.training_v2.trainer_fixed import FixedLoRATrainer
305
+ from acestep.training_v2.fixed_lora_module import AdapterConfig
306
+ from acestep.training_v2.configs import TrainingConfigV2
307
+
308
+ # Load model for training
309
+ model = load_decoder_for_training(
310
+ checkpoint_dir=CHECKPOINT_DIR,
311
+ variant="turbo",
312
+ device="cpu",
313
+ precision="float32",
314
+ )
315
+
316
+ adapter_cfg = AdapterConfig(
317
+ rank=rank,
318
+ alpha=rank,
319
+ dropout=0.0,
320
+ adapter_type="lora",
321
+ )
322
+
323
+ train_cfg = TrainingConfigV2(
324
+ checkpoint_dir=CHECKPOINT_DIR,
325
+ model_variant="turbo",
326
+ dataset_dir=tensor_dir,
327
+ output_dir=output_dir,
328
+ max_epochs=epochs,
329
+ batch_size=1,
330
+ learning_rate=lr,
331
+ device="cpu",
332
+ precision="float32",
333
+ seed=42,
334
+ num_workers=0,
335
+ pin_memory=False,
336
+ )
337
+
338
+ trainer = FixedLoRATrainer(model, adapter_cfg, train_cfg)
339
+
340
+ step_count = 0
341
+ last_loss = 0.0
342
+ for update in trainer.train():
343
+ if hasattr(update, "step"):
344
+ step_count = update.step
345
+ last_loss = update.loss
346
+ if step_count % 5 == 0:
347
+ log_lines.append(f" Step {step_count}: loss={last_loss:.4f}")
348
+ elif isinstance(update, tuple) and len(update) >= 2:
349
+ step_count = update[0]
350
+ last_loss = update[1]
351
+ if step_count % 5 == 0:
352
+ log_lines.append(f" Step {step_count}: loss={last_loss:.4f}")
353
+
354
+ log_lines.append(f"Training complete! Final step: {step_count}, loss: {last_loss:.4f}")
355
+ log_lines.append(f"LoRA saved to: {output_dir}")
356
+
357
+ # Cleanup
358
+ del model, trainer
359
+ gc.collect()
360
+
361
+ except Exception as e:
362
+ import traceback
363
+ log_lines.append(f"ERROR: {e}")
364
+ log_lines.append(traceback.format_exc())
365
+
366
+ return "\n".join(log_lines)
367
+
368
+
369
+ # ---------------------------------------------------------------------------
370
+ # Gradio UI
371
+ # ---------------------------------------------------------------------------
372
+ def build_ui():
373
+ theme = gr.themes.Default()
374
+ try:
375
+ theme = gr.Theme.from_hub("NoCrypt/miku")
376
+ except Exception:
377
+ pass
378
+
379
+ with gr.Blocks(
380
+ theme=theme,
381
+ title="ACE-Step 1.5 CPU",
382
+ css="""
383
+ .main-title { text-align: center; margin-bottom: 0.5em; }
384
+ .status-box { font-family: monospace; font-size: 0.85em; }
385
+ """,
386
+ ) as demo:
387
+ gr.HTML("<h1 class='main-title'>ACE-Step 1.5 Music Generation (CPU)</h1>")
388
+ gr.HTML(
389
+ "<p style='text-align:center;'>Text-to-music generation and LoRA training, "
390
+ "running entirely on CPU. Based on "
391
+ "<a href='https://github.com/ace-step/ACE-Step-1.5'>ACE-Step 1.5</a>.</p>"
392
+ )
393
+
394
+ with gr.Tabs():
395
+ # ---- Generate Tab ----
396
+ with gr.Tab("Generate Music"):
397
+ with gr.Row():
398
+ with gr.Column(scale=2):
399
+ caption_input = gr.Textbox(
400
+ label="Music Description",
401
+ placeholder="e.g. upbeat electronic dance music, 120 BPM",
402
+ lines=3,
403
+ value="upbeat electronic dance music, energetic synth leads, driving bassline",
404
+ )
405
+ lyrics_input = gr.Textbox(
406
+ label="Lyrics (use [Instrumental] for no vocals)",
407
+ placeholder="[Instrumental]",
408
+ lines=3,
409
+ value="[Instrumental]",
410
+ )
411
+ instrumental_cb = gr.Checkbox(
412
+ label="Instrumental (no vocals)",
413
+ value=True,
414
+ )
415
+ with gr.Column(scale=1):
416
+ bpm_input = gr.Number(
417
+ label="BPM (0 = auto)",
418
+ value=120,
419
+ minimum=0,
420
+ maximum=300,
421
+ )
422
+ duration_input = gr.Slider(
423
+ label="Duration (seconds)",
424
+ minimum=10,
425
+ maximum=120,
426
+ value=10,
427
+ step=5,
428
+ )
429
+ seed_input = gr.Number(
430
+ label="Seed (-1 = random)",
431
+ value=-1,
432
+ )
433
+ steps_input = gr.Slider(
434
+ label="Inference Steps (fewer = faster)",
435
+ minimum=1,
436
+ maximum=32,
437
+ value=8,
438
+ step=1,
439
+ )
440
+ lm_size_input = gr.Dropdown(
441
+ label="LM Model Size",
442
+ choices=["0.6B (fast)", "1.7B (balanced)", "4B (best quality)"],
443
+ value="1.7B (balanced)",
444
+ info="Language model for music understanding",
445
+ )
446
+ lora_select = gr.Dropdown(
447
+ label="Use Trained LoRA",
448
+ choices=get_trained_loras(),
449
+ value="None (no LoRA)",
450
+ info="Select a LoRA you trained to apply it",
451
+ )
452
+
453
+ generate_btn = gr.Button("Generate Music", variant="primary")
454
+
455
+ with gr.Row():
456
+ audio_output = gr.Audio(
457
+ label="Generated Audio",
458
+ type="filepath",
459
+ )
460
+ gen_status = gr.Textbox(
461
+ label="Status",
462
+ interactive=False,
463
+ elem_classes="status-box",
464
+ )
465
+
466
+ generate_btn.click(
467
+ fn=generate_music,
468
+ inputs=[
469
+ caption_input,
470
+ lyrics_input,
471
+ instrumental_cb,
472
+ bpm_input,
473
+ duration_input,
474
+ seed_input,
475
+ steps_input,
476
+ lm_size_input,
477
+ lora_select,
478
+ ],
479
+ outputs=[audio_output, gen_status],
480
+ )
481
+
482
+ # ---- Train LoRA Tab ----
483
+ with gr.Tab("Train LoRA"):
484
+ gr.Markdown(
485
+ "### Train a LoRA adapter on your audio files\n"
486
+ "Upload WAV/MP3/FLAC files to fine-tune the model. "
487
+ "Training runs on CPU so keep epochs low and files short."
488
+ )
489
+ with gr.Row():
490
+ with gr.Column():
491
+ audio_upload = gr.File(
492
+ label="Upload Audio Files",
493
+ file_count="multiple",
494
+ file_types=["audio"],
495
+ )
496
+ lora_name_input = gr.Textbox(
497
+ label="LoRA Name",
498
+ value="my_lora",
499
+ )
500
+ with gr.Column():
501
+ epochs_input = gr.Slider(
502
+ label="Epochs",
503
+ minimum=1,
504
+ maximum=10,
505
+ value=1,
506
+ step=1,
507
+ )
508
+ lr_input = gr.Number(
509
+ label="Learning Rate",
510
+ value=1e-4,
511
+ )
512
+ rank_input = gr.Slider(
513
+ label="LoRA Rank",
514
+ minimum=1,
515
+ maximum=64,
516
+ value=8,
517
+ step=1,
518
+ )
519
+
520
+ train_btn = gr.Button("Start Training", variant="primary")
521
+ train_log = gr.Textbox(
522
+ label="Training Log",
523
+ interactive=False,
524
+ lines=15,
525
+ elem_classes="status-box",
526
+ )
527
+
528
+ def train_and_refresh(*args):
529
+ log = train_lora(*args)
530
+ new_loras = get_trained_loras()
531
+ return log, gr.update(choices=new_loras, value=new_loras[-1] if len(new_loras) > 1 else "None (no LoRA)")
532
+
533
+ train_btn.click(
534
+ fn=train_and_refresh,
535
+ inputs=[
536
+ audio_upload,
537
+ lora_name_input,
538
+ epochs_input,
539
+ lr_input,
540
+ rank_input,
541
+ ],
542
+ outputs=[train_log, lora_select],
543
+ )
544
+
545
+ return demo
546
+
547
+
548
+ if __name__ == "__main__":
549
+ demo = build_ui()
550
+ demo.launch(
551
+ server_name="0.0.0.0",
552
+ server_port=7860,
553
+ show_error=True,
554
+ ssr_mode=False,
555
+ )
556
+
requirements.txt ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # ACE-Step CPU requirements
2
+ torch
3
+ torchaudio
4
+ torchvision
5
+ safetensors
6
+ transformers>=4.51.0,<4.58.0
7
+ diffusers
8
+ matplotlib>=3.7.5
9
+ scipy>=1.10.1
10
+ soundfile>=0.13.1
11
+ loguru>=0.7.3
12
+ einops>=0.8.1
13
+ accelerate>=1.12.0
14
+ numba>=0.63.1
15
+ vector-quantize-pytorch>=1.27.15
16
+ peft>=0.18.0
17
+ huggingface_hub