Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -32,9 +32,9 @@ def extraer_texto_pdf(pdf_file):
|
|
| 32 |
# ============= GENERAR AUDIO CON EMOCIÓN MEJORADO =============
|
| 33 |
# ============= GENERAR AUDIO CON EMOCIÓN Y ANÁLISIS DE SENTIMIENTO =============
|
| 34 |
def generar_audio_respuesta(texto, client):
|
| 35 |
-
"""
|
| 36 |
|
| 37 |
-
#
|
| 38 |
texto_limpio = texto.replace("*", "").replace("#", "").replace("`", "").replace("€", " euros").strip()
|
| 39 |
oraciones = re.split(r'[.!?]+', texto_limpio)
|
| 40 |
oraciones = [o.strip() for o in oraciones if o.strip() and len(o.strip()) > 10]
|
|
@@ -42,60 +42,79 @@ def generar_audio_respuesta(texto, client):
|
|
| 42 |
if len(texto_audio) > 400:
|
| 43 |
texto_audio = texto_audio[:397] + "..."
|
| 44 |
|
| 45 |
-
print(f"🎤 Generando audio
|
| 46 |
|
| 47 |
-
# PASO 1:
|
| 48 |
try:
|
| 49 |
-
print("🧠 Analizando emoción
|
| 50 |
emotion_response = client.text_classification(
|
| 51 |
text=texto_audio,
|
| 52 |
-
model="dariolopez/roberta-base-bne-finetuned-EmotionAnalysisSpanish" #
|
| 53 |
)
|
| 54 |
-
|
| 55 |
-
|
| 56 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 57 |
except Exception as e:
|
| 58 |
-
print(f"⚠️ Error
|
| 59 |
emocion_detectada = "neutral"
|
| 60 |
confianza = 0.5
|
| 61 |
|
| 62 |
-
# PASO 2: Modelos TTS
|
| 63 |
modelos_tts = [
|
| 64 |
-
"facebook/mms-tts-spa",
|
| 65 |
-
"
|
| 66 |
-
"
|
| 67 |
]
|
| 68 |
|
| 69 |
for modelo in modelos_tts:
|
| 70 |
try:
|
| 71 |
-
print(f"🔊 Probando
|
|
|
|
|
|
|
| 72 |
audio_data = client.text_to_speech(
|
| 73 |
text=texto_audio,
|
| 74 |
model=modelo
|
| 75 |
)
|
| 76 |
|
| 77 |
-
# Guardar archivo
|
| 78 |
timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
|
| 79 |
audio_path = f"audio_emocional_{emocion_detectada}_{timestamp}.wav"
|
| 80 |
|
| 81 |
with open(audio_path, "wb") as f:
|
| 82 |
if isinstance(audio_data, bytes):
|
| 83 |
f.write(audio_data)
|
|
|
|
|
|
|
|
|
|
|
|
|
| 84 |
else:
|
| 85 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 86 |
|
| 87 |
-
size = os.path.getsize(audio_path)
|
| 88 |
-
if size > 1000:
|
| 89 |
-
print(f"✅ Audio generado: {audio_path} ({size} bytes)")
|
| 90 |
-
return audio_path, emocion_detectada, confianza
|
| 91 |
-
else:
|
| 92 |
-
os.remove(audio_path)
|
| 93 |
-
print(f"⚠️ Archivo vacío, probando siguiente modelo...")
|
| 94 |
except Exception as e:
|
| 95 |
-
|
|
|
|
| 96 |
continue
|
| 97 |
|
| 98 |
-
print("⚠️
|
| 99 |
return None, emocion_detectada, confianza
|
| 100 |
|
| 101 |
# ============= ASISTENTE IA CONVERSACIONAL =============
|
|
|
|
| 32 |
# ============= GENERAR AUDIO CON EMOCIÓN MEJORADO =============
|
| 33 |
# ============= GENERAR AUDIO CON EMOCIÓN Y ANÁLISIS DE SENTIMIENTO =============
|
| 34 |
def generar_audio_respuesta(texto, client):
|
| 35 |
+
"""TTS emocional FUNCIONAL para español - Actualizado diciembre 2025"""
|
| 36 |
|
| 37 |
+
# Limpiar y preparar texto (mismo que antes)
|
| 38 |
texto_limpio = texto.replace("*", "").replace("#", "").replace("`", "").replace("€", " euros").strip()
|
| 39 |
oraciones = re.split(r'[.!?]+', texto_limpio)
|
| 40 |
oraciones = [o.strip() for o in oraciones if o.strip() and len(o.strip()) > 10]
|
|
|
|
| 42 |
if len(texto_audio) > 400:
|
| 43 |
texto_audio = texto_audio[:397] + "..."
|
| 44 |
|
| 45 |
+
print(f"🎤 Generando audio para: '{texto_audio[:80]}...'")
|
| 46 |
|
| 47 |
+
# PASO 1: Análisis emocional (modelo español que SÍ funciona)
|
| 48 |
try:
|
| 49 |
+
print("🧠 Analizando emoción...")
|
| 50 |
emotion_response = client.text_classification(
|
| 51 |
text=texto_audio,
|
| 52 |
+
model="dariolopez/roberta-base-bne-finetuned-EmotionAnalysisSpanish" # Español nativo
|
| 53 |
)
|
| 54 |
+
if emotion_response and len(emotion_response) > 0:
|
| 55 |
+
emocion_detectada = emotion_response[0]['label']
|
| 56 |
+
confianza = emotion_response[0]['score']
|
| 57 |
+
print(f"😊 Emoción: {emocion_detectada} (confianza: {confianza:.2%})")
|
| 58 |
+
else:
|
| 59 |
+
emocion_detectada = "neutral"
|
| 60 |
+
confianza = 0.5
|
| 61 |
except Exception as e:
|
| 62 |
+
print(f"⚠️ Error emocional: {str(e)[:100]}. Usando neutral.")
|
| 63 |
emocion_detectada = "neutral"
|
| 64 |
confianza = 0.5
|
| 65 |
|
| 66 |
+
# PASO 2: Modelos TTS que SÍ funcionan en 2025 (español prioritario)
|
| 67 |
modelos_tts = [
|
| 68 |
+
"facebook/mms-tts-spa", # Español oficial de Meta - Siempre funciona
|
| 69 |
+
"myshell-ai/MeloTTS-Spanish", # Alta calidad, multi-idioma
|
| 70 |
+
"coqui/XTTS-v2" # Fallback versátil (soporta español)
|
| 71 |
]
|
| 72 |
|
| 73 |
for modelo in modelos_tts:
|
| 74 |
try:
|
| 75 |
+
print(f"🔊 Probando: {modelo}")
|
| 76 |
+
|
| 77 |
+
# Generar audio
|
| 78 |
audio_data = client.text_to_speech(
|
| 79 |
text=texto_audio,
|
| 80 |
model=modelo
|
| 81 |
)
|
| 82 |
|
| 83 |
+
# Guardar archivo (mejorado para streams/bytes)
|
| 84 |
timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
|
| 85 |
audio_path = f"audio_emocional_{emocion_detectada}_{timestamp}.wav"
|
| 86 |
|
| 87 |
with open(audio_path, "wb") as f:
|
| 88 |
if isinstance(audio_data, bytes):
|
| 89 |
f.write(audio_data)
|
| 90 |
+
elif hasattr(audio_data, 'read'):
|
| 91 |
+
f.write(audio_data.read())
|
| 92 |
+
elif hasattr(audio_data, 'content'):
|
| 93 |
+
f.write(audio_data.content)
|
| 94 |
else:
|
| 95 |
+
# Para iteradores/chunks
|
| 96 |
+
for chunk in audio_data:
|
| 97 |
+
if chunk:
|
| 98 |
+
f.write(chunk if isinstance(chunk, bytes) else bytes(chunk))
|
| 99 |
+
|
| 100 |
+
# Verificar
|
| 101 |
+
if os.path.exists(audio_path):
|
| 102 |
+
size = os.path.getsize(audio_path)
|
| 103 |
+
print(f"📁 Creado: {audio_path} ({size} bytes)")
|
| 104 |
+
|
| 105 |
+
if size > 2000: # Umbral más bajo para MMS
|
| 106 |
+
print(f"✅ ¡AUDIO GENERADO EXITOSAMENTE!")
|
| 107 |
+
return audio_path, emocion_detectada, confianza
|
| 108 |
+
else:
|
| 109 |
+
print(f"⚠️ Archivo pequeño ({size} bytes), borrando...")
|
| 110 |
+
os.remove(audio_path)
|
| 111 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 112 |
except Exception as e:
|
| 113 |
+
error_msg = str(e)
|
| 114 |
+
print(f"❌ Error con {modelo}: {error_msg[:100]}")
|
| 115 |
continue
|
| 116 |
|
| 117 |
+
print("⚠️ No se generó audio. Verifica límites de API o conexión.")
|
| 118 |
return None, emocion_detectada, confianza
|
| 119 |
|
| 120 |
# ============= ASISTENTE IA CONVERSACIONAL =============
|