CHATBOT_SB / app.py
markIA23's picture
Update app.py
b9bc9ad verified
import streamlit as st
from llama_index.core import StorageContext, load_index_from_storage, VectorStoreIndex, SimpleDirectoryReader, ChatPromptTemplate
from llama_index.llms.huggingface import HuggingFaceInferenceAPI
from dotenv import load_dotenv
from llama_index.embeddings.huggingface import HuggingFaceEmbedding
from llama_index.core import Settings
import os
import base64
# Cargar variables de entorno
load_dotenv()
# Configurar los modelos de LLM y Embeddings
Settings.llm = HuggingFaceInferenceAPI(
model_name="mistralai/Mistral-7B-Instruct-v0.3",
tokenizer_name="mistralai/Mistral-7B-Instruct-v0.3",
context_window=4000, # Ventana de contexto del modelo
token=os.getenv("HF_TOKEN"), # Tu token de Hugging Face
max_new_tokens=512, # Puedes ajustarlo seg煤n tu necesidad
generate_kwargs={"temperature": 0.1},
)
Settings.embed_model = HuggingFaceEmbedding(
model_name="sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2" # Modelo en espa帽ol de Hugging Face
)
# Definir los directorios para almacenamiento persistente y datos
PERSIST_DIR = "./db"
DATA_DIR = "data"
# Asegurar que los directorios existan
os.makedirs(DATA_DIR, exist_ok=True)
os.makedirs(PERSIST_DIR, exist_ok=True)
# Ruta fija para el archivo PDF
FIXED_PDF_PATH = os.path.join(DATA_DIR, "saved_pdf.pdf")
# Ingestar datos una vez al inicio
@st.cache_data
def load_data():
documents = SimpleDirectoryReader(DATA_DIR).load_data()
storage_context = StorageContext.from_defaults()
index = VectorStoreIndex.from_documents(documents)
index.storage_context.persist(persist_dir=PERSIST_DIR)
return index
# Manejar consultas de usuario
def handle_query(query, index):
chat_text_qa_msgs = [
(
"user",
"""Responde en espa帽ol con un m谩ximo de 80 palabras y agrega que para m谩s informaci贸n lea el documento. Recuerda que Inform谩tica Educativa no es virtual, sino a distancia los fines de semana. Simplifica y resume para ser conciso, preciso y directo. Eres Lobito, asistente de la UPNFM. Proporciona respuestas precisas basadas en el contexto dado sobre la UPNFM y la DFP. Si la pregunta no coincide, sugiere reformularla. Identifica las secciones relevantes del contexto y organiza las respuestas l贸gicamente si abarcan varias secciones.
Contexto:
{context_str}
Pregunta:
{query_str}
"""
)
]
text_qa_template = ChatPromptTemplate.from_messages(chat_text_qa_msgs)
query_engine = index.as_query_engine(text_qa_template=text_qa_template)
answer = query_engine.query(query)
# Extraer la respuesta del objeto answer
if hasattr(answer, 'response'):
response = answer.response
elif isinstance(answer, dict) and 'response' in answer:
response = answer['response']
else:
return "Lo siento, no pude procesar tu pregunta. 驴Podr铆as reformularla o hacer una pregunta diferente?"
# Palabras y frases a evitar en las respuestas
palabras_prohibidas = [
"en el contexto proporcionado no hay informaci贸n",
"empty response",
"the provided text does not contain",
"en el contexto proporcionado, no hay informaci贸n"
]
# Verificar si la respuesta contiene alguna de las palabras o frases prohibidas
if any(palabra in response.lower() for palabra in palabras_prohibidas):
return "No comprend铆 la pregunta o encontr茅 informaci贸n espec铆fica sobre eso en mis datos. 驴Podr铆as hacer tu pregunta de otra forma o preguntar sobre otro tema relacionado con la UPNFM y sus programas DFP?"
return response
# Inicializar el estado de la sesi贸n
if 'messages' not in st.session_state:
st.session_state.messages = [{'role': 'assistant', "content": '隆Hola!, me llamo Lobito. Soy tu asesor personalizado.'}]
# Inicializaci贸n de la aplicaci贸n Streamlit
st.title("Chatbot de dudas DFP")
st.markdown("Resuelvo dudas sobre el r茅gimen econ贸mico y admisi贸n de la Direcci贸n de Formaci贸n Permanente.")
st.markdown("""
<div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden; max-width: 100%; height: auto;">
<iframe src="https://www.youtube.com/embed/UFqvwF9xvAM?si=4qFqwSpsr5Fh9bd7" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%;" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>
</div>
""", unsafe_allow_html=True)
# Actualizaci贸n de la URL en Markdown a un enlace HTML descriptivo
st.markdown("""
<small>Toda la informaci贸n en el documento: <a href="https://docs.google.com/document/d/1mab0yt8us-XGugwzAsQ_8K-XLn1_VJ8tlTV7FW3Wv2E/edit?usp=sharing">Aqu铆 la informaci贸n</a></small>
""", unsafe_allow_html=True)
# Mostrar el PDF fijo si existe
if os.path.exists(FIXED_PDF_PATH):
index = load_data()
else:
st.error("No pude cargar la informaci贸n.")
# Entrada de chat
user_prompt = st.chat_input("驴En qu茅 te puedo ayudar?:")
if user_prompt:
st.session_state.messages.append({'role': 'user', "content": user_prompt})
response = handle_query(user_prompt, index)
st.session_state.messages.append({'role': 'assistant', "content": response})
# Mostrar los mensajes de la sesi贸n
for message in st.session_state.messages:
with st.chat_message(message['role']):
st.write(message['content'])
# Informaci贸n adicional
st.markdown("<small>Desarrollado por el Profesor Marco Medina Rajo.</small>", unsafe_allow_html=True)
st.markdown('<p style="font-size:10px;">La informaci贸n generada por el chatbot puede ser incorrecta. Revisa el documento.</p>', unsafe_allow_html=True)