JeCabrera commited on
Commit
2baec9c
·
verified ·
1 Parent(s): 9c1519a

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +550 -545
app.py CHANGED
@@ -1,546 +1,551 @@
1
- from dotenv import load_dotenv
2
- import streamlit as st
3
- import os
4
- import google.generativeai as genai
5
- import random
6
- import datetime
7
- from streamlit import session_state as state
8
- from formulas.webinar_formulas import webinar_formulas
9
- from formulas.webinar_name_formulas import webinar_name_formulas
10
- from formulas.angles_webinar_names import angles_webinar_names
11
-
12
- # Cargar las variables de entorno
13
- load_dotenv()
14
-
15
- # Configurar la API de Google
16
- genai.configure(api_key=os.getenv("GOOGLE_API_KEY"))
17
-
18
- # Función auxiliar para mostrar el contenido generado y los botones de descarga
19
- # In the display_generated_content function, modify the names section:
20
-
21
- def display_generated_content(col, generated_content, content_type):
22
- timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S")
23
-
24
- # Determinar el tipo de contenido para personalizar los botones y títulos
25
- if content_type == "script":
26
- download_label = "DESCARGAR GUIÓN DE WEBINAR ▶▶"
27
- file_name = f"guion_webinar_{timestamp}.txt"
28
- subheader_text = "Tu guión de webinar:"
29
-
30
- # Mostrar botón de descarga superior para guiones
31
- col.download_button(
32
- label=download_label,
33
- data=generated_content,
34
- file_name=file_name,
35
- mime="text/plain",
36
- key=f"download_top_{content_type}"
37
- )
38
-
39
- # Mostrar el contenido generado
40
- col.subheader(subheader_text)
41
- col.markdown(generated_content)
42
-
43
- # Mostrar botón de descarga inferior
44
- col.download_button(
45
- label=download_label,
46
- data=generated_content,
47
- file_name=file_name,
48
- mime="text/plain",
49
- key=f"download_bottom_{content_type}"
50
- )
51
- else: # nombres
52
- subheader_text = "Tus nombres de webinar:"
53
- file_name = f"nombres_webinar_{timestamp}.txt"
54
- download_label = "DESCARGAR NOMBRES DE WEBINAR ▶▶"
55
-
56
- # Contar el número de nombres generados
57
- num_names = len([line for line in generated_content.split('\n') if line.strip().startswith(('1.', '2.', '3.', '4.', '5.', '6.', '7.', '8.', '9.', '10.', '11.', '12.', '13.', '14.', '15.'))])
58
-
59
- # Para los nombres, usar HTML personalizado en lugar de st.download_button
60
- import base64
61
-
62
- # Codificar el contenido para descarga
63
- b64 = base64.b64encode(generated_content.encode()).decode()
64
-
65
- # Crear botón de descarga superior con clase específica
66
- top_button_html = f"""
67
- <div class="custom-download-button names-download-button top-button">
68
- <a href="data:text/plain;base64,{b64}" download="{file_name}">
69
- {download_label}
70
- </a>
71
- </div>
72
- """
73
-
74
- # Crear botón de descarga inferior con clase específica
75
- bottom_button_html = f"""
76
- <div class="custom-download-button names-download-button bottom-button">
77
- <a href="data:text/plain;base64,{b64}" download="{file_name}">
78
- {download_label}
79
- </a>
80
- </div>
81
- """
82
-
83
- # Mostrar botón de descarga superior
84
- col.markdown(top_button_html, unsafe_allow_html=True)
85
-
86
- # Mostrar el contenido generado
87
- col.subheader(subheader_text)
88
- col.markdown(generated_content)
89
-
90
- # Mostrar botón de descarga inferior
91
- col.markdown(bottom_button_html, unsafe_allow_html=True)
92
-
93
- # Implementar la función generate_and_display para reemplazar código duplicado
94
- def generate_and_display(col, generator_func, audience, product, temperature, selected_formula, content_type, **kwargs):
95
- if validate_inputs(audience, product):
96
- try:
97
- with col:
98
- with st.spinner(f"Generando {'guión' if content_type == 'script' else 'nombres'} de webinar...", show_time=True):
99
- # Llamar a la función generadora con los parámetros adecuados
100
- generated_content = generator_func(
101
- audience=audience,
102
- topic=product,
103
- temperature=temperature,
104
- selected_formula=selected_formula,
105
- **kwargs
106
- )
107
-
108
- # Mostrar el contenido generado usando la función auxiliar
109
- display_generated_content(col, generated_content, content_type)
110
-
111
- except ValueError as e:
112
- col.error(f"Error: {str(e)}")
113
- else:
114
- col.error("Por favor, proporciona el público objetivo y el tema del webinar.")
115
-
116
- # Función para crear la configuración del modelo (evita duplicación)
117
- def create_model_config(temperature):
118
- return {
119
- "temperature": temperature,
120
- "top_p": 0.65,
121
- "top_k": 360,
122
- "max_output_tokens": 8196,
123
- }
124
-
125
- # Función para inicializar el modelo
126
- def initialize_model(temperature):
127
- config = create_model_config(temperature)
128
- return genai.GenerativeModel(
129
- model_name="gemini-2.0-flash",
130
- generation_config=config,
131
- )
132
-
133
- # Refactored model interaction function to reduce duplication
134
- def generate_content(prompt_instructions, temperature):
135
- model = initialize_model(temperature)
136
- chat_session = model.start_chat(
137
- history=[
138
- {
139
- "role": "user",
140
- "parts": [prompt_instructions],
141
- },
142
- ]
143
- )
144
- response = chat_session.send_message("Generate the content following exactly the provided instructions. All content must be in Spanish.")
145
- return response.text
146
-
147
- # Función para generar nombres de webinars
148
- # Refactorizar la función generate_webinar_names para que acepte los mismos parámetros que generate_webinar_script
149
- def generate_webinar_names(audience, topic, temperature, selected_formula, number_of_names=5, selected_angle=None, **kwargs):
150
- # Incluir las instrucciones del sistema en el prompt principal
151
- system_prompt = """You are a world-class copywriter, with expertise in crafting compelling and disruptive webinar titles that immediately capture the audience's attention and drive registrations.
152
-
153
- FORMAT RULES:
154
- - Each webinar name must start with number and period
155
- - One webinar name per line
156
- - No explanations or categories
157
- - Add a line break between each name
158
- - Avoid unnecessary : symbols
159
- - Each webinar name must be a complete, intriguing and creative title
160
- - WRITE ALL WEBINAR NAMES IN SPANISH
161
-
162
- FORMAT EXAMPLE:
163
- 1. Nombre del Webinar 1.
164
-
165
- 2. Nombre del Webinar 2.
166
-
167
- 3. Nombre del Webinar 3.
168
-
169
- 4. Nombre del Webinar 4.
170
-
171
- 5. Nombre del Webinar 5.
172
-
173
- IMPORTANT:
174
- - Each webinar name must be unique, memorable and disruptive
175
- - Create curiosity and intrigue with unexpected combinations
176
- - Use creative language that stands out from typical webinar titles
177
- - Incorporate pattern interrupts that make people stop scrolling
178
- - Adapt speaking language from the audience
179
- - Focus on transformative benefits with creative angles
180
- - Follow the selected formula structure but add creative twists
181
- - WRITE ALL WEBINAR NAMES IN SPANISH"""
182
-
183
- # Iniciar el prompt con las instrucciones del sistema
184
- webinar_names_instruction = f"{system_prompt}\n\n"
185
-
186
- # Añadir instrucciones de ángulo solo si no es "NINGUNO" y se proporcionó un ángulo
187
- if selected_angle and selected_angle != "NINGUNO":
188
- webinar_names_instruction += f"""
189
- MAIN ANGLE: {selected_angle}
190
- SPECIFIC ANGLE INSTRUCTIONS:
191
- {angles_webinar_names[selected_angle]["instruction"]}
192
-
193
- IMPORTANT: The {selected_angle} angle should be applied as a "style layer" over the formula structure:
194
- 1. Keep the base structure of the formula intact
195
- 2. Apply the tone and style of the {selected_angle} angle
196
- 3. Ensure that each element of the formula reflects the angle
197
- 4. The angle affects "how" it is said, not "what" is said
198
-
199
- SUCCESSFUL EXAMPLES OF THE {selected_angle} ANGLE:
200
- """
201
- for example in angles_webinar_names[selected_angle]["examples"]:
202
- webinar_names_instruction += f"- {example}\n"
203
-
204
- # Instrucciones específicas para la tarea
205
- webinar_names_instruction += (
206
- f"\nYour task is to create {number_of_names} irresistible, creative and disruptive webinar names for {audience} "
207
- f"that instantly capture attention and generate registrations for a webinar about {topic}. "
208
- f"Focus on awakening genuine curiosity, creating intrigue, and communicating the value they will get by registering."
209
- f"\n\n"
210
- f"IMPORTANT: Use these examples of the selected formula as inspiration, but make your titles more creative and disruptive. "
211
- f"Each example represents a base structure to follow, but add unexpected elements and creative twists"
212
- f":\n\n"
213
- )
214
-
215
- # Agregar ejemplos aleatorios de la fórmula (keeping examples in Spanish)
216
- random_examples = random.sample(selected_formula['examples'], min(5, len(selected_formula['examples'])))
217
- webinar_names_instruction += "EXAMPLES OF THE FORMULA TO FOLLOW (BUT MAKE YOURS MORE CREATIVE):\n"
218
- for i, example in enumerate(random_examples, 1):
219
- webinar_names_instruction += f"{i}. {example}\n"
220
-
221
- # Instrucciones específicas (translated to English)
222
- webinar_names_instruction += "\nSPECIFIC INSTRUCTIONS:\n"
223
- webinar_names_instruction += "1. Use the same basic structure as the examples but add creative twists\n"
224
- webinar_names_instruction += "2. Create curiosity gaps that make people want to learn more\n"
225
- webinar_names_instruction += "3. Use unexpected word combinations that surprise the reader\n"
226
- webinar_names_instruction += "4. Incorporate pattern interrupts that make people stop and think\n"
227
- webinar_names_instruction += f"5. Adapt the content for {audience} while making titles more memorable and disruptive\n\n"
228
- webinar_names_instruction += f"FORMULA TO FOLLOW (AS A BASE):\n{selected_formula['description']}\n\n"
229
- webinar_names_instruction += f"""
230
- CREATIVE TECHNIQUES TO APPLY:
231
- 1. Use unexpected metaphors or analogies
232
- 2. Create intriguing contrasts or paradoxes
233
- 3. Challenge conventional wisdom with provocative statements
234
- 4. Use power words that evoke emotion
235
- 5. Create curiosity with incomplete loops or questions
236
- 6. Use specific numbers or data points that seem unusual
237
-
238
- GENERATE NOW:
239
- Create {number_of_names} creative, disruptive webinar names that use the formula structure as a base but add unexpected creative elements to make them stand out.
240
- """
241
-
242
- # Enviar el mensaje al modelo
243
- # Use the common generate_content function
244
- return generate_content(webinar_names_instruction, temperature)
245
-
246
- # Update the create_input_section function to include the product/offer field
247
- def create_input_section(col, audience_key, product_key, formulas, formula_key, offer_key=None):
248
- audience = col.text_input("¿Quién es tu público objetivo?", placeholder="Ejemplo: Emprendedores digitales", key=audience_key)
249
- product = col.text_input("¿Sobre qué tema es tu webinar?", placeholder="Ejemplo: Marketing de afiliados", key=product_key)
250
-
251
- # Add the new product/offer field if a key is provided
252
- offer = None
253
- if offer_key:
254
- offer = col.text_input("¿Cuál es tu producto u oferta?", placeholder="Ejemplo: Curso de marketing de afiliados", key=offer_key)
255
-
256
- # Formula selection
257
- formula_keys = list(formulas.keys())
258
- selected_formula_key = col.selectbox(
259
- "Selecciona un framework de webinar",
260
- options=formula_keys,
261
- key=formula_key
262
- )
263
-
264
- if offer_key:
265
- return audience, product, selected_formula_key, offer
266
- else:
267
- return audience, product, selected_formula_key
268
-
269
- # Update the generate_webinar_script function to include the offer parameter
270
- def generate_webinar_script(audience, topic, temperature, selected_formula, offer=None, creative_idea=None):
271
- model = initialize_model(temperature)
272
-
273
- # Include offer in the system prompt if provided
274
- offer_text = f" and selling {offer}" if offer else ""
275
-
276
- # Incluir las instrucciones del sistema en el prompt principal
277
- system_prompt = f"""You are a collaborative team of world-class experts working together to create an exceptional webinar script that converts audience into customers.
278
-
279
- THE EXPERT TEAM:
280
-
281
- 1. MASTER WEBINAR STRATEGIST:
282
- - Expert in webinar frameworks and conversion strategies
283
- - Trained in the Perfect Webinar methodology by Russell Brunson
284
- - Ensures the script follows the selected framework structure precisely
285
- - Focuses on strategic placement of key conversion elements
286
-
287
- 2. ELITE DIRECT RESPONSE COPYWRITER:
288
- - Trained by Gary Halbert, Gary Bencivenga, and David Ogilvy
289
- - Creates compelling hooks, stories, and persuasive elements
290
- - Crafts irresistible calls to action that drives conversions
291
- - Ensures the language resonates with the target audience
292
-
293
- 3. AUDIENCE PSYCHOLOGY SPECIALIST:
294
- - Expert in understanding audience motivations and objections
295
- - Creates content that builds genuine connection and trust
296
- - Identifies and addresses hidden fears and desires
297
- - Ensures the content feels personal and relevant
298
-
299
- 4. STORYTELLING MASTER:
300
- - Creates compelling narratives that illustrate key points
301
- - Develops relatable examples and case studies
302
- - Ensures stories support the transformation being offered
303
- - Makes complex concepts accessible through narrative
304
-
305
- 5. WEBINAR ENGAGEMENT EXPERT:
306
- - Specializes in maintaining audience attention throughout
307
- - Creates interactive elements and engagement hooks
308
- - Develops compelling transitions between sections
309
- - Ensures the webinar flows naturally and keeps interest high
310
-
311
- FORMAT REQUIREMENTS:
312
- - Create a complete webinar script with clear sections and subsections
313
- - Include specific talking points for each section
314
- - Write in a conversational, engaging tone
315
- - Include persuasive elements and calls to action
316
- - Follow the selected webinar framework structure exactly
317
- - WRITE THE ENTIRE SCRIPT IN SPANISH
318
- - Start directly with the webinar content without introductory text
319
- - DO NOT include any explanatory text at the beginning like "Here's the webinar script..." or "I've created a webinar script..."
320
-
321
- COLLABORATIVE PROCESS:
322
- As a team of experts, you will:
323
- 1. Analyze the framework '{selected_formula['description']}' to understand its core principles
324
- 2. Identify how to best adapt this framework for {audience} learning about {topic}{offer_text}
325
- 3. Create persuasive language that resonates with {audience}
326
- 4. Ensure the script maintains engagement throughout
327
- 5. Follow the exact structure provided in the framework"""
328
-
329
- # Añadir instrucciones para la idea creativa si existe
330
- if creative_idea:
331
- system_prompt += f"""
332
- CREATIVE CONCEPT:
333
- Use the following creative concept as the central theme for the webinar:
334
- "{creative_idea}"
335
-
336
- CREATIVE CONCEPT INSTRUCTIONS:
337
- 1. This concept should be the unifying theme across the entire webinar
338
- 2. Use it as a metaphor or analogy throughout the presentation
339
- 3. Develop different aspects of this concept in each section
340
- 4. Make sure the concept naturally connects to the product benefits
341
- 5. The concept should make the webinar more memorable and engaging
342
- """
343
-
344
- # Update the task instructions to include the offer
345
- offer_instruction = f" and selling {offer}" if offer else ""
346
-
347
- # Instrucciones específicas para la tarea
348
- webinar_script_instruction = (
349
- f"{system_prompt}\n\n"
350
- f"\nYour task is to create a complete webinar script IN SPANISH for {audience} "
351
- f"about {topic}{offer_instruction} that is persuasive and converts the audience into customers. "
352
- f"The script must follow exactly the structure of the framework '{selected_formula['description']}' "
353
- f"and must include all the necessary elements for a successful webinar."
354
- f"\n\n"
355
- )
356
-
357
- # Estructura del webinar
358
- webinar_script_instruction += "WEBINAR STRUCTURE TO FOLLOW:\n"
359
- for i, step in enumerate(selected_formula['structure'], 1):
360
- webinar_script_instruction += f"{i}. {step}\n"
361
-
362
- # Ejemplos de webinars exitosos
363
- webinar_script_instruction += "\n\nEXAMPLES OF SUCCESSFUL WEBINARS WITH THIS STRUCTURE:\n"
364
- for i, example in enumerate(selected_formula['examples'], 1):
365
- webinar_script_instruction += f"{i}. {example}\n"
366
-
367
- # Instrucciones específicas - Reforzar el español
368
- webinar_script_instruction += f"""
369
- SPECIFIC INSTRUCTIONS:
370
- 1. Create a complete script that follows exactly the provided structure
371
- 2. Include persuasive elements and clear calls to action
372
- 3. Adapt the language and examples specifically for {audience}
373
- 4. Focus on the transformative benefits of {topic}
374
- 5. Include relevant stories and examples that reinforce your points
375
- 6. Use a conversational but professional tone
376
- 7. Make sure each section fulfills its specific purpose in the framework
377
- 8. IMPORTANT: Write the ENTIRE script in Spanish (neutral Latin American Spanish)
378
- 9. DO NOT include any introductory text like "Here's the webinar script..." or "I've created a webinar script..."
379
- 10. Start directly with the webinar title and content
380
- 11. ALL section titles, headers, and content MUST be in Spanish
381
- 12. Ensure ALL examples, stories, and calls to action are in Spanish
382
-
383
- GENERATE NOW:
384
- Create a complete webinar script following faithfully the structure of the selected framework, entirely in Spanish.
385
- """
386
-
387
- # Enviar el mensaje al modelo
388
- chat_session = model.start_chat(
389
- history=[
390
- {
391
- "role": "user",
392
- "parts": [webinar_script_instruction],
393
- },
394
- ]
395
- )
396
- response = chat_session.send_message("Generate the webinar script IN NEUTRAL SPANISH following exactly the provided structure. All content must be in neutral Spanish (not Spain Spanish). Start directly with the webinar content without any introductory text.")
397
-
398
- return response.text
399
-
400
- # Función para validar entradas (evita duplicación)
401
- def validate_inputs(audience, product):
402
- has_audience = audience.strip() != ""
403
- has_product = product.strip() != ""
404
- return has_audience and has_product
405
-
406
- # Update the load_css function comment to be more descriptive
407
- def load_css():
408
- css_path = "styles/styles.css"
409
- if os.path.exists(css_path):
410
- try:
411
- with open(css_path, "r") as f:
412
- st.markdown(f"<style>{f.read()}</style>", unsafe_allow_html=True)
413
- except Exception as e:
414
- st.warning(f"Error al cargar el archivo CSS: {str(e)}")
415
- else:
416
- st.warning(f"No se encontró el archivo CSS en {css_path}")
417
-
418
- # Modify the page config section to include the CSS loading and remove menu
419
- st.set_page_config(
420
- page_title="Perfect Webinar Framework",
421
- layout="wide",
422
- initial_sidebar_state="expanded",
423
- menu_items=None # This removes the three dots menu
424
- )
425
- load_css() # This will load the styles from styles.css
426
-
427
- # Leer el contenido del archivo manual.md
428
- with open("manual.md", "r", encoding="utf-8") as file:
429
- manual_content = file.read()
430
-
431
- # Mostrar el contenido del manual en el sidebar
432
- st.sidebar.markdown(manual_content)
433
-
434
- # Agregar título y subtítulo usando HTML
435
- st.markdown("<h1 style='text-align: center;'>Perfect Webinar Framework</h1>", unsafe_allow_html=True)
436
- st.markdown("<h3 style='text-align: center;'>Crea guiones y títulos de webinars persuasivos que convierten</h3>", unsafe_allow_html=True)
437
-
438
- # Crear pestañas para la interfaz
439
- tab1, tab2 = st.tabs(["Guiones de Webinar", "Nombres de Webinar"])
440
-
441
- # Primera pestaña - Generador de Guiones de Webinar
442
- with tab1:
443
- tab1.subheader("Script Webinar")
444
-
445
- # Crear columnas para la interfaz
446
- col1, col2 = tab1.columns([1, 2])
447
-
448
- # Columna de entrada usando la función reutilizable
449
- with col1:
450
- # Inputs básicos (fuera del acordeón)
451
- webinar_script_audience = st.text_input("¿Quién es tu público objetivo?", placeholder="Ejemplo: Emprendedores digitales", key="webinar_script_audience")
452
- webinar_script_product = st.text_input("¿Sobre qué tema es tu webinar?", placeholder="Ejemplo: Marketing de afiliados", key="webinar_script_product")
453
- webinar_script_offer = st.text_input("¿Cuál es tu producto u oferta?", placeholder="Ejemplo: Curso de marketing de afiliados", key="webinar_script_offer")
454
-
455
- # Botón de generación (movido aquí, justo después de los campos principales)
456
- submit_webinar_script = st.button("GENERAR GUIÓN DE WEBINAR ▶▶", key="generate_webinar_script")
457
-
458
- # Opciones avanzadas en el acordeón
459
- with st.expander("Personaliza tu guión de webinar"):
460
- # Selector de fórmula (ahora dentro del acordeón)
461
- selected_webinar_formula_key = st.selectbox(
462
- "Selecciona un framework de webinar",
463
- options=list(webinar_formulas.keys()),
464
- key="webinar_formula"
465
- )
466
-
467
- # Nuevo campo para la idea creativa
468
- creative_idea = st.text_area(
469
- "Idea creativa (opcional)",
470
- placeholder="Introduce una idea o concepto creativo que quieras usar como tema central en tu webinar",
471
- help="Este concepto será el tema unificador a lo largo de tu webinar, haciéndolo más memorable y atractivo",
472
- key="webinar_creative_idea"
473
- )
474
-
475
- # Slider de creatividad (ya existente)
476
- webinar_script_temperature = st.slider("Creatividad", min_value=0.0, max_value=2.0, value=1.0, step=0.1, key="webinar_script_temp")
477
-
478
- selected_webinar_formula = webinar_formulas[selected_webinar_formula_key]
479
-
480
- # Usar la función generate_and_display para generar y mostrar el guión
481
- if submit_webinar_script:
482
- generate_and_display(
483
- col=col2,
484
- generator_func=generate_webinar_script,
485
- audience=webinar_script_audience,
486
- product=webinar_script_product,
487
- temperature=webinar_script_temperature,
488
- selected_formula=selected_webinar_formula,
489
- content_type="script",
490
- offer=webinar_script_offer if webinar_script_offer.strip() else None,
491
- creative_idea=creative_idea if creative_idea.strip() else None
492
- )
493
-
494
- # Segunda pestaña - Generador de Nombres de Webinar
495
- with tab2:
496
- tab2.subheader("Nombres de Webinar")
497
-
498
- # Crear columnas para la interfaz
499
- col1, col2 = tab2.columns([1, 2])
500
-
501
- # Columna de entrada
502
- with col1:
503
- # Inputs básicos
504
- webinar_names_audience = st.text_input("¿Quién es tu público objetivo?", placeholder="Ejemplo: Emprendedores digitales", key="webinar_names_audience")
505
- webinar_names_product = st.text_input("¿Sobre qué tema es tu webinar?", placeholder="Ejemplo: Marketing de afiliados", key="webinar_names_product")
506
-
507
- # Botón de generación (movido aquí, justo después de los campos principales)
508
- submit_webinar_names = st.button("GENERAR NOMBRES DE WEBINAR ▶▶", key="generate_webinar_names")
509
-
510
- # Opciones avanzadas en el acordeón
511
- with st.expander("Personaliza tus nombres de webinar"):
512
- # Selector de fórmula
513
- selected_name_formula_key = st.selectbox(
514
- "Selecciona una fórmula para tus nombres",
515
- options=list(webinar_name_formulas.keys()),
516
- key="webinar_name_formula"
517
- )
518
-
519
- # Selector de ángulo
520
- selected_angle = st.selectbox(
521
- "Selecciona un ángulo (opcional)",
522
- options=["NINGUNO"] + list(angles_webinar_names.keys()),
523
- key="webinar_name_angle"
524
- )
525
-
526
- # Número de nombres a generar
527
- number_of_names = st.slider("Número de nombres a generar", min_value=3, max_value=15, value=5, step=1, key="number_of_names")
528
-
529
- # Slider de creatividad
530
- webinar_names_temperature = st.slider("Creatividad", min_value=0.0, max_value=2.0, value=1.0, step=0.1, key="webinar_names_temp")
531
-
532
- selected_name_formula = webinar_name_formulas[selected_name_formula_key]
533
-
534
- # Usar la función generate_and_display para generar y mostrar los nombres
535
- if submit_webinar_names:
536
- generate_and_display(
537
- col=col2,
538
- generator_func=generate_webinar_names,
539
- audience=webinar_names_audience,
540
- product=webinar_names_product,
541
- temperature=webinar_names_temperature,
542
- selected_formula=selected_name_formula,
543
- content_type="names",
544
- number_of_names=number_of_names,
545
- selected_angle=selected_angle if selected_angle != "NINGUNO" else None
 
 
 
 
 
546
  )
 
1
+ from dotenv import load_dotenv
2
+ import streamlit as st
3
+ import os
4
+ import google.generativeai as genai
5
+ import random
6
+ import datetime
7
+ from streamlit import session_state as state
8
+ from formulas.webinar_formulas import webinar_formulas
9
+ from formulas.webinar_name_formulas import webinar_name_formulas
10
+ from formulas.angles_webinar_names import angles_webinar_names
11
+
12
+ # Cargar las variables de entorno
13
+ load_dotenv()
14
+
15
+ # Configurar la API de Google
16
+ genai.configure(api_key=os.getenv("GOOGLE_API_KEY"))
17
+
18
+ # Función auxiliar para mostrar el contenido generado y los botones de descarga
19
+ # In the display_generated_content function, modify the names section:
20
+
21
+ # Modificar la función display_generated_content para usar session_state
22
+ def display_generated_content(col, generated_content, content_type):
23
+ timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S")
24
+
25
+ # Guardar el contenido generado en el estado de la sesión
26
+ if content_type == "script":
27
+ state.last_generated_script = generated_content
28
+ download_label = "DESCARGAR GUIÓN DE WEBINAR ▶▶"
29
+ file_name = f"guion_webinar_{timestamp}.txt"
30
+ subheader_text = "Tu guión de webinar:"
31
+
32
+ # Mostrar botón de descarga superior para guiones
33
+ col.download_button(
34
+ label=download_label,
35
+ data=generated_content,
36
+ file_name=file_name,
37
+ mime="text/plain",
38
+ key=f"download_top_{content_type}_{timestamp}", # Añadir timestamp para hacer la key única
39
+ on_click=None # Asegurarse de que no hay callback que recargue la página
40
+ )
41
+
42
+ # Mostrar el contenido generado
43
+ col.subheader(subheader_text)
44
+ col.markdown(generated_content)
45
+
46
+ # Mostrar botón de descarga inferior
47
+ col.download_button(
48
+ label=download_label,
49
+ data=generated_content,
50
+ file_name=file_name,
51
+ mime="text/plain",
52
+ key=f"download_bottom_{content_type}_{timestamp}", # Añadir timestamp para hacer la key única
53
+ on_click=None # Asegurarse de que no hay callback que recargue la página
54
+ )
55
+ else: # nombres
56
+ state.last_generated_names = generated_content
57
+ subheader_text = "Tus nombres de webinar:"
58
+ file_name = f"nombres_webinar_{timestamp}.txt"
59
+ download_label = "DESCARGAR NOMBRES DE WEBINAR ▶▶"
60
+
61
+ # Contar el número de nombres generados
62
+ num_names = len([line for line in generated_content.split('\n') if line.strip().startswith(('1.', '2.', '3.', '4.', '5.', '6.', '7.', '8.', '9.', '10.', '11.', '12.', '13.', '14.', '15.'))])
63
+
64
+ # Para los nombres, usar HTML personalizado en lugar de st.download_button
65
+ import base64
66
+
67
+ # Codificar el contenido para descarga
68
+ b64 = base64.b64encode(generated_content.encode()).decode()
69
+
70
+ # Crear botón de descarga superior con clase específica y timestamp único
71
+ top_button_html = f"""
72
+ <div class="custom-download-button names-download-button top-button">
73
+ <a href="data:text/plain;base64,{b64}" download="{file_name}" id="download_top_{timestamp}">
74
+ {download_label}
75
+ </a>
76
+ </div>
77
+ """
78
+
79
+ # Crear botón de descarga inferior con clase específica y timestamp único
80
+ bottom_button_html = f"""
81
+ <div class="custom-download-button names-download-button bottom-button">
82
+ <a href="data:text/plain;base64,{b64}" download="{file_name}" id="download_bottom_{timestamp}">
83
+ {download_label}
84
+ </a>
85
+ </div>
86
+ """
87
+
88
+ # Mostrar botón de descarga superior
89
+ col.markdown(top_button_html, unsafe_allow_html=True)
90
+
91
+ # Mostrar el contenido generado
92
+ col.subheader(subheader_text)
93
+ col.markdown(generated_content)
94
+
95
+ # Mostrar botón de descarga inferior
96
+ col.markdown(bottom_button_html, unsafe_allow_html=True)
97
+
98
+ # Implementar la función generate_and_display para reemplazar código duplicado
99
+ def generate_and_display(col, generator_func, audience, product, temperature, selected_formula, content_type, **kwargs):
100
+ if validate_inputs(audience, product):
101
+ try:
102
+ with col:
103
+ with st.spinner(f"Generando {'guión' if content_type == 'script' else 'nombres'} de webinar...", show_time=True):
104
+ # Llamar a la función generadora con los parámetros adecuados
105
+ generated_content = generator_func(
106
+ audience=audience,
107
+ topic=product,
108
+ temperature=temperature,
109
+ selected_formula=selected_formula,
110
+ **kwargs
111
+ )
112
+
113
+ # Mostrar el contenido generado usando la función auxiliar
114
+ display_generated_content(col, generated_content, content_type)
115
+
116
+ except ValueError as e:
117
+ col.error(f"Error: {str(e)}")
118
+ else:
119
+ col.error("Por favor, proporciona el público objetivo y el tema del webinar.")
120
+
121
+ # Función para crear la configuración del modelo (evita duplicación)
122
+ def create_model_config(temperature):
123
+ return {
124
+ "temperature": temperature,
125
+ "top_p": 0.65,
126
+ "top_k": 360,
127
+ "max_output_tokens": 8196,
128
+ }
129
+
130
+ # Función para inicializar el modelo
131
+ def initialize_model(temperature):
132
+ config = create_model_config(temperature)
133
+ return genai.GenerativeModel(
134
+ model_name="gemini-2.0-flash",
135
+ generation_config=config,
136
+ )
137
+
138
+ # Refactored model interaction function to reduce duplication
139
+ def generate_content(prompt_instructions, temperature):
140
+ model = initialize_model(temperature)
141
+ chat_session = model.start_chat(
142
+ history=[
143
+ {
144
+ "role": "user",
145
+ "parts": [prompt_instructions],
146
+ },
147
+ ]
148
+ )
149
+ response = chat_session.send_message("Generate the content following exactly the provided instructions. All content must be in Spanish.")
150
+ return response.text
151
+
152
+ # Función para generar nombres de webinars
153
+ # Refactorizar la función generate_webinar_names para que acepte los mismos parámetros que generate_webinar_script
154
+ def generate_webinar_names(audience, topic, temperature, selected_formula, number_of_names=5, selected_angle=None, **kwargs):
155
+ # Incluir las instrucciones del sistema en el prompt principal
156
+ system_prompt = """You are a world-class copywriter, with expertise in crafting compelling and disruptive webinar titles that immediately capture the audience's attention and drive registrations.
157
+
158
+ FORMAT RULES:
159
+ - Each webinar name must start with number and period
160
+ - One webinar name per line
161
+ - No explanations or categories
162
+ - Add a line break between each name
163
+ - Avoid unnecessary : symbols
164
+ - Each webinar name must be a complete, intriguing and creative title
165
+ - WRITE ALL WEBINAR NAMES IN SPANISH
166
+
167
+ FORMAT EXAMPLE:
168
+ 1. Nombre del Webinar 1.
169
+
170
+ 2. Nombre del Webinar 2.
171
+
172
+ 3. Nombre del Webinar 3.
173
+
174
+ 4. Nombre del Webinar 4.
175
+
176
+ 5. Nombre del Webinar 5.
177
+
178
+ IMPORTANT:
179
+ - Each webinar name must be unique, memorable and disruptive
180
+ - Create curiosity and intrigue with unexpected combinations
181
+ - Use creative language that stands out from typical webinar titles
182
+ - Incorporate pattern interrupts that make people stop scrolling
183
+ - Adapt speaking language from the audience
184
+ - Focus on transformative benefits with creative angles
185
+ - Follow the selected formula structure but add creative twists
186
+ - WRITE ALL WEBINAR NAMES IN SPANISH"""
187
+
188
+ # Iniciar el prompt con las instrucciones del sistema
189
+ webinar_names_instruction = f"{system_prompt}\n\n"
190
+
191
+ # Añadir instrucciones de ángulo solo si no es "NINGUNO" y se proporcionó un ángulo
192
+ if selected_angle and selected_angle != "NINGUNO":
193
+ webinar_names_instruction += f"""
194
+ MAIN ANGLE: {selected_angle}
195
+ SPECIFIC ANGLE INSTRUCTIONS:
196
+ {angles_webinar_names[selected_angle]["instruction"]}
197
+
198
+ IMPORTANT: The {selected_angle} angle should be applied as a "style layer" over the formula structure:
199
+ 1. Keep the base structure of the formula intact
200
+ 2. Apply the tone and style of the {selected_angle} angle
201
+ 3. Ensure that each element of the formula reflects the angle
202
+ 4. The angle affects "how" it is said, not "what" is said
203
+
204
+ SUCCESSFUL EXAMPLES OF THE {selected_angle} ANGLE:
205
+ """
206
+ for example in angles_webinar_names[selected_angle]["examples"]:
207
+ webinar_names_instruction += f"- {example}\n"
208
+
209
+ # Instrucciones específicas para la tarea
210
+ webinar_names_instruction += (
211
+ f"\nYour task is to create {number_of_names} irresistible, creative and disruptive webinar names for {audience} "
212
+ f"that instantly capture attention and generate registrations for a webinar about {topic}. "
213
+ f"Focus on awakening genuine curiosity, creating intrigue, and communicating the value they will get by registering."
214
+ f"\n\n"
215
+ f"IMPORTANT: Use these examples of the selected formula as inspiration, but make your titles more creative and disruptive. "
216
+ f"Each example represents a base structure to follow, but add unexpected elements and creative twists"
217
+ f":\n\n"
218
+ )
219
+
220
+ # Agregar ejemplos aleatorios de la fórmula (keeping examples in Spanish)
221
+ random_examples = random.sample(selected_formula['examples'], min(5, len(selected_formula['examples'])))
222
+ webinar_names_instruction += "EXAMPLES OF THE FORMULA TO FOLLOW (BUT MAKE YOURS MORE CREATIVE):\n"
223
+ for i, example in enumerate(random_examples, 1):
224
+ webinar_names_instruction += f"{i}. {example}\n"
225
+
226
+ # Instrucciones específicas (translated to English)
227
+ webinar_names_instruction += "\nSPECIFIC INSTRUCTIONS:\n"
228
+ webinar_names_instruction += "1. Use the same basic structure as the examples but add creative twists\n"
229
+ webinar_names_instruction += "2. Create curiosity gaps that make people want to learn more\n"
230
+ webinar_names_instruction += "3. Use unexpected word combinations that surprise the reader\n"
231
+ webinar_names_instruction += "4. Incorporate pattern interrupts that make people stop and think\n"
232
+ webinar_names_instruction += f"5. Adapt the content for {audience} while making titles more memorable and disruptive\n\n"
233
+ webinar_names_instruction += f"FORMULA TO FOLLOW (AS A BASE):\n{selected_formula['description']}\n\n"
234
+ webinar_names_instruction += f"""
235
+ CREATIVE TECHNIQUES TO APPLY:
236
+ 1. Use unexpected metaphors or analogies
237
+ 2. Create intriguing contrasts or paradoxes
238
+ 3. Challenge conventional wisdom with provocative statements
239
+ 4. Use power words that evoke emotion
240
+ 5. Create curiosity with incomplete loops or questions
241
+ 6. Use specific numbers or data points that seem unusual
242
+
243
+ GENERATE NOW:
244
+ Create {number_of_names} creative, disruptive webinar names that use the formula structure as a base but add unexpected creative elements to make them stand out.
245
+ """
246
+
247
+ # Enviar el mensaje al modelo
248
+ # Use the common generate_content function
249
+ return generate_content(webinar_names_instruction, temperature)
250
+
251
+ # Update the create_input_section function to include the product/offer field
252
+ def create_input_section(col, audience_key, product_key, formulas, formula_key, offer_key=None):
253
+ audience = col.text_input("¿Quién es tu público objetivo?", placeholder="Ejemplo: Emprendedores digitales", key=audience_key)
254
+ product = col.text_input("¿Sobre qué tema es tu webinar?", placeholder="Ejemplo: Marketing de afiliados", key=product_key)
255
+
256
+ # Add the new product/offer field if a key is provided
257
+ offer = None
258
+ if offer_key:
259
+ offer = col.text_input("¿Cuál es tu producto u oferta?", placeholder="Ejemplo: Curso de marketing de afiliados", key=offer_key)
260
+
261
+ # Formula selection
262
+ formula_keys = list(formulas.keys())
263
+ selected_formula_key = col.selectbox(
264
+ "Selecciona un framework de webinar",
265
+ options=formula_keys,
266
+ key=formula_key
267
+ )
268
+
269
+ if offer_key:
270
+ return audience, product, selected_formula_key, offer
271
+ else:
272
+ return audience, product, selected_formula_key
273
+
274
+ # Update the generate_webinar_script function to include the offer parameter
275
+ def generate_webinar_script(audience, topic, temperature, selected_formula, offer=None, creative_idea=None):
276
+ model = initialize_model(temperature)
277
+
278
+ # Include offer in the system prompt if provided
279
+ offer_text = f" and selling {offer}" if offer else ""
280
+
281
+ # Incluir las instrucciones del sistema en el prompt principal
282
+ system_prompt = f"""You are a collaborative team of world-class experts working together to create an exceptional webinar script that converts audience into customers.
283
+
284
+ THE EXPERT TEAM:
285
+
286
+ 1. MASTER WEBINAR STRATEGIST:
287
+ - Expert in webinar frameworks and conversion strategies
288
+ - Trained in the Perfect Webinar methodology by Russell Brunson
289
+ - Ensures the script follows the selected framework structure precisely
290
+ - Focuses on strategic placement of key conversion elements
291
+
292
+ 2. ELITE DIRECT RESPONSE COPYWRITER:
293
+ - Trained by Gary Halbert, Gary Bencivenga, and David Ogilvy
294
+ - Creates compelling hooks, stories, and persuasive elements
295
+ - Crafts irresistible calls to action that drives conversions
296
+ - Ensures the language resonates with the target audience
297
+
298
+ 3. AUDIENCE PSYCHOLOGY SPECIALIST:
299
+ - Expert in understanding audience motivations and objections
300
+ - Creates content that builds genuine connection and trust
301
+ - Identifies and addresses hidden fears and desires
302
+ - Ensures the content feels personal and relevant
303
+
304
+ 4. STORYTELLING MASTER:
305
+ - Creates compelling narratives that illustrate key points
306
+ - Develops relatable examples and case studies
307
+ - Ensures stories support the transformation being offered
308
+ - Makes complex concepts accessible through narrative
309
+
310
+ 5. WEBINAR ENGAGEMENT EXPERT:
311
+ - Specializes in maintaining audience attention throughout
312
+ - Creates interactive elements and engagement hooks
313
+ - Develops compelling transitions between sections
314
+ - Ensures the webinar flows naturally and keeps interest high
315
+
316
+ FORMAT REQUIREMENTS:
317
+ - Create a complete webinar script with clear sections and subsections
318
+ - Include specific talking points for each section
319
+ - Write in a conversational, engaging tone
320
+ - Include persuasive elements and calls to action
321
+ - Follow the selected webinar framework structure exactly
322
+ - WRITE THE ENTIRE SCRIPT IN SPANISH
323
+ - Start directly with the webinar content without introductory text
324
+ - DO NOT include any explanatory text at the beginning like "Here's the webinar script..." or "I've created a webinar script..."
325
+
326
+ COLLABORATIVE PROCESS:
327
+ As a team of experts, you will:
328
+ 1. Analyze the framework '{selected_formula['description']}' to understand its core principles
329
+ 2. Identify how to best adapt this framework for {audience} learning about {topic}{offer_text}
330
+ 3. Create persuasive language that resonates with {audience}
331
+ 4. Ensure the script maintains engagement throughout
332
+ 5. Follow the exact structure provided in the framework"""
333
+
334
+ # Añadir instrucciones para la idea creativa si existe
335
+ if creative_idea:
336
+ system_prompt += f"""
337
+ CREATIVE CONCEPT:
338
+ Use the following creative concept as the central theme for the webinar:
339
+ "{creative_idea}"
340
+
341
+ CREATIVE CONCEPT INSTRUCTIONS:
342
+ 1. This concept should be the unifying theme across the entire webinar
343
+ 2. Use it as a metaphor or analogy throughout the presentation
344
+ 3. Develop different aspects of this concept in each section
345
+ 4. Make sure the concept naturally connects to the product benefits
346
+ 5. The concept should make the webinar more memorable and engaging
347
+ """
348
+
349
+ # Update the task instructions to include the offer
350
+ offer_instruction = f" and selling {offer}" if offer else ""
351
+
352
+ # Instrucciones específicas para la tarea
353
+ webinar_script_instruction = (
354
+ f"{system_prompt}\n\n"
355
+ f"\nYour task is to create a complete webinar script IN SPANISH for {audience} "
356
+ f"about {topic}{offer_instruction} that is persuasive and converts the audience into customers. "
357
+ f"The script must follow exactly the structure of the framework '{selected_formula['description']}' "
358
+ f"and must include all the necessary elements for a successful webinar."
359
+ f"\n\n"
360
+ )
361
+
362
+ # Estructura del webinar
363
+ webinar_script_instruction += "WEBINAR STRUCTURE TO FOLLOW:\n"
364
+ for i, step in enumerate(selected_formula['structure'], 1):
365
+ webinar_script_instruction += f"{i}. {step}\n"
366
+
367
+ # Ejemplos de webinars exitosos
368
+ webinar_script_instruction += "\n\nEXAMPLES OF SUCCESSFUL WEBINARS WITH THIS STRUCTURE:\n"
369
+ for i, example in enumerate(selected_formula['examples'], 1):
370
+ webinar_script_instruction += f"{i}. {example}\n"
371
+
372
+ # Instrucciones específicas - Reforzar el español
373
+ webinar_script_instruction += f"""
374
+ SPECIFIC INSTRUCTIONS:
375
+ 1. Create a complete script that follows exactly the provided structure
376
+ 2. Include persuasive elements and clear calls to action
377
+ 3. Adapt the language and examples specifically for {audience}
378
+ 4. Focus on the transformative benefits of {topic}
379
+ 5. Include relevant stories and examples that reinforce your points
380
+ 6. Use a conversational but professional tone
381
+ 7. Make sure each section fulfills its specific purpose in the framework
382
+ 8. IMPORTANT: Write the ENTIRE script in Spanish (neutral Latin American Spanish)
383
+ 9. DO NOT include any introductory text like "Here's the webinar script..." or "I've created a webinar script..."
384
+ 10. Start directly with the webinar title and content
385
+ 11. ALL section titles, headers, and content MUST be in Spanish
386
+ 12. Ensure ALL examples, stories, and calls to action are in Spanish
387
+
388
+ GENERATE NOW:
389
+ Create a complete webinar script following faithfully the structure of the selected framework, entirely in Spanish.
390
+ """
391
+
392
+ # Enviar el mensaje al modelo
393
+ chat_session = model.start_chat(
394
+ history=[
395
+ {
396
+ "role": "user",
397
+ "parts": [webinar_script_instruction],
398
+ },
399
+ ]
400
+ )
401
+ response = chat_session.send_message("Generate the webinar script IN NEUTRAL SPANISH following exactly the provided structure. All content must be in neutral Spanish (not Spain Spanish). Start directly with the webinar content without any introductory text.")
402
+
403
+ return response.text
404
+
405
+ # Función para validar entradas (evita duplicación)
406
+ def validate_inputs(audience, product):
407
+ has_audience = audience.strip() != ""
408
+ has_product = product.strip() != ""
409
+ return has_audience and has_product
410
+
411
+ # Update the load_css function comment to be more descriptive
412
+ def load_css():
413
+ css_path = "styles/styles.css"
414
+ if os.path.exists(css_path):
415
+ try:
416
+ with open(css_path, "r") as f:
417
+ st.markdown(f"<style>{f.read()}</style>", unsafe_allow_html=True)
418
+ except Exception as e:
419
+ st.warning(f"Error al cargar el archivo CSS: {str(e)}")
420
+ else:
421
+ st.warning(f"No se encontró el archivo CSS en {css_path}")
422
+
423
+ # Modify the page config section to include the CSS loading and remove menu
424
+ st.set_page_config(
425
+ page_title="Perfect Webinar Framework",
426
+ layout="wide",
427
+ initial_sidebar_state="expanded",
428
+ menu_items=None # This removes the three dots menu
429
+ )
430
+ load_css() # This will load the styles from styles.css
431
+
432
+ # Leer el contenido del archivo manual.md
433
+ with open("manual.md", "r", encoding="utf-8") as file:
434
+ manual_content = file.read()
435
+
436
+ # Mostrar el contenido del manual en el sidebar
437
+ st.sidebar.markdown(manual_content)
438
+
439
+ # Agregar título y subtítulo usando HTML
440
+ st.markdown("<h1 style='text-align: center;'>Perfect Webinar Framework</h1>", unsafe_allow_html=True)
441
+ st.markdown("<h3 style='text-align: center;'>Crea guiones y títulos de webinars persuasivos que convierten</h3>", unsafe_allow_html=True)
442
+
443
+ # Crear pestañas para la interfaz
444
+ tab1, tab2 = st.tabs(["Guiones de Webinar", "Nombres de Webinar"])
445
+
446
+ # Primera pestaña - Generador de Guiones de Webinar
447
+ with tab1:
448
+ tab1.subheader("Script Webinar")
449
+
450
+ # Crear columnas para la interfaz
451
+ col1, col2 = tab1.columns([1, 2])
452
+
453
+ # Columna de entrada usando la función reutilizable
454
+ with col1:
455
+ # Inputs básicos (fuera del acordeón)
456
+ webinar_script_audience = st.text_input("¿Quién es tu público objetivo?", placeholder="Ejemplo: Emprendedores digitales", key="webinar_script_audience")
457
+ webinar_script_product = st.text_input("¿Sobre qué tema es tu webinar?", placeholder="Ejemplo: Marketing de afiliados", key="webinar_script_product")
458
+ webinar_script_offer = st.text_input("¿Cuál es tu producto u oferta?", placeholder="Ejemplo: Curso de marketing de afiliados", key="webinar_script_offer")
459
+
460
+ # Botón de generación (movido aquí, justo después de los campos principales)
461
+ submit_webinar_script = st.button("GENERAR GUIÓN DE WEBINAR ▶▶", key="generate_webinar_script")
462
+
463
+ # Opciones avanzadas en el acordeón
464
+ with st.expander("Personaliza tu guión de webinar"):
465
+ # Selector de fórmula (ahora dentro del acordeón)
466
+ selected_webinar_formula_key = st.selectbox(
467
+ "Selecciona un framework de webinar",
468
+ options=list(webinar_formulas.keys()),
469
+ key="webinar_formula"
470
+ )
471
+
472
+ # Nuevo campo para la idea creativa
473
+ creative_idea = st.text_area(
474
+ "Idea creativa (opcional)",
475
+ placeholder="Introduce una idea o concepto creativo que quieras usar como tema central en tu webinar",
476
+ help="Este concepto será el tema unificador a lo largo de tu webinar, haciéndolo más memorable y atractivo",
477
+ key="webinar_creative_idea"
478
+ )
479
+
480
+ # Slider de creatividad (ya existente)
481
+ webinar_script_temperature = st.slider("Creatividad", min_value=0.0, max_value=2.0, value=1.0, step=0.1, key="webinar_script_temp")
482
+
483
+ selected_webinar_formula = webinar_formulas[selected_webinar_formula_key]
484
+
485
+ # Usar la función generate_and_display para generar y mostrar el guión
486
+ if submit_webinar_script:
487
+ generate_and_display(
488
+ col=col2,
489
+ generator_func=generate_webinar_script,
490
+ audience=webinar_script_audience,
491
+ product=webinar_script_product,
492
+ temperature=webinar_script_temperature,
493
+ selected_formula=selected_webinar_formula,
494
+ content_type="script",
495
+ offer=webinar_script_offer if webinar_script_offer.strip() else None,
496
+ creative_idea=creative_idea if creative_idea.strip() else None
497
+ )
498
+
499
+ # Segunda pestaña - Generador de Nombres de Webinar
500
+ with tab2:
501
+ tab2.subheader("Nombres de Webinar")
502
+
503
+ # Crear columnas para la interfaz
504
+ col1, col2 = tab2.columns([1, 2])
505
+
506
+ # Columna de entrada
507
+ with col1:
508
+ # Inputs básicos
509
+ webinar_names_audience = st.text_input("¿Quién es tu público objetivo?", placeholder="Ejemplo: Emprendedores digitales", key="webinar_names_audience")
510
+ webinar_names_product = st.text_input("¿Sobre qué tema es tu webinar?", placeholder="Ejemplo: Marketing de afiliados", key="webinar_names_product")
511
+
512
+ # Botón de generación (movido aquí, justo después de los campos principales)
513
+ submit_webinar_names = st.button("GENERAR NOMBRES DE WEBINAR ▶▶", key="generate_webinar_names")
514
+
515
+ # Opciones avanzadas en el acordeón
516
+ with st.expander("Personaliza tus nombres de webinar"):
517
+ # Selector de fórmula
518
+ selected_name_formula_key = st.selectbox(
519
+ "Selecciona una fórmula para tus nombres",
520
+ options=list(webinar_name_formulas.keys()),
521
+ key="webinar_name_formula"
522
+ )
523
+
524
+ # Selector de ángulo
525
+ selected_angle = st.selectbox(
526
+ "Selecciona un ángulo (opcional)",
527
+ options=["NINGUNO"] + list(angles_webinar_names.keys()),
528
+ key="webinar_name_angle"
529
+ )
530
+
531
+ # Número de nombres a generar
532
+ number_of_names = st.slider("Número de nombres a generar", min_value=3, max_value=15, value=5, step=1, key="number_of_names")
533
+
534
+ # Slider de creatividad
535
+ webinar_names_temperature = st.slider("Creatividad", min_value=0.0, max_value=2.0, value=1.0, step=0.1, key="webinar_names_temp")
536
+
537
+ selected_name_formula = webinar_name_formulas[selected_name_formula_key]
538
+
539
+ # Usar la función generate_and_display para generar y mostrar los nombres
540
+ if submit_webinar_names:
541
+ generate_and_display(
542
+ col=col2,
543
+ generator_func=generate_webinar_names,
544
+ audience=webinar_names_audience,
545
+ product=webinar_names_product,
546
+ temperature=webinar_names_temperature,
547
+ selected_formula=selected_name_formula,
548
+ content_type="names",
549
+ number_of_names=number_of_names,
550
+ selected_angle=selected_angle if selected_angle != "NINGUNO" else None
551
  )