Crisol / app.py
Lukeetah's picture
Update app.py
b425fd5 verified
import gradio as gr
from transformers import pipeline, set_seed
from helpers import generate_audio, generate_bioresonant_sigil, create_quantum_tunnel_gif, create_soul_artifact
import whisper
import time
import os
# --- INICIO DE LA OBRA ---
print("Cargando el Núcleo Oracular y sus componentes...")
QUANTUM_TUNNEL_PATH = create_quantum_tunnel_gif()
INTRO_AUDIO = generate_audio("intro")
OUTRO_AUDIO = generate_audio("outro")
print("Cargando modelo de transcripción Whisper (puede tardar)...")
try:
whisper_model = whisper.load_model("base")
whisper_loaded = True
print("Whisper cargado.")
except Exception as e:
whisper_loaded = False
print(f"Error al cargar Whisper: {e}")
try:
set_seed(int(time.time()))
oracle = pipeline("text2text-generation", model="google/flan-t5-base", device=-1)
oracle_loaded = True
print("Oráculo de texto cargado.")
except Exception as e:
oracle_loaded = False
print(f"Error al cargar el Oráculo de texto: {e}")
# --- LÓGICA DEL ORÁCULO ---
def query_oracle(user_echo):
if not oracle_loaded: return {"title": "Error", "myth": "El Oráculo está en silencio.", "key": "Reinicia la conexión."}
if not user_echo: return {"title": "Silencio", "myth": "No se ha proporcionado materia prima.", "key": "Habla o escribe tu Eco."}
prompt = f"""
Eres un Oráculo. Tu función es transmutar una confesión en un mito de poder.
Analiza la siguiente confesión del usuario.
Responde ÚNICAMENTE con un objeto JSON con tres claves: "title", "myth", "key".
- "title": Crea un título épico para el mito.
- "myth": Escribe un mito de transmutación de 100-150 palabras, en segunda persona ("Tú..."). Usa metáforas profundas. No des consejos.
- "key": Extrae del mito una sola frase corta y poderosa. Esta es la llave resonante del usuario.
Confesión del Usuario: "{user_echo}"
JSON de Respuesta:
"""
try:
response = oracle(prompt, max_length=300, num_beams=4, early_stopping=True)[0]['generated_text']
# Limpiar y parsear la respuesta JSON del modelo
import json
clean_json_str = response.replace("`", "").replace("json", "").strip()
result = json.loads(clean_json_str)
return result
except Exception as e:
print(f"Error parseando la respuesta del Oráculo: {e}\nRespuesta recibida: {response}")
# Fallback por si el JSON falla
return {"title": "Mito Incompleto", "myth": response, "key": "La forma se resistió, pero el contenido es tuyo."}
def transcribe_voice(audio_path):
if not whisper_loaded or audio_path is None:
return "El oído del Oráculo está cerrado, por favor escribe tu Eco."
try:
result = whisper_model.transcribe(audio_path)
return result["text"]
except Exception as e:
print(f"Error de transcripción: {e}")
return ""
# --- INTERFAZ VIVA ---
css = """
@keyframes gradient-animation {
0% { background-position: 0% 50%; } 50% { background-position: 100% 50%; } 100% { background-position: 0% 50%; }
}
@keyframes final-glow {
0% { box-shadow: 0 0 20px #c39cff33; } 50% { box-shadow: 0 0 40px #ffdfa099; } 100% { box-shadow: 0 0 20px #c39cff33; }
}
body { font-family: 'Georgia', serif; }
.gradio-container {
max-width: 800px !important; margin: auto; border: 1px solid #333 !important;
background: linear-gradient(-45deg, #0d0d0d, #1a1224, #0d0d0d, #12241a);
background-size: 400% 400%;
animation: gradient-animation 15s ease infinite;
transition: all 2s ease;
}
.final-state {
background: linear-gradient(-45deg, #1a1224, #24221a, #1a1224, #241a12);
background-size: 400% 400%;
animation: gradient-animation 20s ease infinite, final-glow 5s ease-in-out infinite;
}
/* ... (otros estilos de la v3.0) ... */
.step-title { color: #c39cff; font-size: 24px; font-weight: bold; text-align: center; margin-bottom: 1rem; text-shadow: 0 0 5px #c39cff;}
.step-description { color: #b0b0b0; font-size: 16px; text-align: center; margin-bottom: 2rem; line-height: 1.6;}
.output-text { background-color: #1a1a1a; padding: 1rem; border-radius: 8px; border: 1px solid #333; }
.gr-button { background-color: #4a4a4a; color: #e0e0e0; border: 1px solid #6a6a6a; }
.gr-button:hover { background-color: #c39cff; color: #0d0d0d; border-color: #c39cff; }
"""
with gr.Blocks(css=css, title="Crisol 3.5: El Núcleo Oracular") as app:
app_container = gr.Column(elem_classes="gradio-container")
with app_container:
gr.Markdown("# Crisol 3.5: El Núcleo Oracular")
with gr.Column(visible=True) as step1_ui:
gr.Markdown("<h2 class='step-title'>PASO 1: LA SINTONIZACIÓN</h2>", elem_id="step-title")
gr.Markdown("<p class='step-description'>El Crisol está vivo. Sintoniza tu psique con su resonancia. Cierra los ojos. Escucha.</p>", elem_id="step-description")
gr.Audio(value=INTRO_AUDIO, label="Resonancia Theta (Para Introspección)", autoplay=True)
next_to_step2_btn = gr.Button("Estoy sintonizado. Despertar al Oráculo.")
with gr.Column(visible=False) as step2_ui:
gr.Markdown("<h2 class='step-title'>PASO 2: LA CONFESIÓN SÓNICA</h2>", elem_id="step-title")
gr.Markdown("<p class='step-description'>Habla tu Eco. No lo pienses, siéntelo. La vibración de tu voz es la materia prima. O si lo prefieres, escribe tus palabras en el silencio.</p>", elem_id="step-description")
voice_input = gr.Audio(sources=["microphone"], type="filepath", label="Graba tu Eco aquí:")
text_input = gr.Textbox(lines=4, label="O escribe tu Eco aquí:", placeholder="La transcripción de tu voz aparecerá aquí...")
next_to_tunnel_btn = gr.Button("Entregar al Crisol")
with gr.Column(visible=False) as quantum_tunnel_ui:
gr.Markdown("<h2 class='step-title'>PROCESANDO EN EL NÚCLEO</h2>", elem_id="step-title")
gr.Image(value=QUANTUM_TUNNEL_PATH, show_label=False, show_download_button=False)
gr.Markdown("<p class='step-description'>El Oráculo ha escuchado. El tiempo y el espacio se pliegan. La transmutación es inminente...</p>", elem_id="step-description")
with gr.Column(visible=False) as step3_ui:
gr.Markdown("<h2 class='step-title'>REVELACIÓN DEL ORÁCULO</h2>", elem_id="step-title")
myth_title_output = gr.Markdown("### Título del Mito")
sigil_output = gr.Image(label="Tu Sigilo Bio-Resonante", interactive=False)
myth_output = gr.Textbox(label="El Mito Forjado para Ti", lines=6, interactive=False, elem_classes="output-text")
key_output = gr.Textbox(label="Tu Llave Resonante", lines=1, interactive=False)
next_to_final_btn = gr.Button("Integrar y Reclamar mi Artefacto")
with gr.Column(visible=False) as step4_ui:
gr.Markdown("<h2 class='step-title'>INTEGRACIÓN Y RESONANCIA</h2>", elem_id="step-title")
gr.Markdown("<p class='step-description'>La obra está completa. El antiguo Eco es ahora un Artefacto de poder. Escucha la nueva resonancia de tu ser. Descarga tu verdad.</p>", elem_id="step-description")
gr.Audio(value=OUTRO_AUDIO, label="Resonancia Alfa (Para Conciencia Integrada)", autoplay=True)
artifact_output = gr.Image(label="Tu Artefacto del Alma", interactive=False)
download_button = gr.DownloadButton(label="Descargar mi Artefacto del Alma")
# --- LÓGICA DE FLUJO AVANZADA ---
def s1_to_s2():
return {step1_ui: gr.update(visible=False), step2_ui: gr.update(visible=True)}
next_to_step2_btn.click(s1_to_s2, outputs=[step1_ui, step2_ui])
voice_input.change(transcribe_voice, inputs=voice_input, outputs=text_input)
def s2_to_s3_flow(user_text):
yield {step2_ui: gr.update(visible=False), quantum_tunnel_ui: gr.update(visible=True)}
oracle_response = query_oracle(user_text)
title = oracle_response.get("title", "Sin Título")
myth = oracle_response.get("myth", "Contenido no generado.")
key = oracle_response.get("key", "Sin llave.")
sigil_img = generate_bioresonant_sigil(user_text)
yield {
quantum_tunnel_ui: gr.update(visible=False),
step3_ui: gr.update(visible=True),
myth_title_output: gr.update(value=f"### {title}"),
sigil_output: gr.update(value=sigil_img),
myth_output: gr.update(value=myth),
key_output: gr.update(value=key),
}
next_to_tunnel_btn.click(s2_to_s3_flow, inputs=text_input, outputs=[step2_ui, quantum_tunnel_ui, step3_ui, myth_title_output, sigil_output, myth_output, key_output])
def s3_to_s4(sigil, title, key):
title_clean = title.replace("### ", "")
artifact_path = create_soul_artifact(sigil, title_clean, key)
return {
step3_ui: gr.update(visible=False),
step4_ui: gr.update(visible=True),
app_container: gr.update(elem_classes="gradio-container final-state"),
artifact_output: gr.update(value=artifact_path),
download_button: gr.update(value=artifact_path)
}
next_to_final_btn.click(s3_to_s4, inputs=[sigil_output, myth_title_output, key_output], outputs=[step3_ui, step4_ui, app_container, artifact_output, download_button])
app.launch(debug=True)