Files
marketing-assistant-ai/backend/brand_style.py
T
Michael Ikehi af8f99dea3 feat(feedback): Add content improvement feedback system
Frontend (frontend/app.js):

- Add textarea for improvement feedback

- Add submit button with loading state

- Handle API response and display improved content

Backend (backend/copywriter.py):

- Add improve_copy() method using Cohere API

- Integrate retry mechanism for API calls

Backend (backend/main.py):

- Add /improve-content POST endpoint

- Implement error handling and return improved content with metadata

Testing:

- Verified feedback submission flow

- Confirmed improved content generation

- Tested error scenarios and loading states
2025-04-18 04:39:06 +01:00

266 lines
11 KiB
Python

"""
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()
self.content_formats = {
"website_copy": """
Generate engaging website copy for a brand or business.
- Start with a strong headline and supporting subheadline
- Write in a clear, benefit-driven tone
- Use SEO-friendly keywords naturally
- Structure content with short paragraphs and bullet points
- Include a clear call-to-action at the end
""",
"email": """
Create a marketing or sales email for a target audience.
- Start with a compelling subject line
- Use a warm, conversational tone
- Keep the message focused and value-driven
- Personalize where possible (name, context)
- End with a clear and persuasive CTA
""",
"social_media": """
Write social media content tailored to a specific platform.
- Hook the reader within the first sentence
- Keep the message concise and engaging
- Use platform-appropriate tone and emojis (if applicable)
- Add relevant hashtags and tag accounts when needed
- Include a prompt or CTA to drive interaction
""",
"blog_post": """
Generate a blog article on a given topic or keyword.
- Begin with a strong hook or introduction
- Organize content with subheadings and logical flow
- Use examples, data, and storytelling
- Optimize for SEO with keywords and meta description
- Conclude with a summary or actionable insight
""",
"sales_copy": """
Write persuasive sales copy for a product or service.
- Lead with a strong value proposition
- Address specific pain points and offer solutions
- Highlight features, benefits, and outcomes
- Include social proof (testimonials, stats, etc.)
- End with a direct and compelling CTA
""",
"ad_copy": """
Create short, punchy ad copy for digital or print campaigns.
- Capture attention in the first line
- Use emotional or benefit-driven language
- Keep it brief and persuasive
- Align copy with the target audience
- Include a CTA or promotional message
""",
"video_script": """
Generate a short video script for a marketing video.
- Hook the viewer in the first few seconds
- Introduce the problem and present the solution
- Keep the tone conversational and natural
- Include visual cues and on-screen text ideas
- Wrap up with a strong CTA
""",
"case_study": """
Write a case study that highlights a customer success story.
- Start with a quick summary of the results
- Describe the client and their initial problem
- Explain how the product/service helped
- Include measurable outcomes or metrics
- End with a quote and a CTA to learn more
""",
"product_description": """
Generate a product description that drives interest and conversions.
- Begin with the most attractive benefit
- Mention key features and what makes the product unique
- Use sensory and persuasive language
- Include important specs or FAQs
- End with a micro-CTA (e.g., "Shop now", "View details")
""",
"landing_page": """
Write copy for a focused landing page.
- Use a bold, attention-grabbing headline
- Describe the offer clearly and simply
- Include supporting details that reinforce value
- Remove distractions and focus on a single goal
- Add a CTA above the fold and at the end
""",
"press_release": """
Create a professional press release for an announcement.
- Begin with a headline that summarizes the news
- Use a journalistic tone and structure
- Provide key facts in the first paragraph
- Add quotes from relevant leaders or stakeholders
- End with boilerplate company info and contact details
""",
"newsletter": """
Write a newsletter update for subscribers.
- Start with a warm greeting or short intro
- Highlight the most important news or offer first
- Use engaging sub-sections or article teasers
- Maintain consistent tone with the brand
- Include CTAs to drive clicks or traffic
"""
}
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 to match the established writing style."""
style_instructions = [
"Follow these writing style guidelines:",
"- Use direct commands that empower the reader",
"- Address the reader directly using 'you' and 'your'",
"- Create rhythmic, repetitive patterns in key messages",
"- Maintain a clear, confident, and authoritative tone",
"- Use simple, practical language without jargon",
"- Acknowledge challenges while focusing on solutions",
"- Include empowering phrases that emphasize reader's control and choice"
]
# Content type specific formatting
content_format = self._get_content_format(content_type) if content_type else ""
return "\n".join([
f"Generate content based on this request:",
f"\"{user_prompt}\"",
"",
"\n".join(style_instructions),
content_format
])
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
}
def _get_content_format(self, content_type: str) -> str:
"""
Get formatting instructions for specific content type.
Args:
content_type: Type of content to generate
Returns:
Formatting instructions as string
"""
if not content_type:
return ""
format_instructions = self.content_formats.get(content_type, "")
if format_instructions:
return f"\nContent type specific instructions:\n{format_instructions.strip()}"
return ""
# Create a singleton instance
brand_style_manager = BrandStyleManager()