Spaces:
Running
Running
Upload 12 files
Browse files
app.py
CHANGED
@@ -11,6 +11,131 @@ from session_state import SessionState
|
|
11 |
# Inicializar el estado de la sesión
|
12 |
state = SessionState()
|
13 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
14 |
# Función para cargar CSS personalizado
|
15 |
def load_css(file_path):
|
16 |
with open(file_path) as f:
|
@@ -67,7 +192,7 @@ def display_initial_header():
|
|
67 |
# Descripción (ahora fuera de la columna para ocupar todo el ancho)
|
68 |
st.markdown("""
|
69 |
<div style='text-align: center; width: 100%;'>
|
70 |
-
<p style='font-size: 16px; background-color: #1E3A5F; padding: 12px; border-radius: 8px; margin-top: 10px; color: #4ECDC4; width: 100%; text-align: center;
|
71 |
🎯 Experto en crear Propuestas de Valor Únicas que convierten audiencia en clientes
|
72 |
</p>
|
73 |
</div>
|
@@ -197,134 +322,11 @@ if not state.has_messages():
|
|
197 |
|
198 |
# Procesar entrada del usuario
|
199 |
if prompt := st.chat_input('Describe tu producto/servicio y audiencia objetivo...'):
|
200 |
-
|
201 |
-
if state.chat_id not in past_chats.keys():
|
202 |
-
# Es una nueva conversación, generemos un título basado en el primer mensaje
|
203 |
-
temp_title = f'SesiónChat-{state.chat_id}'
|
204 |
-
past_chats[state.chat_id] = temp_title
|
205 |
-
|
206 |
-
# Generar título para el chat
|
207 |
-
generated_title = state.generate_chat_title(prompt)
|
208 |
-
|
209 |
-
# Actualizamos el título en past_chats
|
210 |
-
if generated_title:
|
211 |
-
state.chat_title = generated_title
|
212 |
-
past_chats[state.chat_id] = generated_title
|
213 |
-
else:
|
214 |
-
state.chat_title = temp_title
|
215 |
-
else:
|
216 |
-
# Ya existe esta conversación, usamos el título guardado
|
217 |
-
state.chat_title = past_chats[state.chat_id]
|
218 |
-
|
219 |
-
joblib.dump(past_chats, 'data/past_chats_list')
|
220 |
-
|
221 |
-
# Mostrar mensaje del usuario
|
222 |
-
with st.chat_message('user', avatar=USER_AVATAR_ICON):
|
223 |
-
st.markdown(prompt)
|
224 |
-
|
225 |
-
# Añadir mensaje del usuario al historial
|
226 |
-
state.add_message('user', prompt)
|
227 |
-
|
228 |
-
# Obtener el prompt del experto
|
229 |
-
puv_expert_prompt = get_puv_expert_prompt()
|
230 |
-
|
231 |
-
# Combinar el prompt del experto con el mensaje del usuario
|
232 |
-
enhanced_prompt = f"{puv_expert_prompt}\n\nUser message: {prompt}"
|
233 |
-
|
234 |
-
# Enviar mensaje al modelo
|
235 |
-
response = state.chat.send_message(
|
236 |
-
enhanced_prompt,
|
237 |
-
stream=True,
|
238 |
-
)
|
239 |
-
|
240 |
-
# Mostrar respuesta del asistente
|
241 |
-
with st.chat_message(
|
242 |
-
name=MODEL_ROLE,
|
243 |
-
avatar=AI_AVATAR_ICON,
|
244 |
-
):
|
245 |
-
message_placeholder = st.empty()
|
246 |
-
full_response = ''
|
247 |
-
|
248 |
-
# Añadir indicador de "escribiendo..."
|
249 |
-
typing_indicator = st.empty()
|
250 |
-
typing_indicator.markdown("*Generando respuesta...*")
|
251 |
-
|
252 |
-
# Mostrar respuesta por fragmentos
|
253 |
-
for chunk in response:
|
254 |
-
for ch in chunk.text:
|
255 |
-
full_response += ch
|
256 |
-
time.sleep(0.01)
|
257 |
-
message_placeholder.write(full_response + '▌')
|
258 |
-
|
259 |
-
# Eliminar indicador de escritura
|
260 |
-
typing_indicator.empty()
|
261 |
-
|
262 |
-
# Mostrar respuesta completa
|
263 |
-
message_placeholder.write(full_response)
|
264 |
-
|
265 |
-
# Añadir respuesta al historial
|
266 |
-
state.add_message(
|
267 |
-
role=MODEL_ROLE,
|
268 |
-
content=state.chat.history[-1].parts[0].text,
|
269 |
-
avatar=AI_AVATAR_ICON,
|
270 |
-
)
|
271 |
-
state.gemini_history = state.chat.history
|
272 |
-
|
273 |
-
# Guardar historial
|
274 |
-
state.save_chat_history()
|
275 |
|
276 |
# Procesar ejemplos seleccionados
|
277 |
if state.has_prompt():
|
278 |
prompt = state.prompt
|
279 |
-
|
280 |
-
# Guardar el chat para después si es nuevo
|
281 |
-
if state.chat_id not in past_chats.keys():
|
282 |
-
temp_title = f'SesiónChat-{state.chat_id}'
|
283 |
-
past_chats[state.chat_id] = temp_title
|
284 |
-
joblib.dump(past_chats, 'data/past_chats_list')
|
285 |
-
|
286 |
-
# Mostrar mensaje del usuario
|
287 |
-
with st.chat_message('user', avatar=USER_AVATAR_ICON):
|
288 |
-
st.markdown(prompt)
|
289 |
-
|
290 |
-
# Añadir mensaje del usuario al historial
|
291 |
-
state.add_message('user', prompt, USER_AVATAR_ICON)
|
292 |
-
|
293 |
-
# Procesar respuesta del modelo
|
294 |
-
if prompt.strip():
|
295 |
-
with st.chat_message(MODEL_ROLE, avatar=AI_AVATAR_ICON):
|
296 |
-
try:
|
297 |
-
response = state.chat.send_message(prompt)
|
298 |
-
st.markdown(response.text)
|
299 |
-
|
300 |
-
# Añadir respuesta al historial
|
301 |
-
state.add_message(MODEL_ROLE, response.text, AI_AVATAR_ICON)
|
302 |
-
|
303 |
-
# Guardar historial actualizado
|
304 |
-
state.save_chat_history()
|
305 |
-
except ValueError as e:
|
306 |
-
st.error("Error: El mensaje no puede estar vacío. Por favor, escribe algo.")
|
307 |
-
|
308 |
# Limpiar el prompt
|
309 |
-
state.clear_prompt()
|
310 |
-
|
311 |
-
# Función para detectar saludos y generar respuestas personalizadas
|
312 |
-
def is_greeting(text):
|
313 |
-
"""Detecta si el texto es un saludo simple"""
|
314 |
-
text = text.lower().strip()
|
315 |
-
greetings = ['hola', 'hey', 'saludos', 'buenos días', 'buenas tardes', 'buenas noches', 'hi', 'hello']
|
316 |
-
return any(greeting in text for greeting in greetings) and len(text.split()) < 4
|
317 |
-
|
318 |
-
def get_greeting_response():
|
319 |
-
"""Genera una respuesta amigable para saludos"""
|
320 |
-
return """¡Hola! 😊 ¡Qué bueno saludarte!
|
321 |
-
|
322 |
-
Soy el Asistente RoboCopy, especializado en crear Propuestas de Valor Únicas (PUVs) que transforman tu comunicación con clientes potenciales.
|
323 |
-
|
324 |
-
Puedo ayudarte a:
|
325 |
-
• Crear PUVs impactantes que destaquen tu oferta
|
326 |
-
• Analizar tu producto/servicio para encontrar su valor diferencial
|
327 |
-
• Adaptar tu mensaje a diferentes audiencias
|
328 |
-
• Aplicar fórmulas probadas de marketing persuasivo
|
329 |
-
|
330 |
-
¿Te gustaría que sigamos trabajando en tus Propuestas de Valor Únicas (PUVs) o tienes alguna otra pregunta en mente?"""
|
|
|
11 |
# Inicializar el estado de la sesión
|
12 |
state = SessionState()
|
13 |
|
14 |
+
# Función para detectar saludos y generar respuestas personalizadas
|
15 |
+
def is_greeting(text):
|
16 |
+
"""Detecta si el texto es un saludo simple"""
|
17 |
+
text = text.lower().strip()
|
18 |
+
greetings = ['hola', 'hey', 'saludos', 'buenos días', 'buenas tardes', 'buenas noches', 'hi', 'hello']
|
19 |
+
return any(greeting in text for greeting in greetings) and len(text.split()) < 4
|
20 |
+
|
21 |
+
def get_greeting_response():
|
22 |
+
"""Genera una respuesta amigable para saludos"""
|
23 |
+
return """¡Hola! 😊 ¡Qué bueno verte por aquí!
|
24 |
+
|
25 |
+
Soy RoboCopy, tu asistente personal para crear Propuestas Únicas de Valor que realmente conecten con tu audiencia.
|
26 |
+
|
27 |
+
Mi especialidad es ayudarte a destacar lo que hace único a tu negocio:
|
28 |
+
• Transformar tus características en beneficios irresistibles
|
29 |
+
• Crear mensajes que capturan la atención inmediata de tus clientes ideales
|
30 |
+
• Diferenciarte de la competencia con palabras que venden
|
31 |
+
|
32 |
+
¿Te gustaría que continuemos trabajando en tu Propuesta Única de Valor o tienes alguna otra pregunta?"""
|
33 |
+
|
34 |
+
# Función para procesar mensajes (unifica la lógica de procesamiento)
|
35 |
+
def process_message(prompt, is_example=False):
|
36 |
+
"""Procesa un mensaje del usuario, ya sea directo o de un ejemplo"""
|
37 |
+
# Guardar el chat para después si es nuevo
|
38 |
+
if state.chat_id not in past_chats.keys():
|
39 |
+
# Es una nueva conversación, generemos un título basado en el primer mensaje
|
40 |
+
temp_title = f'SesiónChat-{state.chat_id}'
|
41 |
+
past_chats[state.chat_id] = temp_title
|
42 |
+
|
43 |
+
# Generar título para el chat
|
44 |
+
generated_title = state.generate_chat_title(prompt)
|
45 |
+
|
46 |
+
# Actualizamos el título en past_chats
|
47 |
+
if generated_title:
|
48 |
+
state.chat_title = generated_title
|
49 |
+
past_chats[state.chat_id] = generated_title
|
50 |
+
else:
|
51 |
+
state.chat_title = temp_title
|
52 |
+
else:
|
53 |
+
# Ya existe esta conversación, usamos el título guardado
|
54 |
+
state.chat_title = past_chats[state.chat_id]
|
55 |
+
|
56 |
+
joblib.dump(past_chats, 'data/past_chats_list')
|
57 |
+
|
58 |
+
# Mostrar mensaje del usuario
|
59 |
+
with st.chat_message('user', avatar=USER_AVATAR_ICON):
|
60 |
+
st.markdown(prompt)
|
61 |
+
|
62 |
+
# Añadir mensaje del usuario al historial
|
63 |
+
state.add_message('user', prompt, USER_AVATAR_ICON)
|
64 |
+
|
65 |
+
# Verificar si es un saludo simple
|
66 |
+
if is_greeting(prompt):
|
67 |
+
# Mostrar respuesta personalizada para saludos
|
68 |
+
greeting_response = get_greeting_response()
|
69 |
+
with st.chat_message(name=MODEL_ROLE, avatar=AI_AVATAR_ICON):
|
70 |
+
st.markdown(greeting_response)
|
71 |
+
|
72 |
+
# Añadir respuesta al historial
|
73 |
+
state.add_message(
|
74 |
+
role=MODEL_ROLE,
|
75 |
+
content=greeting_response,
|
76 |
+
avatar=AI_AVATAR_ICON,
|
77 |
+
)
|
78 |
+
state.save_chat_history()
|
79 |
+
return
|
80 |
+
|
81 |
+
# Procesar respuesta del modelo
|
82 |
+
if prompt.strip():
|
83 |
+
# Obtener el prompt del experto
|
84 |
+
puv_expert_prompt = get_puv_expert_prompt()
|
85 |
+
|
86 |
+
# Combinar el prompt del experto con el mensaje del usuario
|
87 |
+
enhanced_prompt = f"{puv_expert_prompt}\n\nUser message: {prompt}"
|
88 |
+
|
89 |
+
with st.chat_message(MODEL_ROLE, avatar=AI_AVATAR_ICON):
|
90 |
+
try:
|
91 |
+
if is_example:
|
92 |
+
# Para ejemplos, no necesitamos streaming
|
93 |
+
response = state.chat.send_message(prompt)
|
94 |
+
st.markdown(response.text)
|
95 |
+
|
96 |
+
# Añadir respuesta al historial
|
97 |
+
state.add_message(MODEL_ROLE, response.text, AI_AVATAR_ICON)
|
98 |
+
else:
|
99 |
+
# Para entrada directa, usamos streaming
|
100 |
+
response = state.chat.send_message(
|
101 |
+
enhanced_prompt,
|
102 |
+
stream=True,
|
103 |
+
)
|
104 |
+
|
105 |
+
message_placeholder = st.empty()
|
106 |
+
full_response = ''
|
107 |
+
|
108 |
+
# Añadir indicador de "escribiendo..."
|
109 |
+
typing_indicator = st.empty()
|
110 |
+
typing_indicator.markdown("*Generando respuesta...*")
|
111 |
+
|
112 |
+
# Mostrar respuesta por fragmentos
|
113 |
+
for chunk in response:
|
114 |
+
for ch in chunk.text:
|
115 |
+
full_response += ch
|
116 |
+
time.sleep(0.01)
|
117 |
+
message_placeholder.write(full_response + '▌')
|
118 |
+
|
119 |
+
# Eliminar indicador de escritura
|
120 |
+
typing_indicator.empty()
|
121 |
+
|
122 |
+
# Mostrar respuesta completa
|
123 |
+
message_placeholder.write(full_response)
|
124 |
+
|
125 |
+
# Añadir respuesta al historial
|
126 |
+
state.add_message(
|
127 |
+
role=MODEL_ROLE,
|
128 |
+
content=state.chat.history[-1].parts[0].text,
|
129 |
+
avatar=AI_AVATAR_ICON,
|
130 |
+
)
|
131 |
+
|
132 |
+
state.gemini_history = state.chat.history
|
133 |
+
|
134 |
+
# Guardar historial actualizado
|
135 |
+
state.save_chat_history()
|
136 |
+
except ValueError as e:
|
137 |
+
st.error("Error: El mensaje no puede estar vacío. Por favor, escribe algo.")
|
138 |
+
|
139 |
# Función para cargar CSS personalizado
|
140 |
def load_css(file_path):
|
141 |
with open(file_path) as f:
|
|
|
192 |
# Descripción (ahora fuera de la columna para ocupar todo el ancho)
|
193 |
st.markdown("""
|
194 |
<div style='text-align: center; width: 100%;'>
|
195 |
+
<p style='font-size: 16px; background-color: #1E3A5F; padding: 12px; border-radius: 8px; margin-top: 10px; color: #4ECDC4; width: 100%; text-align: center; box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);'>
|
196 |
🎯 Experto en crear Propuestas de Valor Únicas que convierten audiencia en clientes
|
197 |
</p>
|
198 |
</div>
|
|
|
322 |
|
323 |
# Procesar entrada del usuario
|
324 |
if prompt := st.chat_input('Describe tu producto/servicio y audiencia objetivo...'):
|
325 |
+
process_message(prompt, is_example=False)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
326 |
|
327 |
# Procesar ejemplos seleccionados
|
328 |
if state.has_prompt():
|
329 |
prompt = state.prompt
|
330 |
+
process_message(prompt, is_example=True)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
331 |
# Limpiar el prompt
|
332 |
+
state.clear_prompt()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|