Spaces:
Sleeping
Sleeping
File size: 7,548 Bytes
193fffb |
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 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 |
from os import getenv
from dotenv import load_dotenv
import gradio as gr
import os
import json
from langchain_huggingface import HuggingFaceEmbeddings
from langchain_chroma import Chroma
from langchain_openai import ChatOpenAI
from langchain.schema import Document
# Cargar variables de entorno desde un archivo .env
load_dotenv()
# Inicializar el modelo de lenguaje de OpenAI
llm = ChatOpenAI(
openai_api_key=getenv("OPENROUTER_API_KEY"),
openai_api_base=getenv("OPENROUTER_BASE_URL"),
model_name="openai/gpt-4o",
model_kwargs={
"extra_headers": {
"Helicone-Auth": f"Bearer " + getenv("HELICONE_API_KEY")
}
},
)
# Cargar datos de preguntas frecuentes desde un archivo JSON
faqs_path = r"faqs.json"
with open(faqs_path, "r") as file:
faqs_data = json.load(file)
# Cargar datos del menú desde un archivo JSON
menu_path = r"menu.json"
with open(menu_path, "r") as file:
menu_data = json.load(file)
# Definir la ruta del archivo de reservas
reservas_path = r"reservas.json"
# Definir la ruta del archivo PDF del menú
menu_pdf_path = r"menu.pdf"
# Crear el archivo de reservas si no existe
if not os.path.exists(reservas_path):
with open(reservas_path, "w") as file:
json.dump([], file)
# Cargar datos de reservas desde un archivo JSON
with open(reservas_path, "r") as file:
reservas_data = json.load(file)
# Crear documentos a partir de las preguntas frecuentes
faqs_documents = [
Document(
page_content=pair["question"] + " " + pair["answer"],
metadata={"id": str(i)}
)
for i, pair in enumerate(faqs_data)
]
# Crear documentos a partir del menú
menu_documents = [
Document(
page_content=f"{nombre}: Categoría: {info.get('categoria', 'Desconocida')}, "
f"Alérgenos: {', '.join(info.get('alergenos', [])) if info.get('alergenos') else 'Ninguno'}, "
f"Precio: ${info.get('precio', 'Desconocido')}, "
f"Descripción: {info.get('descripcion', 'Sin descripción')}, "
f"Sin Gluten: {'Sí' if info.get('sin_gluten') else 'No'}, "
f"Vegan: {'Sí' if info.get('vegan') else 'No'}",
metadata={"tipo": "menu"}
)
for nombre, info in menu_data.items()
]
# Inicializar el modelo de embeddings de HuggingFace
embeddings = HuggingFaceEmbeddings(model_name="sentence-transformers/all-mpnet-base-v2")
# Inicializar la tienda de vectores Chroma
vectorstore = Chroma(embedding_function=embeddings)
# Agregar documentos de preguntas frecuentes y menú a la tienda de vectores
vectorstore.add_documents(faqs_documents)
vectorstore.add_documents(menu_documents)
# Estado de la reserva
estado_reserva = {}
# Función del chatbot
def chatbot(message, history):
global estado_reserva
message_lower = message.lower()
# Palabras clave para mostrar el menú
menu_keywords = [
"menu completo", "menú completo", "carta completa",
"ver menú", "ver menu", "mostrar menú", "mostrar menu", "quiero ver el menú",
"quiero ver la carta", "mostrar la carta", "ver la carta", "enséñame el menú",
"enséñame la carta", "dame el menú", "dame la carta", "muéstrame el menú",
"muéstrame la carta", "quiero el menú", "quiero la carta", "menu por favor",
"menú por favor", "carta por favor", "puedo ver el menú", "puedo ver la carta"
]
# Mostrar imagen del menú si el mensaje coincide con alguna palabra clave
if any(message_lower.strip() == word for word in menu_keywords):
yield gr.Image("menu.png")
return
# Continuar con el proceso de reserva si está en proceso
if estado_reserva.get("en_proceso"):
if "dia" not in estado_reserva:
estado_reserva["dia"] = message
yield "¿A qué hora deseas la reserva? (Formato HH:MM)"
return
elif "hora" not in estado_reserva:
estado_reserva["hora"] = message
yield "¿Para cuántas personas será la reserva?"
return
elif "personas" not in estado_reserva:
estado_reserva["personas"] = message
yield "A nombre de quién será la reserva?"
return
elif "nombre" not in estado_reserva:
estado_reserva["nombre"] = message
yield "(Opcional) Proporcione un número de teléfono de contacto o escriba 'no' para omitirlo."
return
elif "telefono" not in estado_reserva:
estado_reserva["telefono"] = message if message.lower() != "no" else "No proporcionado"
# Guardar la nueva reserva en el archivo JSON
nueva_reserva = {
"nombre": estado_reserva["nombre"],
"dia": estado_reserva["dia"],
"hora": estado_reserva["hora"],
"personas": estado_reserva["personas"],
"telefono": estado_reserva["telefono"]
}
with open(reservas_path, "r") as file:
reservas_actuales = json.load(file)
reservas_actuales.append(nueva_reserva)
with open(reservas_path, "w") as file:
json.dump(reservas_actuales, file, indent=2)
estado_reserva = {}
yield f"✅ ¡Reserva guardada con éxito! Aquí están los detalles:\n{json.dumps(nueva_reserva, indent=2)}"
return
# Iniciar el proceso de reserva si se menciona en el mensaje
if "reserva" in message_lower or "quiero reservar" in message_lower:
estado_reserva["en_proceso"] = True
yield "¿Para qué día quieres hacer la reserva? (Formato DD/MM/AAAA)"
return
# Buscar documentos relevantes en la tienda de vectores
relevant_docs = vectorstore.similarity_search(message)
# Crear el contexto para el modelo de lenguaje
context_text = "\n\n".join([doc.page_content for doc in relevant_docs])
final_prompt = (
"Eres un asistente virtual en un restaurante. Puedes responder preguntas sobre el menú, las reservas y las preguntas frecuentes. "
"Si el usuario menciona restricciones dietéticas, haz recomendaciones basadas en el menú disponible.\n\n"
f"{json.dumps(menu_data, indent=2)}\n\n"
f"Contexto relevante encontrado en la base de datos:\n{context_text}\n\n"
f"Pregunta: {message}\n"
"Respuesta:"
)
# Generar la respuesta del modelo de lenguaje
messages = [{"role": "user", "content": final_prompt}]
response = llm.stream(messages)
partial_response = ""
for chunk in response:
if chunk and hasattr(chunk, "content"):
content = chunk.content
if content is not None:
partial_response += content
yield partial_response
# Configurar la interfaz de Gradio
demo = gr.ChatInterface(
chatbot,
chatbot=gr.Chatbot(height=400, type="messages"),
textbox=gr.Textbox(placeholder="Escribe tu mensaje aquí...", container=False, scale=7),
title="ChatBot Restaurante",
description="Asistente virtual para reservas, menú y preguntas frecuentes.",
theme="ocean",
examples=[
"¿Cuáles son los horarios del restaurante?",
"¿Dónde están ubicados?",
"¿Aceptan pagos con tarjeta?",
"Quiero ver la carta",
"Quiero hacer una reserva"
],
type="messages",
editable=True,
save_history=True,
)
# Ejecutar la aplicación
if __name__ == "__main__":
demo.queue().launch()
|