|
from dotenv import load_dotenv |
|
import os |
|
import google.generativeai as genai |
|
import random |
|
from src.data.story_formulas import story_formulas |
|
|
|
class StoryGenerator: |
|
def __init__(self): |
|
load_dotenv() |
|
genai.configure(api_key=os.getenv("GOOGLE_API_KEY")) |
|
|
|
self.generation_config = { |
|
"temperature": 1.0, |
|
"top_p": 0.65, |
|
"top_k": 360, |
|
"max_output_tokens": 8196, |
|
} |
|
|
|
self.model = genai.GenerativeModel( |
|
model_name="gemini-2.0-flash", |
|
generation_config=self.generation_config |
|
) |
|
|
|
|
|
def generate_headline(self, story, formula_type, product, target_audience, mood, temperature): |
|
"""Función para generar un titular basado en la historia""" |
|
system_prompt = """Eres un experto copywriter especializado en crear titulares persuasivos. |
|
IMPORTANTE: |
|
- Genera SOLO UN TITULAR |
|
- No incluyas explicaciones ni etiquetas |
|
- El titular debe estar entre comillas "titular" |
|
- No uses números ni viñetas |
|
- El titular debe fluir naturalmente con la historia |
|
- El titular DEBE estar directamente relacionado con el contenido de la historia |
|
- Evita titulares genéricos que podrían aplicar a cualquier historia |
|
- Extrae elementos específicos de la historia para crear un titular único |
|
""" |
|
|
|
formula_prompts = { |
|
"GPS": f""" |
|
{system_prompt} |
|
|
|
INSTRUCCIONES PARA TITULAR GPS: |
|
Crea un titular que combine: |
|
1. Meta: Un resultado deseable para {target_audience} |
|
2. Periodo: Una situación cotidiana o momento del día |
|
3. Superación: Un conector con toque de humor (sin, incluso si, aunque, etc.) |
|
|
|
ESTRUCTURA REQUERIDA: |
|
[Meta deseable] + [Momento cotidiano] + [Conector humorístico] |
|
|
|
EJEMPLOS EFECTIVOS: |
|
- "Domina el arte de la inversión mientras te cepillas los dientes incluso si confundes Excel con PowerPoint" |
|
- "Aprende un nuevo idioma durante tus visitas al baño aunque solo sepas decir gracias y por favor" |
|
- "Conquista el miedo a hablar en público durante el desayuno a pesar de que te tiemblen hasta las pestañas" |
|
- "Desarrolla músculos preparando café cuando levantar la taza te parece ejercicio extremo" |
|
- "Domina la fotografía profesional en el supermercado aun con ese celular que sobrevivió tres caídas" |
|
|
|
VALIDACIONES: |
|
- ¿Incluye una meta clara y deseable? |
|
- ¿Menciona un momento cotidiano específico? |
|
- ¿Usa un conector humorístico natural? |
|
- ¿Mantiene el humor sin ser ridículo? |
|
- ¿Es relevante para {target_audience}? |
|
|
|
Historia a titular: |
|
{story} |
|
""", |
|
|
|
"AIDA": f""" |
|
{system_prompt} |
|
|
|
INSTRUCCIONES PARA TITULAR AIDA: |
|
Crea un titular que combine: |
|
1. Atención: Gancho sorprendente o contraintuitivo |
|
2. Interés: Desarrollo que intriga |
|
3. Deseo: Promesa transformadora |
|
4. Acción: Siguiente paso natural |
|
|
|
ESTRUCTURA REQUERIDA: |
|
[Gancho sorprendente] + [Desarrollo intrigante] + [Promesa] |
|
|
|
EJEMPLOS EFECTIVOS: |
|
- "¿Sabías que el 83% de los emprendedores exitosos dedican menos de 2 horas al día a reuniones?" |
|
- "La mayoría no sabe que existe una técnica de ventas basada en videojuegos" |
|
- "Contrario a lo que piensas, el momento más productivo del día no es por la mañana" |
|
- "Como el bambú japonés, este método crece invisible hasta explotar en resultados" |
|
- "Los atletas olímpicos entrenan menos horas pero logran más gracias a esta técnica" |
|
|
|
VALIDACIONES: |
|
- ¿El gancho genera curiosidad inmediata? |
|
- ¿El desarrollo mantiene el interés? |
|
- ¿La promesa es creíble y atractiva? |
|
- ¿Mantiene coherencia con la historia? |
|
- ¿Es relevante para {target_audience}? |
|
|
|
Historia a titular: |
|
{story} |
|
""", |
|
|
|
"4U": f""" |
|
{system_prompt} |
|
|
|
INSTRUCCIONES PARA TITULAR 4U: |
|
Combina estratégicamente: |
|
1. Útil: Beneficio práctico y tangible |
|
2. Urgente: Motivador de acción inmediata |
|
3. Único: Diferenciador memorable |
|
4. Ultra-específico: Detalles precisos y medibles |
|
|
|
ESTRUCTURA REQUERIDA: |
|
[Beneficio útil] + [Elemento único] + [Detalle ultra-específico] + [Urgencia] |
|
|
|
EJEMPLOS EFECTIVOS: |
|
- "Aprende 347 palabras en alemán memorizando solo 12 minutos al día mientras cocinas" |
|
- "Cultiva 27 tipos de hierbas aromáticas en 1.5 metros cuadrados de balcón" |
|
- "Automatiza 89% de tus tareas administrativas dedicando 31 minutos cada lunes" |
|
- "La técnica de un cartero rural ayuda a 1893 personas a organizar su tiempo" |
|
- "Un bibliotecario retirado genera 12437 euros vendiendo libros antiguos" |
|
|
|
VALIDACIONES: |
|
- ¿Incluye un beneficio claro y medible? |
|
- ¿Tiene un elemento diferenciador único? |
|
- ¿Usa datos específicos y creíbles? |
|
- ¿Genera sensación de urgencia natural? |
|
- ¿Es relevante para {target_audience}? |
|
|
|
Historia a titular: |
|
{story} |
|
""" |
|
} |
|
headline_prompt = formula_prompts.get(formula_type, f""" |
|
{system_prompt} |
|
|
|
INSTRUCCIONES ESPECÍFICAS: |
|
Genera un titular persuasivo y memorable que: |
|
- Conecte directamente con la historia narrada |
|
- Refleje la transformación o experiencia descrita |
|
- Use elementos específicos mencionados en el contenido |
|
- Mantenga un tono {mood} coherente con la narrativa |
|
- Sea conciso pero impactante |
|
- No mencione directamente "{product}" |
|
- Genere curiosidad mientras mantiene la relevancia |
|
|
|
IMPORTANTE: |
|
- El titular debe surgir naturalmente de la historia |
|
- Usa palabras clave y conceptos presentes en la narrativa |
|
- Evita titulares genéricos que podrían aplicar a cualquier historia |
|
|
|
Historia a titular: |
|
{story} |
|
""") |
|
response = model.generate_content([headline_prompt]) |
|
if response and response.parts: |
|
|
|
headline_text = response.parts[0].text.strip() |
|
import re |
|
match = re.search(r'"([^"]*)"', headline_text) |
|
if match: |
|
return match.group(1) |
|
return headline_text |
|
return None |
|
|
|
|
|
def generate_story(self, formula_type, target_audience, product, action, mood, length, temperature, story_topic=None): |
|
|
|
|
|
self.generation_config["temperature"] = temperature |
|
|
|
if formula_type not in story_formulas: |
|
raise ValueError("Fórmula no válida") |
|
|
|
|
|
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 |
|
""" |
|
|
|
|
|
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 |
|
""" |
|
|
|
|
|
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 short paragraphs (2-4 lines maximum) |
|
- Number of paragraphs should adjust to requested length |
|
- Each section must flow naturally into the next |
|
- No explicit section labels |
|
- Include smooth transitions between parts |
|
- Story must feel complete and cohesive |
|
- Break text for better readability and impact |
|
|
|
FORMULA APPLICATION: |
|
- The selected formula MUST be applied to the entire story |
|
- Review and follow the structure from story_formulas[formula_type]["description"] |
|
- Use examples in story_formulas[formula_type]["examples"] as inspiration |
|
- Formula provides framework, tone provides emotional layer |
|
- Paragraphs can be more or fewer than formula steps |
|
- Structure should be present but not obvious |
|
|
|
CONTENT AND AUDIENCE: |
|
- Focus on relatable, everyday situations |
|
- Describe specific audience problems and obstacles |
|
- Use details that generate immediate identification |
|
- Story must faithfully reflect audience's real life |
|
- Problems and situations must be 100% recognizable |
|
- Base narrative on real audience pain points |
|
- Each story must be unique and memorable |
|
- Avoid clichés and generic scenarios |
|
|
|
TONE AND STYLE: |
|
- Mood only affects emotional tone, not structure |
|
- Emotions should arise from real situations |
|
- Keep focus on audience regardless of tone |
|
- Selected tone must remain consistent |
|
- Both formula and tone must complement each other |
|
- Maintain voice appropriate for target audience |
|
|
|
SPECIAL CONSIDERATIONS FOR GHA: |
|
- Story must develop around specified topic |
|
- Topic should be the main thread |
|
- Integrate product/service naturally within topic context |
|
- Keep topic as central narrative element |
|
|
|
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 |
|
|
|
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 in English |
|
|
|
CALL TO ACTION GUIDELINES: |
|
In the end of each story create a natural and persuasive call to action that: |
|
|
|
Flows naturally from the story |
|
Focuses on transformation and benefits |
|
KEY ELEMENTS IN EVERY CTA: |
|
|
|
Transformational Benefit → What will change in their life |
|
Implicit Social Proof → Others have already achieved it |
|
Simple Next Step → A clear and achievable action |
|
Natural Urgency → Based on benefits, not scarcity |
|
|
|
IMPORTANT: |
|
|
|
The CTA must flow naturally from the story |
|
Maintain the established emotional tone |
|
Use language that inspires rather than pressures |
|
Connect with the transformation described in the story |
|
""" |
|
story_instruction = f"{system_prompt}\n\n{audience_analysis}\n\n" |
|
|
|
|
|
if formula_type == "GHA" and story_topic: |
|
story_instruction += f""" |
|
INTEGRACIÓN DEL TEMA CENTRAL EN LA HISTORIA: |
|
|
|
TEMA PRINCIPAL: "{story_topic}" |
|
|
|
1. ESTRUCTURA NARRATIVA: |
|
- Primer párrafo: Introduce el tema "{story_topic}" de forma cautivadora |
|
- Desarrollo: Profundiza en la experiencia/situación relacionada con el tema |
|
- Clímax: Momento de transformación donde el producto se integra naturalmente |
|
- Cierre: Resolución que conecta el tema con la solución propuesta |
|
|
|
2. DESARROLLO DEL TEMA: |
|
- Usa el tema como hilo conductor de toda la historia |
|
- Describe situaciones específicas relacionadas con {story_topic} |
|
- Incluye detalles y experiencias únicas del tema |
|
- Mantén el foco en la perspectiva de {target_audience} sobre {story_topic} |
|
|
|
3. INTEGRACIÓN DEL PRODUCTO: |
|
- NO menciones {product} hasta haber desarrollado bien el tema |
|
- El producto debe surgir como solución natural a una situación del tema |
|
- Conecta los beneficios de {product} con aspectos específicos de {story_topic} |
|
- Mantén el protagonismo del tema por encima del producto |
|
|
|
4. ELEMENTOS OBLIGATORIOS: |
|
- Mínimo 3 referencias específicas a {story_topic} |
|
- Al menos 2 situaciones o momentos relacionados con el tema |
|
- Una conexión clara entre el tema y la necesidad del producto |
|
- Un cierre que refuerce la relación entre tema y solución |
|
|
|
5. VALIDACIONES: |
|
- ¿La historia gira realmente en torno a {story_topic}? |
|
- ¿Se mantiene el tema como elemento central? |
|
- ¿La integración del producto es natural dentro del contexto del tema? |
|
- ¿El llamado a la acción conecta con el tema desarrollado? |
|
|
|
RECORDATORIO IMPORTANTE: |
|
- La historia debe ser 100% sobre {story_topic} |
|
- El producto es secundario al tema |
|
- Cada párrafo debe contener elementos del tema |
|
- La transformación debe estar directamente relacionada con {story_topic} |
|
""" |
|
|
|
|
|
story_instruction += f""" |
|
EJEMPLOS DE INTEGRACIÓN DEL TEMA: |
|
|
|
Si el tema es una experiencia personal: |
|
❌ "Un día cualquiera..." |
|
✓ "Aquella mañana en [situación específica del tema]..." |
|
|
|
Si el tema es una situación: |
|
❌ "Las personas suelen..." |
|
✓ "En medio de [detalle específico del tema]..." |
|
|
|
Si el tema es un concepto: |
|
❌ "Todos queremos mejorar..." |
|
✓ "Cuando te enfrentas a [aspecto específico del tema]..." |
|
|
|
ESTRUCTURA DEL PÁRRAFO INICIAL: |
|
1. Situación específica del {story_topic} |
|
2. Conexión emocional con {target_audience} |
|
3. Transición hacia el desarrollo |
|
""" |
|
|
|
|
|
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 |
|
""" |
|
|
|
|
|
if formula_type == "GHA" and story_topic: |
|
system_prompt += f""" |
|
INSTRUCCIONES ESPECÍFICAS PARA GHA: |
|
- El titular DEBE incorporar elementos del story_topic: "{story_topic}" |
|
- Mantén el enfoque principal en la transformación o experiencia relacionada con el tema |
|
- Usa palabras clave o conceptos específicos mencionados en la historia |
|
- Asegúrate de que el titular refleje la esencia del story_topic |
|
- La conexión entre el titular y el tema debe ser clara y natural |
|
CALL TO ACTION GUIDELINES: |
|
In the end of each story create a natural and persuasive call to action that: |
|
|
|
Flows naturally from the story |
|
Focuses on transformation and benefits |
|
KEY ELEMENTS IN EVERY CTA: |
|
|
|
Transformational Benefit → What will change in their life |
|
Implicit Social Proof → Others have already achieved it |
|
Simple Next Step → A clear and achievable action |
|
Natural Urgency → Based on benefits, not scarcity |
|
|
|
IMPORTANT: |
|
|
|
The CTA must flow naturally from the story |
|
Maintain the established emotional tone |
|
Use language that inspires rather than pressures |
|
Connect with the transformation described in the story |
|
""" |
|
|
|
|
|
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}: |
|
""" |
|
|
|
|
|
random_examples = random.sample(story_formulas[formula_type]['examples'], |
|
min(3, len(story_formulas[formula_type]['examples']))) |
|
|
|
|
|
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']} |
|
Acción: {example['action']} |
|
Historia: |
|
{example['story']} |
|
""" |
|
|
|
|
|
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 |
|
""" |
|
|
|
|
|
story_instruction += f"\nFÓRMULA A SEGUIR:\n{story_formulas[formula_type]['description']}\n\n" |
|
|
|
|
|
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 |
|
""" |
|
|
|
|
|
story_instruction = f"{natural_instruction}\n\n{story_instruction}" |
|
|
|
|
|
response = self.model.generate_content([story_instruction]) |
|
if response and response.parts: |
|
story = response.parts[0].text.strip() |
|
formula_types = ["GPS", "AIDA", "4U", "Númerica Suprema"] |
|
selected_formula = random.choice(formula_types) |
|
headline = generate_headline_for_story(story, selected_formula, product, target_audience, mood, temperature) |
|
if headline: |
|
return f"{headline}\n\n{story}" |
|
raise ValueError("No se pudo generar la historia") |