Spaces:
Running
Running
Update app.py
Browse files
app.py
CHANGED
@@ -4,8 +4,8 @@ import joblib
|
|
4 |
import streamlit as st
|
5 |
import google.generativeai as genai
|
6 |
from dotenv import load_dotenv
|
7 |
-
|
8 |
-
from puv_formulas import
|
9 |
|
10 |
# Función para cargar CSS personalizado
|
11 |
def load_css(file_path):
|
@@ -76,10 +76,10 @@ with st.sidebar:
|
|
76 |
placeholder='_',
|
77 |
)
|
78 |
# Save new chats after a message has been sent to AI
|
79 |
-
# TODO: Give user a chance to name chat
|
80 |
st.session_state.chat_title = f'SesiónChat-{st.session_state.chat_id}'
|
81 |
|
82 |
-
st.write('#
|
|
|
83 |
|
84 |
# Chat history (allows to ask multiple questions)
|
85 |
try:
|
@@ -94,49 +94,6 @@ except:
|
|
94 |
st.session_state.messages = []
|
95 |
st.session_state.gemini_history = []
|
96 |
print('new_cache made')
|
97 |
-
|
98 |
-
# Inicializar el modelo con system prompt solo si no existe o si cambiamos de chat
|
99 |
-
if not hasattr(st.session_state, 'puv_model') or st.session_state.get('current_chat_id') != st.session_state.chat_id:
|
100 |
-
system_prompt = get_puv_system_prompt()
|
101 |
-
|
102 |
-
# Crear un contexto con las fórmulas de PUV para el modelo
|
103 |
-
formulas_context = "Fórmulas de PUV disponibles:\n\n"
|
104 |
-
for formula_name, formula_data in puv_formulas.items():
|
105 |
-
formulas_context += f"## {formula_name}\n"
|
106 |
-
formulas_context += f"{formula_data['description']}\n\n"
|
107 |
-
formulas_context += "Ejemplos:\n"
|
108 |
-
for example in formula_data['examples']:
|
109 |
-
formulas_context += f"- Audiencia: {example['target_audience']}\n"
|
110 |
-
formulas_context += f"- Producto/Servicio: {example['product_service']}\n"
|
111 |
-
formulas_context += f"- PUV: {example['uvp']}\n\n"
|
112 |
-
|
113 |
-
# Añadir las fórmulas al contexto del modelo
|
114 |
-
enhanced_system_prompt = system_prompt + "\n\nREFERENCIA DE FÓRMULAS:\n" + formulas_context
|
115 |
-
|
116 |
-
st.session_state.puv_model = genai.GenerativeModel(
|
117 |
-
model_name='gemini-2.0-flash',
|
118 |
-
system_instruction=enhanced_system_prompt
|
119 |
-
)
|
120 |
-
st.session_state.current_chat_id = st.session_state.chat_id
|
121 |
-
|
122 |
-
# Inicializar el chat con el historial existente
|
123 |
-
history_for_model = []
|
124 |
-
for msg in st.session_state.gemini_history:
|
125 |
-
if isinstance(msg, dict) and 'role' in msg and 'parts' in msg:
|
126 |
-
# El formato ya es correcto
|
127 |
-
history_for_model.append(msg)
|
128 |
-
elif isinstance(msg, dict) and 'role' in msg and 'content' in msg:
|
129 |
-
# Convertir del formato antiguo al nuevo
|
130 |
-
history_for_model.append({
|
131 |
-
'role': msg['role'],
|
132 |
-
'parts': [{'text': msg['content']}]
|
133 |
-
})
|
134 |
-
|
135 |
-
st.session_state.puv_chat = st.session_state.puv_model.start_chat(
|
136 |
-
history=history_for_model
|
137 |
-
)
|
138 |
-
|
139 |
-
# Modelo estándar para otras operaciones (como generar títulos)
|
140 |
st.session_state.model = genai.GenerativeModel('gemini-2.0-flash')
|
141 |
st.session_state.chat = st.session_state.model.start_chat(
|
142 |
history=st.session_state.gemini_history,
|
@@ -150,8 +107,51 @@ for message in st.session_state.messages:
|
|
150 |
):
|
151 |
st.markdown(message['content'])
|
152 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
153 |
# React to user input
|
154 |
-
if prompt := st.chat_input('
|
155 |
# Save this as a chat for later
|
156 |
if st.session_state.chat_id not in past_chats.keys():
|
157 |
# Es una nueva conversación, generemos un título basado en el primer mensaje
|
@@ -196,9 +196,57 @@ if prompt := st.chat_input('¿En qué puedo ayudarte con tu Propuesta Única de
|
|
196 |
)
|
197 |
)
|
198 |
|
199 |
-
#
|
200 |
-
|
201 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
202 |
stream=True,
|
203 |
)
|
204 |
|
@@ -209,25 +257,20 @@ if prompt := st.chat_input('¿En qué puedo ayudarte con tu Propuesta Única de
|
|
209 |
):
|
210 |
message_placeholder = st.empty()
|
211 |
full_response = ''
|
|
|
212 |
|
213 |
# Añade un indicador de "escribiendo..."
|
214 |
typing_indicator = st.empty()
|
215 |
-
typing_indicator.markdown("*
|
216 |
|
217 |
# Streams in a chunk at a time
|
218 |
-
for chunk in
|
219 |
-
|
220 |
-
|
221 |
-
|
222 |
-
|
223 |
-
|
224 |
-
|
225 |
-
if i < len(words) - 1:
|
226 |
-
full_response += ' '
|
227 |
-
time.sleep(0.1) # Velocidad ajustada para mejor legibilidad
|
228 |
-
# Rewrites with a cursor at end
|
229 |
-
message_placeholder.write(full_response + '▌')
|
230 |
-
|
231 |
# Elimina el indicador de escritura
|
232 |
typing_indicator.empty()
|
233 |
# Write full message with placeholder
|
@@ -237,14 +280,11 @@ if prompt := st.chat_input('¿En qué puedo ayudarte con tu Propuesta Única de
|
|
237 |
st.session_state.messages.append(
|
238 |
dict(
|
239 |
role=MODEL_ROLE,
|
240 |
-
content=
|
241 |
avatar=AI_AVATAR_ICON,
|
242 |
)
|
243 |
)
|
244 |
-
|
245 |
-
# Actualizar el historial de Gemini
|
246 |
-
st.session_state.gemini_history = st.session_state.puv_chat.history
|
247 |
-
|
248 |
# Save to file
|
249 |
joblib.dump(
|
250 |
st.session_state.messages,
|
@@ -253,4 +293,4 @@ if prompt := st.chat_input('¿En qué puedo ayudarte con tu Propuesta Única de
|
|
253 |
joblib.dump(
|
254 |
st.session_state.gemini_history,
|
255 |
f'data/{st.session_state.chat_id}-gemini_messages',
|
256 |
-
)
|
|
|
4 |
import streamlit as st
|
5 |
import google.generativeai as genai
|
6 |
from dotenv import load_dotenv
|
7 |
+
# Importación simplificada del archivo puv_formulas
|
8 |
+
from puv_formulas import get_puv_formulas
|
9 |
|
10 |
# Función para cargar CSS personalizado
|
11 |
def load_css(file_path):
|
|
|
76 |
placeholder='_',
|
77 |
)
|
78 |
# Save new chats after a message has been sent to AI
|
|
|
79 |
st.session_state.chat_title = f'SesiónChat-{st.session_state.chat_id}'
|
80 |
|
81 |
+
st.write('# Generador de Propuestas de Valor Únicas (PUVs)')
|
82 |
+
st.write('Describe tu producto/servicio y audiencia objetivo para generar PUVs personalizadas.')
|
83 |
|
84 |
# Chat history (allows to ask multiple questions)
|
85 |
try:
|
|
|
94 |
st.session_state.messages = []
|
95 |
st.session_state.gemini_history = []
|
96 |
print('new_cache made')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
97 |
st.session_state.model = genai.GenerativeModel('gemini-2.0-flash')
|
98 |
st.session_state.chat = st.session_state.model.start_chat(
|
99 |
history=st.session_state.gemini_history,
|
|
|
107 |
):
|
108 |
st.markdown(message['content'])
|
109 |
|
110 |
+
# Mensaje inicial del sistema si es un chat nuevo
|
111 |
+
if not st.session_state.messages:
|
112 |
+
with st.chat_message(
|
113 |
+
name=MODEL_ROLE,
|
114 |
+
avatar=AI_AVATAR_ICON,
|
115 |
+
):
|
116 |
+
st.markdown("""
|
117 |
+
Hola, soy tu asistente de IA especializado en crear Propuestas de Valor Únicas.
|
118 |
+
|
119 |
+
Te ayudo a desarrollar mensajes persuasivos que conectan con tu audiencia y convierten visitantes en clientes. Para crear las mejores propuestas, necesito información sobre:
|
120 |
+
|
121 |
+
- Tu producto o servicio
|
122 |
+
- Tu audiencia objetivo
|
123 |
+
- Los problemas que resuelves
|
124 |
+
- Tus ventajas competitivas
|
125 |
+
|
126 |
+
Utilizo diferentes fórmulas como la Tradicional, Anti-tradicional, Contrato Imposible y Reto Ridículo para crear propuestas adaptadas a tu negocio.
|
127 |
+
|
128 |
+
¿En qué puedo ayudarte hoy?
|
129 |
+
""")
|
130 |
+
|
131 |
+
# Add system message to chat history
|
132 |
+
st.session_state.messages.append(
|
133 |
+
dict(
|
134 |
+
role=MODEL_ROLE,
|
135 |
+
content="""
|
136 |
+
Hola, soy tu asistente de IA especializado en crear Propuestas de Valor Únicas.
|
137 |
+
|
138 |
+
Te ayudo a desarrollar mensajes persuasivos que conectan con tu audiencia y convierten visitantes en clientes. Para crear las mejores propuestas, necesito información sobre:
|
139 |
+
|
140 |
+
- Tu producto o servicio
|
141 |
+
- Tu audiencia objetivo
|
142 |
+
- Los problemas que resuelves
|
143 |
+
- Tus ventajas competitivas
|
144 |
+
|
145 |
+
Utilizo diferentes fórmulas como la Tradicional, Anti-tradicional, Contrato Imposible y Reto Ridículo para crear propuestas adaptadas a tu negocio.
|
146 |
+
|
147 |
+
¿En qué puedo ayudarte hoy?
|
148 |
+
""",
|
149 |
+
avatar=AI_AVATAR_ICON,
|
150 |
+
)
|
151 |
+
)
|
152 |
+
|
153 |
# React to user input
|
154 |
+
if prompt := st.chat_input('Describe tu producto/servicio y audiencia objetivo...'):
|
155 |
# Save this as a chat for later
|
156 |
if st.session_state.chat_id not in past_chats.keys():
|
157 |
# Es una nueva conversación, generemos un título basado en el primer mensaje
|
|
|
196 |
)
|
197 |
)
|
198 |
|
199 |
+
# Construir el prompt para el modelo con todas las fórmulas disponibles
|
200 |
+
puv_expert_prompt = """You are a collaborative team of world-class experts working together to create exceptional Unique Value Propositions (UVPs) that convert audience into customers.
|
201 |
+
THE EXPERT TEAM:
|
202 |
+
1. MASTER UVP STRATEGIST:
|
203 |
+
- Expert in UVP frameworks and conversion strategies
|
204 |
+
- Ensures the UVPs follow the selected framework structure precisely
|
205 |
+
- Focuses on strategic placement of key conversion elements
|
206 |
+
2. ELITE DIRECT RESPONSE COPYWRITER:
|
207 |
+
- Trained by Gary Halbert, Gary Bencivenga, and David Ogilvy
|
208 |
+
- Creates compelling hooks and persuasive elements
|
209 |
+
- Ensures the language resonates with the target audience
|
210 |
+
3. AUDIENCE PSYCHOLOGY SPECIALIST:
|
211 |
+
- Expert in understanding audience motivations and objections
|
212 |
+
- Creates content that builds genuine connection and trust
|
213 |
+
- Identifies and addresses hidden fears and desires
|
214 |
+
4. STORYTELLING MASTER:
|
215 |
+
- Creates compelling narratives that illustrate key points
|
216 |
+
- Makes complex concepts accessible through narrative
|
217 |
+
5. ENGAGEMENT EXPERT:
|
218 |
+
- Specializes in creating memorable and impactful statements
|
219 |
+
- Ensures the UVPs are clear, concise and compelling
|
220 |
+
|
221 |
+
You are a UVP (Unique Value Proposition) expert. Analyze (internally only, do not output the analysis) the user's message to identify information about their product/service and target audience.
|
222 |
+
|
223 |
+
If the user is asking for UVPs, create THREE different UVPs in Spanish language using the most appropriate formula from your knowledge. If the user is asking a question about UVPs or marketing, answer it helpfully.
|
224 |
+
|
225 |
+
When creating UVPs, follow these CRITICAL INSTRUCTIONS:
|
226 |
+
- Each UVP must be specific and measurable
|
227 |
+
- Focus on the transformation journey
|
228 |
+
- Use natural, conversational language
|
229 |
+
- Avoid generic phrases and buzzwords
|
230 |
+
- Maximum 2 lines per UVP
|
231 |
+
|
232 |
+
If creating UVPs, output in this format:
|
233 |
+
"Basado en tu descripción, aquí tienes tres propuestas de valor únicas (PUVs) para tu [producto/servicio]:
|
234 |
+
|
235 |
+
1. [First UVP]
|
236 |
+
2. [Second UVP]
|
237 |
+
3. [Third UVP]
|
238 |
+
|
239 |
+
Estas PUVs destacan [principales beneficios]. ¿Hay alguna que te guste más o quieres que ajuste algún aspecto?"
|
240 |
+
|
241 |
+
If answering a question, provide a helpful, expert response in Spanish.
|
242 |
+
"""
|
243 |
+
|
244 |
+
# Combinar el prompt del experto con el mensaje del usuario
|
245 |
+
enhanced_prompt = f"{puv_expert_prompt}\n\nUser message: {prompt}"
|
246 |
+
|
247 |
+
## Send message to AI
|
248 |
+
response = st.session_state.chat.send_message(
|
249 |
+
enhanced_prompt,
|
250 |
stream=True,
|
251 |
)
|
252 |
|
|
|
257 |
):
|
258 |
message_placeholder = st.empty()
|
259 |
full_response = ''
|
260 |
+
assistant_response = response
|
261 |
|
262 |
# Añade un indicador de "escribiendo..."
|
263 |
typing_indicator = st.empty()
|
264 |
+
typing_indicator.markdown("*Generando respuesta...*")
|
265 |
|
266 |
# Streams in a chunk at a time
|
267 |
+
for chunk in response:
|
268 |
+
# Simulate stream of chunk
|
269 |
+
for ch in chunk.text.split(' '):
|
270 |
+
full_response += ch + ' '
|
271 |
+
time.sleep(0.1)
|
272 |
+
# Rewrites with a cursor at end
|
273 |
+
message_placeholder.write(full_response + '▌')
|
|
|
|
|
|
|
|
|
|
|
|
|
274 |
# Elimina el indicador de escritura
|
275 |
typing_indicator.empty()
|
276 |
# Write full message with placeholder
|
|
|
280 |
st.session_state.messages.append(
|
281 |
dict(
|
282 |
role=MODEL_ROLE,
|
283 |
+
content=st.session_state.chat.history[-1].parts[0].text,
|
284 |
avatar=AI_AVATAR_ICON,
|
285 |
)
|
286 |
)
|
287 |
+
st.session_state.gemini_history = st.session_state.chat.history
|
|
|
|
|
|
|
288 |
# Save to file
|
289 |
joblib.dump(
|
290 |
st.session_state.messages,
|
|
|
293 |
joblib.dump(
|
294 |
st.session_state.gemini_history,
|
295 |
f'data/{st.session_state.chat_id}-gemini_messages',
|
296 |
+
)
|