from dotenv import load_dotenv import streamlit as st import os import google.generativeai as genai from cta_formulas import cta_formulas from styles import apply_styles from tone_formulas import tone_settings # Cargar variables de entorno load_dotenv() # Configurar API de Google Gemini genai.configure(api_key=os.getenv("GOOGLE_API_KEY")) def get_gemini_response(product_service, target_audience, desired_action, formula_type, tone_type, temperature, postdata_theme=None, cta_count=5, story_context=None): if not product_service or not target_audience or not desired_action: return "Por favor, completa todos los campos requeridos." formula = cta_formulas[formula_type] tone = tone_settings[tone_type] # Lista de fórmulas que ya incluyen P.D. en su estructura formulas_with_pd = ["El Último Aviso (No tan Último)", "Cierra con Corazón", "Gancho Cachondo"] # Preparar información de postdata postdata_instruction = "" if postdata_theme: # Solo aplicar la instrucción de postdata si la fórmula tiene PD en su estructura if formula_type in formulas_with_pd: postdata_instruction = f""" POSTDATA THEME: Use the following theme for the P.S. section: {postdata_theme} IMPORTANT: For formulas with P.S.2 sections, use a DIFFERENT theme or approach than the one used in P.S.1. DO NOT repeat the same urgency factor, benefit, or discount information in both postdatas. Examples: - If P.S.1 mentions "only 2 days left", P.S.2 should NOT mention time limits again - If P.S.1 talks about "limited spots", P.S.2 should focus on a different benefit or feature Make sure each postdata adds unique value and persuasion elements. """ # Preparar información de contexto/historia story_instruction = "" if story_context: story_instruction = f""" STORY CONTEXT: Incorporate elements from the following story/context into your CTAs when appropriate: {story_context} Use this context to make the CTAs more relatable, authentic, and emotionally resonant. You can reference specific elements, metaphors, or situations from the story. """ model = genai.GenerativeModel('gemini-2.0-flash') full_prompt = f""" You are an expert copywriter specialized in creating persuasive Calls to Action (CTAs). Analyze (internally, don't include in output) the following information: BUSINESS INFORMATION: Product/Service: {product_service} Target Audience: {target_audience} Desired Action: {desired_action} CTA Type: {formula_type} Tone Style: {tone['style']} Keywords to consider: {', '.join(tone['keywords'])} {formula["description"]} {postdata_instruction} {story_instruction} First, analyze (but don't show) these points: 1. TARGET AUDIENCE ANALYSIS: - What motivates them to take action? - What obstacles prevent them from acting? - What immediate benefits are they seeking? - What fears or doubts do they have? - What language and tone resonates with them? 2. PERSUASION ELEMENTS: - How to make the desired action more appealing? - What emotional triggers will resonate most? - How to create a sense of urgency naturally? - What unique value proposition to emphasize? - How to minimize perceived risk? Based on your internal analysis, create {cta_count} different CTAs following EXACTLY the formula structure: {formula["description"]} CRITICAL INSTRUCTIONS: - Follow the exact formula structure shown in the description above - Create {cta_count} different CTAs using the same formula pattern - ALL CTAs MUST BE IN SPANISH - DO NOT add postdata (P.S.) to formulas that don't include it in their structure - When a formula includes multiple postdatas (P.S.1 and P.S.2), make sure they focus on DIFFERENT themes and don't repeat the same urgency factors or benefits - If a story context was provided, weave elements from it naturally into the CTAs EXAMPLES TO FOLLOW: {formula["examples"]} Output EXACTLY in this format based on {formula_type}: 1. Follow format from {formula["examples"]} 2. Follow format from {formula["examples"]} 3. Follow format from {formula["examples"]} """ response = model.generate_content([full_prompt], generation_config={"temperature": temperature}) return response.parts[0].text if response and response.parts else "Error al generar contenido." # Configurar la aplicación Streamlit st.set_page_config(page_title="CTA Generator", page_icon="🎯", layout="wide") # Leer y mostrar el manual en el sidebar with open("manual.md", "r", encoding="utf-8") as file: manual_content = file.read() st.sidebar.markdown(manual_content) # Aplicar estilos st.markdown(apply_styles(), unsafe_allow_html=True) # Título de la app st.markdown("<h1>Generador de CTAs Persuasivos</h1>", unsafe_allow_html=True) st.markdown("<h3>Crea llamados a la acción que motiven a tu audiencia a dar el siguiente paso.</h3>", unsafe_allow_html=True) # Remove the duplicate manual expander from here # Crear dos columnas col1, col2 = st.columns([0.4, 0.6]) # 40% for left column, 60% for right column # Columna izquierda para inputs with col1: target_audience = st.text_area( "¿Cuál es tu público objetivo?", placeholder="Ejemplo: Emprendedores que buscan automatizar su negocio..." ) product_service = st.text_area( "¿Cuál es tu producto o servicio?", placeholder="Ejemplo: Curso de automatización con IA, Software de gestión..." ) desired_action = st.text_area( "¿Qué acción quieres que realicen?", placeholder="Ejemplo: Registrarse al webinar, Descargar la guía gratuita..." ) # Mover el botón aquí, antes del acordeón generate_button = st.button("Generar CTAs") with st.expander("Opciones avanzadas"): formula_type = st.selectbox( "Tipo de CTA:", options=list(cta_formulas.keys()) ) tone_type = st.selectbox( "Tono del CTA:", options=list(tone_settings.keys()), ) # Nuevos campos para postdata postdata_theme = st.text_input( "Tema o enfoque para la postdata (opcional)", placeholder="Ejemplo: urgencia, beneficio, descuento" ) # Mover el campo de historia aquí, después del tema de postdata story_context = st.text_area( "Historia o contexto (opcional)", placeholder="Ejemplo: Escribe el texto para crear una P.D. más específica a tus requerimientos" ) cta_count = st.number_input( "Número de llamados a la acción", min_value=1, max_value=5, value=3 ) temperature = st.slider( "Nivel de creatividad:", min_value=0.0, max_value=2.0, value=1.0, step=0.1, help="Valores más altos generan CTAs más creativos pero menos predecibles." ) # Columna derecha para resultados with col2: if generate_button and (response := get_gemini_response( product_service, target_audience, desired_action, formula_type, tone_type, temperature, postdata_theme, cta_count, story_context )): st.markdown("### Tus Llamados a la Acción") st.write(response)