JeCabrera commited on
Commit
8cdd62a
·
verified ·
1 Parent(s): 2e00321

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +388 -388
app.py CHANGED
@@ -1,388 +1,388 @@
1
- from dotenv import load_dotenv
2
- import streamlit as st
3
- import os
4
- import google.generativeai as genai
5
- import random
6
- from streamlit import session_state as state
7
- from formulas import email_formulas # Updated import statement
8
- from angles import angles
9
-
10
- # Cargar las variables de entorno
11
- load_dotenv()
12
-
13
- # Configurar la API de Google
14
- genai.configure(api_key=os.getenv("GOOGLE_API_KEY"))
15
-
16
- # Fórmulas con ejemplos y explicaciones
17
- # email_formulas dictionary has been moved to formulas/email_formulas.py
18
-
19
- # Cambiar el nombre de la función
20
- def generate_emails(number_of_emails, target_audience, product, temperature, selected_formula, selected_angle, file_content="", image_parts=None, is_image=False, emotion="", desired_action=""):
21
- # Crear la configuración del modelo
22
- generation_config = {
23
- "temperature": temperature,
24
- "top_p": 0.65,
25
- "top_k": 360,
26
- "max_output_tokens": 8196,
27
- }
28
-
29
- model = genai.GenerativeModel(
30
- model_name="gemini-2.0-flash",
31
- generation_config=generation_config,
32
- )
33
-
34
- # Angle dictionaries have been moved to angles/angle_data.py
35
-
36
- # Incluir las instrucciones del sistema en el prompt principal
37
- system_prompt = f"""You are a world-class direct response copywriter trained by Gary Halbert, Gary Bencivenga, and David Ogilvy.
38
-
39
- You have helped many marketers before me persuade their clients through emotional email sequences.
40
- Your task is to create email sequences that make my [buyer persona] feel [emotion] about my [product/service] and convince them to register/take [desired action].
41
-
42
- FORMAT RULES:
43
- - Each email must have a clear and attractive subject line
44
- - Include personalized greeting
45
- - The email body must be persuasive and emotional
46
- - Include a clear call to action
47
- - Add a professional signature
48
- - Separate each email with a dividing line
49
-
50
- IMPORTANT ANGLE INSTRUCTIONS:
51
- - The selected angle MUST be applied to EACH email
52
- - The angle modifies HOW the message is expressed, not its structure
53
- - Think of the angle as a "tone overlay" on the content
54
- - The formula provides the structure, the angle provides the style
55
- - Both must work together seamlessly
56
-
57
- FORMAT EXAMPLE:
58
- ---
59
- SUBJECT: [Attractive subject line]
60
-
61
- Hello [Name],
62
-
63
- [Email body with persuasive and emotional content]
64
-
65
- [Clear call to action]
66
-
67
- [Signature]
68
- ---
69
-
70
- IMPORTANT:
71
- - Each email must be unique and memorable
72
- - Avoid clichés and generalities
73
- - Maintain a persuasive but credible tone
74
- - Adapt language to the target audience
75
- - Focus on transformative benefits
76
- - Follow the selected angle style while maintaining the structure"""
77
-
78
- # Iniciar el prompt con las instrucciones del sistema
79
- email_instruction = f"{system_prompt}\n\n"
80
-
81
- # Añadir contenido del archivo si existe
82
- if file_content:
83
- email_instruction += f"""
84
- REFERENCE CONTENT:
85
- Carefully analyze the following content as a reference for generating emails:
86
- {file_content[:3000]}
87
-
88
- ANALYSIS INSTRUCTIONS:
89
- 1. Extract key information about the product or service mentioned
90
- 2. Identify the tone, style, and language used
91
- 3. Detect any data about the target audience or customer avatar
92
- 4. Look for benefits, features, or pain points mentioned
93
- 5. Use relevant terms, phrases, or concepts from the content
94
- 6. Maintain consistency with the brand identity or main message
95
- 7. Adapt the emails to resonate with the provided content
96
-
97
- IMPORTANT COMBINATIONS:
98
- """
99
- # Updated conditions for specific input combinations
100
- if product and not target_audience:
101
- email_instruction += f"""- FILE + PRODUCT: You have a reference document and product ({product}). Create emails that highlight this specific product's benefits and features using insights from the document. Extract audience information from the document to better target the emails.
102
- """
103
- elif target_audience and not product:
104
- email_instruction += f"""- FILE + TARGET AUDIENCE: You have a reference document and target audience ({target_audience}). Create emails tailored to this specific audience using language and concepts from the document. Identify products or services from the document that would appeal to this audience.
105
- """
106
- elif product and target_audience:
107
- email_instruction += f"""- PRODUCT + TARGET AUDIENCE: You have both product ({product}) and target audience ({target_audience}). Create emails that connect this specific product with this specific audience, using insights from the document to strengthen the connection.
108
- """
109
-
110
- email_instruction += """
111
- IMPORTANT: Naturally integrate the elements found in the content with the selected formula and angle.
112
- """
113
-
114
- # Añadir instrucciones de ángulo solo si no es "NINGUNO"
115
- if selected_angle != "NINGUNO":
116
- email_instruction += f"""
117
- MAIN ANGLE: {selected_angle}
118
- SPECIFIC ANGLE INSTRUCTIONS:
119
- {angles[selected_angle]["instruction"]}
120
-
121
- IMPORTANT: The angle {selected_angle} must be applied as a "style layer" over the formula structure:
122
- 1. Keep the base structure of the formula intact
123
- 2. Apply the tone and style of the {selected_angle} angle
124
- 3. Ensure each element of the formula reflects the angle
125
- 4. The angle affects "how" it's said, not "what" is said
126
-
127
- SUCCESSFUL EXAMPLES OF THE {selected_angle} ANGLE:
128
- """
129
- for example in angles[selected_angle]["examples"]:
130
- email_instruction += f"- {example}\n"
131
-
132
- # Dentro de la función, actualizar el prompt para incluir emoción y acción deseada
133
- email_instruction += (
134
- f"\nYour task is to create {number_of_emails} persuasive emails for {target_audience} "
135
- f"that evoke {emotion} and convince them to {desired_action} about {product}. "
136
- )
137
-
138
- if selected_angle != "NINGUNO":
139
- email_instruction += f"IMPORTANT: Each email MUST follow the {selected_angle} angle clearly and consistently.\n\n"
140
-
141
- email_instruction += (
142
- f"Avoid obvious mentions of {product} and focus on generating genuine interest"
143
- )
144
-
145
- if selected_angle != "NINGUNO":
146
- email_instruction += f" using the selected angle"
147
-
148
- email_instruction += ".\n\n"
149
-
150
- email_instruction += (
151
- f"IMPORTANT: Carefully study these examples of the selected formula. "
152
- f"Each example represents the style and structure to follow"
153
- )
154
-
155
- if selected_angle != "NINGUNO":
156
- email_instruction += f", adapted to the {selected_angle} angle"
157
-
158
- email_instruction += ":\n\n"
159
-
160
- # Agregar 5 ejemplos aleatorios de la fórmula
161
- random_examples = random.sample(selected_formula['examples'], min(5, len(selected_formula['examples'])))
162
-
163
- email_instruction += "FORMULA EXAMPLES TO FOLLOW:\n"
164
- for i, example in enumerate(random_examples, 1):
165
- email_instruction += f"{i}. {example}\n"
166
-
167
- email_instruction += "\nSPECIFIC INSTRUCTIONS:\n"
168
- email_instruction += "1. Maintain the same structure and length as the previous examples\n"
169
- email_instruction += "2. Use the same tone and writing style\n"
170
- email_instruction += "3. Replicate the phrase construction patterns\n"
171
- email_instruction += "4. Preserve the level of specificity and detail\n"
172
- email_instruction += f"5. Adapt the content for {target_audience} while maintaining the essence of the examples\n\n"
173
-
174
- email_instruction += f"FORMULA TO FOLLOW:\n{selected_formula['description']}\n\n"
175
-
176
- # CORRECTO (con indentación):
177
- if selected_angle != "NINGUNO":
178
- email_instruction += f"""
179
- FINAL REMINDER:
180
- 1. Follow the structure of the selected formula
181
- 2. Apply the angle as a "style layer"
182
- 3. Maintain coherence between formula and angle
183
- 4. Ensure each email reflects both elements
184
-
185
- GENERATE NOW:
186
- Create {number_of_headlines} emails that faithfully follow the style and structure of the examples shown.
187
- """
188
- else:
189
- email_instruction += f"""
190
- GENERATE NOW:
191
- Create {number_of_headlines} emails that faithfully follow the style and structure of the examples shown.
192
- """
193
-
194
- # Modificar la forma de enviar el mensaje según si hay imagen o no
195
- if is_image and image_parts:
196
- chat_session = model.start_chat(
197
- history=[
198
- {
199
- "role": "user",
200
- "parts": [
201
- email_instruction, # Cambiar headlines_instruction por email_instruction
202
- image_parts
203
- ],
204
- },
205
- ]
206
- )
207
- response = chat_session.send_message("Genera los emails siguiendo exactamente el estilo de los ejemplos mostrados, inspirándote en la imagen proporcionada.")
208
- else:
209
- chat_session = model.start_chat(
210
- history=[
211
- {
212
- "role": "user",
213
- "parts": [email_instruction], # Cambiar headlines_instruction por email_instruction
214
- },
215
- ]
216
- )
217
- response = chat_session.send_message("Genera los emails siguiendo exactamente el estilo de los ejemplos mostrados.")
218
-
219
- return response.text
220
-
221
- # Configurar la interfaz de usuario con Streamlit
222
- st.set_page_config(page_title="Email Composer", layout="wide")
223
-
224
- # Leer el contenido del archivo manual.md
225
- with open("manual.md", "r", encoding="utf-8") as file:
226
- manual_content = file.read()
227
-
228
- # Mostrar el contenido del manual en el sidebar
229
- st.sidebar.markdown(manual_content)
230
-
231
- # Load CSS from file
232
- with open("styles/main.css", "r") as f:
233
- css = f.read()
234
-
235
- # Apply the CSS
236
- st.markdown(f"<style>{css}</style>", unsafe_allow_html=True)
237
-
238
- # Centrar el título y el subtítulo
239
- st.markdown("<h1 style='text-align: center;'>Generador de Emails</h1>", unsafe_allow_html=True)
240
- st.markdown("<h4 style='text-align: center;'>Transforma tu marketing con emails persuasivos que convierten. Esta aplicación es tu arma secreta para crear emails emocionales de respuesta directa que impulsan a la acción.</h4>", unsafe_allow_html=True)
241
-
242
- # Crear columnas
243
- col1, col2 = st.columns([1, 2])
244
-
245
- # Columnas de entrada
246
- with col1:
247
- target_audience = st.text_input("¿Quién es tu público objetivo?", placeholder="Ejemplo: Estudiantes Universitarios")
248
- product = st.text_input("¿Qué producto/servicio estás promocionando?", placeholder="Ejemplo: Curso de Inglés")
249
- number_of_emails = st.selectbox("Número de Emails", options=[1, 2, 3, 4, 5], index=2)
250
-
251
- # Crear un único acordeón para fórmula, creatividad y ángulo
252
- with st.expander("Personaliza tus emails"):
253
- temperature = st.slider("Creatividad", min_value=0.0, max_value=2.0, value=1.0, step=0.1)
254
-
255
- emotion = st.selectbox(
256
- "¿Qué emoción quieres evocar?",
257
- options=["Curiosidad", "Miedo", "Esperanza", "Entusiasmo", "Confianza", "Urgencia"]
258
- )
259
-
260
- desired_action = st.text_input("Acción deseada", placeholder="Ejemplo: Registrarse para una prueba gratuita")
261
-
262
- selected_formula_key = st.selectbox(
263
- "Selecciona una fórmula para tus emails",
264
- options=list(email_formulas.email_formulas.keys()) # Updated reference
265
- )
266
-
267
- # Automatically use the keys from the angles dictionary
268
- # Make sure "NINGUNO" appears first, then the rest alphabetically
269
- angle_keys = ["NINGUNO"] + sorted([key for key in angles.keys() if key != "NINGUNO"])
270
- selected_angle = st.selectbox(
271
- "Selecciona un ángulo para tus emails",
272
- options=angle_keys
273
- )
274
-
275
- # Añadir cargador de archivos dentro del acordeón
276
- uploaded_file = st.file_uploader("📄 Archivo o imagen de referencia",
277
- type=['txt', 'pdf', 'docx', 'jpg', 'jpeg', 'png'])
278
-
279
- file_content = ""
280
- is_image = False
281
- image_parts = None
282
-
283
- if uploaded_file is not None:
284
- file_type = uploaded_file.name.split('.')[-1].lower()
285
-
286
- # Manejar archivos de texto
287
- if file_type in ['txt', 'pdf', 'docx']:
288
- if file_type == 'txt':
289
- try:
290
- file_content = uploaded_file.read().decode('utf-8')
291
- st.success(f"Archivo TXT cargado correctamente: {uploaded_file.name}")
292
- except Exception as e:
293
- st.error(f"Error al leer el archivo TXT: {str(e)}")
294
- file_content = ""
295
-
296
- elif file_type == 'pdf':
297
- try:
298
- import PyPDF2
299
- pdf_reader = PyPDF2.PdfReader(uploaded_file)
300
- file_content = ""
301
- for page in pdf_reader.pages:
302
- file_content += page.extract_text() + "\n"
303
- st.success(f"Archivo PDF cargado correctamente: {uploaded_file.name}")
304
- except Exception as e:
305
- st.error(f"Error al leer el archivo PDF: {str(e)}")
306
- file_content = ""
307
-
308
- elif file_type == 'docx':
309
- try:
310
- import docx
311
- doc = docx.Document(uploaded_file)
312
- file_content = "\n".join([para.text for para in doc.paragraphs])
313
- st.success(f"Archivo DOCX cargado correctamente: {uploaded_file.name}")
314
- except Exception as e:
315
- st.error(f"Error al leer el archivo DOCX: {str(e)}")
316
- file_content = ""
317
-
318
- # Manejar archivos de imagen
319
- elif file_type in ['jpg', 'jpeg', 'png']:
320
- try:
321
- from PIL import Image
322
- image = Image.open(uploaded_file)
323
- image_bytes = uploaded_file.getvalue()
324
- image_parts = {
325
- "mime_type": uploaded_file.type,
326
- "data": image_bytes
327
- }
328
- is_image = True
329
- st.image(image, caption="Imagen cargada", use_column_width=True)
330
- except Exception as e:
331
- st.error(f"Error processing image: {str(e)}")
332
- is_image = False
333
-
334
- selected_formula = email_formulas.email_formulas[selected_formula_key] # Updated reference
335
-
336
- # Botón de enviar
337
- submit = st.button("Generar Emails")
338
-
339
- # Mostrar los emails generados
340
- if submit:
341
- # Check if we have a valid combination of inputs
342
- has_file = 'file_content' in locals() and file_content.strip() != ""
343
- has_product = product.strip() != ""
344
- has_audience = target_audience.strip() != ""
345
- has_emotion = 'emotion' in locals() and emotion.strip() != ""
346
- has_action = 'desired_action' in locals() and desired_action.strip() != ""
347
-
348
- # Valid combinations:
349
- # 1. File + Product (no audience needed)
350
- # 2. File + Audience (no product needed)
351
- # 3. Product + Audience (traditional way)
352
- valid_inputs = (
353
- (has_file and has_product) or
354
- (has_file and has_audience) or
355
- (has_product and has_audience and has_emotion and has_action)
356
- )
357
-
358
- if valid_inputs and selected_formula:
359
- try:
360
- # Update the function call to include emotion and desired_action
361
- generated_emails = generate_emails(
362
- number_of_emails,
363
- target_audience,
364
- product,
365
- temperature,
366
- selected_formula,
367
- selected_angle,
368
- file_content if 'file_content' in locals() else "",
369
- image_parts if 'image_parts' in locals() else None,
370
- is_image if 'is_image' in locals() else False,
371
- emotion, # Añadir el parámetro de emoción
372
- desired_action # Añadir el parámetro de acción deseada
373
- )
374
- col2.markdown(f"""
375
- <div class="results-container">
376
- <h4>Tus emails persuasivos:</h4>
377
- <p>{generated_emails}</p>
378
- </div>
379
- """, unsafe_allow_html=True)
380
- except ValueError as e:
381
- col2.error(f"Error: {str(e)}")
382
- else:
383
- if not selected_formula:
384
- col2.error("Por favor selecciona una fórmula.")
385
- elif not (has_emotion and has_action):
386
- col2.error("Por favor especifica la emoción que quieres evocar y la acción deseada.")
387
- else:
388
- col2.error("Por favor proporciona al menos una de estas combinaciones: archivo + producto, archivo + público objetivo, o producto + público objetivo + emoción + acción deseada.")
 
1
+ from dotenv import load_dotenv
2
+ import streamlit as st
3
+ import os
4
+ import google.generativeai as genai
5
+ import random
6
+ from streamlit import session_state as state
7
+ from formulas import email_formulas # Updated import statement
8
+ from angles import angles
9
+
10
+ # Cargar las variables de entorno
11
+ load_dotenv()
12
+
13
+ # Configurar la API de Google
14
+ genai.configure(api_key=os.getenv("GOOGLE_API_KEY"))
15
+
16
+ # Fórmulas con ejemplos y explicaciones
17
+ # email_formulas dictionary has been moved to formulas/email_formulas.py
18
+
19
+ # Cambiar el nombre de la función
20
+ def generate_emails(number_of_emails, target_audience, product, temperature, selected_formula, selected_angle, file_content="", image_parts=None, is_image=False, emotion="", desired_action=""):
21
+ # Crear la configuración del modelo
22
+ generation_config = {
23
+ "temperature": temperature,
24
+ "top_p": 0.65,
25
+ "top_k": 360,
26
+ "max_output_tokens": 8196,
27
+ }
28
+
29
+ model = genai.GenerativeModel(
30
+ model_name="gemini-2.0-flash",
31
+ generation_config=generation_config,
32
+ )
33
+
34
+ # Angle dictionaries have been moved to angles/angle_data.py
35
+
36
+ # Incluir las instrucciones del sistema en el prompt principal
37
+ system_prompt = f"""You are a world-class direct response copywriter trained by Gary Halbert, Gary Bencivenga, and David Ogilvy.
38
+
39
+ You have helped many marketers before me persuade their clients through emotional email sequences.
40
+ Your task is to create email sequences that make my [buyer persona] feel [emotion] about my [product/service] and convince them to register/take [desired action].
41
+
42
+ FORMAT RULES:
43
+ - Each email must have a clear and attractive subject line
44
+ - Include personalized greeting
45
+ - The email body must be persuasive and emotional
46
+ - Include a clear call to action
47
+ - Add a professional signature
48
+ - Separate each email with a dividing line
49
+
50
+ IMPORTANT ANGLE INSTRUCTIONS:
51
+ - The selected angle MUST be applied to EACH email
52
+ - The angle modifies HOW the message is expressed, not its structure
53
+ - Think of the angle as a "tone overlay" on the content
54
+ - The formula provides the structure, the angle provides the style
55
+ - Both must work together seamlessly
56
+
57
+ FORMAT EXAMPLE:
58
+ ---
59
+ SUBJECT: [Attractive subject line]
60
+
61
+ Hello [Name],
62
+
63
+ [Email body with persuasive and emotional content]
64
+
65
+ [Clear call to action]
66
+
67
+ [Signature]
68
+ ---
69
+
70
+ IMPORTANT:
71
+ - Each email must be unique and memorable
72
+ - Avoid clichés and generalities
73
+ - Maintain a persuasive but credible tone
74
+ - Adapt language to the target audience
75
+ - Focus on transformative benefits
76
+ - Follow the selected angle style while maintaining the structure"""
77
+
78
+ # Iniciar el prompt con las instrucciones del sistema
79
+ email_instruction = f"{system_prompt}\n\n"
80
+
81
+ # Añadir contenido del archivo si existe
82
+ if file_content:
83
+ email_instruction += f"""
84
+ REFERENCE CONTENT:
85
+ Carefully analyze the following content as a reference for generating emails:
86
+ {file_content[:3000]}
87
+
88
+ ANALYSIS INSTRUCTIONS:
89
+ 1. Extract key information about the product or service mentioned
90
+ 2. Identify the tone, style, and language used
91
+ 3. Detect any data about the target audience or customer avatar
92
+ 4. Look for benefits, features, or pain points mentioned
93
+ 5. Use relevant terms, phrases, or concepts from the content
94
+ 6. Maintain consistency with the brand identity or main message
95
+ 7. Adapt the emails to resonate with the provided content
96
+
97
+ IMPORTANT COMBINATIONS:
98
+ """
99
+ # Updated conditions for specific input combinations
100
+ if product and not target_audience:
101
+ email_instruction += f"""- FILE + PRODUCT: You have a reference document and product ({product}). Create emails that highlight this specific product's benefits and features using insights from the document. Extract audience information from the document to better target the emails.
102
+ """
103
+ elif target_audience and not product:
104
+ email_instruction += f"""- FILE + TARGET AUDIENCE: You have a reference document and target audience ({target_audience}). Create emails tailored to this specific audience using language and concepts from the document. Identify products or services from the document that would appeal to this audience.
105
+ """
106
+ elif product and target_audience:
107
+ email_instruction += f"""- PRODUCT + TARGET AUDIENCE: You have both product ({product}) and target audience ({target_audience}). Create emails that connect this specific product with this specific audience, using insights from the document to strengthen the connection.
108
+ """
109
+
110
+ email_instruction += """
111
+ IMPORTANT: Naturally integrate the elements found in the content with the selected formula and angle.
112
+ """
113
+
114
+ # Añadir instrucciones de ángulo solo si no es "NINGUNO"
115
+ if selected_angle != "NINGUNO":
116
+ email_instruction += f"""
117
+ MAIN ANGLE: {selected_angle}
118
+ SPECIFIC ANGLE INSTRUCTIONS:
119
+ {angles[selected_angle]["instruction"]}
120
+
121
+ IMPORTANT: The angle {selected_angle} must be applied as a "style layer" over the formula structure:
122
+ 1. Keep the base structure of the formula intact
123
+ 2. Apply the tone and style of the {selected_angle} angle
124
+ 3. Ensure each element of the formula reflects the angle
125
+ 4. The angle affects "how" it's said, not "what" is said
126
+
127
+ SUCCESSFUL EXAMPLES OF THE {selected_angle} ANGLE:
128
+ """
129
+ for example in angles[selected_angle]["examples"]:
130
+ email_instruction += f"- {example}\n"
131
+
132
+ # Dentro de la función, actualizar el prompt para incluir emoción y acción deseada
133
+ email_instruction += (
134
+ f"\nYour task is to create {number_of_emails} persuasive emails for {target_audience} "
135
+ f"that evoke {emotion} and convince them to {desired_action} about {product}. "
136
+ )
137
+
138
+ if selected_angle != "NINGUNO":
139
+ email_instruction += f"IMPORTANT: Each email MUST follow the {selected_angle} angle clearly and consistently.\n\n"
140
+
141
+ email_instruction += (
142
+ f"Avoid obvious mentions of {product} and focus on generating genuine interest"
143
+ )
144
+
145
+ if selected_angle != "NINGUNO":
146
+ email_instruction += f" using the selected angle"
147
+
148
+ email_instruction += ".\n\n"
149
+
150
+ email_instruction += (
151
+ f"IMPORTANT: Carefully study these examples of the selected formula. "
152
+ f"Each example represents the style and structure to follow"
153
+ )
154
+
155
+ if selected_angle != "NINGUNO":
156
+ email_instruction += f", adapted to the {selected_angle} angle"
157
+
158
+ email_instruction += ":\n\n"
159
+
160
+ # Agregar 5 ejemplos aleatorios de la fórmula
161
+ random_examples = random.sample(selected_formula['examples'], min(5, len(selected_formula['examples'])))
162
+
163
+ email_instruction += "FORMULA EXAMPLES TO FOLLOW:\n"
164
+ for i, example in enumerate(random_examples, 1):
165
+ email_instruction += f"{i}. {example}\n"
166
+
167
+ email_instruction += "\nSPECIFIC INSTRUCTIONS:\n"
168
+ email_instruction += "1. Maintain the same structure and length as the previous examples\n"
169
+ email_instruction += "2. Use the same tone and writing style\n"
170
+ email_instruction += "3. Replicate the phrase construction patterns\n"
171
+ email_instruction += "4. Preserve the level of specificity and detail\n"
172
+ email_instruction += f"5. Adapt the content for {target_audience} while maintaining the essence of the examples\n\n"
173
+
174
+ email_instruction += f"FORMULA TO FOLLOW:\n{selected_formula['description']}\n\n"
175
+
176
+ # CORRECTO (con indentación):
177
+ if selected_angle != "NINGUNO":
178
+ email_instruction += f"""
179
+ FINAL REMINDER:
180
+ 1. Follow the structure of the selected formula
181
+ 2. Apply the angle as a "style layer"
182
+ 3. Maintain coherence between formula and angle
183
+ 4. Ensure each email reflects both elements
184
+
185
+ GENERATE NOW:
186
+ Create {number_of_emails} emails that faithfully follow the style and structure of the examples shown.
187
+ """
188
+ else:
189
+ email_instruction += f"""
190
+ GENERATE NOW:
191
+ Create {number_of_emails} emails that faithfully follow the style and structure of the examples shown.
192
+ """
193
+
194
+ # Modificar la forma de enviar el mensaje según si hay imagen o no
195
+ if is_image and image_parts:
196
+ chat_session = model.start_chat(
197
+ history=[
198
+ {
199
+ "role": "user",
200
+ "parts": [
201
+ email_instruction, # Cambiar headlines_instruction por email_instruction
202
+ image_parts
203
+ ],
204
+ },
205
+ ]
206
+ )
207
+ response = chat_session.send_message("Genera los emails siguiendo exactamente el estilo de los ejemplos mostrados, inspirándote en la imagen proporcionada.")
208
+ else:
209
+ chat_session = model.start_chat(
210
+ history=[
211
+ {
212
+ "role": "user",
213
+ "parts": [email_instruction], # Cambiar headlines_instruction por email_instruction
214
+ },
215
+ ]
216
+ )
217
+ response = chat_session.send_message("Genera los emails siguiendo exactamente el estilo de los ejemplos mostrados.")
218
+
219
+ return response.text
220
+
221
+ # Configurar la interfaz de usuario con Streamlit
222
+ st.set_page_config(page_title="Email Composer", layout="wide")
223
+
224
+ # Leer el contenido del archivo manual.md
225
+ with open("manual.md", "r", encoding="utf-8") as file:
226
+ manual_content = file.read()
227
+
228
+ # Mostrar el contenido del manual en el sidebar
229
+ st.sidebar.markdown(manual_content)
230
+
231
+ # Load CSS from file
232
+ with open("styles/main.css", "r") as f:
233
+ css = f.read()
234
+
235
+ # Apply the CSS
236
+ st.markdown(f"<style>{css}</style>", unsafe_allow_html=True)
237
+
238
+ # Centrar el título y el subtítulo
239
+ st.markdown("<h1 style='text-align: center;'>Generador de Emails</h1>", unsafe_allow_html=True)
240
+ st.markdown("<h4 style='text-align: center;'>Transforma tu marketing con emails persuasivos que convierten. Esta aplicación es tu arma secreta para crear emails emocionales de respuesta directa que impulsan a la acción.</h4>", unsafe_allow_html=True)
241
+
242
+ # Crear columnas
243
+ col1, col2 = st.columns([1, 2])
244
+
245
+ # Columnas de entrada
246
+ with col1:
247
+ target_audience = st.text_input("¿Quién es tu público objetivo?", placeholder="Ejemplo: Estudiantes Universitarios")
248
+ product = st.text_input("¿Qué producto/servicio estás promocionando?", placeholder="Ejemplo: Curso de Inglés")
249
+ number_of_emails = st.selectbox("Número de Emails", options=[1, 2, 3, 4, 5], index=2)
250
+
251
+ # Crear un único acordeón para fórmula, creatividad y ángulo
252
+ with st.expander("Personaliza tus emails"):
253
+ temperature = st.slider("Creatividad", min_value=0.0, max_value=2.0, value=1.0, step=0.1)
254
+
255
+ emotion = st.selectbox(
256
+ "¿Qué emoción quieres evocar?",
257
+ options=["Curiosidad", "Miedo", "Esperanza", "Entusiasmo", "Confianza", "Urgencia"]
258
+ )
259
+
260
+ desired_action = st.text_input("Acción deseada", placeholder="Ejemplo: Registrarse para una prueba gratuita")
261
+
262
+ selected_formula_key = st.selectbox(
263
+ "Selecciona una fórmula para tus emails",
264
+ options=list(email_formulas.email_formulas.keys()) # Updated reference
265
+ )
266
+
267
+ # Automatically use the keys from the angles dictionary
268
+ # Make sure "NINGUNO" appears first, then the rest alphabetically
269
+ angle_keys = ["NINGUNO"] + sorted([key for key in angles.keys() if key != "NINGUNO"])
270
+ selected_angle = st.selectbox(
271
+ "Selecciona un ángulo para tus emails",
272
+ options=angle_keys
273
+ )
274
+
275
+ # Añadir cargador de archivos dentro del acordeón
276
+ uploaded_file = st.file_uploader("📄 Archivo o imagen de referencia",
277
+ type=['txt', 'pdf', 'docx', 'jpg', 'jpeg', 'png'])
278
+
279
+ file_content = ""
280
+ is_image = False
281
+ image_parts = None
282
+
283
+ if uploaded_file is not None:
284
+ file_type = uploaded_file.name.split('.')[-1].lower()
285
+
286
+ # Manejar archivos de texto
287
+ if file_type in ['txt', 'pdf', 'docx']:
288
+ if file_type == 'txt':
289
+ try:
290
+ file_content = uploaded_file.read().decode('utf-8')
291
+ st.success(f"Archivo TXT cargado correctamente: {uploaded_file.name}")
292
+ except Exception as e:
293
+ st.error(f"Error al leer el archivo TXT: {str(e)}")
294
+ file_content = ""
295
+
296
+ elif file_type == 'pdf':
297
+ try:
298
+ import PyPDF2
299
+ pdf_reader = PyPDF2.PdfReader(uploaded_file)
300
+ file_content = ""
301
+ for page in pdf_reader.pages:
302
+ file_content += page.extract_text() + "\n"
303
+ st.success(f"Archivo PDF cargado correctamente: {uploaded_file.name}")
304
+ except Exception as e:
305
+ st.error(f"Error al leer el archivo PDF: {str(e)}")
306
+ file_content = ""
307
+
308
+ elif file_type == 'docx':
309
+ try:
310
+ import docx
311
+ doc = docx.Document(uploaded_file)
312
+ file_content = "\n".join([para.text for para in doc.paragraphs])
313
+ st.success(f"Archivo DOCX cargado correctamente: {uploaded_file.name}")
314
+ except Exception as e:
315
+ st.error(f"Error al leer el archivo DOCX: {str(e)}")
316
+ file_content = ""
317
+
318
+ # Manejar archivos de imagen
319
+ elif file_type in ['jpg', 'jpeg', 'png']:
320
+ try:
321
+ from PIL import Image
322
+ image = Image.open(uploaded_file)
323
+ image_bytes = uploaded_file.getvalue()
324
+ image_parts = {
325
+ "mime_type": uploaded_file.type,
326
+ "data": image_bytes
327
+ }
328
+ is_image = True
329
+ st.image(image, caption="Imagen cargada", use_column_width=True)
330
+ except Exception as e:
331
+ st.error(f"Error processing image: {str(e)}")
332
+ is_image = False
333
+
334
+ selected_formula = email_formulas.email_formulas[selected_formula_key] # Updated reference
335
+
336
+ # Botón de enviar
337
+ submit = st.button("Generar Emails")
338
+
339
+ # Mostrar los emails generados
340
+ if submit:
341
+ # Check if we have a valid combination of inputs
342
+ has_file = 'file_content' in locals() and file_content.strip() != ""
343
+ has_product = product.strip() != ""
344
+ has_audience = target_audience.strip() != ""
345
+ has_emotion = 'emotion' in locals() and emotion.strip() != ""
346
+ has_action = 'desired_action' in locals() and desired_action.strip() != ""
347
+
348
+ # Valid combinations:
349
+ # 1. File + Product (no audience needed)
350
+ # 2. File + Audience (no product needed)
351
+ # 3. Product + Audience (traditional way)
352
+ valid_inputs = (
353
+ (has_file and has_product) or
354
+ (has_file and has_audience) or
355
+ (has_product and has_audience and has_emotion and has_action)
356
+ )
357
+
358
+ if valid_inputs and selected_formula:
359
+ try:
360
+ # Update the function call to include emotion and desired_action
361
+ generated_emails = generate_emails(
362
+ number_of_emails,
363
+ target_audience,
364
+ product,
365
+ temperature,
366
+ selected_formula,
367
+ selected_angle,
368
+ file_content if 'file_content' in locals() else "",
369
+ image_parts if 'image_parts' in locals() else None,
370
+ is_image if 'is_image' in locals() else False,
371
+ emotion, # Añadir el parámetro de emoción
372
+ desired_action # Añadir el parámetro de acción deseada
373
+ )
374
+ col2.markdown(f"""
375
+ <div class="results-container">
376
+ <h4>Tus emails persuasivos:</h4>
377
+ <p>{generated_emails}</p>
378
+ </div>
379
+ """, unsafe_allow_html=True)
380
+ except ValueError as e:
381
+ col2.error(f"Error: {str(e)}")
382
+ else:
383
+ if not selected_formula:
384
+ col2.error("Por favor selecciona una fórmula.")
385
+ elif not (has_emotion and has_action):
386
+ col2.error("Por favor especifica la emoción que quieres evocar y la acción deseada.")
387
+ else:
388
+ col2.error("Por favor proporciona al menos una de estas combinaciones: archivo + producto, archivo + público objetivo, o producto + público objetivo + emoción + acción deseada.")