Spaces:
Runtime error
Runtime error
Update app.py
Browse files
app.py
CHANGED
|
@@ -107,6 +107,9 @@ def parse_pmns(md):
|
|
| 107 |
elif low.startswith("percusion:"):
|
| 108 |
p = line.split(":", 1)[1].strip().lower()
|
| 109 |
sec["percusion"] = p if p in PERCUSSION_STYLES else "ninguno"
|
|
|
|
|
|
|
|
|
|
| 110 |
|
| 111 |
if not sec["notes"]: errors.append("falta notas")
|
| 112 |
for tok in sec["chords"].split():
|
|
@@ -215,7 +218,9 @@ def midi_to_mp3(midi_path, mp3_path):
|
|
| 215 |
if os.path.exists(wav_path): os.unlink(wav_path)
|
| 216 |
return mp3_path
|
| 217 |
|
| 218 |
-
SYSTEM = """Escribe SOLO el texto de la partitura. Nada de charla. Formato exacto
|
|
|
|
|
|
|
| 219 |
|
| 220 |
# Titulo
|
| 221 |
## Tempo
|
|
@@ -223,18 +228,24 @@ SYSTEM = """Escribe SOLO el texto de la partitura. Nada de charla. Formato exact
|
|
| 223 |
## Estructura
|
| 224 |
### Intro
|
| 225 |
instrumento: piano
|
| 226 |
-
notas: C4q E4q G4q C5h
|
| 227 |
-
acordes: C4
|
| 228 |
|
| 229 |
-
###
|
| 230 |
instrumento: guitar
|
| 231 |
-
notas: A3q C4q E4q A4h G4q F4q E4q
|
| 232 |
-
acordes: Am4 F2
|
| 233 |
|
| 234 |
### Estribillo
|
| 235 |
instrumento: strings
|
| 236 |
-
|
| 237 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 238 |
|
| 239 |
### Outro
|
| 240 |
instrumento: piano
|
|
@@ -253,7 +264,7 @@ def clean_score(text):
|
|
| 253 |
if "notas:" not in md.lower(): return None
|
| 254 |
return md.strip()
|
| 255 |
|
| 256 |
-
def generate_text(model, tokenizer, messages, max_new=
|
| 257 |
text = tokenizer.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)
|
| 258 |
inputs = tokenizer(text, return_tensors="pt").to(model.device)
|
| 259 |
with torch.no_grad():
|
|
@@ -355,19 +366,19 @@ footer, .built-with, [class*="footer"] { display: none !important; }
|
|
| 355 |
HEADER_HTML = f"""<div id="aether-topbar"><div id="aether-logo">馃幖</div><div id="aether-brand-name">{STUDIO_NAME}</div><span id="aether-brand-model">{MODEL_DISPLAY_NAME}</span></div>"""
|
| 356 |
SELECT_JS = """<script>function selectSong(id) { const el = document.querySelector('#song-selector input, #song-selector textarea'); if (el) { el.value = id; el.dispatchEvent(new Event('input', { bubbles: true })); el.dispatchEvent(new Event('change', { bubbles: true })); } }</script>"""
|
| 357 |
|
| 358 |
-
@spaces.GPU(duration=
|
| 359 |
def generate_song(prompt):
|
| 360 |
model, tokenizer = load_model()
|
| 361 |
model.to("cuda")
|
| 362 |
messages = [{"role": "system", "content": SYSTEM}, {"role": "user", "content": f"Comp贸n: {prompt}"}]
|
| 363 |
-
return generate_text(model, tokenizer, messages, max_new=
|
| 364 |
|
| 365 |
def process_request(prompt):
|
| 366 |
if not prompt or not prompt.strip():
|
| 367 |
yield "Escribe qu茅 canci贸n quieres.", "", render_library(), gr.update(), gr.update()
|
| 368 |
return
|
| 369 |
|
| 370 |
-
yield "馃幖 *Componiendo...*", "", render_library(), gr.update(), gr.update()
|
| 371 |
raw_output = generate_song(prompt)
|
| 372 |
md = clean_score(raw_output)
|
| 373 |
|
|
|
|
| 107 |
elif low.startswith("percusion:"):
|
| 108 |
p = line.split(":", 1)[1].strip().lower()
|
| 109 |
sec["percusion"] = p if p in PERCUSSION_STYLES else "ninguno"
|
| 110 |
+
elif low.startswith("repetir:"):
|
| 111 |
+
m = re.search(r"(\d+)", line)
|
| 112 |
+
sec["repeat"] = max(1, min(8, int(m.group(1)))) if m else 1
|
| 113 |
|
| 114 |
if not sec["notes"]: errors.append("falta notas")
|
| 115 |
for tok in sec["chords"].split():
|
|
|
|
| 218 |
if os.path.exists(wav_path): os.unlink(wav_path)
|
| 219 |
return mp3_path
|
| 220 |
|
| 221 |
+
SYSTEM = """Escribe SOLO el texto de la partitura. Nada de charla. Formato exacto.
|
| 222 |
+
|
| 223 |
+
Para que la canci贸n dure 1 minuto, escribe OBLIGATORIAMENTE 8 secciones (Intro, Verso 1, Pre-Estribillo, Estribillo, Verso 2, Puente, Climax, Outro). Escribe al menos 12 notas por secci贸n. Usa el campo "repetir: 2" en los estribillos.
|
| 224 |
|
| 225 |
# Titulo
|
| 226 |
## Tempo
|
|
|
|
| 228 |
## Estructura
|
| 229 |
### Intro
|
| 230 |
instrumento: piano
|
| 231 |
+
notas: C4q E4q G4q C5h E5q D5q C5h
|
| 232 |
+
acordes: C4 G4
|
| 233 |
|
| 234 |
+
### Verso 1
|
| 235 |
instrumento: guitar
|
| 236 |
+
notas: A3q C4q E4q A4h G4q F4q E4q D4q C4q D4h
|
| 237 |
+
acordes: Am4 F2 C4 G4
|
| 238 |
|
| 239 |
### Estribillo
|
| 240 |
instrumento: strings
|
| 241 |
+
repetir: 2
|
| 242 |
+
notas: F4q G4q A4q C5h D5q C5q A4q G4h F4q E4q D4q C4h
|
| 243 |
+
acordes: F4 C4 G4 Am4
|
| 244 |
+
|
| 245 |
+
### Puente
|
| 246 |
+
instrumento: flute
|
| 247 |
+
notas: D5q E5q F5q G5h E5q D5q C5q A4q G4q F4q E4q D4h
|
| 248 |
+
acordes: Dm4 G4 C4 Am4
|
| 249 |
|
| 250 |
### Outro
|
| 251 |
instrumento: piano
|
|
|
|
| 264 |
if "notas:" not in md.lower(): return None
|
| 265 |
return md.strip()
|
| 266 |
|
| 267 |
+
def generate_text(model, tokenizer, messages, max_new=1500):
|
| 268 |
text = tokenizer.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)
|
| 269 |
inputs = tokenizer(text, return_tensors="pt").to(model.device)
|
| 270 |
with torch.no_grad():
|
|
|
|
| 366 |
HEADER_HTML = f"""<div id="aether-topbar"><div id="aether-logo">馃幖</div><div id="aether-brand-name">{STUDIO_NAME}</div><span id="aether-brand-model">{MODEL_DISPLAY_NAME}</span></div>"""
|
| 367 |
SELECT_JS = """<script>function selectSong(id) { const el = document.querySelector('#song-selector input, #song-selector textarea'); if (el) { el.value = id; el.dispatchEvent(new Event('input', { bubbles: true })); el.dispatchEvent(new Event('change', { bubbles: true })); } }</script>"""
|
| 368 |
|
| 369 |
+
@spaces.GPU(duration=30, size="xlarge")
|
| 370 |
def generate_song(prompt):
|
| 371 |
model, tokenizer = load_model()
|
| 372 |
model.to("cuda")
|
| 373 |
messages = [{"role": "system", "content": SYSTEM}, {"role": "user", "content": f"Comp贸n: {prompt}"}]
|
| 374 |
+
return generate_text(model, tokenizer, messages, max_new=1500)
|
| 375 |
|
| 376 |
def process_request(prompt):
|
| 377 |
if not prompt or not prompt.strip():
|
| 378 |
yield "Escribe qu茅 canci贸n quieres.", "", render_library(), gr.update(), gr.update()
|
| 379 |
return
|
| 380 |
|
| 381 |
+
yield "馃幖 *Componiendo (esto tomar谩 m谩s tiempo para generar 1 minuto de m煤sica)...*", "", render_library(), gr.update(), gr.update()
|
| 382 |
raw_output = generate_song(prompt)
|
| 383 |
md = clean_score(raw_output)
|
| 384 |
|