import os import time import groq from google.cloud import texttospeech_v1 as texttospeech import streamlit as st from dotenv import load_dotenv import speech_recognition as sr from datetime import datetime, timedelta from streamlit_autorefresh import st_autorefresh # Configurar la página de Streamlit st.set_page_config(page_title="Galatea Asistente - OMARDENT", layout="wide") # Estilo CSS para el fondo st.markdown( """ """, unsafe_allow_html=True ) # Agregar el logo st.image("Logo icon.jpg", use_column_width=True) # Asegúrate de que el archivo icon.jpg esté en la misma carpeta # Cargar las claves API desde el archivo .env load_dotenv() groq_api_key = os.getenv("GROQ_API_KEY") os.environ["GOOGLE_APPLICATION_CREDENTIALS"] = "credentials/botidinamix-g.json" # Verificar que la clave API de Groq está configurada if not groq_api_key: st.error("No API key provided for Groq. Please set your API key in the .env file.") else: # Inicializar el cliente de Groq client_groq = groq.Groq(api_key=groq_api_key) # Función para obtener respuesta de Groq y generar audio con Google TTS def obtener_respuesta_groq(pregunta, contexto="", modelo="llama3-8b-8192", temperatura=0.5): if not pregunta: st.error("La pregunta no puede estar vacía.") return "Lo siento, la pregunta no puede estar vacía." try: with st.spinner('Evaluando su respuesta...'): # Hacer la llamada a la API de Groq con el rol de Galatea contexto = "Actúas como Galatea, la asistente virtual de la clínica odontológica Omardent. Tu función es recordar citas y eventos de forma clara y profesional." response = client_groq.chat.completions.create( messages=[ {"role": "system", "content": contexto}, {"role": "user", "content": pregunta} ], model=modelo ) # Acceder al contenido de la respuesta de Groq respuesta = response.choices[0].message.content.strip() # Configurar la solicitud de síntesis de voz (Google TTS) client = texttospeech.TextToSpeechClient() input_text = texttospeech.SynthesisInput(text=respuesta) voice = texttospeech.VoiceSelectionParams( language_code="es-ES", ssml_gender=texttospeech.SsmlVoiceGender.FEMALE ) audio_config = texttospeech.AudioConfig( audio_encoding=texttospeech.AudioEncoding.MP3 ) # Realizar la solicitud de síntesis de voz response_audio = client.synthesize_speech( input=input_text, voice=voice, audio_config=audio_config ) # Guardar el archivo de audio temporalmente audio_file_path = f'tmp_respuesta_{int(time.time())}.mp3' with open(audio_file_path, 'wb') as audio_file: audio_file.write(response_audio.audio_content) # Devolver la respuesta y la ruta del archivo de audio return respuesta, audio_file_path except Exception as e: st.error(f"Error al generar la respuesta y el audio: {e}") return "Lo siento, ocurrió un error al procesar tu solicitud.", None # Función para manejar el chat del asistente def mostrar_galatea_asistente(): st.title("🦷 Galatea - Asistente Virtual OMARDENT") # Inicializa el historial del chat y el temporizador if 'mensajes_chat' not in st.session_state: st.session_state['mensajes_chat'] = [] if 'respuesta_programada' not in st.session_state: st.session_state['respuesta_programada'] = None # Mostrar los mensajes del chat for mensaje in st.session_state['mensajes_chat']: clase = "user" if mensaje["role"] == "user" else "assistant" st.markdown(f'
', unsafe_allow_html=True) # Entrada de texto para la pregunta del usuario pregunta_usuario = st.text_input("Escribe tu pregunta aquí:") # Selector de intervalo de tiempo intervalo = st.selectbox("Selecciona el intervalo de tiempo (minutos)", [1, 2, 5, 10, 15, 30, 60]) # Grabar y transcribir audio if st.button("Grabar y Transcribir Audio"): recognizer = sr.Recognizer() with sr.Microphone() as source: st.info("Grabando...") audio = recognizer.listen(source, timeout=5) st.info("Grabación completa") try: text = recognizer.recognize_google(audio, language="es-ES") pregunta_usuario = text # Usar la transcripción como la pregunta except sr.UnknownValueError: st.error("No se pudo entender el audio") except sr.RequestError: st.error("Error al solicitar el servicio de reconocimiento de voz") # Programar la pregunta para ser respondida después del intervalo de tiempo seleccionado if st.button("Programar Respuesta"): if pregunta_usuario: # Guardar la pregunta en el historial st.session_state['mensajes_chat'].append({"role": "user", "content": pregunta_usuario}) # Calcular el tiempo en segundos tiempo_en_segundos = intervalo * 60 tiempo_ejecucion = datetime.now() + timedelta(minutes=intervalo) st.success(f"La respuesta se generará a las {tiempo_ejecucion.strftime('%H:%M:%S')}") # Guardar la información de la respuesta programada st.session_state['respuesta_programada'] = { 'pregunta': pregunta_usuario, 'tiempo_ejecucion': tiempo_ejecucion, 'tiempo_en_segundos': tiempo_en_segundos, 'audio_file_path': None, 'notificacion_reproducida': False # Para saber si se ha reproducido la notificación } # Actualizar la interfaz cada segundo para verificar si el tiempo ha pasado y mostrar el contador st_autorefresh(interval=1000, key="data_refresh") # Verificar si hay una respuesta programada que deba ejecutarse if 'respuesta_programada' in st.session_state and st.session_state['respuesta_programada']: respuesta_programada = st.session_state['respuesta_programada'] # Mostrar el contador del tiempo restante tiempo_restante = respuesta_programada['tiempo_ejecucion'] - datetime.now() if tiempo_restante.total_seconds() > 0: minutos, segundos = divmod(int(tiempo_restante.total_seconds()), 60) horas, minutos = divmod(minutos, 60) tiempo_restante_str = f"{horas}h {minutos}m {segundos}s" if horas > 0 else f"{minutos}m {segundos}s" st.info(f"Tiempo restante: {tiempo_restante_str}") if st.session_state['respuesta_programada']['notificacion_reproducida'] and st.session_state['respuesta_programada']['audio_file_path'] is None: respuesta, audio_file_path = obtener_respuesta_groq(respuesta_programada['pregunta']) # Guardar la respuesta y el audio en el estado st.session_state['mensajes_chat'].append({"role": "assistant", "content": respuesta}) st.session_state['respuesta_programada']['audio_file_path'] = audio_file_path # Reproducir el audio si ya fue generado if st.session_state['respuesta_programada']['audio_file_path']: audio_file_path = st.session_state['respuesta_programada']['audio_file_path'] with open(audio_file_path, "rb") as audio_file: st.audio(audio_file.read(), format="audio/mp3") # Función principal def main(): mostrar_galatea_asistente() if __name__ == "__main__": main()