""" Brand style module for the Marketing Assistant AI. Ensures generated content aligns with Adriana James' brand voice and tone. """ import json import os from typing import Dict, List, Any, Optional from pathlib import Path from loguru import logger import config class BrandStyleManager: """Manages brand style guidelines and ensures content consistency.""" def __init__(self): """Initialize the BrandStyleManager with default or stored style guidelines.""" self.style_path = Path(config.DATA_DIR) / "style_guidelines" / "brand_style.json" self.style_guidelines = self._load_or_create_style() logger.info("BrandStyleManager initialized successfully") def _load_or_create_style(self) -> Dict[str, Any]: """Load existing style guidelines or create new ones with defaults.""" try: if self.style_path.exists(): with open(self.style_path, 'r') as f: style = json.load(f) logger.info("Loaded existing brand style guidelines") return style else: # Create directory if it doesn't exist self.style_path.parent.mkdir(exist_ok=True) # Use default style guidelines style = config.DEFAULT_BRAND_STYLE # Save default style with open(self.style_path, 'w') as f: json.dump(style, f, indent=2) logger.info("Created default brand style guidelines") return style except Exception as e: logger.error(f"Error loading or creating style guidelines: {str(e)}") # Fall back to default style return config.DEFAULT_BRAND_STYLE def get_style_guidelines(self) -> Dict[str, Any]: """ Get current brand style guidelines. Returns: Dictionary of style guidelines """ return self.style_guidelines def update_style_guidelines(self, new_style: Dict[str, Any]) -> Dict[str, Any]: """ Update brand style guidelines. Args: new_style: Dictionary with new style guidelines Returns: Updated style guidelines dictionary """ try: # Merge new style with existing for key, value in new_style.items(): self.style_guidelines[key] = value # Ensure brand name is preserved self.style_guidelines['brand_name'] = config.BRAND_NAME # Save updated style with open(self.style_path, 'w') as f: json.dump(self.style_guidelines, f, indent=2) logger.info("Updated brand style guidelines") return self.style_guidelines except Exception as e: logger.error(f"Error updating style guidelines: {str(e)}") raise def format_prompt_with_brand_style(self, user_prompt: str, content_type: Optional[str] = None) -> str: """ Format user prompt with brand style guidelines for the LLM. Args: user_prompt: Original user prompt content_type: Type of content being generated Returns: Formatted prompt with brand style instructions """ style = self.style_guidelines # Create a formatted prompt with brand style instructions prompt_parts = [ f"Generate marketing content for {style['brand_name']} based on the following request:", f"\"{user_prompt}\"", "\nFollow these brand style guidelines:", f"- Brand Name: {style['brand_name']}", f"- Tone: {', '.join(style.get('tone', []))}", f"- Voice Characteristics: {', '.join(style.get('voice_characteristics', []))}", ] # Add taboo words if any if 'taboo_words' in style and style['taboo_words']: prompt_parts.append(f"- Avoid these words: {', '.join(style['taboo_words'])}") # Add preferred terms if any if 'preferred_terms' in style and style['preferred_terms']: terms = [f"use '{value}' instead of '{key}'" for key, value in style['preferred_terms'].items()] prompt_parts.append(f"- Preferred terminology: {'; '.join(terms)}") # Add content type specific instructions if content_type: if content_type == "email_campaign": prompt_parts.append("- Format as a professional email with subject line, greeting, body, and signature") elif content_type == "social_media": prompt_parts.append("- Format as a concise social media post with appropriate hashtags") elif content_type == "blog_post": prompt_parts.append("- Format as a blog post with title, introduction, body with subheadings, and conclusion") elif content_type == "website_copy": prompt_parts.append("- Format as website copy with clear headings and concise paragraphs") elif content_type == "ad_copy": prompt_parts.append("- Format as advertising copy with headline, body, and clear call to action") # Combine all parts formatted_prompt = "\n".join(prompt_parts) logger.debug("Created formatted prompt with brand style") return formatted_prompt def check_content_alignment(self, content: str) -> Dict[str, Any]: """ Check if generated content aligns with brand style guidelines. Args: content: Generated marketing content Returns: Dictionary with alignment metrics and suggestions """ style = self.style_guidelines taboo_words = style.get('taboo_words', []) preferred_terms = style.get('preferred_terms', {}) # Check for taboo words found_taboo_words = [] for word in taboo_words: if word.lower() in content.lower(): found_taboo_words.append(word) # Check for preferred terminology terminology_issues = [] for avoid, use in preferred_terms.items(): if avoid.lower() in content.lower(): terminology_issues.append(f"Found '{avoid}', should use '{use}' instead") # Calculate an overall alignment score (simple implementation) issues_count = len(found_taboo_words) + len(terminology_issues) alignment_score = max(0, 100 - (issues_count * 10)) # Reduce score for each issue return { 'alignment_score': alignment_score, 'taboo_words_found': found_taboo_words, 'terminology_issues': terminology_issues, 'aligned': alignment_score >= 80 # Consider aligned if score is 80% or higher } # Create a singleton instance brand_style_manager = BrandStyleManager()