# app.py - Migración completa del Generador Fonoaudiológico a Gradio/HF import gradio as gr import requests import json from datetime import datetime import PyPDF2 import io from huggingface_hub import InferenceClient import os import re # Configuración de modelos de Hugging Face (gratuitos) MODEL_OPTIONS = { "Llama 3.2 (Recomendado)": "meta-llama/Llama-3.2-1B-Instruct", "Mistral 7B": "mistralai/Mistral-7B-Instruct-v0.1", "Flan-T5 Large": "google/flan-t5-large", "Phi-3 Mini": "microsoft/Phi-3-mini-4k-instruct" } # Cliente de inferencia HF client = InferenceClient() def extraer_edad_de_descripcion(descripcion): """Extrae la edad en meses de la descripción del usuario""" # Buscar patrones como "48 meses", "4 años", "3a 6m", etc. meses_match = re.search(r'(\d+)\s*meses?', descripcion.lower()) if meses_match: return int(meses_match.group(1)) anos_match = re.search(r'(\d+)\s*años?', descripcion.lower()) if anos_match: return int(anos_match.group(1)) * 12 # Buscar patrón "3a 6m" o similar anos_meses_match = re.search(r'(\d+)a\s*(\d+)m', descripcion.lower()) if anos_meses_match: anos = int(anos_meses_match.group(1)) meses = int(anos_meses_match.group(2)) return (anos * 12) + meses # Por defecto, asumir que cualquier número es edad en meses numero_match = re.search(r'\d+', descripcion) if numero_match: return int(numero_match.group()) return 60 # Default 5 años def extract_text_from_pdf(pdf_files): """Extrae texto de archivos PDF subidos""" if not pdf_files: return "" extracted_texts = [] for pdf_file in pdf_files: try: with open(pdf_file.name, 'rb') as file: pdf_reader = PyPDF2.PdfReader(file) text = "" for page in pdf_reader.pages: text += page.extract_text() + "\n" # Limitar texto para evitar exceso de tokens text_preview = text[:800] + "..." if len(text) > 800 else text extracted_texts.append(f"📄 **{pdf_file.name}**:\n{text_preview}\n") except Exception as e: extracted_texts.append(f"❌ Error leyendo {pdf_file.name}: {str(e)}\n") return "\n".join(extracted_texts) def generar_actividad_fonoaudiologica( modelo_seleccionado, descripcion_usuario, es_pediatrica, objetivo_especifico, duracion, tipo_sesion, contexto_adicional, archivos_pdf, progress=gr.Progress() ): """Función principal que genera la actividad fonoaudiológica""" # Validaciones (igual que en el JS original) if not descripcion_usuario or not descripcion_usuario.strip(): return "⚠️ **Error**: Por favor ingresa la descripción del usuario" if not objetivo_especifico or not objetivo_especifico.strip(): return "⚠️ **Error**: Por favor ingresa el objetivo específico" if not duracion or duracion < 15: return "⚠️ **Error**: La duración debe ser de al menos 15 minutos" # Progress bar progress(0.1, "Analizando información del paciente...") # Extraer edad de la descripción (lógica del JS original) edad_meses = extraer_edad_de_descripcion(descripcion_usuario) es_nino = edad_meses < 144 or es_pediatrica # < 12 años progress(0.3, "Procesando referencias científicas...") # Extraer texto de PDFs referencias_pdf = extract_text_from_pdf(archivos_pdf) if archivos_pdf else "" progress(0.5, "Generando actividad con IA...") # Construir prompt detallado (basado en el JS original) prompt = f"""Eres un fonoaudiólogo experto especializado en terapia del habla y lenguaje. Genera una actividad terapéutica profesional y detallada con esta información: INFORMACIÓN DEL PACIENTE: - Descripción: {descripcion_usuario} - Edad estimada: {edad_meses} meses ({edad_meses//12} años y {edad_meses%12} meses) - Tipo de sesión: {'Pediátrica - usar lenguaje lúdico y juegos' if es_pediatrica else 'Adulto/Adolescente - lenguaje profesional'} OBJETIVO TERAPÉUTICO: - Objetivo específico: {objetivo_especifico} - Duración de la sesión: {duracion} minutos - Modalidad: {tipo_sesion} CONTEXTO ADICIONAL: {contexto_adicional if contexto_adicional else 'No se proporcionó contexto adicional'} REFERENCIAS CIENTÍFICAS: {referencias_pdf[:600] if referencias_pdf else 'Sin referencias adicionales proporcionadas'} INSTRUCCIONES PARA GENERAR LA ACTIVIDAD: 1. **TÍTULO**: Crea un título específico y atractivo {'con emojis y lenguaje lúdico' if es_nino else 'profesional'} 2. **OBJETIVO SMART**: Reformula el objetivo usando criterios SMART (Específico, Medible, Alcanzable, Relevante, Temporal) 3. **DESCRIPCIÓN GENERAL**: {'Lenguaje amigable y motivador para el niño' if es_nino else 'Descripción técnica profesional'} 4. **MATERIALES**: Lista específica de materiales necesarios {'incluyendo juguetes y elementos lúdicos' if es_nino else 'con enfoque terapéutico profesional'} 5. **PROCEDIMIENTO PASO A PASO**: Divide en fases con tiempos estimados: - Fase inicial: {int(duracion * 0.2)} minutos {'(Calentamiento con juegos)' if es_nino else '(Preparación)'} - Fase principal: {int(duracion * 0.6)} minutos {'(Actividad principal divertida)' if es_nino else '(Desarrollo de la técnica)'} - Fase final: {int(duracion * 0.2)} minutos {'(Celebración de logros)' if es_nino else '(Síntesis y cierre)'} 6. **EVALUACIÓN**: - Criterios de logro {'con sistema de recompensas' if es_nino else 'objetivos y cuantificables'} - Métodos de evaluación apropiados para la edad - Tipo de retroalimentación 7. **ADAPTACIONES**: Sugerencias para diferentes niveles o necesidades especiales 8. **FUNDAMENTACIÓN TEÓRICA**: Base científica de la actividad (cuando sea apropiado) Responde en español, con formato claro y estructurado. {'Usa emojis y lenguaje motivador' if es_nino else 'Mantén un tono profesional'}.""" try: progress(0.7, "Conectando con modelo de IA...") # Seleccionar modelo model_name = MODEL_OPTIONS.get(modelo_seleccionado, MODEL_OPTIONS["Flan-T5 Large"]) # Generar respuesta con Hugging Face response = client.text_generation( prompt, model=model_name, max_new_tokens=1500, temperature=0.7, repetition_penalty=1.1, do_sample=True ) progress(0.9, "Formateando respuesta...") # Formatear respuesta final (similar al renderizado del JS) actividad_generada = f"""# 🧠 ACTIVIDAD FONOAUDIOLÓGICA GENERADA **📅 Fecha de generación:** {datetime.now().strftime("%d/%m/%Y a las %H:%M")} **👤 Paciente:** {edad_meses//12} años y {edad_meses%12} meses ({edad_meses} meses total) **🤖 Modelo IA:** {modelo_seleccionado} **⏱️ Duración:** {duracion} minutos | **👥 Modalidad:** {tipo_sesion} --- {response} --- ## 📊 RESUMEN EJECUTIVO **🎯 Enfoque de la sesión:** {'🧸 Pediátrico con metodología lúdica' if es_pediatrica else '👩‍⚕️ Clínico profesional'} **📋 Información procesada:** - ✅ Descripción del usuario analizada - ✅ Objetivo específico integrado - ✅ Duración y modalidad consideradas {'- ✅ Referencias científicas incorporadas' if referencias_pdf else '- ⚪ Sin referencias adicionales'} **⚠️ NOTA PROFESIONAL IMPORTANTE:** *Esta actividad ha sido generada por Inteligencia Artificial basándose en la información proporcionada. Como profesional de la fonoaudiología, es fundamental que revises, adaptes y valides la pertinencia clínica de esta propuesta antes de implementarla con pacientes reales. La IA es una herramienta de apoyo, pero el criterio profesional y la evaluación clínica directa son insustituibles.* --- ## 👨‍⚕️ INFORMACIÓN DEL DESARROLLADOR **Desarrollado por:** Flgo. Cristóbal San Martín **Instagram:** [@tufonoayuda](https://instagram.com/tufonoayuda) **Tecnología:** Hugging Face + Gradio + IA Generativa *Herramienta diseñada específicamente para profesionales de la fonoaudiología en Chile y Latinoamérica.*""" progress(1.0, "¡Actividad generada exitosamente!") return actividad_generada except Exception as e: error_msg = f"""❌ **ERROR AL GENERAR LA ACTIVIDAD** **Detalles del error:** {str(e)} **Posibles soluciones:** 1. **Intenta con otro modelo:** Cambia el modelo de IA seleccionado 2. **Simplifica el contexto:** Reduce el texto en "Contexto adicional" 3. **Verifica los PDFs:** Asegúrate de que los archivos no estén dañados 4. **Revisa la conexión:** Problemas temporales con Hugging Face **Información técnica:** - Modelo utilizado: {modelo_seleccionado} - Timestamp: {datetime.now().strftime("%d/%m/%Y %H:%M:%S")} - Duración solicitada: {duracion} min - Modalidad: {tipo_sesion} *Si el problema persiste, intenta nuevamente en unos minutos.*""" return error_msg # Crear la interfaz principal de Gradio def crear_interfaz(): with gr.Blocks( title="🧠 Generador IA Fonoaudiológico - HF Spaces", theme=gr.themes.Soft( primary_hue="indigo", secondary_hue="blue", neutral_hue="slate" ), css=""" .gradio-container { max-width: 1400px !important; } .highlight-header { background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); padding: 25px; border-radius: 15px; color: white; text-align: center; margin-bottom: 25px; } .form-section { background: rgba(255, 255, 255, 0.95); backdrop-filter: blur(10px); border-radius: 15px; padding: 20px; border: 1px solid rgba(255, 255, 255, 0.2); } .result-area { background: #f8f9fa; border-radius: 10px; padding: 15px; } """ ) as demo: # Header con el mismo estilo que tu app original gr.HTML("""

🧠 Generador IA de Actividades Fonoaudiológicas

✨ Potenciado con Hugging Face para Fonoaudiólog@s

Migración completa desde tu app original - Todas las funcionalidades incluidas

""") with gr.Row(): # Columna izquierda - Formulario (replica tu diseño original) with gr.Column(scale=1, elem_classes=["form-section"]): # Selección de modelo IA gr.Markdown("### 🤖 Configuración del Modelo IA") modelo_ia = gr.Dropdown( label="Modelo de Lenguaje", choices=list(MODEL_OPTIONS.keys()), value="Flan-T5 Large", info="💡 Llama 3.2 da mejores resultados pero es más lento" ) gr.Markdown("### 👤 Información del Usuario") descripcion_usuario = gr.Textbox( label="Descripción del usuario (edad en meses y contexto)", placeholder="Ej: Niño de 48 meses con retraso en el desarrollo del lenguaje expresivo, comprende órdenes simples pero presenta dificultades en la articulación de fonemas líquidos", lines=3, info="💡 Incluye edad en meses/años y características principales" ) es_pediatrica = gr.Checkbox( label="🎯 Sesión Pediátrica (lenguaje lúdico adaptado)", value=True, info="Activa para usar metodología lúdica y lenguaje motivador" ) gr.Markdown("### 🎯 Objetivo y Configuración de Sesión") objetivo_especifico = gr.Textbox( label="Objetivo específico (basado en Taxonomía de Bloom)", placeholder="Ej: Mejorar la articulación del fonema /r/ en palabras bisílabas mediante ejercicios de repetición y modelado", lines=2, info="📚 Niveles Bloom: Recordar → Comprender → Aplicar → Analizar → Evaluar → Crear" ) with gr.Row(): duracion = gr.Slider( label="⏱️ Duración (minutos)", minimum=15, maximum=120, value=45, step=5, info="Tiempo total de la sesión terapéutica" ) tipo_sesion = gr.Dropdown( label="👥 Tipo de sesión", choices=["Individual", "Grupal", "Para el hogar", "Mixta"], value="Individual" ) gr.Markdown("### 📚 Contexto Adicional (Expandible)") contexto_adicional = gr.Textbox( label="Información adicional detallada", placeholder="Estrategias específicas, materiales preferidos, observaciones clínicas, preferencias del paciente, historia clínica relevante...", lines=6, info="💡 Incluye estrategias como: Terapia Miofuncional, Bobath, Prompt, MIT, LSVT, VitalStim" ) gr.Markdown("### 📄 Referencias Científicas (Opcional)") archivos_pdf = gr.File( label="Subir archivos PDF", file_count="multiple", file_types=[".pdf"], info="📚 Arrastra archivos PDF aquí o selecciona - máximo 50MB por archivo" ) # Botón principal (mismo diseño que tu app) generar_btn = gr.Button( "✨ Generar Actividad con IA", variant="primary", size="lg", elem_id="generate-button" ) # Columna derecha - Resultado with gr.Column(scale=1): gr.Markdown("### 📋 Actividad Lista para Generar") resultado_actividad = gr.Textbox( label="", placeholder="""🧠 Actividad Lista para Generar Completa los campos de la izquierda y haz clic en "Generar Actividad". La IA creará una actividad personalizada que incluirá: • 🎯 Título específico y atractivo • 📝 Objetivo SMART reformulado • 🎨 Lista de materiales necesarios • ⚡ Procedimiento paso a paso con tiempos • 📊 Criterios de evaluación • 🔧 Adaptaciones sugeridas • 📚 Fundamentación teórica ¡Tu actividad fonoaudiológica personalizada estará lista en segundos!""", lines=35, max_lines=40, show_copy_button=True, elem_classes=["result-area"] ) # Conectar la funcionalidad (igual que tu addEventListener original) generar_btn.click( fn=generar_actividad_fonoaudiologica, inputs=[ modelo_ia, descripcion_usuario, es_pediatrica, objetivo_especifico, duracion, tipo_sesion, contexto_adicional, archivos_pdf ], outputs=resultado_actividad, show_progress=True ) # Footer idéntico al tuyo gr.HTML("""
👨‍⚕️

Desarrollado por

Flgo. Cristóbal San Martín

📱

Sígueme en

@tufonoayuda

Tecnología

Hugging Face Spaces

⚠️ Nota Profesional: Esta herramienta genera actividades basadas en IA como apoyo al trabajo profesional. Siempre revisa y adapta las actividades según tu criterio clínico antes de implementar con pacientes.

🚀 Migrado desde tu aplicación original • Todas las funcionalidades preservadas • Optimizado para Hugging Face

""") return demo # Ejecutar aplicación if __name__ == "__main__": demo = crear_interfaz() demo.launch( share=True, server_name="0.0.0.0", show_error=True, favicon_path=None, show_tips=True )