JeCabrera commited on
Commit
8056e64
·
verified ·
1 Parent(s): 3f3d8a3

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +274 -274
app.py CHANGED
@@ -1,274 +1,274 @@
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 headline_formulas
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
- # headline_formulas dictionary has been moved to formulas/headline_formulas.py
18
-
19
- def generate_headlines(number_of_headlines, target_audience, product, temperature, selected_formula, selected_angle, base_copy=None):
20
- # Crear la configuración del modelo
21
- generation_config = {
22
- "temperature": temperature,
23
- "top_p": 0.65,
24
- "top_k": 360,
25
- "max_output_tokens": 8196,
26
- }
27
-
28
- model = genai.GenerativeModel(
29
- model_name="gemini-2.0-flash",
30
- generation_config=generation_config,
31
- )
32
-
33
- # Angle dictionaries have been moved to angles/angle_data.py
34
-
35
- # Incluir las instrucciones del sistema en el prompt principal
36
- system_prompt = f"""You are a world-class copywriter, with expertise in crafting hooks, headlines, and subject lines that immediately capture the reader's attention, prompting them to open the email or continue reading.
37
-
38
- FORMAT RULES:
39
- - Each headline must start with number and period
40
- - One headline per line
41
- - No explanations or categories
42
- - Add a line break between each headline
43
- - Avoid unnecessary : symbols
44
- - Each headline must be a complete and intriguing sentence
45
-
46
- IMPORTANT ANGLE INSTRUCTIONS:
47
- - The selected angle MUST be applied to EVERY headline
48
- - The angle modifies HOW the formula is expressed, not its structure
49
- - Think of the angle as a "tone overlay" on the formula
50
- - The formula provides the structure, the angle provides the style
51
- - Both must work together seamlessly
52
-
53
- FORMAT EXAMPLE:
54
- 1. Titular 1.
55
-
56
- 2. Titular 2.
57
-
58
- 3. Titular 3.
59
-
60
- 4. Titular 4.
61
-
62
- 5. Titular 5.
63
-
64
- IMPORTANT:
65
- - Each headline must be unique and memorable
66
- - Avoid clichés and generalities
67
- - Maintain an intriguing but credible tone
68
- - Adapt speaking language from the audience
69
- - Focus on transformative benefits
70
- - Follow the selected angle style while maintaining formula structure"""
71
-
72
- # Iniciar el prompt con las instrucciones del sistema
73
- headlines_instruction = f"{system_prompt}\n\n"
74
-
75
- # Add base copy instructions if provided
76
- if base_copy and base_copy.strip():
77
- headlines_instruction += f"""
78
- BASE COPY TO USE:
79
- The following text should be used as the primary source of information and inspiration for generating headlines:
80
-
81
- {base_copy}
82
-
83
- IMPORTANT: Extract key concepts, benefits, and language from this base copy to create your headlines.
84
- Use the tone, style, and specific terminology from this text whenever possible.
85
- """
86
-
87
- # Añadir instrucciones de ángulo solo si no es "NINGUNO"
88
- if selected_angle != "NINGUNO":
89
- headlines_instruction += f"""
90
- ÁNGULO PRINCIPAL: {selected_angle}
91
- INSTRUCCIONES DE ÁNGULO ESPECÍFICAS:
92
- {angles[selected_angle]["instruction"]}
93
-
94
- IMPORTANT: The angle {selected_angle} must be applied as a "style layer" over the formula structure:
95
- 1. Keep the base structure of the formula intact
96
- 2. Apply the tone and style of the angle {selected_angle}
97
- 3. Ensure that each element of the formula reflects the angle
98
- 4. The angle affects "how" it is said, not "what" is said
99
-
100
- SUCCESSFUL EXAMPLES OF THE ANGLE {selected_angle}:
101
- """
102
- for example in angles[selected_angle]["examples"]:
103
- headlines_instruction += f"- {example}\n"
104
-
105
- headlines_instruction += (
106
- f"\nYour task is to create {number_of_headlines} irresistible headlines for {target_audience} "
107
- f"that instantly capture attention and generate curiosity about {product}. "
108
- )
109
-
110
- if selected_angle != "NINGUNO":
111
- headlines_instruction += f"IMPORTANT: Each headline MUST follow the {selected_angle} angle clearly and consistently.\n\n"
112
-
113
- headlines_instruction += (
114
- f"Avoid obvious mentions of {product} and focus on awakening genuine interest"
115
- )
116
-
117
- if selected_angle != "NINGUNO":
118
- headlines_instruction += f" using the selected angle"
119
-
120
- headlines_instruction += ".\n\n"
121
-
122
- headlines_instruction += (
123
- f"IMPORTANT: Carefully study these examples of the selected formula. "
124
- f"Each example represents the style and structure to follow"
125
- )
126
-
127
- if selected_angle != "NINGUNO":
128
- headlines_instruction += f", adapted to the {selected_angle} angle"
129
-
130
- headlines_instruction += ":\n\n"
131
-
132
- # Add 5 random examples of the formula
133
- random_examples = random.sample(selected_formula['examples'], min(5, len(selected_formula['examples'])))
134
-
135
- headlines_instruction += "FORMULA EXAMPLES TO FOLLOW:\n"
136
- for i, example in enumerate(random_examples, 1):
137
- headlines_instruction += f"{i}. {example}\n"
138
-
139
- headlines_instruction += "\nSPECIFIC INSTRUCTIONS:\n"
140
- headlines_instruction += "1. Maintain the same structure and length as the previous examples\n"
141
- headlines_instruction += "2. Use the same tone and writing style\n"
142
- headlines_instruction += "3. Replicate the patterns of phrase construction\n"
143
- headlines_instruction += "4. Preserve the level of specificity and detail\n"
144
- headlines_instruction += f"5. Adapt the content for {target_audience} while maintaining the essence of the examples\n\n"
145
-
146
- headlines_instruction += f"FORMULA TO FOLLOW:\n{selected_formula['description']}\n\n"
147
-
148
- # CORRECT (with indentation):
149
- if selected_angle != "NINGUNO":
150
- headlines_instruction += f"""
151
- FINAL REMINDER:
152
- 1. Follow the structure of the selected formula
153
- 2. Apply the angle as a "style layer"
154
- 3. Maintain coherence between formula and angle
155
- 4. Ensure each headline reflects both elements
156
-
157
- GENERATE NOW:
158
- Create {number_of_headlines} headlines that faithfully follow the style and structure of the examples shown.
159
- """
160
- else:
161
- headlines_instruction += f"""
162
- GENERATE NOW:
163
- Create {number_of_headlines} headlines that faithfully follow the style and structure of the examples shown.
164
- """
165
-
166
- # Send the message to the model (without image conditions)
167
- chat_session = model.start_chat(
168
- history=[
169
- {
170
- "role": "user",
171
- "parts": [headlines_instruction],
172
- },
173
- ]
174
- )
175
- response = chat_session.send_message("Genera los titulares siguiendo exactamente el estilo de los ejemplos mostrados.")
176
-
177
- return response.text
178
-
179
- # Configurar la interfaz de usuario con Streamlit
180
- st.set_page_config(page_title="Enchanted Hooks", layout="wide")
181
-
182
- # Leer el contenido del archivo manual.md
183
- with open("manual.md", "r", encoding="utf-8") as file:
184
- manual_content = file.read()
185
-
186
- # Mostrar el contenido del manual en el sidebar
187
- st.sidebar.markdown(manual_content)
188
-
189
- # Load CSS from file
190
- with open("styles/main.css", "r") as f:
191
- css = f.read()
192
-
193
- # Apply the CSS
194
- st.markdown(f"<style>{css}</style>", unsafe_allow_html=True)
195
-
196
- # Centrar el título y el subtítulo
197
- st.markdown("<h1 style='text-align: center;'>Enchanted Hooks</h1>", unsafe_allow_html=True)
198
- st.markdown("<h4 style='text-align: center;'>Imagina poder conjurar títulos que no solo informan, sino que encantan. Esta app es tu varita mágica en el mundo del copywriting, transformando cada concepto en un titular cautivador que deja a todos deseando más.</h4>", unsafe_allow_html=True)
199
-
200
- # Crear columnas
201
- col1, col2 = st.columns([1, 2])
202
-
203
- # Columnas de entrada
204
- with col1:
205
- target_audience = st.text_input("¿Quién es tu público objetivo?", placeholder="Ejemplo: Estudiantes Universitarios")
206
- product = st.text_input("¿Qué producto tienes en mente?", placeholder="Ejemplo: Curso de Inglés")
207
-
208
- # Crear un único acordeón para fórmula, creatividad y ángulo
209
- with st.expander("Personaliza tus titulares"):
210
- # Moved formula selection above number of headlines
211
- selected_formula_key = st.selectbox(
212
- "Selecciona una fórmula para tus titulares",
213
- options=list(headline_formulas.keys())
214
- )
215
-
216
- # Added number of headlines after formula selection
217
- number_of_headlines = st.selectbox("Número de Titulares", options=[1, 2, 3, 4, 5, 6, 7, 8, 9, 10], index=4)
218
-
219
- # New text area for base copy
220
- base_copy = st.text_area(
221
- "Texto base para generar titulares (opcional)",
222
- placeholder="Agrega aquí un texto que sirva como base para generar los titulares. Si lo dejas vacío, se generarán basados en el producto y público objetivo.",
223
- height=150
224
- )
225
-
226
- temperature = st.slider("Creatividad", min_value=0.0, max_value=2.0, value=1.0, step=0.1)
227
-
228
- # Automatically use the keys from the angles dictionary
229
- # Make sure "NINGUNO" appears first, then the rest alphabetically
230
- angle_keys = ["NINGUNO"] + sorted([key for key in angles.keys() if key != "NINGUNO"])
231
- selected_angle = st.selectbox(
232
- "Selecciona el ángulo para tus titulares",
233
- options=angle_keys
234
- )
235
-
236
- selected_formula = headline_formulas[selected_formula_key]
237
-
238
- # Botón de enviar con estilo personalizado (moved outside the expander)
239
- submit = st.button("Generar Titulares", key="submit_button", use_container_width=True)
240
-
241
- # Mostrar los titulares generados
242
- if submit:
243
- # Check if we have valid inputs
244
- has_product = product.strip() != ""
245
- has_audience = target_audience.strip() != ""
246
- has_base_copy = base_copy and base_copy.strip() != ""
247
-
248
- # Valid combination: Either (Product + Audience) or Base Copy
249
- valid_inputs = (has_product and has_audience) or has_base_copy
250
-
251
- if valid_inputs and selected_formula:
252
- try:
253
- generated_headlines = generate_headlines(
254
- number_of_headlines,
255
- target_audience,
256
- product,
257
- temperature,
258
- selected_formula,
259
- selected_angle,
260
- base_copy if has_base_copy else None
261
- )
262
- col2.markdown(f"""
263
- <div class="results-container">
264
- <h4>Observa la magia en acción:</h4>
265
- <p>{generated_headlines}</p>
266
- </div>
267
- """, unsafe_allow_html=True)
268
- except ValueError as e:
269
- col2.error(f"Error: {str(e)}")
270
- else:
271
- if not selected_formula:
272
- col2.error("Por favor, selecciona una fórmula.")
273
- elif not has_base_copy:
274
- col2.error("Por favor, proporciona el público objetivo y el producto, o un texto base.")
 
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 headline_formulas
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
+ # headline_formulas dictionary has been moved to formulas/headline_formulas.py
18
+
19
+ def generate_headlines(number_of_headlines, target_audience, product, temperature, selected_formula, selected_angle, base_copy=None):
20
+ # Crear la configuración del modelo
21
+ generation_config = {
22
+ "temperature": temperature,
23
+ "top_p": 0.65,
24
+ "top_k": 360,
25
+ "max_output_tokens": 8196,
26
+ }
27
+
28
+ model = genai.GenerativeModel(
29
+ model_name="gemini-2.0-flash",
30
+ generation_config=generation_config,
31
+ )
32
+
33
+ # Angle dictionaries have been moved to angles/angle_data.py
34
+
35
+ # Incluir las instrucciones del sistema en el prompt principal
36
+ system_prompt = f"""You are a world-class copywriter, with expertise in crafting hooks, headlines, and subject lines that immediately capture the reader's attention, prompting them to open the email or continue reading.
37
+
38
+ FORMAT RULES:
39
+ - Each headline must start with number and period
40
+ - One headline per line
41
+ - No explanations or categories
42
+ - Add a line break between each headline
43
+ - Avoid unnecessary : symbols
44
+ - Each headline must be a complete and intriguing sentence
45
+
46
+ IMPORTANT ANGLE INSTRUCTIONS:
47
+ - The selected angle MUST be applied to EVERY headline
48
+ - The angle modifies HOW the formula is expressed, not its structure
49
+ - Think of the angle as a "tone overlay" on the formula
50
+ - The formula provides the structure, the angle provides the style
51
+ - Both must work together seamlessly
52
+
53
+ FORMAT EXAMPLE:
54
+ 1. Titular 1.
55
+
56
+ 2. Titular 2.
57
+
58
+ 3. Titular 3.
59
+
60
+ 4. Titular 4.
61
+
62
+ 5. Titular 5.
63
+
64
+ IMPORTANT:
65
+ - Each headline must be unique and memorable
66
+ - Avoid clichés and generalities
67
+ - Maintain an intriguing but credible tone
68
+ - Adapt speaking language from the audience
69
+ - Focus on transformative benefits
70
+ - Follow the selected angle style while maintaining formula structure"""
71
+
72
+ # Iniciar el prompt con las instrucciones del sistema
73
+ headlines_instruction = f"{system_prompt}\n\n"
74
+
75
+ # Add base copy instructions if provided
76
+ if base_copy and base_copy.strip():
77
+ headlines_instruction += f"""
78
+ BASE COPY TO USE:
79
+ The following text should be used as the primary source of information and inspiration for generating headlines:
80
+
81
+ {base_copy}
82
+
83
+ IMPORTANT: Extract key concepts, benefits, and language from this base copy to create your headlines.
84
+ Use the tone, style, and specific terminology from this text whenever possible.
85
+ """
86
+
87
+ # Añadir instrucciones de ángulo solo si no es "NINGUNO"
88
+ if selected_angle != "NINGUNO":
89
+ headlines_instruction += f"""
90
+ ÁNGULO PRINCIPAL: {selected_angle}
91
+ INSTRUCCIONES DE ÁNGULO ESPECÍFICAS:
92
+ {angles[selected_angle]["instruction"]}
93
+
94
+ IMPORTANT: The angle {selected_angle} must be applied as a "style layer" over the formula structure:
95
+ 1. Keep the base structure of the formula intact
96
+ 2. Apply the tone and style of the angle {selected_angle}
97
+ 3. Ensure that each element of the formula reflects the angle
98
+ 4. The angle affects "how" it is said, not "what" is said
99
+
100
+ SUCCESSFUL EXAMPLES OF THE ANGLE {selected_angle}:
101
+ """
102
+ for example in angles[selected_angle]["examples"]:
103
+ headlines_instruction += f"- {example}\n"
104
+
105
+ headlines_instruction += (
106
+ f"\nYour task is to create {number_of_headlines} irresistible headlines for {target_audience} "
107
+ f"that instantly capture attention and generate curiosity about {product}. "
108
+ )
109
+
110
+ if selected_angle != "NINGUNO":
111
+ headlines_instruction += f"IMPORTANT: Each headline MUST follow the {selected_angle} angle clearly and consistently.\n\n"
112
+
113
+ headlines_instruction += (
114
+ f"Avoid obvious mentions of {product} and focus on awakening genuine interest"
115
+ )
116
+
117
+ if selected_angle != "NINGUNO":
118
+ headlines_instruction += f" using the selected angle"
119
+
120
+ headlines_instruction += ".\n\n"
121
+
122
+ headlines_instruction += (
123
+ f"IMPORTANT: Carefully study these examples of the selected formula. "
124
+ f"Each example represents the style and structure to follow"
125
+ )
126
+
127
+ if selected_angle != "NINGUNO":
128
+ headlines_instruction += f", adapted to the {selected_angle} angle"
129
+
130
+ headlines_instruction += ":\n\n"
131
+
132
+ # Add 5 random examples of the formula
133
+ random_examples = random.sample(selected_formula['examples'], min(5, len(selected_formula['examples'])))
134
+
135
+ headlines_instruction += "FORMULA EXAMPLES TO FOLLOW:\n"
136
+ for i, example in enumerate(random_examples, 1):
137
+ headlines_instruction += f"{i}. {example}\n"
138
+
139
+ headlines_instruction += "\nSPECIFIC INSTRUCTIONS:\n"
140
+ headlines_instruction += "1. Maintain the same structure and length as the previous examples\n"
141
+ headlines_instruction += "2. Use the same tone and writing style\n"
142
+ headlines_instruction += "3. Replicate the patterns of phrase construction\n"
143
+ headlines_instruction += "4. Preserve the level of specificity and detail\n"
144
+ headlines_instruction += f"5. Adapt the content for {target_audience} while maintaining the essence of the examples\n\n"
145
+
146
+ headlines_instruction += f"FORMULA TO FOLLOW:\n{selected_formula['description']}\n\n"
147
+
148
+ # CORRECT (with indentation):
149
+ if selected_angle != "NINGUNO":
150
+ headlines_instruction += f"""
151
+ FINAL REMINDER:
152
+ 1. Follow the structure of the selected formula
153
+ 2. Apply the angle as a "style layer"
154
+ 3. Maintain coherence between formula and angle
155
+ 4. Ensure each headline reflects both elements
156
+
157
+ GENERATE NOW:
158
+ Create {number_of_headlines} headlines that faithfully follow the style and structure of the examples shown.
159
+ """
160
+ else:
161
+ headlines_instruction += f"""
162
+ GENERATE NOW:
163
+ Create {number_of_headlines} headlines that faithfully follow the style and structure of the examples shown.
164
+ """
165
+
166
+ # Send the message to the model (without image conditions)
167
+ chat_session = model.start_chat(
168
+ history=[
169
+ {
170
+ "role": "user",
171
+ "parts": [headlines_instruction],
172
+ },
173
+ ]
174
+ )
175
+ response = chat_session.send_message("Genera los titulares siguiendo exactamente el estilo de los ejemplos mostrados.")
176
+
177
+ return response.text
178
+
179
+ # Configurar la interfaz de usuario con Streamlit
180
+ st.set_page_config(page_title="Enchanted Hooks", layout="wide")
181
+
182
+ # Leer el contenido del archivo manual.md
183
+ with open("manual.md", "r", encoding="utf-8") as file:
184
+ manual_content = file.read()
185
+
186
+ # Mostrar el contenido del manual en el sidebar
187
+ st.sidebar.markdown(manual_content)
188
+
189
+ # Load CSS from file
190
+ with open("styles/main.css", "r") as f:
191
+ css = f.read()
192
+
193
+ # Apply the CSS
194
+ st.markdown(f"<style>{css}</style>", unsafe_allow_html=True)
195
+
196
+ # Centrar el título y el subtítulo
197
+ st.markdown("<h1 style='text-align: center;'>Enchanted Hooks</h1>", unsafe_allow_html=True)
198
+ st.markdown("<h4 style='text-align: center;'>Imagina poder conjurar títulos que no solo informan, sino que encantan. Esta app es tu varita mágica en el mundo del copywriting, transformando cada concepto en un titular cautivador que deja a todos deseando más.</h4>", unsafe_allow_html=True)
199
+
200
+ # Crear columnas
201
+ col1, col2 = st.columns([1, 2])
202
+
203
+ # Columnas de entrada
204
+ with col1:
205
+ target_audience = st.text_input("¿Quién es tu público objetivo?", placeholder="Ejemplo: Estudiantes Universitarios")
206
+ product = st.text_input("¿Qué producto tienes en mente?", placeholder="Ejemplo: Curso de Inglés")
207
+
208
+ # Botón de enviar con estilo personalizado (moved right after product input)
209
+ submit = st.button("Generar Titulares", key="submit_button", use_container_width=True)
210
+
211
+ # Crear un único acordeón para fórmula, creatividad y ángulo
212
+ with st.expander("Personaliza tus titulares"):
213
+ # Moved formula selection above number of headlines
214
+ selected_formula_key = st.selectbox(
215
+ "Selecciona una fórmula para tus titulares",
216
+ options=list(headline_formulas.keys())
217
+ )
218
+
219
+ # Added number of headlines after formula selection
220
+ number_of_headlines = st.selectbox("Número de Titulares", options=[1, 2, 3, 4, 5, 6, 7, 8, 9, 10], index=4)
221
+
222
+ # New text area for base copy
223
+ base_copy = st.text_area(
224
+ "Texto base para generar titulares (opcional)",
225
+ placeholder="Agrega aquí un texto que sirva como base para generar los titulares. Si lo dejas vacío, se generarán basados en el producto y público objetivo.",
226
+ height=150
227
+ )
228
+
229
+ temperature = st.slider("Creatividad", min_value=0.0, max_value=2.0, value=1.0, step=0.1)
230
+
231
+ # Automatically use the keys from the angles dictionary
232
+ # Make sure "NINGUNO" appears first, then the rest alphabetically
233
+ angle_keys = ["NINGUNO"] + sorted([key for key in angles.keys() if key != "NINGUNO"])
234
+ selected_angle = st.selectbox(
235
+ "Selecciona el ángulo para tus titulares",
236
+ options=angle_keys
237
+ )
238
+
239
+ selected_formula = headline_formulas[selected_formula_key]
240
+
241
+ # Mostrar los titulares generados
242
+ if submit:
243
+ # Check if we have valid inputs
244
+ has_product = product.strip() != ""
245
+ has_audience = target_audience.strip() != ""
246
+ has_base_copy = base_copy and base_copy.strip() != ""
247
+
248
+ # Valid combination: Either (Product + Audience) or Base Copy
249
+ valid_inputs = (has_product and has_audience) or has_base_copy
250
+
251
+ if valid_inputs and selected_formula:
252
+ try:
253
+ generated_headlines = generate_headlines(
254
+ number_of_headlines,
255
+ target_audience,
256
+ product,
257
+ temperature,
258
+ selected_formula,
259
+ selected_angle,
260
+ base_copy if has_base_copy else None
261
+ )
262
+ col2.markdown(f"""
263
+ <div class="results-container">
264
+ <h4>Observa la magia en acción:</h4>
265
+ <p>{generated_headlines}</p>
266
+ </div>
267
+ """, unsafe_allow_html=True)
268
+ except ValueError as e:
269
+ col2.error(f"Error: {str(e)}")
270
+ else:
271
+ if not selected_formula:
272
+ col2.error("Por favor, selecciona una fórmula.")
273
+ elif not has_base_copy:
274
+ col2.error("Por favor, proporciona el público objetivo y el producto, o un texto base.")