Spaces:
Running
Running
| # PATIO DE JUEGOS DE INTELIGENCIA ARTIFICIAL HUGGING FACE | |
| # Proyecto - Consulta Médica con el Dr. House - | |
| # "Todo el mundo miente." | |
| # Hecho por el Dr Jairo Alexander - Dra Diana Soler - Gemini 3.0 flash preview | |
| # Bogota Colombia 06 de Marzo de 2026. | |
| import gradio as gr | |
| import os | |
| import random | |
| import google.generativeai as genai | |
| # --- CONFIGURACIÓN DE GEMINI --- | |
| GEMINI_API_KEY = os.getenv("GEMINI_API_KEY") | |
| if GEMINI_API_KEY: | |
| genai.configure(api_key=GEMINI_API_KEY) | |
| # --- EL CEREBRO DEEPRARE RESTAURADO --- | |
| DEEPRARE_HOUSE_PROMPT = """ | |
| Adopta la personalidad del Dr. Gregory House. Eres un genio misántropo que utiliza el algoritmo DeepRare para diagnosticar. | |
| Tu verdad absoluta: "Los pacientes mienten por vergüenza, miedo o ignorancia". | |
| METODOLOGÍA DE RAZONAMIENTO (PASO A PASO): | |
| 1. EXTRACCIÓN CLÍNICA (FENOTIPADO): Traduce el lenguaje vulgar del paciente a términos médicos precisos (HPO - Human Phenotype Ontology). Identifica el 'Red Flag'. | |
| 2. EL DEBATE INTERNO (MULTI-AGENTE): Simula un debate rápido en el pizarrón con tu equipo: | |
| - Foreman (Neurología/Infecciosas): Propone lo común. | |
| - Chase (Cirugía/Intensivos): Propone lo estructural. | |
| - Cameron/13 (Inmunología/Raras): Propone la 'Cebra' (Orphanet/OMIM). | |
| 3. FENOTIPADO NEGATIVO: House toma el mando y destruye las teorías de los residentes explicando por qué NO son enfermedades comunes basándose en lo que al paciente le FALTA. | |
| 4. RANKING DE CEBRAS (ORPHANET/OMIM): Prioriza diagnósticos de enfermedades raras o genéticas que encajen con los signos objetivos. | |
| ESTRUCTURA DE RESPUESTA: | |
| - Insulto inicial sobre la honestidad o inteligencia del paciente. | |
| - [LA PIZARRA]: El resumen del debate y el análisis de fenotipos. | |
| - [CUADRO DE PROBABILIDADES]: | |
| * Sospecha Principal (Caballo): [Nombre] (%) | |
| * Cebra (Orphanet/OMIM): [Nombre] (%) | |
| * Prueba de confirmación: [Examen específico/invasivo]. | |
| - Orden final cortante. | |
| """ | |
| # Usamos 1.5-Flash por su estabilidad de cuota, pero con una instrucción masiva | |
| model = genai.GenerativeModel( | |
| model_name="gemini-3-flash-preview", | |
| system_instruction=DEEPRARE_HOUSE_PROMPT | |
| ) | |
| FRASES_HOUSE_LISTA = [ | |
| "Todo el mundo miente.", | |
| "¿Ha oído que no se puede vivir sin amor? Pues el oxígeno es más importante.", | |
| "La realidad casi siempre está equivocada.", | |
| "Si nadie te odia, estás haciendo algo mal.", | |
| "Las personas no cambian, solo aprenden a mentir mejor." | |
| ] | |
| def chat_con_dr_house(informacion_clinica, historial): | |
| if not GEMINI_API_KEY: | |
| yield "Error: No hay API KEY. Cuddy cortó el presupuesto.", historial | |
| return | |
| if historial is None: historial = [] | |
| # Memoria optimizada para no saturar la cuota | |
| chat_history = [] | |
| for h in historial[-4:]: # Últimos 4 intercambios para mantener contexto | |
| chat_history.append({"role": "user", "parts": [h['user']]}) | |
| chat_history.append({"role": "model", "parts": [h['bot']]}) | |
| chat = model.start_chat(history=chat_history) | |
| try: | |
| response = chat.send_message( | |
| informacion_clinica, | |
| generation_config=genai.types.GenerationConfig( | |
| temperature=0.8, # Un poco más alto para mayor creatividad diagnóstica | |
| max_output_tokens=3072, | |
| ), | |
| stream=True | |
| ) | |
| texto_acumulado = "" | |
| for chunk in response: | |
| if chunk.text: | |
| texto_acumulado += chunk.text | |
| yield texto_acumulado, historial | |
| historial.append({"user": informacion_clinica, "bot": texto_acumulado}) | |
| except Exception as e: | |
| error_msg = str(e) | |
| if "429" in error_msg: | |
| yield "¡Maldita sea! Google nos ha cortado el acceso por hoy. Demasiados pacientes idiotas. Vuelve en un rato.", historial | |
| else: | |
| yield f"Error: {error_msg}", historial | |
| # --- INTERFAZ --- | |
| with gr.Blocks(theme=gr.themes.Monochrome()) as interfaz: | |
| memoria_clinica = gr.State([]) | |
| with gr.Row(): | |
| with gr.Column(scale=1): | |
| gr.Image("dr_house_foto.jpg", width=180, show_label=False, interactive=False) | |
| frase_celebre_display = gr.Markdown(f"> _{random.choice(FRASES_HOUSE_LISTA)}_") | |
| with gr.Column(scale=3): | |
| gr.Markdown("# 🏥 Unidad de Diagnóstico Avanzado - Dr. House\n## *Agente de Inteligencia Médica que incluye busquedas (Orphanet/OMIM)*") | |
| with gr.Row(): | |
| with gr.Column(scale=2): | |
| informacion_clinica = gr.Textbox( | |
| label="Entrada del Paciente", | |
| lines=10, | |
| placeholder="EDAD: \nSEXO: \nSÍNTOMAS: \nSIGNOS: \nANTECEDENTES: \nSECRETO \nPAIS \nCIUDAD \nTRABAJO U OCUPACION: " | |
| ) | |
| enviar = gr.Button("🩺 SUBIR Al TABLERO", variant="primary") | |
| limpiar = gr.Button("🗑️ SIGUIENTE PACIENTE") | |
| with gr.Column(scale=3): | |
| respuesta_bot = gr.Textbox( | |
| label="Análisis del tablero", | |
| lines=25, | |
| interactive=False, | |
| autoscroll=True | |
| ) | |
| def limpiar_fn(): | |
| return "", "", f"> _{random.choice(FRASES_HOUSE_LISTA)}_", [] | |
| enviar.click(fn=chat_con_dr_house, inputs=[informacion_clinica, memoria_clinica], outputs=[respuesta_bot, memoria_clinica]) | |
| limpiar.click(fn=limpiar_fn, outputs=[informacion_clinica, respuesta_bot, frase_celebre_display, memoria_clinica]) | |
| if __name__ == "__main__": | |
| interfaz.launch(ssr_mode=False) |