JeCabrera's picture
Update app.py
dab4076 verified
from dotenv import load_dotenv
import streamlit as st
import os
import google.generativeai as genai
import random
from streamlit import session_state as state
from formulas import headline_formulas
from angles import angles
# Cargar las variables de entorno
load_dotenv()
# Configurar la API de Google
genai.configure(api_key=os.getenv("GOOGLE_API_KEY"))
# Fórmulas con ejemplos y explicaciones
# headline_formulas dictionary has been moved to formulas/headline_formulas.py
def generate_headlines(number_of_headlines, target_audience, product, temperature, selected_formula, selected_angle, base_copy=None):
# Crear la configuración del modelo
generation_config = {
"temperature": temperature,
"top_p": 0.65,
"top_k": 360,
"max_output_tokens": 8196,
}
model = genai.GenerativeModel(
model_name="gemini-2.0-flash",
generation_config=generation_config,
)
# Angle dictionaries have been moved to angles/angle_data.py
# Incluir las instrucciones del sistema en el prompt principal
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.
FORMAT RULES:
- Each headline must start with number and period
- One headline per line
- No explanations or categories
- Add a line break between each headline
- Avoid unnecessary : symbols
- Each headline must be a complete and intriguing sentence
IMPORTANT ANGLE INSTRUCTIONS:
- The selected angle MUST be applied to EVERY headline
- The angle modifies HOW the formula is expressed, not its structure
- Think of the angle as a "tone overlay" on the formula
- The formula provides the structure, the angle provides the style
- Both must work together seamlessly
FORMAT EXAMPLE:
1. Titular 1.
2. Titular 2.
3. Titular 3.
4. Titular 4.
5. Titular 5.
IMPORTANT:
- Each headline 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 angle style while maintaining formula structure"""
# Iniciar el prompt con las instrucciones del sistema
headlines_instruction = f"{system_prompt}\n\n"
# Add base copy instructions if provided
if base_copy and base_copy.strip():
headlines_instruction += f"""
BASE COPY TO USE:
The following text should be used as the primary source of information and inspiration for generating headlines:
{base_copy}
IMPORTANT: Extract key concepts, benefits, and language from this base copy to create your headlines.
Use the tone, style, and specific terminology from this text whenever possible.
"""
# Añadir instrucciones de ángulo solo si no es "NINGUNO"
if selected_angle != "NINGUNO":
headlines_instruction += f"""
ÁNGULO PRINCIPAL: {selected_angle}
INSTRUCCIONES DE ÁNGULO ESPECÍFICAS:
{angles[selected_angle]["instruction"]}
IMPORTANT: The angle {selected_angle} must 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 angle {selected_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 ANGLE {selected_angle}:
"""
for example in angles[selected_angle]["examples"]:
headlines_instruction += f"- {example}\n"
headlines_instruction += (
f"\nYour task is to create {number_of_headlines} irresistible headlines for {target_audience} "
f"that instantly capture attention and generate curiosity about {product}. "
)
if selected_angle != "NINGUNO":
headlines_instruction += f"IMPORTANT: Each headline MUST follow the {selected_angle} angle clearly and consistently.\n\n"
headlines_instruction += (
f"Avoid obvious mentions of {product} and focus on awakening genuine interest"
)
if selected_angle != "NINGUNO":
headlines_instruction += f" using the selected angle"
headlines_instruction += ".\n\n"
headlines_instruction += (
f"IMPORTANT: Carefully study these examples of the selected formula. "
f"Each example represents the style and structure to follow"
)
if selected_angle != "NINGUNO":
headlines_instruction += f", adapted to the {selected_angle} angle"
headlines_instruction += ":\n\n"
# Add 5 random examples of the formula
random_examples = random.sample(selected_formula['examples'], min(5, len(selected_formula['examples'])))
headlines_instruction += "FORMULA EXAMPLES TO FOLLOW:\n"
for i, example in enumerate(random_examples, 1):
headlines_instruction += f"{i}. {example}\n"
headlines_instruction += "\nSPECIFIC INSTRUCTIONS:\n"
headlines_instruction += "1. Maintain the same structure and length as the previous examples\n"
headlines_instruction += "2. Use the same tone and writing style\n"
headlines_instruction += "3. Replicate the patterns of phrase construction\n"
headlines_instruction += "4. Preserve the level of specificity and detail\n"
headlines_instruction += f"5. Adapt the content for {target_audience} while maintaining the essence of the examples\n\n"
headlines_instruction += f"FORMULA TO FOLLOW:\n{selected_formula['description']}\n\n"
# CORRECT (with indentation):
if selected_angle != "NINGUNO":
headlines_instruction += f"""
FINAL REMINDER:
1. Follow the structure of the selected formula
2. Apply the angle as a "style layer"
3. Maintain coherence between formula and angle
4. Ensure each headline reflects both elements
GENERATE NOW:
Create {number_of_headlines} headlines that faithfully follow the style and structure of the examples shown.
"""
else:
headlines_instruction += f"""
GENERATE NOW:
Create {number_of_headlines} headlines that faithfully follow the style and structure of the examples shown.
"""
# Send the message to the model (without image conditions)
chat_session = model.start_chat(
history=[
{
"role": "user",
"parts": [headlines_instruction],
},
]
)
response = chat_session.send_message("Genera los titulares siguiendo exactamente el estilo de los ejemplos mostrados.")
return response.text
# Configurar la interfaz de usuario con Streamlit
st.set_page_config(page_title="Enchanted Hooks", layout="wide")
# 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)
# Load CSS from file
with open("styles/main.css", "r") as f:
css = f.read()
# Apply the CSS
st.markdown(f"<style>{css}</style>", unsafe_allow_html=True)
# Centrar el título y el subtítulo
st.markdown("<h1 style='text-align: center;'>Enchanted Hooks</h1>", unsafe_allow_html=True)
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)
# Crear columnas
col1, col2 = st.columns([1, 2])
# Columnas de entrada
with col1:
target_audience = st.text_input("¿Quién es tu público objetivo?", placeholder="Ejemplo: Estudiantes Universitarios")
product = st.text_input("¿Qué producto tienes en mente?", placeholder="Ejemplo: Curso de Inglés")
# Botón de enviar con estilo personalizado (moved right after product input)
submit = st.button("Generar Titulares", key="submit_button", use_container_width=True)
# Crear un único acordeón para fórmula, creatividad y ángulo
with st.expander("Personaliza tus titulares"):
# Moved text area for base copy above formula selection
base_copy = st.text_area(
"Correo o copy para inspiración de titulares",
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.",
height=150
)
# Formula selection after the text area
selected_formula_key = st.selectbox(
"Selecciona una fórmula para tus titulares",
options=list(headline_formulas.keys())
)
# Angle selection moved before number of headlines
angle_keys = ["NINGUNO"] + sorted([key for key in angles.keys() if key != "NINGUNO"])
selected_angle = st.selectbox(
"Selecciona el ángulo para tus titulares",
options=angle_keys
)
# Number of headlines moved after angle selection
number_of_headlines = st.selectbox("Número de Titulares", options=[1, 2, 3, 4, 5, 6, 7, 8, 9, 10], index=4)
# Temperature slider remains at the bottom
temperature = st.slider("Creatividad", min_value=0.0, max_value=2.0, value=1.0, step=0.1)
selected_formula = headline_formulas[selected_formula_key]
# Mostrar los titulares generados
if submit:
# Check if we have valid inputs
has_product = product.strip() != ""
has_audience = target_audience.strip() != ""
has_base_copy = base_copy and base_copy.strip() != ""
# Valid combination: Either (Product + Audience) or Base Copy
valid_inputs = (has_product and has_audience) or has_base_copy
if valid_inputs and selected_formula:
try:
generated_headlines = generate_headlines(
number_of_headlines,
target_audience,
product,
temperature,
selected_formula,
selected_angle,
base_copy if has_base_copy else None
)
col2.markdown(f"""
<div class="results-container">
<h4>Observa la magia en acción:</h4>
<p>{generated_headlines}</p>
</div>
""", unsafe_allow_html=True)
except ValueError as e:
col2.error(f"Error: {str(e)}")
else:
if not selected_formula:
col2.error("Por favor, selecciona una fórmula.")
elif not has_base_copy:
col2.error("Por favor, proporciona el público objetivo y el producto, o un texto base.")