Spaces:
Sleeping
Sleeping
| 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)}") | |
| #Función para generar un titular basado en la historia | |
| 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} | |
| """ | |
| } | |
| # Validate formula type | |
| if formula_type not in formula_prompts: | |
| raise ValueError("Tipo de fórmula no válida. Use: GPS, AIDA, o 4U") | |
| headline_prompt = formula_prompts[formula_type] | |
| response = self.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 | |
| """ | |
| # 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 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" | |
| # Instrucciones específicas para GHA cuando hay story_topic | |
| 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} | |
| """ | |
| # Añadir ejemplos específicos para el tipo de tema | |
| 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 | |
| """ | |
| # 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 | |
| """ | |
| 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 | |
| """ | |
| # 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']} | |
| Acción: {example['action']} | |
| 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}" | |
| # Generate the story using retries | |
| return self._generate_story_with_retries(story_instruction, formula_type, product, target_audience, mood, temperature, action) | |
| except Exception as e: | |
| raise ValueError(f"Error generating story: {str(e)}") | |
| def _generate_story_with_retries(self, story_instruction, formula_type, product, target_audience, mood, temperature, action): | |
| max_attempts = 3 | |
| attempts = 0 | |
| story = "" | |
| while attempts < max_attempts: | |
| try: | |
| # Generación de contenido utilizando el modelo | |
| response = self.model.generate_content([story_instruction]) | |
| if response and response.parts: | |
| story = response.parts[0].text.strip() | |
| if story: | |
| # Generación del titular si la historia es válida | |
| formula_types = ["GPS", "AIDA", "4U"] | |
| selected_formula = random.choice(formula_types) | |
| headline = self.generate_headline( | |
| story, | |
| selected_formula, | |
| product, | |
| target_audience, | |
| mood, | |
| temperature | |
| ) | |
| # Devolver la historia con el titular si existe | |
| return f"{headline}\n\n{story}" if headline else story | |
| except Exception as e: | |
| print(f"Intento {attempts + 1} fallido: {str(e)}") | |
| attempts += 1 | |
| raise ValueError("No se pudo generar la historia después de varios intentos.") |