Files
marketing-assistant-ai/backend/brand_style.py
T

175 lines
7.0 KiB
Python
Raw Normal View History

"""
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()