JeCabrera commited on
Commit
fa423f3
·
verified ·
1 Parent(s): 58664cf

Upload app.py

Browse files
Files changed (1) hide show
  1. app.py +250 -100
app.py CHANGED
@@ -36,6 +36,70 @@ MODEL_ROLE = 'ai'
36
  AI_AVATAR_ICON = '🤖' # Cambia el emoji por uno de robot para coincidir con tu logo
37
  USER_AVATAR_ICON = '👤' # Añade un avatar para el usuario
38
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
39
  # Create a data/ folder if it doesn't already exist
40
  try:
41
  os.mkdir('data/')
@@ -73,11 +137,32 @@ with st.sidebar:
73
  format_func=lambda x: past_chats.get(x, 'Nuevo Chat' if x != st.session_state.chat_id else st.session_state.chat_title),
74
  placeholder='_',
75
  )
76
- # Save new chats after a message has been sent to AI
77
- # TODO: Give user a chance to name chat
78
- st.session_state.chat_title = f'SesiónChat-{st.session_state.chat_id}'
 
 
 
 
 
 
79
 
80
- st.write('# Chatea con Gemini')
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
81
 
82
  # Chat history (allows to ask multiple questions)
83
  try:
@@ -89,113 +174,178 @@ try:
89
  )
90
  print('old cache')
91
  except:
92
- st.session_state.messages = []
 
93
  st.session_state.gemini_history = []
94
  print('new_cache made')
95
- st.session_state.model = genai.GenerativeModel('gemini-2.0-flash')
 
 
 
 
 
96
  st.session_state.chat = st.session_state.model.start_chat(
97
  history=st.session_state.gemini_history,
98
  )
99
 
100
- # Display chat messages from history on app rerun
101
- for message in st.session_state.messages:
102
- with st.chat_message(
103
- name=message['role'],
104
- avatar=message.get('avatar'),
105
- ):
106
- st.markdown(message['content'])
 
 
 
 
 
 
 
107
 
108
  # React to user input
109
- if prompt := st.chat_input('¿En qué puedo ayudarte hoy?'): # Mensaje más amigable
110
- # Save this as a chat for later
111
- if st.session_state.chat_id not in past_chats.keys():
112
- # Es una nueva conversación, generemos un título basado en el primer mensaje
113
- # Primero, guardamos un título temporal
114
- temp_title = f'SesiónChat-{st.session_state.chat_id}'
115
- past_chats[st.session_state.chat_id] = temp_title
 
116
 
117
- # Generamos un título basado en el contenido del mensaje
118
- try:
119
- # Usamos el mismo modelo para generar un título corto
120
- title_generator = genai.GenerativeModel('gemini-2.0-flash')
121
- title_response = title_generator.generate_content(
122
- f"Genera un título corto (máximo 5 palabras) que describa de qué trata esta consulta, sin usar comillas ni puntuación: '{prompt}'")
123
-
124
- # Obtenemos el título generado
125
- generated_title = title_response.text.strip()
 
 
 
 
 
 
 
 
 
 
 
126
 
127
- # Actualizamos el título en past_chats
128
- if generated_title:
129
- st.session_state.chat_title = generated_title
130
- past_chats[st.session_state.chat_id] = generated_title
131
- else:
 
 
 
 
 
 
 
 
 
 
 
 
 
132
  st.session_state.chat_title = temp_title
133
- except Exception as e:
134
- print(f"Error al generar título: {e}")
135
- st.session_state.chat_title = temp_title
136
- else:
137
- # Ya existe esta conversación, usamos el título guardado
138
- st.session_state.chat_title = past_chats[st.session_state.chat_id]
139
-
140
- joblib.dump(past_chats, 'data/past_chats_list')
141
-
142
- # Display user message in chat message container
143
- with st.chat_message('user', avatar=USER_AVATAR_ICON): # Añade el avatar del usuario
144
- st.markdown(prompt)
145
- # Add user message to chat history
146
- st.session_state.messages.append(
147
- dict(
148
- role='user',
149
- content=prompt,
150
- )
151
- )
152
- ## Send message to AI
153
- response = st.session_state.chat.send_message(
154
- prompt,
155
- stream=True,
156
- )
157
- # Display assistant response in chat message container
158
- with st.chat_message(
159
- name=MODEL_ROLE,
160
- avatar=AI_AVATAR_ICON,
161
- ):
162
- message_placeholder = st.empty()
163
- full_response = ''
164
- assistant_response = response
165
 
166
- # Añade un indicador de "escribiendo..."
167
- typing_indicator = st.empty()
168
- typing_indicator.markdown("*RoboCopy está escribiendo...*")
169
 
170
- # Streams in a chunk at a time
171
- for chunk in response:
172
- # Simulate stream of chunk
173
- # TODO: Chunk missing `text` if API stops mid-stream ("safety"?)
174
- for ch in chunk.text.split(' '):
175
- full_response += ch + ' '
176
- time.sleep(0.1) # Aumentado de 0.05 a 0.1 segundos para una velocidad más lenta
177
- # Rewrites with a cursor at end
178
- message_placeholder.write(full_response + '▌')
179
- # Elimina el indicador de escritura
180
- typing_indicator.empty()
181
- # Write full message with placeholder
182
- message_placeholder.write(full_response)
183
-
184
- # Add assistant response to chat history
185
- st.session_state.messages.append(
186
- dict(
187
- role=MODEL_ROLE,
188
- content=st.session_state.chat.history[-1].parts[0].text,
189
- avatar=AI_AVATAR_ICON,
190
  )
191
- )
192
- st.session_state.gemini_history = st.session_state.chat.history
193
- # Save to file
194
- joblib.dump(
195
- st.session_state.messages,
196
- f'data/{st.session_state.chat_id}-st_messages',
197
- )
198
- joblib.dump(
199
- st.session_state.gemini_history,
200
- f'data/{st.session_state.chat_id}-gemini_messages',
201
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
36
  AI_AVATAR_ICON = '🤖' # Cambia el emoji por uno de robot para coincidir con tu logo
37
  USER_AVATAR_ICON = '👤' # Añade un avatar para el usuario
38
 
39
+ # Definición del prompt multipersona para el sistema
40
+ SYSTEM_PROMPT = """
41
+ 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.
42
+
43
+ EL EQUIPO DE EXPERTOS:
44
+ 1. ESTRATEGA MAESTRO DE MARKETING:
45
+ - Experto en marcos de propuestas de valor y estrategias de conversión
46
+ - Asegura que las PUVs sigan la estructura de fórmula seleccionada con precisión
47
+ - Se enfoca en la colocación estratégica de elementos clave de conversión
48
+
49
+ 2. COPYWRITER ELITE DE RESPUESTA DIRECTA:
50
+ - Crea ganchos, historias y elementos persuasivos convincentes
51
+ - Elabora propuestas de valor irresistibles que impulsan conversiones
52
+ - Asegura que el lenguaje resuene con la audiencia objetivo
53
+
54
+ 3. ESPECIALISTA EN PSICOLOGÍA DE AUDIENCIA:
55
+ - Experto en comprender las motivaciones y objeciones de la audiencia
56
+ - Crea contenido que construye conexión genuina y confianza
57
+ - Identifica y aborda miedos y deseos ocultos
58
+
59
+ 4. MAESTRO DE DIFERENCIACIÓN:
60
+ - Crea propuestas únicas que destacan entre la competencia
61
+ - Desarrolla ejemplos y casos de estudio relacionables
62
+ - Asegura que las PUVs apoyen la transformación que se ofrece
63
+
64
+ 5. EXPERTO EN CONVERSIÓN:
65
+ - Se especializa en crear PUVs que mantengan la atención y generen acción
66
+ - Crea elementos interactivos y ganchos de engagement
67
+ - Asegura que las PUVs fluyan naturalmente y mantengan el interés alto
68
+ """
69
+
70
+ # Mensaje de bienvenida mejorado
71
+ WELCOME_MESSAGE = """
72
+ # 🚀 ¡Bienvenido a RoboCopy PUV Creator! 🚀
73
+
74
+ Somos un equipo de expertos en marketing y psicología de audiencia, especializados en crear **Propuestas Únicas de Valor (PUVs)** que transforman visitantes en clientes.
75
+
76
+ ## 💼 ¿Qué podemos hacer por ti?
77
+
78
+ Creamos PUVs poderosas y persuasivas que:
79
+ - **Capturan la atención** de tu audiencia ideal
80
+ - **Comunican claramente** el valor único de tu oferta
81
+ - **Convierten visitantes** en clientes leales
82
+
83
+ ## 📋 Para ayudarte, necesitamos conocer:
84
+
85
+ 1️⃣ **Tu producto o servicio**: ¿Qué ofreces exactamente? Cuéntanos sus características principales.
86
+
87
+ 2️⃣ **Tu audiencia objetivo**: ¿Quiénes son tus clientes ideales? Sé lo más específico posible.
88
+
89
+ 3️⃣ **La fórmula que prefieres**:
90
+ - **A) Problema-Solución**: "Para [audiencia] que sufre [problema], [producto] proporciona [solución]"
91
+ - **B) Antes-Después**: "Transforma [situación actual] en [situación deseada] con [producto]"
92
+ - **C) Beneficio Principal**: "[Producto] te ayuda a [beneficio principal] sin [obstáculo común]"
93
+
94
+ ## 🔍 Nuestro proceso:
95
+
96
+ 1. Analizaremos los puntos de dolor de tu audiencia
97
+ 2. Identificaremos los beneficios clave de tu producto/servicio
98
+ 3. Crearemos TRES propuestas únicas de valor potentes y persuasivas
99
+
100
+ **¡Comencemos!** Por favor, comparte los detalles de tu producto/servicio, audiencia objetivo y la fórmula que prefieres.
101
+ """
102
+
103
  # Create a data/ folder if it doesn't already exist
104
  try:
105
  os.mkdir('data/')
 
137
  format_func=lambda x: past_chats.get(x, 'Nuevo Chat' if x != st.session_state.chat_id else st.session_state.chat_title),
138
  placeholder='_',
139
  )
140
+
141
+ # Inicializar el título de chat si es necesario
142
+ if st.session_state.get('chat_title') is None:
143
+ if st.session_state.chat_id in past_chats:
144
+ st.session_state.chat_title = past_chats[st.session_state.chat_id]
145
+ else:
146
+ st.session_state.chat_title = 'Nuevo Chat'
147
+
148
+ st.write('# Creador de Propuestas Únicas de Valor')
149
 
150
+ # Inicializar mensajes si es un chat nuevo
151
+ if not st.session_state.get('messages'):
152
+ st.session_state.messages = []
153
+ # Eliminamos el mensaje automático de bienvenida
154
+ # No añadimos ningún mensaje inicial
155
+ with st.chat_message(name=MODEL_ROLE, avatar=AI_AVATAR_ICON):
156
+ st.markdown(WELCOME_MESSAGE)
157
+
158
+ # Guardamos en el historial
159
+ st.session_state.messages.append(
160
+ dict(
161
+ role=MODEL_ROLE,
162
+ content=WELCOME_MESSAGE,
163
+ avatar=AI_AVATAR_ICON,
164
+ )
165
+ )
166
 
167
  # Chat history (allows to ask multiple questions)
168
  try:
 
174
  )
175
  print('old cache')
176
  except:
177
+ if not st.session_state.get('messages'):
178
+ st.session_state.messages = []
179
  st.session_state.gemini_history = []
180
  print('new_cache made')
181
+
182
+ # Configuración del modelo sin el parámetro system_instruction
183
+ model = genai.GenerativeModel(
184
+ model_name='gemini-2.0-flash'
185
+ )
186
+ st.session_state.model = model
187
  st.session_state.chat = st.session_state.model.start_chat(
188
  history=st.session_state.gemini_history,
189
  )
190
 
191
+ # Si es un chat nuevo, enviar el prompt del sistema como primer mensaje
192
+ if not st.session_state.gemini_history:
193
+ # Enviamos el prompt del sistema como primer mensaje (invisible para el usuario)
194
+ st.session_state.chat.send_message(SYSTEM_PROMPT)
195
+ # No guardamos este mensaje en st.session_state.messages para que no se muestre al usuario
196
+ # pero sí en gemini_history para que el modelo lo recuerde
197
+ st.session_state.gemini_history = st.session_state.chat.history
198
+ # Display chat messages from history on app rerun
199
+ for message in st.session_state.messages:
200
+ with st.chat_message(
201
+ name=message['role'],
202
+ avatar=message.get('avatar'),
203
+ ):
204
+ st.markdown(message['content'])
205
 
206
  # React to user input
207
+ if prompt := st.chat_input('¿Cuál es tu producto o servicio?'): # Mensaje más específico
208
+ # Verificar si es la primera interacción y el usuario pregunta por las funciones
209
+ is_asking_about_functions = any(keyword in prompt.lower() for keyword in
210
+ ["qué haces", "funciones", "ayudar", "puedes hacer", "cómo funciona", "para qué sirves"])
211
+
212
+ if is_asking_about_functions and not past_chats.get(st.session_state.chat_id):
213
+ # Si pregunta por las funciones, mostrar el mensaje de bienvenida
214
+ response_content = WELCOME_MESSAGE
215
 
216
+ # Display assistant response in chat message container
217
+ with st.chat_message(name=MODEL_ROLE, avatar=AI_AVATAR_ICON):
218
+ st.markdown(response_content)
219
+
220
+ # Add to chat history
221
+ st.session_state.messages.append(
222
+ dict(
223
+ role=MODEL_ROLE,
224
+ content=response_content,
225
+ avatar=AI_AVATAR_ICON,
226
+ )
227
+ )
228
+ else:
229
+ # Procesamiento normal para otras preguntas
230
+ # Save this as a chat for later
231
+ if st.session_state.chat_id not in past_chats.keys():
232
+ # Es una nueva conversación, generemos un título basado en el primer mensaje
233
+ # Primero, guardamos un título temporal
234
+ temp_title = f'PUV-{st.session_state.chat_id}'
235
+ past_chats[st.session_state.chat_id] = temp_title
236
 
237
+ # Generamos un título basado en el contenido del mensaje
238
+ try:
239
+ # Usamos el mismo modelo para generar un título corto
240
+ title_generator = genai.GenerativeModel('gemini-2.0-flash')
241
+ title_response = title_generator.generate_content(
242
+ f"Genera un título corto (máximo 5 palabras) que describa de qué producto o servicio trata esta consulta, sin usar comillas ni puntuación: '{prompt}'")
243
+
244
+ # Obtenemos el título generado
245
+ generated_title = title_response.text.strip()
246
+
247
+ # Actualizamos el título en past_chats
248
+ if generated_title:
249
+ st.session_state.chat_title = f"PUV: {generated_title}"
250
+ past_chats[st.session_state.chat_id] = f"PUV: {generated_title}"
251
+ else:
252
+ st.session_state.chat_title = temp_title
253
+ except Exception as e:
254
+ print(f"Error al generar título: {e}")
255
  st.session_state.chat_title = temp_title
256
+ else:
257
+ # Ya existe esta conversación, usamos el título guardado
258
+ st.session_state.chat_title = past_chats[st.session_state.chat_id]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
259
 
260
+ joblib.dump(past_chats, 'data/past_chats_list')
 
 
261
 
262
+ # Display user message in chat message container
263
+ with st.chat_message('user', avatar=USER_AVATAR_ICON):
264
+ st.markdown(prompt)
265
+ # Add user message to chat history
266
+ st.session_state.messages.append(
267
+ dict(
268
+ role='user',
269
+ content=prompt,
270
+ )
 
 
 
 
 
 
 
 
 
 
 
271
  )
272
+
273
+ # Implementación de reintentos con retroceso exponencial
274
+ max_retries = 3
275
+ retry_count = 0
276
+ while retry_count < max_retries:
277
+ try:
278
+ ## Send message to AI
279
+ response = st.session_state.chat.send_message(
280
+ prompt,
281
+ stream=True,
282
+ )
283
+
284
+ # Display assistant response in chat message container
285
+ with st.chat_message(
286
+ name=MODEL_ROLE,
287
+ avatar=AI_AVATAR_ICON,
288
+ ):
289
+ message_placeholder = st.empty()
290
+ full_response = ''
291
+ assistant_response = response
292
+
293
+ # Añade un indicador de "escribiendo..."
294
+ typing_indicator = st.empty()
295
+ typing_indicator.markdown("*Nuestro equipo de expertos está analizando tu información...*")
296
+
297
+ # Streams in a chunk at a time
298
+ for chunk in response:
299
+ # Simulate stream of chunk
300
+ for ch in chunk.text.split(' '):
301
+ full_response += ch + ' '
302
+ time.sleep(0.1)
303
+ # Rewrites with a cursor at end
304
+ message_placeholder.write(full_response + '▌')
305
+ # Elimina el indicador de escritura
306
+ typing_indicator.empty()
307
+ # Write full message with placeholder
308
+ message_placeholder.write(full_response)
309
+
310
+ # Add assistant response to chat history
311
+ st.session_state.messages.append(
312
+ dict(
313
+ role=MODEL_ROLE,
314
+ content=st.session_state.chat.history[-1].parts[0].text,
315
+ avatar=AI_AVATAR_ICON,
316
+ )
317
+ )
318
+ st.session_state.gemini_history = st.session_state.chat.history
319
+ # Save to file
320
+ joblib.dump(
321
+ st.session_state.messages,
322
+ f'data/{st.session_state.chat_id}-st_messages',
323
+ )
324
+ joblib.dump(
325
+ st.session_state.gemini_history,
326
+ f'data/{st.session_state.chat_id}-gemini_messages',
327
+ )
328
+ # Si llegamos aquí, la solicitud fue exitosa
329
+ break
330
+
331
+ except Exception as e:
332
+ retry_count += 1
333
+ if retry_count >= max_retries:
334
+ # Si agotamos los reintentos, mostramos un mensaje de error
335
+ with st.chat_message(name=MODEL_ROLE, avatar=AI_AVATAR_ICON):
336
+ st.error(f"Lo sentimos, estamos experimentando problemas para procesar tu solicitud. Por favor, intenta de nuevo más tarde. Error: {str(e)}")
337
+ st.session_state.messages.append(
338
+ dict(
339
+ role=MODEL_ROLE,
340
+ content=f"Lo sentimos, estamos experimentando problemas para procesar tu solicitud. Por favor, intenta de nuevo más tarde. Error: {str(e)}",
341
+ avatar=AI_AVATAR_ICON,
342
+ )
343
+ )
344
+ joblib.dump(
345
+ st.session_state.messages,
346
+ f'data/{st.session_state.chat_id}-st_messages',
347
+ )
348
+ else:
349
+ # Esperamos antes de reintentar (retroceso exponencial)
350
+ wait_time = (2 ** retry_count) + (time.time() % 1)
351
+ time.sleep(wait_time)