Spaces:
Sleeping
Sleeping
from dotenv import load_dotenv | |
import streamlit as st | |
import os | |
import google.generativeai as genai | |
import random | |
load_dotenv() | |
genai.configure(api_key=os.getenv("GOOGLE_API_KEY")) | |
story_formulas = { | |
"PASA": { | |
"description": """ | |
La fórmula P.A.S.A. es una de las estructuras más efectivas en copywriting, diseñada para crear una conexión emocional profunda que lleva a la acción. | |
TEORÍA: | |
Esta fórmula se basa en la psicología del dolor y el alivio, siguiendo el principio de que las personas están más motivadas a evitar el dolor que a buscar el placer. | |
ESTRUCTURA: | |
1. Problema: | |
- Identifica un dolor específico y real | |
- Debe ser inmediatamente reconocible por la audiencia | |
- Se presenta desde la perspectiva del lector | |
- Usa lenguaje empático y comprensivo | |
2. Agitación: | |
- Profundiza en las consecuencias emocionales | |
- Explora ramificaciones futuras | |
- Aumenta la tensión psicológica | |
- Crea un punto de inflexión emocional | |
3. Solución: | |
- Presenta la respuesta de forma natural | |
- Enfoca en beneficios transformacionales | |
- Construye credibilidad gradualmente | |
- Demuestra el cambio positivo | |
4. Acción: | |
- Propone el siguiente paso lógico | |
- Minimiza la fricción y resistencia | |
- Crea sentido de urgencia | |
- Ofrece garantías implícitas | |
""", | |
"examples": [ | |
{ | |
"title": "App de Meditación", | |
"target": "Profesionales estresados", | |
"story": """ | |
El insomnio se había convertido en su compañero más fiel. Sara miraba el reloj: 3 AM, otra vez. | |
Los días se volvían borrosos, su concentración desaparecía. Las reuniones importantes se convertían en una lucha por mantener los ojos abiertos, mientras su productividad se desplomaba. | |
Todo cambió cuando descubrió MeditaApp. Sus ejercicios de respiración guiada y meditaciones nocturnas la ayudaron a encontrar ese interruptor mental que necesitaba para desconectar. | |
Descarga MeditaApp hoy y recupera tus noches. Tus primeros 7 días son gratuitos, porque creemos que una noche de buen sueño no tiene precio. | |
""" | |
}, | |
{ | |
"title": "Curso de Finanzas Personales", | |
"target": "Jóvenes profesionales", | |
"story": """ | |
Cada notificación del banco le provocaba un nudo en el estómago. Miguel evitaba revisar su cuenta, sabiendo que los números rojos lo esperaban. | |
Las deudas crecían mientras sus sueños se alejaban. La idea de comprar una casa o empezar un negocio parecía cada vez más inalcanzable, y la ansiedad financiera lo consumía día y noche. | |
Entonces encontró FinanzasMaster. El curso no solo le enseñó a manejar su dinero, sino a construir un futuro financiero sólido. En seis meses, eliminó sus deudas y comenzó a ver crecer sus ahorros. | |
Únete a FinanzasMaster hoy. Transforma tu relación con el dinero con nuestro programa probado de 12 semanas. Matrícula con 50% de descuento esta semana. | |
""" | |
} | |
] | |
}, | |
"GHA": { | |
"description": """ | |
La fórmula G.H.A. (Gancho-Historia-Acción) es una estructura narrativa poderosa que utiliza el storytelling para crear conexiones emocionales y motivar a la acción. | |
TEORÍA: | |
Esta fórmula aprovecha el poder de las historias para captar la atención, generar empatía y motivar el cambio, basándose en la identificación con los problemas y dolores de la audiencia. | |
ESTRUCTURA: | |
1. Gancho: | |
- Abre identificando un problema o dolor específico de la audiencia | |
- Conecta emocionalmente con la frustración o necesidad | |
- Genera identificación inmediata con la situación | |
- Plantea el escenario desde la perspectiva del dolor actual | |
2. Historia: | |
- Desarrolla la narrativa mostrando las consecuencias del problema | |
- Explora cómo el dolor afecta diferentes aspectos de la vida | |
- Mantiene la tensión emocional sobre el problema | |
- Introduce el producto como solución natural al dolor | |
- Demuestra la transformación positiva posible | |
3. Acción: | |
- Surge como respuesta natural al deseo de eliminar el dolor | |
- Presenta la acción como el puente hacia el beneficio deseado | |
- Enfatiza la urgencia de resolver el problema | |
- Minimiza las barreras para tomar acción | |
- Refuerza los beneficios específicos que se obtendrán | |
""", | |
"examples": [ | |
{ | |
"title": "Programa de Fitness", | |
"target": "Personas que quieren comenzar a ejercitarse", | |
"story": """ | |
"Nunca seré una persona fitness", me repetía cada vez que veía esas fotos perfectas en Instagram. Mi realidad eran 3 minutos de ejercicio y 20 de excusas. | |
Un día, mientras subía las escaleras a mi departamento, tuve que detenerme en el segundo piso, jadeando. Mi hijo de 5 años me miró preocupado y me preguntó: "¿Mami, estás enferma?". Ese momento cambió todo. | |
FitLife no me prometió un cuerpo de revista, me ofreció algo mejor: la capacidad de jugar con mi hijo sin quedarme sin aliento. Empecé con 10 minutos diarios, luego 15, y ahora corremos juntos en el parque. | |
Comienza tu historia de transformación hoy. Únete a FitLife y descubre cómo 15 minutos pueden cambiar tu vida. Primera semana gratis, porque tu bienestar no puede esperar. | |
""" | |
} | |
] | |
} | |
} | |
def generate_story(formula_type, target_audience, product, action, mood, length, story_topic=None): | |
"""Función unificada para generar historias""" | |
model = genai.GenerativeModel("gemini-2.0-flash") | |
if formula_type not in story_formulas: | |
raise ValueError("Fórmula no válida") | |
# Añadir instrucciones de naturalidad al inicio del prompt | |
natural_instruction = f""" | |
IMPORTANTE - NATURALIDAD EN LA HISTORIA: | |
- NO menciones "{product}" de forma literal o forzada | |
- Introduce el producto/servicio de manera sutil y orgánica en la narrativa | |
- Evita que suene como una fórmula publicitaria | |
- La solución debe surgir naturalmente de la historia | |
- Usa variaciones y descripciones naturales en lugar del nombre exacto | |
- La historia debe fluir como una conversación real, no como un anuncio | |
Por ejemplo, si el producto es "Webinar sobre Yoga": | |
❌ "Entonces descubrí el Webinar sobre Yoga" | |
✅ "Encontré estas clases en línea donde aprendí a conectar con mi cuerpo" | |
Si es un curso: | |
❌ "Me inscribí en el Curso de Marketing Digital" | |
✅ "Comencé a aprender sobre el mundo del marketing en línea" | |
""" | |
# Análisis del público objetivo | |
audience_analysis = f""" | |
ANÁLISIS DEL PÚBLICO OBJETIVO: {target_audience} | |
INSTRUCCIONES DE ANÁLISIS: | |
1. Dolores y Problemas: | |
- Identifica los problemas cotidianos específicos de {target_audience} | |
- Reconoce sus frustraciones y miedos más profundos | |
- Analiza las consecuencias emocionales de estos problemas | |
- Considera el impacto en su vida diaria | |
2. Creencias y Valores: | |
- Comprende sus creencias limitantes | |
- Identifica sus aspiraciones y sueños | |
- Reconoce sus valores fundamentales | |
- Entiende sus motivaciones principales | |
3. Situaciones de Vida: | |
- Visualiza sus rutinas diarias | |
- Identifica momentos de tensión o conflicto | |
- Reconoce sus contextos sociales y profesionales | |
- Comprende sus responsabilidades y presiones | |
4. Puntos de Dolor Específicos: | |
- Problemas prácticos: [analiza sus dificultades concretas] | |
- Dolores emocionales: [identifica sus preocupaciones más profundas] | |
- Miedos: [reconoce sus temores principales] | |
- Frustraciones: [entiende sus obstáculos recurrentes] | |
CONTEXTO NARRATIVO: | |
- Si hay story_topic ("{story_topic if story_topic else 'No especificado'}"), | |
úsalo como escenario o contexto para desarrollar la historia | |
- El protagonista debe reflejar fielmente las características de {target_audience} | |
- Los problemas y situaciones deben ser 100% reconocibles por la audiencia | |
- La transformación debe abordar directamente sus dolores específicos | |
""" | |
# Definir el system prompt dentro de la función | |
system_prompt = """You are a world-class copywriter, specialized in crafting persuasive stories that emotionally connect with readers and drive them to action. | |
FORMAT RULES: | |
- Story must be structured in clear paragraphs | |
- Each section must flow naturally into the next | |
- No explicit section labels | |
- Maintain consistent tone throughout | |
- Include smooth transitions between parts | |
- Story must feel complete and cohesive | |
IMPORTANT STRUCTURE INSTRUCTIONS: | |
- The selected formula MUST be applied to the entire story | |
- Review and follow the structure detailed in story_formulas[formula_type]["description"] | |
- Use the examples in story_formulas[formula_type]["examples"] as inspiration | |
- Formula provides the framework, tone provides the emotional layer | |
- Both must work together seamlessly | |
IMPORTANT: | |
- Each story must be unique and memorable | |
- Avoid clichés and generic scenarios | |
- Maintain a credible and authentic voice | |
- Adapt language to target audience | |
- Focus on emotional transformation | |
- Follow formula structure while maintaining selected tone | |
- Never explicitly label sections | |
- Integrate product and call-to-action organically | |
STORY STRUCTURE GUIDELINES: | |
1. Study the formula description carefully | |
2. Review provided examples for style and flow | |
3. Maintain similar paragraph length and structure | |
4. Use consistent emotional intensity | |
5. Mirror the narrative progression | |
6. Adapt content for target audience while keeping formula essence | |
TONE AND STYLE: | |
- Selected tone must remain consistent | |
- Tone modifies HOW the story is told | |
- Formula provides structure, tone provides emotion | |
- Both elements must complement each other | |
- Maintain voice appropriate for target audience | |
LANGUAGE INSTRUCTIONS: | |
- Generate the story in Spanish | |
- Use natural, fluent Spanish | |
- Maintain cultural relevance for Spanish-speaking audiences | |
- Ensure idioms and expressions are appropriate for Spanish | |
- Keep all story content in Spanish, only system instructions are in English | |
KEY ELEMENTS TO INCLUDE: | |
- Emotional hooks that grab attention | |
- Relatable situations and characters | |
- Sensory details and vivid descriptions | |
- Natural problem-solution progression | |
- Organic product integration | |
- Compelling but subtle call-to-action""" | |
story_instruction = f"{system_prompt}\n\n{audience_analysis}\n\n" | |
# Instrucciones específicas para GHA cuando hay story_topic | |
if formula_type == "GHA" and story_topic: | |
story_instruction += f""" | |
STORY TOPIC INTEGRATION GUIDELINES: | |
- The story topic "{story_topic}" MUST be the central theme of the narrative | |
- Build the entire story around this specific topic/experience | |
- Use the topic as the main hook to capture attention | |
- Weave the product naturally into this specific narrative | |
- Ensure the story feels authentic to the given topic | |
- Maintain the emotional core of the topic throughout | |
REQUIRED STORY ELEMENTS: | |
1. Opening hook must directly relate to "{story_topic}" | |
2. Story must maintain focus on this specific topic/experience | |
3. Product integration should feel natural within this context | |
4. Character development should align with the topic | |
5. Emotional journey must connect to the specific situation | |
6. Resolution should tie topic and product together seamlessly | |
STORY STRUCTURE FOR THIS TOPIC: | |
1. Hook: Begin with a compelling aspect of {story_topic} | |
2. Development: Explore the challenges/emotions related to this specific situation | |
3. Integration: Show how {product} naturally fits into this context | |
4. Resolution: Demonstrate transformation while staying true to the topic | |
""" | |
# Añadir instrucciones sobre el producto y beneficios | |
story_instruction += f""" | |
PRODUCT INTEGRATION GUIDELINES: | |
- Evita menciones obvias de {product} | |
- Enfócate en despertar interés genuino mostrando beneficios transformacionales | |
- Integra el producto de manera natural en la narrativa | |
- Destaca cómo el producto mejora la vida del protagonista | |
- Mantén el tono {mood} al describir los beneficios | |
IMPORTANT REMINDER: | |
- The entire story must be written in Spanish | |
- Use natural expressions and cultural references appropriate for Spanish-speaking audiences | |
- Ensure the story flows naturally in Spanish | |
""" | |
# Instrucciones de estudio de ejemplos | |
story_instruction += f""" | |
IMPORTANTE: Estudia cuidadosamente estos ejemplos de la fórmula seleccionada. | |
Cada ejemplo representa el estilo y estructura a seguir, adaptados al tono {mood}: | |
""" | |
# Seleccionar ejemplos aleatorios | |
random_examples = random.sample(story_formulas[formula_type]['examples'], | |
min(3, len(story_formulas[formula_type]['examples']))) | |
# Agregar ejemplos seleccionados | |
story_instruction += "\nEJEMPLOS DE LA FÓRMULA A SEGUIR:\n" | |
for i, example in enumerate(random_examples, 1): | |
story_instruction += f""" | |
Ejemplo {i}: | |
Título: {example['title']} | |
Audiencia: {example['target']} | |
Historia: | |
{example['story']} | |
""" | |
# Agregar instrucciones específicas | |
story_instruction += """ | |
INSTRUCCIONES ESPECÍFICAS: | |
1. Mantén la misma estructura y longitud que los ejemplos anteriores | |
2. Usa el mismo tono y estilo de escritura, adaptado al mood especificado | |
3. Replica los patrones de construcción de frases y transiciones | |
4. Conserva el nivel de especificidad y detalle en las descripciones | |
5. Adapta el contenido para la audiencia manteniendo la esencia de los ejemplos | |
6. Integra los beneficios del producto de manera sutil y convincente | |
7. Asegura que la transformación del protagonista sea creíble y emotiva | |
""" | |
# Agregar la descripción de la fórmula | |
story_instruction += f"\nFÓRMULA A SEGUIR:\n{story_formulas[formula_type]['description']}\n\n" | |
# Recordatorio final | |
story_instruction += f""" | |
RECORDATORIO FINAL: | |
1. Sigue la estructura de la fórmula seleccionada | |
2. Aplica el tono {mood} de manera consistente | |
3. Mantén la coherencia narrativa | |
4. Asegura que la historia refleje una transformación auténtica | |
5. Integra {product} y sus beneficios de forma natural | |
6. Culmina con un llamado a la acción convincente: {action} | |
GENERA AHORA: | |
Crea una historia persuasiva de {length} palabras en español que siga fielmente el estilo y estructura de los ejemplos mostrados, | |
manteniendo un tono {mood} y enfocándote en la transformación que {product} puede traer a la vida de {target_audience}. | |
IMPORTANT FINAL REMINDER: | |
- Write the complete story in Spanish | |
- Ensure natural flow and cultural relevance | |
- Maintain authentic Spanish expressions and tone | |
""" | |
# Asegúrate de que las instrucciones de naturalidad estén al inicio del prompt | |
story_instruction = f"{natural_instruction}\n\n{story_instruction}" | |
response = model.generate_content([story_instruction]) | |
if response and response.parts: | |
return response.parts[0].text.strip() | |
raise ValueError("No se pudo generar la historia") | |
# Inicializar la aplicación Streamlit | |
st.set_page_config(page_title="Generador de Historias", page_icon=":pencil:", layout="wide") | |
# Título y subtítulo | |
st.markdown("<h1 style='text-align: center;'>Story Genius Maker</h1>", unsafe_allow_html=True) | |
st.markdown("<h3 style='text-align: center;'>Teje historias inolvidables en segundos, guiado por la magia de la inteligencia artificial que da vida a tus ideas en relatos cautivadores.</h3>", unsafe_allow_html=True) | |
# Crear las columnas para el diseño (40% para la izquierda, 60% para la derecha) | |
col1, col2 = st.columns([2, 3]) | |
# Cambiar el comportamiento del slider cuando se seleccione "GHA" | |
with col1: | |
target_audience = st.text_input("Público objetivo", | |
placeholder="¿A quién está dirigido tu mensaje?") | |
product = st.text_input("Producto/Servicio", | |
placeholder="¿Qué estás ofreciendo?") | |
action = st.text_area("Llamado a la acción", | |
placeholder="¿Qué acción específica debe tomar tu audiencia?") | |
# Personalización adicional | |
with st.expander("Personaliza tu historia"): | |
# Código de selección de fórmula movido aquí | |
available_formulas = list(story_formulas.keys()) | |
formula_display_names = [] | |
formula_mapping = {} | |
for formula in available_formulas: | |
display_name = '.'.join(list(formula)) if formula.isupper() else formula | |
formula_display_names.append(display_name) | |
formula_mapping[display_name] = formula | |
formula = st.radio( | |
"Selecciona la fórmula para generar tu historia:", | |
formula_display_names | |
) | |
selected_formula = formula_mapping[formula] | |
# Resto de las opciones de personalización | |
mood = st.selectbox("Tono de la historia:", | |
["Emocional", "Triste", "Feliz", "Horror", "Comedia", "Romántico"]) | |
if selected_formula == "GHA": | |
length = st.slider("Longitud de la historia (palabras):", | |
min_value=50, max_value=200, value=150, step=10) | |
else: | |
length = st.slider("Longitud de la historia (palabras):", | |
min_value=50, max_value=150, value=100, step=10) | |
# Campo story_topic fuera del expander pero dependiente de la fórmula seleccionada | |
story_topic = None | |
if selected_formula == "GHA": | |
story_topic = st.text_area( | |
"De qué quieres que trate la historia", | |
placeholder="Explica si hay algo específico sobre lo que te gustaría contar (puede ser una vivencia personal, película, cuento, personaje ficticio, etc.)." | |
) | |
# Botón para generar contenido | |
submit = st.button("Generar mi historia") | |
# Mostrar el contenido generado en la columna derecha (col2) | |
with col2: | |
if submit: | |
if target_audience and product and action: | |
try: | |
# Verificar si es GHA y necesita story_topic | |
if selected_formula == "GHA": | |
if story_topic: | |
response = generate_story(selected_formula, target_audience, product, | |
action, mood, length, story_topic) | |
else: | |
st.error("Por favor, completa todos los campos requeridos para la fórmula G.H.A.") | |
response = "" | |
else: | |
response = generate_story(selected_formula, target_audience, product, | |
action, mood, length) | |
if response: | |
st.subheader("Historia generada:") | |
st.write(response) | |
except ValueError as e: | |
st.error(f"Error: {str(e)}") | |
else: | |
st.error("Por favor, completa todos los campos requeridos (Público objetivo, Producto y Acción).") | |