File size: 4,861 Bytes
32802b5
 
dd5582f
32802b5
 
 
 
dd5582f
32802b5
 
dd5582f
dd93648
32802b5
 
dd93648
32802b5
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
09461d3
32802b5
 
 
 
 
09461d3
32802b5
 
 
 
 
 
 
 
09461d3
32802b5
dd93648
32802b5
09461d3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
32802b5
 
 
09461d3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
dd5582f
 
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
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:
        handle = Entrez.esearch(db="pubmed", term=pregunta, 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[:300]}...\n")  # Limitar a 300 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:
        url = f"https://api.duckduckgo.com/?q={pregunta}&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"][:200]  # Limitar a 200 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:
        inputs = tokenizer(
            f"Eres un profesor médico con vasto conocimiento en fisiología, bioquímica, farmacología y otras áreas médicas. "
            f"Explica de manera clara, sencilla y didáctica. Utiliza términos médicos y explícalos dentro de tus respuestas. "
            f"Si no estás seguro de algo, di 'No tengo suficiente información para responder a eso'. Pregunta: {pregunta}",
            return_tensors="pt"
        ).to("cpu")
        
        with torch.no_grad():
            outputs = model.generate(**inputs, max_length=100)  # Reducir max_length para mayor velocidad
        
        return tokenizer.decode(outputs[0], skip_special_tokens=True)

    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: #f0f8ff;

}

"""

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()