JeCabrera commited on
Commit
c0073a3
·
verified ·
1 Parent(s): e28c5c9

Upload app.py

Browse files
Files changed (1) hide show
  1. app.py +115 -131
app.py CHANGED
@@ -22,13 +22,19 @@ CONFIG = {
22
  }
23
  }
24
 
25
- # Usar CONFIG en lugar de constantes separadas
26
  st.set_page_config(
27
  page_title=CONFIG['page']['title'],
28
  page_icon=CONFIG['page']['icon'],
29
  layout=CONFIG['page']['layout']
30
  )
31
 
 
 
 
 
 
 
32
  def load_css(file_path):
33
  try:
34
  with open(file_path) as f:
@@ -44,43 +50,27 @@ def load_css(file_path):
44
  </style>
45
  """, unsafe_allow_html=True)
46
 
47
- load_dotenv()
48
- GOOGLE_API_KEY=os.environ.get('GOOGLE_API_KEY')
49
- genai.configure(api_key=GOOGLE_API_KEY)
50
-
51
- new_chat_id = f'{time.time()}'
52
- # Configuración de avatares e identificadores
53
- MODEL_ROLE = 'ai'
54
- AI_AVATAR_ICON = '🤖'
55
- USER_AVATAR_ICON = '👤' # Aseguramos que el emoji sea visible
56
- AI_AVATAR_ICON = '🤖'
57
-
58
- # Función para manejar títulos de chat de manera unificada
59
  def get_chat_title(messages):
60
  if not messages:
61
  return "Nuevo Chat"
62
  first_msg = messages[0]['content'] if messages else ""
63
- # Limitar el título a los primeros 30 caracteres
64
  title = first_msg[:30] + "..." if len(first_msg) > 30 else first_msg
65
  return title
66
 
67
  def get_formulas_for_prompt():
68
- """Genera texto formateado con las fórmulas PUV para incluir en el prompt del sistema"""
69
  prompt_text = "\nFÓRMULAS DE PROPUESTAS ÚNICAS DE VALOR (PUVs):\n\n"
70
 
71
  for key, formula in puv_formulas.items():
72
  prompt_text += f"🔹 {key}:\n"
73
  prompt_text += f" - Descripción: {formula.get('description', 'Descripción no disponible').strip()}\n"
74
 
75
- # Extraer estructura de la descripción
76
  if 'Structure:' in formula.get('description', ''):
77
  estructura = formula['description'].split('Structure:')[1].split('Key elements:')[0].strip()
78
  prompt_text += " - Estructura Base:\n"
79
  for line in estructura.split('\n'):
80
- if line.strip(): # Ignorar líneas vacías
81
  prompt_text += f" * {line.strip()}\n"
82
 
83
- # Manejar ejemplos
84
  ejemplos = formula.get('examples', [])[:2]
85
  if ejemplos:
86
  prompt_text += " - Ejemplos destacados:\n"
@@ -93,7 +83,98 @@ def get_formulas_for_prompt():
93
 
94
  return prompt_text
95
 
96
- # Definición COMPLETA del prompt multipersona para el sistema
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
97
  SYSTEM_PROMPT = f"""
98
  Eres un equipo colaborativo de expertos de clase mundial trabajando juntos para crear Propuestas Únicas de Valor (PUVs) excepcionales que conviertan a la audiencia en clientes.
99
 
@@ -126,8 +207,9 @@ WELCOME_MESSAGE = """
126
  ¿En qué puedo ayudarte hoy?
127
  """
128
 
129
- # Inicializar el estado de la sesión
130
- # Inicialización unificada
 
131
  if 'chats_in_memory' not in st.session_state:
132
  st.session_state.update({
133
  'chats_in_memory': {},
@@ -138,54 +220,48 @@ if 'chats_in_memory' not in st.session_state:
138
  'gemini_history': []
139
  })
140
 
141
- # Sidebar allows a list of past chats
142
  with st.sidebar:
143
- # Centrar el logo
144
  col1, col2, col3 = st.columns([1, 2, 1])
145
  with col2:
146
  st.image("assets/robocopy_logo.png", width=300)
147
 
148
  st.write('# Chats Anteriores')
149
 
150
- # Simplificar la lógica del selector de chat
151
  chat_options = [new_chat_id] + list(st.session_state.chats_in_memory.keys())
152
  current_index = chat_options.index(st.session_state.current_chat_id) if st.session_state.current_chat_id in chat_options else 0
153
 
154
- # Modificar a:
155
  st.session_state.current_chat_id = st.selectbox(
156
- label='Selecciona un chat anterior',
157
- options=chat_options,
158
- index=current_index,
159
- format_func=lambda x: st.session_state.chats_in_memory.get(x, {}).get('title', 'Nuevo Chat'),
160
- key='chat_selector_unique'
161
  )
162
 
163
- # Botón para borrar el historial
164
  if st.button('🗑️ Borrar Historial de Chat Actual'):
165
  if st.session_state.current_chat_id in st.session_state.chats_in_memory:
166
  del st.session_state.chats_in_memory[st.session_state.current_chat_id]
167
  st.session_state.messages = []
168
  st.session_state.gemini_history = []
169
  st.session_state.chat_title = 'Nuevo Chat'
170
- st.rerun() # Versión actualizada del comando
171
 
172
- # Configuración del modelo
173
  model = genai.GenerativeModel(model_name='gemini-2.0-flash')
174
  st.session_state.model = model
175
  st.session_state.chat = st.session_state.model.start_chat(history=st.session_state.gemini_history)
176
 
177
- # Si es un chat nuevo, enviar el prompt del sistema como primer mensaje
178
  if not st.session_state.gemini_history:
179
- # Enviamos el prompt del sistema como primer mensaje (invisible para el usuario)
180
  st.session_state.chat.send_message(SYSTEM_PROMPT)
181
  st.session_state.gemini_history = st.session_state.chat.history
182
 
183
- # Mostrar mensajes del historial
184
  for message in st.session_state.messages:
185
  with st.chat_message(name=message['role'], avatar=message.get('avatar', USER_AVATAR_ICON if message['role'] == 'user' else AI_AVATAR_ICON)):
186
  st.markdown(message['content'])
187
 
188
- # ===== SECCIÓN DE EJEMPLOS =====
189
  if st.session_state.show_examples and not st.session_state.messages:
190
  main_container = st.container()
191
  with main_container:
@@ -211,16 +287,14 @@ if st.session_state.show_examples and not st.session_state.messages:
211
 
212
  st.markdown("---")
213
 
214
- # Entrada del usuario
215
  if prompt := st.chat_input('¿En qué puedo ayudarte hoy?'):
216
- # Añadir el mensaje del usuario primero
217
  with st.chat_message("user", avatar=USER_AVATAR_ICON):
218
  st.markdown(prompt)
219
  add_message("user", prompt, USER_AVATAR_ICON)
220
 
221
  is_first_message = len(st.session_state.messages) == 0
222
 
223
- # Añadir inicialización de chat si no existe
224
  if st.session_state.current_chat_id not in st.session_state.chats_in_memory:
225
  st.session_state.chats_in_memory[st.session_state.current_chat_id] = {
226
  'messages': [],
@@ -228,7 +302,6 @@ if prompt := st.chat_input('¿En qué puedo ayudarte hoy?'):
228
  'title': 'Nuevo Chat'
229
  }
230
 
231
- # Generar título basado en el primer mensaje del usuario
232
  try:
233
  title_response = st.session_state.model.generate_content(
234
  f"Genera un título corto (máximo 5 palabras) que describa esta consulta, sin comillas: '{prompt}'"
@@ -238,101 +311,12 @@ if prompt := st.chat_input('¿En qué puedo ayudarte hoy?'):
238
  except Exception as e:
239
  st.session_state.chat_title = f"Chat-{st.session_state.current_chat_id}"
240
 
241
- # Actualizar título en memoria
242
  st.session_state.chats_in_memory[st.session_state.current_chat_id]['title'] = st.session_state.chat_title
243
 
244
- # El mensaje de bienvenida se añade SIEMPRE que hay input
245
- # Debe condicionarse a is_first_message
246
  if is_first_message:
247
  add_message(MODEL_ROLE, WELCOME_MESSAGE, AI_AVATAR_ICON)
248
  with st.chat_message(name=MODEL_ROLE, avatar=AI_AVATAR_ICON):
249
  st.markdown(WELCOME_MESSAGE)
250
  update_chat_memory()
251
 
252
- process_model_response(prompt) # Mantener dentro del bloque
253
-
254
- # En la sección de ejemplos principal agregar:
255
- if 'show_examples' not in st.session_state:
256
- st.session_state.show_examples = True # Forzar muestra inicial
257
-
258
- if st.session_state.show_examples:
259
- # Añadir mensajes de ejemplo con avatares visibles
260
- add_message('ai', WELCOME_MESSAGE, AI_AVATAR_ICON)
261
- add_message('ai', "¿Quieres que te muestre algunos ejemplos de PUVs?", AI_AVATAR_ICON)
262
-
263
- # Usar contenedor para ancho completo
264
- main_container = st.container()
265
-
266
- with main_container:
267
- st.title("💡 RoboCopy - Asistente de PUVs")
268
- st.markdown("### Tu experto en crear Propuestas Únicas de Valor que convierten")
269
-
270
- st.markdown("### 🎯 Prueba estos ejemplos:")
271
-
272
- # Usar columnas con proporción ajustada para mejor distribución
273
- col1, col2 = st.columns([1, 1])
274
-
275
- with col1:
276
- if st.button("¿Cuál es la mejor fórmula para mi PUV? 🤔", use_container_width=True):
277
- handle_example_click("¿Podrías explicarme cuál es la mejor fórmula para crear una PUV efectiva para mi negocio?")
278
-
279
- if st.button("Necesito una PUV para mi tienda online 🛍️", use_container_width=True):
280
- handle_example_click("Quiero crear una PUV para mi tienda online de ropa sostenible dirigida a mujeres de 25-35 años")
281
-
282
- with col2:
283
- if st.button("Ayúdame a mejorar mi PUV actual ✨", use_container_width=True):
284
- handle_example_click("¿Podrías ayudarme a mejorar mi PUV actual para hacerla más persuasiva?")
285
-
286
- if st.button("Crear PUV para servicios profesionales 👔", use_container_width=True):
287
- handle_example_click("Necesito una PUV para mi servicio de consultoría en marketing digital")
288
-
289
- st.markdown("---")
290
-
291
- def add_message(role, content, avatar):
292
- """Función centralizada para añadir mensajes al historial"""
293
- message = {
294
- 'role': role,
295
- 'content': content,
296
- 'avatar': avatar
297
- }
298
- st.session_state.messages.append(message)
299
- return message
300
-
301
- def update_chat_memory():
302
- """Función centralizada para actualizar el chat en memoria"""
303
- st.session_state.chats_in_memory[st.session_state.current_chat_id].update({
304
- 'messages': st.session_state.messages,
305
- 'gemini_history': st.session_state.gemini_history,
306
- 'title': st.session_state.chat_title
307
- })
308
-
309
- def handle_example_click(prompt_text):
310
- """Función para manejar clicks en ejemplos"""
311
- st.session_state.update({
312
- 'show_examples': False,
313
- 'messages': [],
314
- 'current_chat_id': str(time.time()),
315
- 'gemini_history': [],
316
- 'chat_title': 'Nuevo Chat'
317
- })
318
-
319
- if st.session_state.current_chat_id not in st.session_state.chats_in_memory:
320
- st.session_state.chats_in_memory[st.session_state.current_chat_id] = {
321
- 'messages': [],
322
- 'gemini_history': [],
323
- 'title': 'Nuevo Chat'
324
- }
325
-
326
- try:
327
- title_response = st.session_state.model.generate_content(
328
- f"Título para consulta de ejemplo: '{prompt_text}' (máximo 4 palabras)"
329
- )
330
- st.session_state.chat_title = title_response.text.strip()[:25]
331
- except Exception as e:
332
- st.session_state.chat_title = f"Ejemplo-{time.strftime('%H:%M')}"
333
-
334
- st.session_state.chats_in_memory[st.session_state.current_chat_id]['title'] = st.session_state.chat_title
335
- process_model_response(prompt_text)
336
-
337
- st.markdown("---")
338
-
 
22
  }
23
  }
24
 
25
+ # Configuración de página
26
  st.set_page_config(
27
  page_title=CONFIG['page']['title'],
28
  page_icon=CONFIG['page']['icon'],
29
  layout=CONFIG['page']['layout']
30
  )
31
 
32
+ # Configuración de avatares e identificadores
33
+ MODEL_ROLE = 'ai'
34
+ AI_AVATAR_ICON = '🤖'
35
+ USER_AVATAR_ICON = '👤'
36
+
37
+ # === FUNCIONES AUXILIARES ===
38
  def load_css(file_path):
39
  try:
40
  with open(file_path) as f:
 
50
  </style>
51
  """, unsafe_allow_html=True)
52
 
 
 
 
 
 
 
 
 
 
 
 
 
53
  def get_chat_title(messages):
54
  if not messages:
55
  return "Nuevo Chat"
56
  first_msg = messages[0]['content'] if messages else ""
 
57
  title = first_msg[:30] + "..." if len(first_msg) > 30 else first_msg
58
  return title
59
 
60
  def get_formulas_for_prompt():
 
61
  prompt_text = "\nFÓRMULAS DE PROPUESTAS ÚNICAS DE VALOR (PUVs):\n\n"
62
 
63
  for key, formula in puv_formulas.items():
64
  prompt_text += f"🔹 {key}:\n"
65
  prompt_text += f" - Descripción: {formula.get('description', 'Descripción no disponible').strip()}\n"
66
 
 
67
  if 'Structure:' in formula.get('description', ''):
68
  estructura = formula['description'].split('Structure:')[1].split('Key elements:')[0].strip()
69
  prompt_text += " - Estructura Base:\n"
70
  for line in estructura.split('\n'):
71
+ if line.strip():
72
  prompt_text += f" * {line.strip()}\n"
73
 
 
74
  ejemplos = formula.get('examples', [])[:2]
75
  if ejemplos:
76
  prompt_text += " - Ejemplos destacados:\n"
 
83
 
84
  return prompt_text
85
 
86
+ def add_message(role, content, avatar):
87
+ message = {
88
+ 'role': role,
89
+ 'content': content,
90
+ 'avatar': avatar
91
+ }
92
+ st.session_state.messages.append(message)
93
+ return message
94
+
95
+ def update_chat_memory():
96
+ st.session_state.chats_in_memory[st.session_state.current_chat_id].update({
97
+ 'messages': st.session_state.messages,
98
+ 'gemini_history': st.session_state.gemini_history,
99
+ 'title': st.session_state.chat_title
100
+ })
101
+
102
+ def handle_model_error(error, retry_count, max_retries):
103
+ if retry_count >= max_retries:
104
+ error_message = f"Lo siento, estoy experimentando problemas para procesar tu solicitud. Por favor, intenta de nuevo más tarde. Error: {str(error)}"
105
+ with st.chat_message(name=MODEL_ROLE, avatar=AI_AVATAR_ICON):
106
+ st.error(error_message)
107
+ add_message(MODEL_ROLE, error_message, AI_AVATAR_ICON)
108
+ update_chat_memory()
109
+ return True
110
+ return False
111
+
112
+ def mostrar_con_efecto_escritura(texto, velocidad=0.05):
113
+ placeholder = st.empty()
114
+ contenido_actual = ""
115
+
116
+ for caracter in texto:
117
+ contenido_actual += caracter
118
+ placeholder.markdown(contenido_actual + "▌")
119
+ time.sleep(velocidad)
120
+
121
+ placeholder.markdown(contenido_actual)
122
+ return contenido_actual
123
+
124
+ def process_model_response(prompt, max_retries=3):
125
+ retry_count = 0
126
+ while retry_count < max_retries:
127
+ try:
128
+ response = st.session_state.chat.send_message(prompt, stream=True)
129
+ full_text = "".join(chunk.text for chunk in response)
130
+ mensaje_mostrado = mostrar_con_efecto_escritura(full_text, velocidad=0.01)
131
+
132
+ add_message(MODEL_ROLE, mensaje_mostrado, AI_AVATAR_ICON)
133
+ st.session_state.gemini_history = st.session_state.chat.history
134
+ update_chat_memory()
135
+ return True
136
+
137
+ except Exception as e:
138
+ retry_count += 1
139
+ if handle_model_error(e, retry_count, max_retries):
140
+ return False
141
+ wait_time = (1.5 ** retry_count)
142
+ time.sleep(wait_time)
143
+ return False
144
+
145
+ def handle_example_click(prompt_text):
146
+ st.session_state.update({
147
+ 'show_examples': False,
148
+ 'messages': [],
149
+ 'current_chat_id': str(time.time()),
150
+ 'gemini_history': [],
151
+ 'chat_title': 'Nuevo Chat'
152
+ })
153
+
154
+ if st.session_state.current_chat_id not in st.session_state.chats_in_memory:
155
+ st.session_state.chats_in_memory[st.session_state.current_chat_id] = {
156
+ 'messages': [],
157
+ 'gemini_history': [],
158
+ 'title': 'Nuevo Chat'
159
+ }
160
+
161
+ try:
162
+ title_response = st.session_state.model.generate_content(
163
+ f"Título para consulta de ejemplo: '{prompt_text}' (máximo 4 palabras)"
164
+ )
165
+ st.session_state.chat_title = title_response.text.strip()[:25]
166
+ except Exception as e:
167
+ st.session_state.chat_title = f"Ejemplo-{time.strftime('%H:%M')}"
168
+
169
+ st.session_state.chats_in_memory[st.session_state.current_chat_id]['title'] = st.session_state.chat_title
170
+ process_model_response(prompt_text)
171
+
172
+ # === CONFIGURACIÓN INICIAL ===
173
+ load_dotenv()
174
+ GOOGLE_API_KEY = os.environ.get('GOOGLE_API_KEY')
175
+ genai.configure(api_key=GOOGLE_API_KEY)
176
+
177
+ # Definición del prompt del sistema
178
  SYSTEM_PROMPT = f"""
179
  Eres un equipo colaborativo de expertos de clase mundial trabajando juntos para crear Propuestas Únicas de Valor (PUVs) excepcionales que conviertan a la audiencia en clientes.
180
 
 
207
  ¿En qué puedo ayudarte hoy?
208
  """
209
 
210
+ # === INICIALIZACIÓN DEL ESTADO ===
211
+ new_chat_id = str(time.time())
212
+
213
  if 'chats_in_memory' not in st.session_state:
214
  st.session_state.update({
215
  'chats_in_memory': {},
 
220
  'gemini_history': []
221
  })
222
 
223
+ # === SIDEBAR ===
224
  with st.sidebar:
 
225
  col1, col2, col3 = st.columns([1, 2, 1])
226
  with col2:
227
  st.image("assets/robocopy_logo.png", width=300)
228
 
229
  st.write('# Chats Anteriores')
230
 
 
231
  chat_options = [new_chat_id] + list(st.session_state.chats_in_memory.keys())
232
  current_index = chat_options.index(st.session_state.current_chat_id) if st.session_state.current_chat_id in chat_options else 0
233
 
 
234
  st.session_state.current_chat_id = st.selectbox(
235
+ label='Selecciona un chat anterior',
236
+ options=chat_options,
237
+ index=current_index,
238
+ format_func=lambda x: st.session_state.chats_in_memory.get(x, {}).get('title', 'Nuevo Chat'),
239
+ key='chat_selector_unique'
240
  )
241
 
 
242
  if st.button('🗑️ Borrar Historial de Chat Actual'):
243
  if st.session_state.current_chat_id in st.session_state.chats_in_memory:
244
  del st.session_state.chats_in_memory[st.session_state.current_chat_id]
245
  st.session_state.messages = []
246
  st.session_state.gemini_history = []
247
  st.session_state.chat_title = 'Nuevo Chat'
248
+ st.rerun()
249
 
250
+ # === CONFIGURACIÓN DEL MODELO ===
251
  model = genai.GenerativeModel(model_name='gemini-2.0-flash')
252
  st.session_state.model = model
253
  st.session_state.chat = st.session_state.model.start_chat(history=st.session_state.gemini_history)
254
 
 
255
  if not st.session_state.gemini_history:
 
256
  st.session_state.chat.send_message(SYSTEM_PROMPT)
257
  st.session_state.gemini_history = st.session_state.chat.history
258
 
259
+ # === MOSTRAR MENSAJES DEL HISTORIAL ===
260
  for message in st.session_state.messages:
261
  with st.chat_message(name=message['role'], avatar=message.get('avatar', USER_AVATAR_ICON if message['role'] == 'user' else AI_AVATAR_ICON)):
262
  st.markdown(message['content'])
263
 
264
+ # === SECCIÓN DE EJEMPLOS ===
265
  if st.session_state.show_examples and not st.session_state.messages:
266
  main_container = st.container()
267
  with main_container:
 
287
 
288
  st.markdown("---")
289
 
290
+ # === ENTRADA DEL USUARIO ===
291
  if prompt := st.chat_input('¿En qué puedo ayudarte hoy?'):
 
292
  with st.chat_message("user", avatar=USER_AVATAR_ICON):
293
  st.markdown(prompt)
294
  add_message("user", prompt, USER_AVATAR_ICON)
295
 
296
  is_first_message = len(st.session_state.messages) == 0
297
 
 
298
  if st.session_state.current_chat_id not in st.session_state.chats_in_memory:
299
  st.session_state.chats_in_memory[st.session_state.current_chat_id] = {
300
  'messages': [],
 
302
  'title': 'Nuevo Chat'
303
  }
304
 
 
305
  try:
306
  title_response = st.session_state.model.generate_content(
307
  f"Genera un título corto (máximo 5 palabras) que describa esta consulta, sin comillas: '{prompt}'"
 
311
  except Exception as e:
312
  st.session_state.chat_title = f"Chat-{st.session_state.current_chat_id}"
313
 
 
314
  st.session_state.chats_in_memory[st.session_state.current_chat_id]['title'] = st.session_state.chat_title
315
 
 
 
316
  if is_first_message:
317
  add_message(MODEL_ROLE, WELCOME_MESSAGE, AI_AVATAR_ICON)
318
  with st.chat_message(name=MODEL_ROLE, avatar=AI_AVATAR_ICON):
319
  st.markdown(WELCOME_MESSAGE)
320
  update_chat_memory()
321
 
322
+ process_model_response(prompt)