File size: 5,813 Bytes
32802b5
 
dd5582f
32802b5
 
 
 
dd5582f
32802b5
 
dd5582f
dd93648
32802b5
 
dd93648
32802b5
 
 
 
 
 
 
 
344ca58
 
 
 
32802b5
 
 
 
 
 
 
 
e3487ab
32802b5
 
 
 
 
 
09461d3
32802b5
 
 
 
344ca58
e3487ab
344ca58
09461d3
32802b5
 
 
e3487ab
32802b5
 
 
 
09461d3
32802b5
dd93648
32802b5
09461d3
344ca58
 
 
09461d3
e3487ab
344ca58
 
 
09461d3
 
 
89d98f5
 
e3487ab
344ca58
e3487ab
 
89d98f5
09461d3
344ca58
 
 
e3487ab
344ca58
 
09461d3
 
 
 
32802b5
 
 
09461d3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
dd5582f
 
32802b5
 
344ca58
 
 
 
 
 
 
32802b5
 
 
dd5582f
32802b5
 
 
 
 
 
dd5582f
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
from transformers import AutoModelForCausalLM, AutoTokenizer
import torch
import gradio as gr
from Bio import Entrez
import requests
from functools import lru_cache
import logging

# Configurar logging
logging.basicConfig(level=logging.INFO)

# Cargar un modelo de lenguaje médico más pequeño (optimizado para CPU)
model_name = "microsoft/BioGPT"
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModelForCausalLM.from_pretrained(model_name).to("cpu")  # Usar CPU

# Configurar PubMed
Entrez.email = "[email protected]"  # Proporciona un correo válido

# Función para buscar en PubMed con caché
@lru_cache(maxsize=100)
def buscar_en_pubmed(pregunta):
    try:
        # Agregar palabras clave médicas a la pregunta
        termino = f"{pregunta} AND (medical OR health OR disease)"
        
        handle = Entrez.esearch(db="pubmed", term=termino, retmax=1)  # Buscar solo 1 artículo
        record = Entrez.read(handle)
        handle.close()
        
        if record["IdList"]:
            referencias = []
            for id_articulo in record["IdList"]:
                handle = Entrez.efetch(db="pubmed", id=id_articulo, rettype="abstract", retmode="text")
                resumen = handle.read()
                referencias.append(f"Artículo {id_articulo}:\n{resumen[:500]}...\n")  # Aumentar el límite a 500 caracteres
                handle.close()
            return "\n".join(referencias)
        else:
            return "No encontré artículos relevantes en PubMed."
    except Exception as e:
        logging.error(f"Error al buscar en PubMed: {e}")
        return "Error al buscar en PubMed. Inténtalo de nuevo."

# Función para buscar en Internet con tiempo de espera
def buscar_en_internet(pregunta):
    try:
        # Agregar palabras clave médicas a la pregunta
        termino = f"{pregunta} medical OR healthcare OR treatment"
        url = f"https://api.duckduckgo.com/?q={termino}&format=json"
        respuesta = requests.get(url, timeout=10)  # Incrementa el tiempo de espera a 10 segundos
        datos = respuesta.json()
        
        if "Abstract" in datos and datos["Abstract"]:
            return datos["Abstract"][:300]  # Aumentar el límite a 300 caracteres
        else:
            return "No encontré información en Internet."
    except Exception as e:
        logging.error(f"Error al buscar en Internet: {e}")
        return "Error al buscar en Internet. Inténtalo de nuevo."

# Función para generar respuestas del modelo (optimizada para CPU)
def generar_respuesta(pregunta):
    try:
        # Truncar la pregunta si es demasiado larga
        pregunta = pregunta[:500]  # Limitar a 500 caracteres
        
        inputs = tokenizer(
            f"Explica {pregunta} de forma clara y detallada. Incluye causas, síntomas, diagnóstico y tratamiento si corresponde.",
            return_tensors="pt",
            max_length=512,  # Limitar la longitud máxima de entrada
            truncation=True
        ).to("cpu")
        
        with torch.no_grad():
            outputs = model.generate(
                **inputs,
                max_new_tokens=400,  # Aumentar el límite para respuestas más largas
                do_sample=True,      # Usar muestreo para respuestas más naturales
                temperature=0.5,     # Reducir la creatividad para respuestas más precisas
                num_beams=6          # Mejorar la coherencia
            )
        
        respuesta = tokenizer.decode(outputs[0], skip_special_tokens=True)
        
        # Eliminar el prompt de la respuesta
        respuesta = respuesta.replace(f"Explica {pregunta} de forma clara y detallada. Incluye causas, síntomas, diagnóstico y tratamiento si corresponde.", "").strip()
        
        return respuesta

    except Exception as e:
        logging.error(f"Error al generar respuesta del modelo: {e}")
        return "No pude generar una respuesta. Inténtalo de nuevo."

# Función principal para hacer preguntas al bot
def pregunta_medica_con_carga(pregunta):
    try:
        # Validar la entrada
        if not isinstance(pregunta, str) or not pregunta.strip():
            yield "Por favor, ingresa una pregunta válida."
            return
        
        yield "Procesando tu pregunta..."  # Mensaje de carga
        
        # Respuesta del modelo médico
        respuesta_modelo = generar_respuesta(pregunta)
        
        # Buscar en PubMed
        referencias_pubmed = buscar_en_pubmed(pregunta)
        
        # Buscar en Internet
        respuesta_internet = buscar_en_internet(pregunta)
        
        # Combinar respuestas
        respuesta_final = (
            f"Respuesta del Profesor Médico:\n{respuesta_modelo}\n\n"
            f"Referencias de PubMed:\n{referencias_pubmed}\n\n"
            f"Información de Internet:\n{respuesta_internet}"
        )
        
        yield respuesta_final

    except Exception as e:
        logging.error(f"Error inesperado: {e}")
        yield "Lo siento, ocurrió un error al procesar tu pregunta. Por favor, inténtalo de nuevo más tarde."

# Crear la interfaz web con Gradio
css = """

.gradio-container {

    background-color: #f9f9f9;

    font-family: Arial, sans-serif;

}

.gr-button {

    background-color: #007bff;

    color: white;

    border-radius: 5px;

}

"""

interfaz = gr.Interface(
    fn=pregunta_medica_con_carga,
    inputs=gr.Textbox(label="Pregunta"),
    outputs=gr.Textbox(label="Respuesta"),
    title="Profesor Médico Bot",
    description="Pregúntale al Profesor Médico sobre medicina. Te explicará de manera clara y didáctica.",
    css=css
)

# Lanzar la interfaz
interfaz.launch()