Ideal_Client / app.py
JeCabrera's picture
Update app.py
4b010b5 verified
raw
history blame
22.2 kB
from dotenv import load_dotenv
import streamlit as st
import os
import google.generativeai as genai
import random
import datetime
from streamlit import session_state as state
from angles import angles
from formulas.webinar_formulas import webinar_formulas
from formulas.webinar_name_formulas import webinar_name_formulas
from formulas.angles_webinar_names import angles_webinar_names
# Cargar las variables de entorno
load_dotenv()
# Configurar la API de Google
genai.configure(api_key=os.getenv("GOOGLE_API_KEY"))
# Create a reusable function for the UI input section
def create_input_section(col, audience_key, product_key, formula_options, formula_key):
audience = col.text_input("驴Qui茅n es tu p煤blico objetivo?", placeholder="Ejemplo: Emprendedores digitales", key=audience_key)
product = col.text_input("驴Sobre qu茅 tema es tu webinar?", placeholder="Ejemplo: Marketing en redes sociales", key=product_key)
selected_formula_key = col.selectbox(
"Selecciona un framework de webinar" if "script" in audience_key else "Selecciona una f贸rmula para tus nombres de webinar",
options=list(formula_options.keys()),
key=formula_key
)
return audience, product, selected_formula_key
# Create a reusable function for generation and display
def generate_and_display(col, generator_func, audience, product, temperature, selected_formula, **kwargs):
if validate_inputs(audience, product):
try:
with col:
with st.spinner("Generando contenido...", show_time=True):
# Extract only the parameters that the generator function accepts
if generator_func.__name__ == "generate_webinar_script":
generated_content = generator_func(
audience=audience,
topic=product,
temperature=temperature,
selected_formula=selected_formula
)
else:
generated_content = generator_func(
audience=audience,
topic=product,
temperature=temperature,
selected_formula=selected_formula,
**kwargs
)
# For webinar scripts, add download buttons
if "script" in kwargs.get("content_type", ""):
timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S")
st.download_button(
label="DESCARGAR GUION DE MI WEBINAR",
data=generated_content,
file_name=f"guion_webinar_{timestamp}.md",
mime="text/markdown",
key="download_top"
)
st.subheader("Tu " + ("gui贸n de webinar:" if "script" in kwargs.get("content_type", "") else "nombres de webinar:"))
st.markdown(generated_content)
# Add bottom download button for scripts
if "script" in kwargs.get("content_type", ""):
st.download_button(
label="DESCARGAR GUION DE MI WEBINAR",
data=generated_content,
file_name=f"guion_webinar_{timestamp}.md",
mime="text/markdown",
key="download_bottom"
)
except ValueError as e:
col.error(f"Error: {str(e)}")
else:
col.error("Por favor, proporciona el p煤blico objetivo y el tema del webinar.")
# Funci贸n para crear la configuraci贸n del modelo (evita duplicaci贸n)
def create_model_config(temperature):
return {
"temperature": temperature,
"top_p": 0.65,
"top_k": 360,
"max_output_tokens": 8196,
}
# Funci贸n para inicializar el modelo
def initialize_model(temperature):
config = create_model_config(temperature)
return genai.GenerativeModel(
model_name="gemini-2.0-flash",
generation_config=config,
)
# Refactored model interaction function to reduce duplication
def generate_content(prompt_instructions, temperature):
model = initialize_model(temperature)
chat_session = model.start_chat(
history=[
{
"role": "user",
"parts": [prompt_instructions],
},
]
)
response = chat_session.send_message("Generate the content following exactly the provided instructions. All content must be in Spanish.")
return response.text
# Funci贸n para generar nombres de webinars
def generate_webinar_names(number_of_names, target_audience, product, temperature, selected_formula, selected_angle=None):
# Incluir las instrucciones del sistema en el prompt principal
system_prompt = """You are a world-class copywriter, with expertise in crafting compelling webinar titles that immediately capture the audience's attention and drive registrations.
FORMAT RULES:
- Each webinar name must start with number and period
- One webinar name per line
- No explanations or categories
- Add a line break between each name
- Avoid unnecessary : symbols
- Each webinar name must be a complete and intriguing title
- WRITE ALL WEBINAR NAMES IN SPANISH
FORMAT EXAMPLE:
1. Nombre del Webinar 1.
2. Nombre del Webinar 2.
3. Nombre del Webinar 3.
4. Nombre del Webinar 4.
5. Nombre del Webinar 5.
IMPORTANT:
- Each webinar name must be unique and memorable
- Avoid clich茅s and generalities
- Maintain an intriguing but credible tone
- Adapt speaking language from the audience
- Focus on transformative benefits
- Follow the selected formula structure
- WRITE ALL WEBINAR NAMES IN SPANISH"""
# Iniciar el prompt con las instrucciones del sistema
webinar_names_instruction = f"{system_prompt}\n\n"
# A帽adir instrucciones de 谩ngulo solo si no es "NINGUNO" y se proporcion贸 un 谩ngulo
if selected_angle and selected_angle != "NINGUNO":
webinar_names_instruction += f"""
MAIN ANGLE: {selected_angle}
SPECIFIC ANGLE INSTRUCTIONS:
{angles_webinar_names[selected_angle]["instruction"]}
IMPORTANT: The {selected_angle} angle should be applied as a "style layer" over the formula structure:
1. Keep the base structure of the formula intact
2. Apply the tone and style of the {selected_angle} angle
3. Ensure that each element of the formula reflects the angle
4. The angle affects "how" it is said, not "what" is said
SUCCESSFUL EXAMPLES OF THE {selected_angle} ANGLE:
"""
for example in angles_webinar_names[selected_angle]["examples"]:
webinar_names_instruction += f"- {example}\n"
# Instrucciones espec铆ficas para la tarea
webinar_names_instruction += (
f"\nYour task is to create {number_of_names} irresistible webinar names for {target_audience} "
f"that instantly capture attention and generate registrations for a webinar about {product}. "
f"Focus on awakening genuine interest and communicating the value they will get by registering."
f"\n\n"
f"IMPORTANT: Carefully study these examples of the selected formula. "
f"Each example represents the style and structure to follow"
f":\n\n"
)
# Agregar ejemplos aleatorios de la f贸rmula (keeping examples in Spanish)
random_examples = random.sample(selected_formula['examples'], min(5, len(selected_formula['examples'])))
webinar_names_instruction += "EXAMPLES OF THE FORMULA TO FOLLOW:\n"
for i, example in enumerate(random_examples, 1):
webinar_names_instruction += f"{i}. {example}\n"
# Instrucciones espec铆ficas (translated to English)
webinar_names_instruction += "\nSPECIFIC INSTRUCTIONS:\n"
webinar_names_instruction += "1. Maintain the same structure and length as the previous examples\n"
webinar_names_instruction += "2. Use the same tone and writing style\n"
webinar_names_instruction += "3. Replicate the phrase construction patterns\n"
webinar_names_instruction += "4. Preserve the level of specificity and detail\n"
webinar_names_instruction += f"5. Adapt the content for {target_audience} while maintaining the essence of the examples\n\n"
webinar_names_instruction += f"FORMULA TO FOLLOW:\n{selected_formula['description']}\n\n"
webinar_names_instruction += f"""
GENERATE NOW:
Create {number_of_names} webinar names that faithfully follow the style and structure of the examples shown.
"""
# Enviar el mensaje al modelo
# Use the common generate_content function
return generate_content(webinar_names_instruction, temperature)
def generate_webinar_script(audience, topic, temperature, selected_formula):
model = initialize_model(temperature)
# Incluir las instrucciones del sistema en el prompt principal
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.
THE EXPERT TEAM:
1. MASTER WEBINAR STRATEGIST:
- Expert in webinar frameworks and conversion strategies
- Trained in the Perfect Webinar methodology by Russell Brunson
- Ensures the script follows the selected framework structure precisely
- Focuses on strategic placement of key conversion elements
2. ELITE DIRECT RESPONSE COPYWRITER:
- Trained by Gary Halbert, Gary Bencivenga, and David Ogilvy
- Creates compelling hooks, stories, and persuasive elements
- Crafts irresistible calls to action that drive conversions
- Ensures the language resonates with the target audience
3. AUDIENCE PSYCHOLOGY SPECIALIST:
- Expert in understanding audience motivations and objections
- Creates content that builds genuine connection and trust
- Identifies and addresses hidden fears and desires
- Ensures the content feels personal and relevant
4. STORYTELLING MASTER:
- Creates compelling narratives that illustrate key points
- Develops relatable examples and case studies
- Ensures stories support the transformation being offered
- Makes complex concepts accessible through narrative
5. WEBINAR ENGAGEMENT EXPERT:
- Specializes in maintaining audience attention throughout
- Creates interactive elements and engagement hooks
- Develops compelling transitions between sections
- Ensures the webinar flows naturally and keeps interest high
AUDIENCE UNDERSTANDING:
You understand how real people interact with webinar content:
- They quickly lose interest if the content feels generic or corporate
- They only stay engaged when the content feels personal and sparks genuine curiosity
- They respond to messages that seem delivered by a real person, not a corporation
- They engage with content that hooks them from the first line and maintains interest throughout
FORMAT RULES:
- Create a complete webinar script with clear sections and subsections
- Include specific talking points for each section
- Write in a conversational, engaging tone
- Include persuasive elements and calls to action
- Follow the selected webinar framework structure exactly
- WRITE THE ENTIRE SCRIPT IN SPANISH
- DO NOT include any introductory text or explanations about the script
- Start directly with the webinar content
IMPORTANT:
- The script must be comprehensive and ready to use
- Include specific examples and stories relevant to the topic
- Maintain a persuasive but authentic tone
- Adapt language to match the target audience
- Focus on transformative benefits and clear value proposition
- Follow the selected formula structure precisely
- WRITE THE ENTIRE SCRIPT IN SPANISH
- DO NOT include phrases like "Aqu铆 tienes un guion completo" or any other meta-commentary
COLLABORATIVE PROCESS:
As a team of experts, you will:
1. Analyze the framework '{selected_formula['description']}' to understand its core principles
2. Identify how to best adapt this framework for {audience} learning about {topic}
3. Determine the most effective storytelling opportunities within the framework
4. Create persuasive language that resonates with {audience}
5. Ensure the script maintains engagement throughout
6. Adapt the content to be accessible to beginners while still valuable to experienced individuals
7. Follow the exact structure provided in the framework
Each expert will contribute their specialized knowledge to create a cohesive, compelling script that:
- Follows the exact structure of the selected framework
- Engages the audience from start to finish
- Addresses audience pain points and desires
- Presents {topic} in a clear, compelling way
- Drives conversions through strategic calls to action"""
# Iniciar el prompt con las instrucciones del sistema
webinar_script_instruction = f"{system_prompt}\n\n"
# Instrucciones espec铆ficas para la tarea
webinar_script_instruction += (
f"\nYour task is to create a complete webinar script IN SPANISH for {audience} "
f"about {topic} that is persuasive and converts the audience into customers. "
f"The script must follow exactly the structure of the framework '{selected_formula['description']}' "
f"and must include all the necessary elements for a successful webinar."
f"\n\n"
)
# Estructura del webinar
webinar_script_instruction += "WEBINAR STRUCTURE TO FOLLOW:\n"
for i, step in enumerate(selected_formula['structure'], 1):
webinar_script_instruction += f"{i}. {step}\n"
# Ejemplos de webinars exitosos
webinar_script_instruction += "\n\nEXAMPLES OF SUCCESSFUL WEBINARS WITH THIS STRUCTURE:\n"
for i, example in enumerate(selected_formula['examples'], 1):
webinar_script_instruction += f"{i}. {example}\n"
# Instrucciones espec铆ficas
webinar_script_instruction += f"""
SPECIFIC INSTRUCTIONS:
1. Create a complete script that follows exactly the provided structure
2. Include persuasive elements and clear calls to action
3. Adapt the language and examples specifically for {audience}
4. Focus on the transformative benefits of {topic}
5. Include relevant stories and examples that reinforce your points
6. Use a conversational but professional tone
7. Make sure each section fulfills its specific purpose in the framework
8. IMPORTANT: Write the entire script in Spanish
GENERATE NOW:
Create a complete webinar script following faithfully the structure of the selected framework.
"""
# Enviar el mensaje al modelo
chat_session = model.start_chat(
history=[
{
"role": "user",
"parts": [webinar_script_instruction],
},
]
)
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).")
return response.text
# Funci贸n para validar entradas (evita duplicaci贸n)
def validate_inputs(audience, product):
has_audience = audience.strip() != ""
has_product = product.strip() != ""
return has_audience and has_product
# Update the load_css function comment to be more descriptive
def load_css():
css_path = "styles/styles.css"
if os.path.exists(css_path):
try:
with open(css_path, "r") as f:
st.markdown(f"<style>{f.read()}</style>", unsafe_allow_html=True)
except Exception as e:
st.warning(f"Error al cargar el archivo CSS: {str(e)}")
else:
st.warning(f"No se encontr贸 el archivo CSS en {css_path}")
# Create a reusable function for custom buttons
# At the top of your file, define the styles dictionary
styles = {
"button": """
<style>
div.stButton > button:first-child {
background-color: #FF4B4B;
color: white;
font-weight: bold;
padding: 0.5rem 1rem;
border-radius: 0.5rem;
border: none;
transition: all 0.3s;
}
div.stButton > button:hover {
background-color: #FF2525;
transform: translateY(-2px);
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
}
</style>
""",
"download_button": """
<style>
div.stDownloadButton > button:first-child {
background-color: #4CAF50;
color: white;
font-weight: bold;
padding: 0.5rem 1rem;
border-radius: 0.5rem;
border: none;
transition: all 0.3s;
}
div.stDownloadButton > button:hover {
background-color: #45a049;
transform: translateY(-2px);
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
}
</style>
"""
}
# Then modify your create_custom_button function to be much simpler:
def create_custom_button(label, button_key):
# Apply the button style once at the beginning of your app
# (You can move this to your main app code if you prefer)
st.markdown(styles["button"], unsafe_allow_html=True)
# Just return a regular Streamlit button
return st.button(label, key=button_key)
# Modify the page config section to include the CSS loading
st.set_page_config(page_title="Perfect Webinar Framework", layout="wide")
load_css()
# Leer el contenido del archivo manual.md
with open("manual.md", "r", encoding="utf-8") as file:
manual_content = file.read()
# Mostrar el contenido del manual en el sidebar
st.sidebar.markdown(manual_content)
# Crear pesta帽as para la interfaz
tab1, tab2 = st.tabs(["Guiones de Webinar", "Nombres de Webinar"])
# Primera pesta帽a - Generador de Guiones de Webinar
with tab1:
tab1.subheader("Script Webinar")
# Crear columnas para la interfaz
col1, col2 = tab1.columns([1, 2])
# Columna de entrada usando la funci贸n reutilizable
with col1:
webinar_script_audience, webinar_script_product, selected_webinar_formula_key = create_input_section(
col1,
"webinar_script_audience",
"webinar_script_product",
webinar_formulas,
"webinar_formula"
)
# Usar la funci贸n reutilizable para crear el bot贸n personalizado
submit_webinar_script = create_custom_button("Generar Gui贸n de Webinar", "generate_webinar_script")
# Opciones avanzadas
with st.expander("Personaliza tu gui贸n de webinar"):
webinar_script_temperature = st.slider("Creatividad", min_value=0.0, max_value=2.0, value=1.0, step=0.1, key="webinar_script_temp")
selected_webinar_formula = webinar_formulas[selected_webinar_formula_key]
# Generar y mostrar el gui贸n usando la funci贸n reutilizable
if submit_webinar_script:
generate_and_display(
col2,
generate_webinar_script,
webinar_script_audience,
webinar_script_product,
webinar_script_temperature,
selected_webinar_formula,
content_type="script"
)
# Segunda pesta帽a - Generador de Nombres de Webinar
with tab2:
tab2.subheader("Nombres de Webinar")
# Crear columnas para la interfaz
col1, col2 = tab2.columns([1, 2])
# Columna de entrada usando la funci贸n reutilizable
with col1:
webinar_name_audience, webinar_name_product, selected_webinar_name_formula_key = create_input_section(
col1,
"webinar_name_audience",
"webinar_name_product",
webinar_name_formulas,
"webinar_name_formula"
)
number_of_names = st.selectbox("N煤mero de nombres", options=[1, 2, 3, 4, 5, 6, 7, 8, 9, 10], index=4, key="number_of_names")
# Usar la funci贸n reutilizable para crear el bot贸n personalizado
submit_webinar_names = create_custom_button("Generar Nombres de Webinar", "generate_webinar_names")
# Opciones avanzadas
with st.expander("Personaliza tus nombres de webinar"):
webinar_name_temperature = st.slider("Creatividad", min_value=0.0, max_value=2.0, value=1.0, step=0.1, key="webinar_name_temp")
# Configurar opciones de 谩ngulo
angle_keys = ["NINGUNO"] + sorted([key for key in angles_webinar_names.keys() if key != "NINGUNO"])
selected_angle = st.selectbox(
"Selecciona el 谩ngulo para tus nombres",
options=angle_keys,
key="webinar_name_angle"
)
selected_webinar_name_formula = webinar_name_formulas[selected_webinar_name_formula_key]
# Generar y mostrar los nombres usando la funci贸n reutilizable
if submit_webinar_names:
generate_and_display(
col2,
generate_webinar_names,
webinar_name_audience,
webinar_name_product,
webinar_name_temperature,
selected_webinar_name_formula,
content_type="names",
number_of_names=number_of_names,
selected_angle=selected_angle if selected_angle != "NINGUNO" else None
)
if validate_inputs(webinar_name_audience, webinar_name_product):
try:
with col2:
with st.spinner("Generando tus nombres de webinar...", show_time=True):
generated_webinar_names = generate_webinar_names(
number_of_names,
webinar_name_audience,
webinar_name_product,
webinar_name_temperature,
selected_webinar_name_formula,
selected_angle if selected_angle != "NINGUNO" else None
)
st.subheader("Tus nombres de webinar:")
st.markdown(generated_webinar_names)
except ValueError as e:
col2.error(f"Error: {str(e)}")
else:
col2.error("Por favor, proporciona el p煤blico objetivo y el tema del webinar.")