Spaces:
Sleeping
Sleeping
| import streamlit as st | |
| import openai | |
| from dotenv import load_dotenv | |
| import nltk | |
| import os | |
| import tempfile | |
| from nltk.tokenize import word_tokenize | |
| from nltk.corpus import stopwords | |
| from nltk.stem import SnowballStemmer | |
| import PyPDF2 | |
| import time | |
| from google.cloud import texttospeech | |
| from streamlit_webrtc import webrtc_streamer, WebRtcMode, AudioProcessorBase | |
| from Historial.historial_chat import cargar_historial, guardar_historial | |
| from agent_functions import menu_df, tomar_pedido_agente, procesar_orden_agente, generar_pdf_orden, obtener_respuesta, generar_mensaje_automatico | |
| # Configuración de NLTK | |
| nltk.download('punkt') | |
| nltk.download('stopwords') | |
| # Cargar la clave API desde el archivo .env | |
| load_dotenv() | |
| os.environ["GOOGLE_APPLICATION_CREDENTIALS"] = "botidinamix-g.json" | |
| openai.api_key = os.getenv("OPENAI_API_KEY") | |
| # Función para extraer texto del PDF | |
| def extraer_texto_pdf(archivo): | |
| texto = "" | |
| if archivo: | |
| with tempfile.NamedTemporaryFile(delete=False) as temp_file: | |
| temp_file.write(archivo.read()) | |
| temp_file_path = temp_file.name | |
| with open(temp_file_path, 'rb') as file: | |
| reader = PyPDF2.PdfReader(file) | |
| for page in range(len(reader.pages)): | |
| texto += reader.pages[page].extract_text() | |
| os.unlink(temp_file_path) | |
| return texto | |
| # Función para preprocesar texto | |
| def preprocesar_texto(texto): | |
| tokens = word_tokenize(texto, language='spanish') | |
| tokens = [word.lower() for word in tokens if word.isalpha()] | |
| stopwords_es = set(stopwords.words('spanish')) | |
| tokens = [word for word in tokens if word not in stopwords_es] | |
| stemmer = SnowballStemmer('spanish') | |
| tokens = [stemmer.stem(word) for word in tokens] | |
| return " ".join(tokens) | |
| # Clase para procesar audio | |
| class AudioProcessor(AudioProcessorBase): | |
| def __init__(self): | |
| self.audio_bytes = b'' | |
| def recv(self, frame): | |
| self.audio_bytes += frame.to_ndarray().tobytes() | |
| return frame | |
| # Main App | |
| def main(): | |
| # --- Diseño general --- | |
| st.set_page_config(page_title="Asistente Virtual", page_icon="🤖") | |
| # --- Estilos CSS personalizados --- | |
| st.markdown( | |
| """ | |
| <style> | |
| body { | |
| background: rgb(241,241,234); | |
| background: radial-gradient(circle, rgba(241,241,234,1) 4%, rgba(255,127,8,1) 36%, rgba(235,255,8,1) 94%, rgba(0,0,255,1) 99%); | |
| } | |
| h1, h2, h3, h4, h5, h6 { | |
| color: green !important; | |
| font-weight: bold !important; | |
| } | |
| .stChatFloatingInputContainer { | |
| background-color: rgba(255, 255, 255, 0.8); | |
| border-radius: 10px; | |
| } | |
| .stTextInput > div > div > input { | |
| color: #333; | |
| } | |
| [data-testid="stChatMessage"] { | |
| background-color: black !important; | |
| color: gold !important; | |
| border-radius: 10px; | |
| } | |
| [data-testid="stChatMessage"] p { | |
| color: gold !important; | |
| } | |
| ::-webkit-scrollbar { | |
| width: 16px; | |
| } | |
| ::-webkit-scrollbar-thumb { | |
| background-color: #FFD700; | |
| border-radius: 10px; | |
| } | |
| .st-spinner > div { | |
| border-top-color: transparent; | |
| border-right-color: transparent; | |
| animation: spin 1s linear infinite; | |
| } | |
| @keyframes spin { | |
| from { transform: rotate(0deg); } | |
| to { transform: rotate(360deg); } | |
| } | |
| </style> | |
| """, | |
| unsafe_allow_html=True, | |
| ) | |
| # --- Barra lateral --- | |
| with st.sidebar: | |
| st.image("hamburguesa napolitana.jpg") | |
| st.title("🤖 RESTAURANTE SAZON BURGER 🍔✨-BOTIDINAMIX AI") | |
| st.markdown("---") | |
| # Opciones de navegación | |
| pagina = st.selectbox("Selecciona una página", ["Chat", "Subir PDF", "Agentes"]) | |
| # --- Página principal --- | |
| if pagina == "Chat": | |
| mostrar_chat() | |
| elif pagina == "Subir PDF": | |
| mostrar_subir_pdf() | |
| elif pagina == "Agentes": | |
| mostrar_agentes() | |
| else: | |
| mostrar_principal() | |
| def mostrar_chat(): | |
| # --- Botones de historial --- | |
| if st.button("Buscar Historial"): | |
| st.session_state.mostrar_historial = True | |
| if st.button("Borrar Historial"): | |
| st.session_state.mensajes = [] | |
| st.session_state.mostrar_historial = False | |
| st.success("Historial borrado correctamente") | |
| # --- Chatbot --- | |
| if 'mensajes' not in st.session_state: | |
| st.session_state.mensajes = cargar_historial() | |
| for mensaje in st.session_state.mensajes: | |
| with st.chat_message(mensaje["role"]): | |
| st.markdown(mensaje["content"]) | |
| # Función para manejar la entrada de audio | |
| def on_audio(audio_bytes): | |
| with st.spinner("Transcribiendo..."): | |
| transcript = openai.Audio.transcribe("whisper-1", audio_bytes) | |
| pregunta_usuario = transcript["text"] | |
| st.session_state.mensajes.append({"role": "user", "content": pregunta_usuario, "timestamp": time.time()}) | |
| with st.chat_message("user"): | |
| st.markdown(pregunta_usuario) | |
| st.subheader("🎤 Captura de voz") | |
| st.info("Haz clic en el micrófono y comienza a hablar. Tu pregunta se transcribirá automáticamente.") | |
| with st.container(): | |
| if st.button("Grabar 🎙️"): | |
| st.session_state.run_webrtc = True | |
| if st.session_state.get("run_webrtc", False): | |
| webrtc_ctx = webrtc_streamer( | |
| key="example", | |
| mode=WebRtcMode.SENDONLY, | |
| audio_receiver_size=256, | |
| rtc_configuration={ | |
| "iceServers": [{"urls": ["stun:stun.l.google.com:19302"]}] | |
| }, | |
| media_stream_constraints={"audio": True}, | |
| audio_processor_factory=AudioProcessor, | |
| ) | |
| if webrtc_ctx.audio_receiver: | |
| audio_frames = webrtc_ctx.audio_receiver.get_frames(timeout=1) | |
| for audio_frame in audio_frames: | |
| audio_bytes = audio_frame.to_ndarray().tobytes() | |
| on_audio(audio_bytes) | |
| st.markdown("---") | |
| st.subheader("📄 Subir PDF") | |
| st.info("Sube un archivo PDF y el asistente responderá en función de su contenido.") | |
| archivo_pdf = st.file_uploader("Selecciona un archivo PDF", type=["pdf"]) | |
| texto_extraido = "" | |
| if archivo_pdf: | |
| texto_extraido = extraer_texto_pdf(archivo_pdf) | |
| st.success("Texto extraído del PDF exitosamente.") | |
| st.text_area("Texto extraído", value=texto_extraido, height=200) | |
| if not texto_extraido: | |
| texto_extraido = st.text_area("Texto extraído", height=200) | |
| texto_preprocesado = preprocesar_texto(texto_extraido) | |
| # --- Opciones de entrada de usuario --- | |
| st.markdown("---") | |
| pregunta_usuario = st.text_input("Escribe tu pregunta:") | |
| if st.button("Enviar"): | |
| if pregunta_usuario: | |
| st.session_state.mensajes.append({"role": "user", "content": pregunta_usuario, "timestamp": time.time()}) | |
| with st.chat_message("user"): | |
| st.markdown(pregunta_usuario) | |
| with st.spinner("Generando respuesta..."): | |
| respuesta, audio_path = obtener_respuesta(pregunta_usuario, texto_preprocesado, modelo="gpt-4", temperatura=0.5) | |
| st.session_state.mensajes.append({"role": "assistant", "content": respuesta, "timestamp": time.time()}) | |
| with st.chat_message("assistant"): | |
| st.markdown(respuesta) | |
| st.audio(audio_path, format="audio/mp3", start_time=0, autoplay=True) | |
| # Reproducir video automáticamente | |
| st.video("https://www.canva.com/design/DAGJTK28LQ8/VJaWOIwiJcHVuEuTnVx_vA/edit?utm_content=DAGJTK28LQ8&utm_campaign=designshare&utm_medium=link2&utm_source=sharebutton", start_time=0) | |
| guardar_historial(st.session_state.mensajes) | |
| else: | |
| st.warning("Por favor, ingresa una pregunta antes de enviar.") | |
| def mostrar_subir_pdf(): | |
| st.subheader("📄 Subir PDF") | |
| st.info("Sube un archivo PDF y el asistente responderá en función de su contenido.") | |
| archivo_pdf = st.file_uploader("Selecciona un archivo PDF", type=["pdf"]) | |
| texto_extraido = "" | |
| if archivo_pdf: | |
| texto_extraido = extraer_texto_pdf(archivo_pdf) | |
| st.success("Texto extraído del PDF exitosamente.") | |
| st.text_area("Texto extraído", value=texto_extraido, height=200) | |
| if not texto_extraido: | |
| texto_extraido = st.text_area("Texto extraído", height=200) | |
| texto_preprocesado = preprocesar_texto(texto_extraido) | |
| # --- Opciones de entrada de usuario --- | |
| st.markdown("---") | |
| pregunta_usuario = st.text_input("Escribe tu pregunta:") | |
| if st.button("Enviar"): | |
| if pregunta_usuario: | |
| st.session_state.mensajes.append({"role": "user", "content": pregunta_usuario, "timestamp": time.time()}) | |
| with st.chat_message("user"): | |
| st.markdown(pregunta_usuario) | |
| with st.spinner("Generando respuesta..."): | |
| respuesta, audio_path = obtener_respuesta(pregunta_usuario, texto_preprocesado, modelo="gpt-4", temperatura=0.5) | |
| st.session_state.mensajes.append({"role": "assistant", "content": respuesta, "timestamp": time.time()}) | |
| with st.chat_message("assistant"): | |
| st.markdown(respuesta) | |
| st.audio(audio_path, format="audio/mp3", start_time=0, autoplay=True) | |
| guardar_historial(st.session_state.mensajes) | |
| else: | |
| st.warning("Por favor, ingresa una pregunta antes de enviar.") | |
| def mostrar_agentes(): | |
| st.subheader("📋 Menú y Pedidos") | |
| st.success("Menú cargado exitosamente. Listo para tomar pedidos.") | |
| st.write(menu_df) | |
| # Captura de pedido | |
| st.markdown("Selecciona los items del menú:") | |
| items_seleccionados = st.multiselect("Items", menu_df['item'].tolist()) | |
| if st.button("Tomar Pedido"): | |
| if items_seleccionados: | |
| pedido_usuario = ','.join(items_seleccionados) | |
| confirmados = tomar_pedido_agente(pedido_usuario) | |
| st.info(f"Pedido confirmado: {confirmados}") | |
| total = procesar_orden_agente(','.join(confirmados)) | |
| st.success(f"Total del pedido: ${total}") | |
| # Generar PDF de la orden | |
| order_details = {item: {'price': menu_df[menu_df['item'] == item]['price'].values[0]} for item in confirmados} | |
| pdf_path = generar_pdf_orden(order_details) | |
| st.markdown(f"[Descargar PDF de la Orden]({pdf_path})", unsafe_allow_html=True) | |
| # Generar mensaje automático | |
| mensaje_automatico = generar_mensaje_automatico(confirmados) | |
| st.session_state.mensajes_agente.append({"role": "assistant", "content": mensaje_automatico, "timestamp": time.time()}) | |
| with st.chat_message("assistant"): | |
| st.markdown(mensaje_automatico) | |
| # --- Chat para Agentes --- | |
| st.subheader("Chat con Agentes") | |
| if 'mensajes_agente' not in st.session_state: | |
| st.session_state.mensajes_agente = [] | |
| for mensaje in st.session_state.mensajes_agente: | |
| with st.chat_message(mensaje["role"]): | |
| st.markdown(mensaje["content"]) | |
| agente_pregunta = st.text_input("Escribe tu pregunta para el agente:") | |
| if st.button("Enviar al Agente"): | |
| if agente_pregunta: | |
| st.session_state.mensajes_agente.append({"role": "user", "content": agente_pregunta, "timestamp": time.time()}) | |
| with st.chat_message("user"): | |
| st.markdown(agente_pregunta) | |
| # Procesar la respuesta del agente | |
| with st.spinner("El agente está respondiendo..."): | |
| respuesta_agente, audio_path = obtener_respuesta(agente_pregunta, '', modelo="gpt-4", temperatura=0.5) | |
| st.session_state.mensajes_agente.append({"role": "assistant", "content": respuesta_agente, "timestamp": time.time()}) | |
| with st.chat_message("assistant"): | |
| st.markdown(respuesta_agente) | |
| st.audio(audio_path, format="audio/mp3", start_time=0, autoplay=True) | |
| else: | |
| st.warning("Por favor, ingresa una pregunta antes de enviar.") | |
| def mostrar_principal(): | |
| st.subheader("🗣️ Asistente Virtual con Chat y Respuestas en Voz") | |
| st.video("", start_time=0) | |
| if 'mensajes' not in st.session_state: | |
| st.session_state.mensajes = [] | |
| for mensaje in st.session_state.mensajes: | |
| with st.chat_message(mensaje["role"]): | |
| st.markdown(mensaje["content"]) | |
| pregunta_usuario = st.text_input("Escribe tu pregunta:") | |
| if st.button("Enviar"): | |
| if pregunta_usuario: | |
| st.session_state.mensajes.append({"role": "user", "content": pregunta_usuario, "timestamp": time.time()}) | |
| with st.chat_message("user"): | |
| st.markdown(pregunta_usuario) | |
| with st.spinner("Generando respuesta..."): | |
| respuesta, audio_path = obtener_respuesta(pregunta_usuario, '', modelo="gpt-4", temperatura=0.5) | |
| st.session_state.mensajes.append({"role": "assistant", "content": respuesta, "timestamp": time.time()}) | |
| with st.chat_message("assistant"): | |
| st.markdown(respuesta) | |
| st.audio(audio_path, format="audio/mp3", start_time=0, autoplay=True) | |
| else: | |
| st.warning("Por favor, ingresa una pregunta antes de enviar.") | |
| if __name__ == "__main__": | |
| main() | |