AlvearRendon / app.py
AlbertDuvan's picture
Upload app.py
e3487ab verified
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()