Josedcape commited on
Commit
c378bb7
·
verified ·
1 Parent(s): 7d8fa55

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +146 -193
app.py CHANGED
@@ -1,201 +1,154 @@
 
1
  import streamlit as st
2
- import openai
3
  from dotenv import load_dotenv
4
- import nltk
5
  import os
6
- import tempfile
7
- from nltk.tokenize import word_tokenize
8
- from nltk.corpus import stopwords
9
- from nltk.stem import SnowballStemmer
10
- import PyPDF2
11
- import time
12
- from google.cloud import texttospeech
13
- from streamlit_webrtc import webrtc_streamer, WebRtcMode, AudioProcessorBase
14
-
15
- # Configuración de NLTK
16
- nltk.download('punkt')
17
- nltk.download('stopwords')
18
-
19
- # Cargar la clave API desde el archivo .env
20
  load_dotenv()
21
- os.environ["GOOGLE_APPLICATION_CREDENTIALS"] = "botidinamix-g.json"
22
  openai.api_key = os.getenv("OPENAI_API_KEY")
23
 
24
- # Función para extraer texto del PDF
25
- def extraer_texto_pdf(archivo):
26
- texto = ""
27
- if archivo:
28
- with tempfile.NamedTemporaryFile(delete=False) as temp_file:
29
- temp_file.write(archivo.read())
30
- temp_file_path = temp_file.name
31
- with open(temp_file_path, 'rb') as file:
32
- reader = PyPDF2.PdfReader(file)
33
- for page in range(len(reader.pages)):
34
- texto += reader.pages[page].extract_text()
35
- os.unlink(temp_file_path)
36
- return texto
37
-
38
- # Función para preprocesar texto
39
- def preprocesar_texto(texto):
40
- tokens = word_tokenize(texto, language='spanish')
41
- tokens = [word.lower() for word in tokens if word.isalpha()]
42
- stopwords_es = set(stopwords.words('spanish'))
43
- tokens = [word for word in tokens if word not in stopwords_es]
44
- stemmer = SnowballStemmer('spanish')
45
- tokens = [stemmer.stem(word) for word in tokens]
46
- return " ".join(tokens)
47
-
48
- # Clase para procesar audio
49
- class AudioProcessor(AudioProcessorBase):
50
- def __init__(self):
51
- self.audio_bytes = b''
52
-
53
- def recv(self, frame):
54
- self.audio_bytes += frame.to_ndarray().tobytes()
55
- return frame
56
-
57
- # Función para obtener respuestas
58
- def obtener_respuesta(pregunta, contexto="", modelo="gpt-4", temperatura=0.5):
59
- respuesta = openai.Completion.create(
60
- engine=modelo,
61
- prompt=f"Pregunta: {pregunta}\nContexto: {contexto}\nRespuesta:",
62
- max_tokens=150,
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
63
  temperature=temperatura,
64
- ).choices[0].text.strip()
65
-
66
- client = texttospeech.TextToSpeechClient()
67
- synthesis_input = texttospeech.SynthesisInput(text=respuesta)
68
- voice = texttospeech.VoiceSelectionParams(
69
- language_code="es-ES",
70
- ssml_gender=texttospeech.SsmlVoiceGender.NEUTRAL,
71
- )
72
- audio_config = texttospeech.AudioConfig(
73
- audio_encoding=texttospeech.AudioEncoding.MP3,
74
- )
75
- response = client.synthesize_speech(
76
- input=synthesis_input, voice=voice, audio_config=audio_config
77
- )
78
- audio_path = tempfile.NamedTemporaryFile(delete=False, suffix=".mp3").name
79
- with open(audio_path, "wb") as out:
80
- out.write(response.audio_content)
81
-
82
- return respuesta, audio_path
83
-
84
- # Main App
85
- def main():
86
- # --- Diseño general ---
87
- st.set_page_config(page_title="Asistente Teológico", page_icon="📖")
88
-
89
- # --- Estilos CSS personalizados ---
90
- st.markdown(
91
- """
92
- <style>
93
- body {
94
- background: #f2f3f5;
95
- color: #333;
96
- }
97
- .stButton>button {
98
- background-color: #4CAF50;
99
- color: white;
100
- border-radius: 10px;
101
- }
102
- .stTextInput>div>div>input {
103
- border: 1px solid #4CAF50;
104
- border-radius: 10px;
105
- }
106
- .stMarkdown>div>p {
107
- color: #4CAF50;
108
- font-weight: bold;
109
- }
110
- .stAudio {
111
- margin-top: 20px;
112
- border: 2px solid #4CAF50;
113
- border-radius: 10px;
114
- }
115
- .stFileUploader>div>div>input {
116
- border: 1px solid #4CAF50;
117
- border-radius: 10px;
118
- }
119
- </style>
120
- """,
121
- unsafe_allow_html=True,
122
  )
123
-
124
- # --- Encabezado ---
125
- st.image("biblie.jpg")
126
- st.title("📖 LOS CODIGOS DE DIOS - BOTIDINAMIX AI")
127
- st.markdown("Bienvenido al Asistente Teológico, donde puedes preguntar sobre interpretaciones y reflexiones bíblicas.")
128
-
129
- # --- Subir PDF ---
130
- st.subheader("📄 Subir PDF")
131
- st.info("Sube un archivo PDF con contenido bíblico y el asistente responderá en función de su contenido.")
132
- archivo_pdf = st.file_uploader("Selecciona un archivo PDF", type=["pdf"])
133
-
134
- texto_extraido = ""
135
- if archivo_pdf:
136
- texto_extraido = extraer_texto_pdf(archivo_pdf)
137
- st.success("Texto extraído del PDF exitosamente.")
138
- st.text_area("Texto extraído", value=texto_extraido, height=200)
139
-
140
- if not texto_extraido:
141
- texto_extraido = st.text_area("Texto extraído", height=200)
142
-
143
- texto_preprocesado = preprocesar_texto(texto_extraido)
144
-
145
- # --- Chat ---
146
- st.subheader("🗣️ Chat con el Asistente")
147
- if 'mensajes' not in st.session_state:
148
- st.session_state.mensajes = []
149
-
150
- for mensaje in st.session_state.mensajes:
151
- with st.chat_message(mensaje["role"]):
152
- st.markdown(mensaje["content"])
153
-
154
- def on_audio(audio_bytes):
155
- with st.spinner("Transcribiendo..."):
156
- transcript = openai.Audio.transcribe("whisper-1", audio_bytes)
157
- pregunta_usuario = transcript["text"]
158
- st.session_state.mensajes.append({"role": "user", "content": pregunta_usuario, "timestamp": time.time()})
159
- with st.chat_message("user"):
160
- st.markdown(pregunta_usuario)
161
-
162
- st.subheader("🎤 Captura de voz")
163
- st.info("Haz clic en el micrófono y comienza a hablar. Tu pregunta se transcribirá automáticamente.")
164
- if st.button("Grabar 🎙️"):
165
- webrtc_ctx = webrtc_streamer(
166
- key="example",
167
- mode=WebRtcMode.SENDONLY,
168
- audio_receiver_size=256,
169
- rtc_configuration={
170
- "iceServers": [{"urls": ["stun:stun.l.google.com:19302"]}]
171
- },
172
- media_stream_constraints={"audio": True},
173
- audio_processor_factory=AudioProcessor,
174
- )
175
-
176
- if webrtc_ctx.audio_receiver:
177
- audio_frames = webrtc_ctx.audio_receiver.get_frames(timeout=1)
178
- for audio_frame in audio_frames:
179
- audio_bytes = audio_frame.to_ndarray().tobytes()
180
- on_audio(audio_bytes)
181
-
182
- st.markdown("---")
183
- pregunta_usuario = st.text_input("Escribe tu pregunta sobre la Biblia:")
184
- if st.button("Enviar"):
185
- if pregunta_usuario:
186
- st.session_state.mensajes.append({"role": "user", "content": pregunta_usuario, "timestamp": time.time()})
187
- with st.chat_message("user"):
188
- st.markdown(pregunta_usuario)
189
-
190
- with st.spinner("Generando respuesta..."):
191
- respuesta, audio_path = obtener_respuesta(pregunta_usuario, texto_preprocesado, modelo="gpt-4", temperatura=0.5)
192
- st.session_state.mensajes.append({"role": "assistant", "content": respuesta, "timestamp": time.time()})
193
- with st.chat_message("assistant"):
194
- st.markdown(respuesta)
195
- st.audio(audio_path, format="audio/mp3", start_time=0, autoplay=True)
196
- else:
197
- st.warning("Por favor, ingresa una pregunta antes de enviar.")
198
-
199
- if __name__ == "__main__":
200
- main()
201
-
 
 
 
1
+ import pandas as pd
2
  import streamlit as st
 
3
  from dotenv import load_dotenv
4
+ import openai
5
  import os
6
+
7
+ # Configuración de la clave API
 
 
 
 
 
 
 
 
 
 
 
 
8
  load_dotenv()
 
9
  openai.api_key = os.getenv("OPENAI_API_KEY")
10
 
11
+ # Clases para la gestión de pedidos
12
+ class PedidoAgent:
13
+ def __init__(self, menu_csv_path):
14
+ self.menu_csv_path = menu_csv_path
15
+ self.menu_data = self.load_menu()
16
+
17
+ def load_menu(self):
18
+ try:
19
+ df_menu = pd.read_csv(self.menu_csv_path)
20
+ productos = df_menu["Producto"].tolist()
21
+ precios = df_menu["Precio"].tolist()
22
+ return {"productos": productos, "precios": precios}
23
+ except Exception as e:
24
+ st.error(f"Error al cargar el menú: {e}")
25
+ return None
26
+
27
+ def realizar_pedido(self, state):
28
+ if not self.menu_data:
29
+ st.warning("No se pudo cargar el menú.")
30
+ return
31
+
32
+ productos = self.menu_data["productos"]
33
+ precios = self.menu_data["precios"]
34
+
35
+ # Interfaz de usuario para seleccionar productos y cantidades
36
+ with st.form("pedido_form"):
37
+ producto_seleccionado = st.selectbox("Producto:", productos)
38
+ cantidad = st.number_input("Cantidad:", min_value=1, value=1)
39
+ submitted = st.form_submit_button("Agregar al pedido")
40
+
41
+ if submitted:
42
+ precio = precios[productos.index(producto_seleccionado)]
43
+ state.pedidos.append(
44
+ {"Producto": producto_seleccionado, "Cantidad": cantidad, "Precio": precio}
45
+ )
46
+ st.success("Pedido agregado correctamente")
47
+
48
+ # Mostrar el pedido actual
49
+ st.subheader("Pedido actual:")
50
+ if state.pedidos:
51
+ df_pedidos = pd.DataFrame(state.pedidos)
52
+ st.table(df_pedidos)
53
+
54
+ class CalculoPedidoAgent:
55
+ def calcular_total(self, state):
56
+ st.subheader("Resumen del Pedido")
57
+ if state.pedidos:
58
+ df_pedidos = pd.DataFrame(state.pedidos)
59
+ st.table(df_pedidos)
60
+ total = df_pedidos["Cantidad"].mul(df_pedidos["Precio"]).sum()
61
+ st.markdown(f"**Total: ${total:.2f}**")
62
+ else:
63
+ st.info("El pedido está vacío.")
64
+
65
+ # Función para obtener respuesta de OpenAI
66
+ def obtener_respuesta(pregunta, modelo="gpt-4", temperatura=0.5):
67
+ response = openai.ChatCompletion.create(
68
+ model=modelo,
69
+ messages=[{"role": "system", "content": "You are a knowledgeable theological assistant."},
70
+ {"role": "user", "content": pregunta}],
71
  temperature=temperatura,
72
+ max_tokens=150,
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
73
  )
74
+ respuesta = response['choices'][0]['message']['content']
75
+ return respuesta
76
+
77
+ # Configuración de Streamlit
78
+ st.set_page_config(page_title="Asistente Teológico", page_icon="📖")
79
+
80
+ # Estilos CSS personalizados
81
+ st.markdown(
82
+ """
83
+ <style>
84
+ body {
85
+ background: #f2f3f5;
86
+ color: #333;
87
+ }
88
+ .stButton>button {
89
+ background-color: #4CAF50;
90
+ color: white;
91
+ border-radius: 10px;
92
+ }
93
+ .stTextInput>div>div>input {
94
+ border: 1px solid #4CAF50;
95
+ border-radius: 10px;
96
+ }
97
+ .stMarkdown>div>p {
98
+ color: #4CAF50;
99
+ font-weight: bold;
100
+ }
101
+ .stAudio {
102
+ margin-top: 20px;
103
+ border: 2px solid #4CAF50;
104
+ border-radius: 10px;
105
+ }
106
+ .stFileUploader>div>div>input {
107
+ border: 1px solid #4CAF50;
108
+ border-radius: 10px;
109
+ }
110
+ </style>
111
+ """,
112
+ unsafe_allow_html=True,
113
+ )
114
+
115
+ # Encabezado
116
+ st.image("biblia.jpg")
117
+ st.title("📖 Asistente Teológico - BOTIDINAMIX AI")
118
+ st.markdown("Bienvenido al Asistente Teológico, donde puedes preguntar sobre interpretaciones y reflexiones bíblicas.")
119
+
120
+ # Chat
121
+ st.subheader("🗣️ Chat con el Asistente")
122
+ if 'mensajes' not in st.session_state:
123
+ st.session_state.mensajes = []
124
+
125
+ for mensaje in st.session_state.mensajes:
126
+ with st.chat_message(mensaje["role"]):
127
+ st.markdown(mensaje["content"])
128
+
129
+ pregunta_usuario = st.text_input("Escribe tu pregunta sobre la Biblia:")
130
+ if st.button("Enviar"):
131
+ if pregunta_usuario:
132
+ st.session_state.mensajes.append({"role": "user", "content": pregunta_usuario, "timestamp": time.time()})
133
+ with st.chat_message("user"):
134
+ st.markdown(pregunta_usuario)
135
+
136
+ with st.spinner("Generando respuesta..."):
137
+ respuesta = obtener_respuesta(pregunta_usuario)
138
+ st.session_state.mensajes.append({"role": "assistant", "content": respuesta, "timestamp": time.time()})
139
+ with st.chat_message("assistant"):
140
+ st.markdown(respuesta)
141
+ else:
142
+ st.warning("Por favor, ingresa una pregunta antes de enviar.")
143
+
144
+ # Gestión de pedidos
145
+ st.subheader("📋 Gestión de Pedidos")
146
+ menu_csv_path = "menu.csv" # Ruta al archivo CSV del menú
147
+ if 'pedidos' not in st.session_state:
148
+ st.session_state.pedidos = []
149
+
150
+ pedido_agent = PedidoAgent(menu_csv_path)
151
+ calculo_pedido_agent = CalculoPedidoAgent()
152
+
153
+ pedido_agent.realizar_pedido(st.session_state)
154
+ calculo_pedido_agent.calcular_total(st.session_state)