Spaces:
Build error
Build error
| import streamlit as st | |
| import openai | |
| import os | |
| import time | |
| import base64 | |
| import random | |
| from dotenv import load_dotenv | |
| from google.cloud import texttospeech, aiplatform | |
| from google.auth import default | |
| import PyPDF2 | |
| from fpdf import FPDF | |
| import tempfile | |
| # Cargar variables de entorno desde el archivo .env | |
| load_dotenv() | |
| openai.api_key = os.getenv("OPENAI_API_KEY") | |
| google_api_key = os.getenv("GOOGLE_API_KEY") | |
| google_cx = os.getenv("GOOGLE_CX") | |
| os.environ["GOOGLE_APPLICATION_CREDENTIALS"] = "botidinamix-g.json" | |
| project_id = os.getenv("GOOGLE_PROJECT_ID") | |
| location = os.getenv("GOOGLE_LOCATION") | |
| # Configuración de Streamlit | |
| st.set_page_config(page_title="Asistente Teológico", page_icon="📖") | |
| # Estilos CSS personalizados | |
| st.markdown( | |
| """ | |
| <style> | |
| @import url('https://fonts.googleapis.com/css2?family=Roboto:wght@400;700&display=swap'); | |
| body { | |
| background-color: #000000; | |
| color: #ECF0F1; | |
| background-image: url('https://s1.1zoom.me/big0/395/Fields_Sunrises_and_499477.jpg'); | |
| background-size: cover; | |
| font-family: 'Roboto', sans-serif; | |
| } | |
| .stButton>button { | |
| background-color: #4CAF50; | |
| color: white; | |
| border-radius: 10px; | |
| font-size: 16px; | |
| padding: 10px 20px; | |
| } | |
| .stTextInput>div>div>input { | |
| border: 1px solid #4CAF50; | |
| border-radius: 10px; | |
| font-size: 16px; | |
| padding: 10px; | |
| } | |
| .stMarkdown>div>p { | |
| color: black; | |
| max-height: 300px; | |
| overflow-y: auto; | |
| font-size: 16px; | |
| } | |
| .stMarkdown>h1, .stMarkdown>h2, .stMarkdown>h3, .stMarkdown>h4, .stMarkdown>h5, .stMarkdown>h6 { | |
| color: white; | |
| font-weight: bold; | |
| font-style: italic; | |
| } | |
| .stAudio { | |
| margin-top: 20px; | |
| border: 2px solid #4CAF50; | |
| border-radius: 10px; | |
| } | |
| .stFileUploader>div>div>input { | |
| border: 1px solid #4CAF50; | |
| border-radius: 10px; | |
| font-size: 16px; | |
| } | |
| .spinner { | |
| border: 8px solid #f3f3f3; | |
| border-top: 8px solid #4CAF50; | |
| border-radius: 50%; | |
| width: 60px; | |
| height: 60px; | |
| animation: spin 1s linear infinite; | |
| } | |
| @keyframes spin { | |
| 0% { transform: rotate(0deg); } | |
| 100% { transform: rotate(360deg); } | |
| } | |
| .video-container { | |
| border: 3px solid blue; | |
| background-color: gold; | |
| padding: 10px; | |
| border-radius: 10px; | |
| margin-bottom: 20px; | |
| } | |
| .assistant-response { | |
| max-height: 200px; | |
| overflow-y: auto; | |
| font-size: 16px; | |
| } | |
| </style> | |
| """, | |
| unsafe_allow_html=True, | |
| ) | |
| # Encabezado | |
| st.image("biblie.jpg") | |
| st.title("📖 LOS CÓDIGOS DE DIOS - BOTIDINAMIX AI") | |
| st.markdown("Bienvenido al Asistente Teológico, donde puedes preguntar sobre interpretaciones y reflexiones bíblicas.") | |
| # Barra lateral para la navegación | |
| st.sidebar.title("Navegación") | |
| page = st.sidebar.selectbox("Selecciona una página", ["Página Principal", "Chat Asistente", "Generador de Frases Bíblicas", "Recibir Reflexión", "La conexión", "Diario Reflexivo"]) | |
| # Inicializar el cliente de Vertex AI | |
| credentials, _ = default() | |
| aiplatform.init(project=project_id, location=location, credentials=credentials) | |
| # Función para generar imágenes con Vertex AI | |
| def generar_imagen_vertex(prompt): | |
| response = aiplatform.TextToImageModel.from_pretrained("text-to-image").predict({"prompt": prompt}) | |
| return response["generated_images"][0]["image_uri"] | |
| # Función para generar texto con Vertex AI | |
| def generar_texto_vertex(prompt): | |
| response = aiplatform.TextGenerationModel.from_pretrained("text-bison").predict({"prompt": prompt}) | |
| return response["generated_text"] | |
| # Función para generar reflexión usando Vertex AI | |
| def generar_reflexion(keyword): | |
| prompt = f"Genera una reflexión inspiradora sobre {keyword} en el contexto de la espiritualidad y la Biblia." | |
| respuesta = generar_texto_vertex(prompt) | |
| return respuesta | |
| # Función para convertir texto a voz | |
| def text_to_speech_base64(text): | |
| client = texttospeech.TextToSpeechClient() | |
| input_text = texttospeech.SynthesisInput(text=text) | |
| voice = texttospeech.VoiceSelectionParams(language_code="es-ES", ssml_gender=texttospeech.SsmlVoiceGender.NEUTRAL) | |
| audio_config = texttospeech.AudioConfig(audio_encoding=texttospeech.AudioEncoding.MP3) | |
| response = client.synthesize_speech(input=input_text, voice=voice, audio_config=audio_config) | |
| return base64.b64encode(response.audio_content).decode("utf-8") | |
| # Función para obtener un audio aleatorio de la carpeta "reflexiones" | |
| def obtener_audio_aleatorio(): | |
| carpeta_reflexiones = "reflexiones" # Cambia esta ruta por la correcta | |
| archivos = os.listdir(carpeta_reflexiones) | |
| archivos_mp3 = [archivo for archivo in archivos if archivo.endswith(".mp3")] | |
| if archivos_mp3: | |
| audio_seleccionado = random.choice(archivos_mp3) | |
| with open(os.path.join(carpeta_reflexiones, audio_seleccionado), "rb") as audio_file: | |
| audio_bytes = audio_file.read() | |
| return base64.b64encode(audio_bytes).decode("utf-8"), audio_seleccionado | |
| return None, None | |
| # Función para extraer texto de un PDF | |
| def extraer_texto_pdf(pdf_path): | |
| text = "" | |
| with open(pdf_path, "rb") as file: | |
| reader = PyPDF2.PdfFileReader(file) | |
| for page_num in range(reader.numPages): | |
| text += reader.getPage(page_num).extract_text() | |
| return text | |
| # Función "La conexión" para generar oraciones del PDF | |
| def generar_oracion_desde_pdf(): | |
| pdf_path = "diario-de-oraciones.pdf" # Ruta al PDF | |
| texto_pdf = extraer_texto_pdf(pdf_path) | |
| prompt = f"Genera una oración inspiradora basada en el siguiente texto: {texto_pdf[:2000]}" # Limitar a los primeros 2000 caracteres | |
| respuesta = generar_texto_vertex(prompt) | |
| return respuesta | |
| # Función para generar y descargar un PDF con la entrada del diario | |
| def generar_pdf(fecha, versiculo, rema, investigacion, reflexion): | |
| pdf = FPDF() | |
| pdf.add_page() | |
| pdf.set_font("Arial", size=12) | |
| pdf.set_fill_color(230, 230, 230) | |
| pdf.set_text_color(0, 0, 0) | |
| pdf.image("flores.png", x=10, y=8, w=190) # Puedes cambiar la imagen por otra | |
| pdf.ln(20) | |
| pdf.cell(0, 10, f"Fecha: {fecha}", ln=True, fill=True) | |
| pdf.cell(0, 10, f"Versículo: {versiculo}", ln=True, fill=True) | |
| pdf.cell(0, 10, "Rema:", ln=True, fill=True) | |
| pdf.multi_cell(0, 10, rema, fill=True) | |
| pdf.cell(0, 10, "Investigación:", ln=True, fill=True) | |
| pdf.multi_cell(0, 10, investigacion, fill=True) | |
| pdf.cell(0, 10, "Reflexión:", ln=True, fill=True) | |
| pdf.multi_cell(0, 10, reflexion, fill=True) | |
| with tempfile.NamedTemporaryFile(delete=False, suffix=".pdf") as tmpfile: | |
| pdf.output(tmpfile.name) | |
| return tmpfile.name | |
| if page == "Página Principal": | |
| # Video de YouTube que se reproduce automáticamente | |
| st.markdown( | |
| """ | |
| <iframe width="560" height="315" src="https://www.youtube.com/embed/dPRrJ8za3qU?autoplay=1&mute=1" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen></iframe> | |
| """, | |
| unsafe_allow_html=True, | |
| ) | |
| elif page == "Chat Asistente": | |
| # Chat con el asistente | |
| st.subheader("🗣️ Chat con el Asistente") | |
| if 'mensajes' not in st.session_state: | |
| st.session_state.mensajes = [] | |
| for mensaje in st.session_state.mensajes: | |
| with st.chat_message(mensaje["role"]): | |
| if isinstance(mensaje["content"], str): | |
| st.markdown(mensaje["content"]) | |
| elif isinstance(mensaje["content"], bytes): | |
| st.image(mensaje["content"]) | |
| pregunta_usuario = st.text_input("Escribe tu pregunta sobre la Biblia:", key="pregunta_input") | |
| imagen_usuario = st.file_uploader("Sube una imagen (opcional):", type=["png", "jpg", "jpeg"]) | |
| if st.button("Enviar"): | |
| if pregunta_usuario or imagen_usuario: | |
| 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) | |
| if imagen_usuario: | |
| imagen_bytes = imagen_usuario.getvalue() | |
| st.session_state.mensajes.append({"role": "user", "content": imagen_bytes, "timestamp": time.time()}) | |
| with st.chat_message("user"): | |
| st.image(imagen_bytes) | |
| # Limpiar el campo de texto usando JavaScript para evitar el error de modificación del estado | |
| st.markdown( | |
| """ | |
| <script> | |
| document.querySelector('input[type="text"]').value = ""; | |
| </script> | |
| """, | |
| unsafe_allow_html=True, | |
| ) | |
| with st.spinner("Meditando su respuesta..."): | |
| with st.empty(): | |
| spinner = st.markdown('<div class="spinner"></div>', unsafe_allow_html=True) | |
| time.sleep(2) # Simulación del tiempo de procesamiento | |
| spinner.empty() | |
| if pregunta_usuario: | |
| respuesta = generar_reflexion(pregunta_usuario) | |
| st.session_state.mensajes.append({"role": "assistant", "content": respuesta, "timestamp": time.time()}) | |
| with st.chat_message("assistant"): | |
| st.markdown(f'<div class="assistant-response">{respuesta}</div>', unsafe_allow_html=True) | |
| # Convertir texto a voz | |
| audio_base64 = text_to_speech_base64(respuesta) | |
| audio_html = f""" | |
| <audio autoplay> | |
| <source src="data:audio/mp3;base64,{audio_base64}" type="audio/mp3"> | |
| </audio> | |
| """ | |
| st.markdown(audio_html, unsafe_allow_html=True) | |
| # Reproducir video automáticamente | |
| st.markdown('<div class="video-container">', unsafe_allow_html=True) | |
| st.markdown( | |
| """ | |
| <video autoplay loop muted playsinline style="width: 100%;"> | |
| <source src="https://cdn.pika.art/v1/3d0aafad-36b6-4341-b2bf-b4d5fbcf0445/Hola_bienvenido_a_este_maravilloso_programa._Donde_podr_s_conocer_y_profundizar_m_s_en_la_palabra_de_seed3422648958323119.mp4" type="video/mp4"> | |
| </video> | |
| """, | |
| unsafe_allow_html=True, | |
| ) | |
| st.markdown('</div>', unsafe_allow_html=True) | |
| else: | |
| st.warning("Por favor, ingresa una pregunta antes de enviar.") | |
| elif page == "Generador de Frases Bíblicas": | |
| # Función para generar una imagen y reflexión | |
| def generar_imagen_y_reflexion(keyword): | |
| try: | |
| reflexion = generar_reflexion(keyword) | |
| audio_base64 = text_to_speech_base64(reflexion) | |
| imagen_url = generar_imagen_vertex(f"spirituality {keyword}") | |
| st.image(imagen_url) | |
| st.markdown(reflexion) | |
| audio_html = f""" | |
| <audio autoplay> | |
| <source src="data:audio/mp3;base64,{audio_base64}" type="audio/mp3"> | |
| </audio> | |
| """ | |
| st.markdown(audio_html, unsafe_allow_html=True) | |
| except Exception as e: | |
| st.error(f"Error al generar la imagen y reflexión: {e}") | |
| st.subheader("✨ Generador de Frases Bíblicas") | |
| keyword = st.text_input("Introduce una palabra clave:") | |
| if st.button("Generar"): | |
| if keyword: | |
| generar_imagen_y_reflexion(keyword) | |
| else: | |
| st.warning("Por favor, introduce una palabra clave.") | |
| elif page == "Recibir Reflexión": | |
| st.subheader("🔊 Recibir Reflexión") | |
| if st.button("Reproducir Reflexión"): | |
| audio_base64, audio_nombre = obtener_audio_aleatorio() | |
| if audio_base64: | |
| st.markdown(f"Reproduciendo: {audio_nombre}") | |
| audio_html = f""" | |
| <audio autoplay> | |
| <source src="data:audio/mp3;base64,{audio_base64}" type="audio/mp3"> | |
| </audio> | |
| """ | |
| st.markdown(audio_html, unsafe_allow_html=True) | |
| else: | |
| st.warning("No se encontraron reflexiones en la carpeta especificada.") | |
| elif page == "La conexión": | |
| st.subheader("🙏 La conexión: Generador de Oraciones") | |
| if st.button("Generar Oración"): | |
| oracion = generar_oracion_desde_pdf() | |
| st.markdown(oracion) | |
| audio_base64 = text_to_speech_base64(oracion) | |
| audio_html = f""" | |
| <audio autoplay> | |
| <source src="data:audio/mp3;base64,{audio_base64}" type="audio/mp3"> | |
| </audio> | |
| """ | |
| st.markdown(audio_html, unsafe_allow_html=True) | |
| elif page == "Diario Reflexivo": | |
| st.subheader("📔 Diario Reflexivo") | |
| with st.form("diario_reflexivo_form"): | |
| fecha = st.date_input("Fecha") | |
| versiculo = st.text_input("Versículo") | |
| rema = st.text_area("Rema") | |
| investigacion = st.text_area("Investigación en la palabra de Dios") | |
| reflexion = st.text_area("Reflexión") | |
| submit_button = st.form_submit_button(label="Guardar en PDF") | |
| if submit_button: | |
| pdf_path = generar_pdf(fecha, versiculo, rema, investigacion, reflexion) | |
| with open(pdf_path, "rb") as f: | |
| st.download_button( | |
| label="Descargar Diario Reflexivo en PDF", | |
| data=f, | |
| file_name="diario_reflexivo.pdf", | |
| mime="application/pdf" | |
| ) | |