|
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):
|
|
try:
|
|
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
|
|
)
|
|
except Exception as e:
|
|
raise ValueError(f"Error initializing StoryGenerator: {str(e)}")
|
|
|
|
|
|
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):
|
|
try:
|
|
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
|
|
- Importante:
|
|
- 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:
|
|
INCORRECTO: "Un día cualquiera..."
|
|
CORRECTO: "Aquella mañana en [situación específica del tema]..."
|
|
|
|
Si el tema es una situación:
|
|
INCORRECTO: "Las personas suelen..."
|
|
CORRECTO: "En medio de [detalle específico del tema]..."
|
|
|
|
Si el tema es un concepto:
|
|
INCORRECTO: "Todos queremos mejorar..."
|
|
CORRECTO: "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])
|
|
|
|
response = self.model.generate_content([story_instruction])
|
|
if not response or not response.parts:
|
|
raise ValueError("La API no generó una respuesta válida")
|
|
|
|
story = response.parts[0].text.strip()
|
|
if not story:
|
|
raise ValueError("La historia generada está vacía")
|
|
|
|
formula_types = ["GPS", "AIDA", "4U", "Númerica Suprema"]
|
|
selected_formula = random.choice(formula_types)
|
|
headline = self.generate_headline(story, selected_formula, product, target_audience, mood, temperature)
|
|
|
|
if headline:
|
|
return f"{headline}\n\n{story}"
|
|
return story
|
|
|
|
except Exception as e:
|
|
raise ValueError(f"No se pudo generar la historia: {str(e)}") |