CODIGOSDIOSa2 / app.py
Josedcape's picture
Update app.py
7099996 verified
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"
)