Onboarding Manager and Router Manager refactored, analytics and background jobs added, database setup updated, environment setup updated, frontend updated, backend updated. Critical onboarding database migration implemented.
1083 lines
49 KiB
Python
1083 lines
49 KiB
Python
"""
|
|
Persona Quality Improvement Service
|
|
Continuously improves persona quality through feedback and learning.
|
|
"""
|
|
|
|
import json
|
|
from typing import Dict, Any, List, Optional, Tuple
|
|
from datetime import datetime, timedelta
|
|
from loguru import logger
|
|
from sqlalchemy.orm import Session
|
|
|
|
from models.enhanced_persona_models import (
|
|
EnhancedWritingPersona,
|
|
EnhancedPlatformPersona,
|
|
PersonaQualityMetrics,
|
|
PersonaLearningData
|
|
)
|
|
from services.database import get_db_session
|
|
from services.persona.enhanced_linguistic_analyzer import EnhancedLinguisticAnalyzer
|
|
|
|
class PersonaQualityImprover:
|
|
"""Service for continuously improving persona quality and accuracy."""
|
|
|
|
def __init__(self):
|
|
"""Initialize the quality improver."""
|
|
self.linguistic_analyzer = EnhancedLinguisticAnalyzer()
|
|
logger.debug("PersonaQualityImprover initialized")
|
|
|
|
def assess_persona_quality_comprehensive(
|
|
self,
|
|
core_persona: Dict[str, Any],
|
|
platform_personas: Dict[str, Any],
|
|
linguistic_analysis: Dict[str, Any],
|
|
user_preferences: Optional[Dict[str, Any]] = None
|
|
) -> Dict[str, Any]:
|
|
"""
|
|
Comprehensive quality assessment for quality-first approach.
|
|
"""
|
|
try:
|
|
# Calculate comprehensive quality metrics
|
|
quality_metrics = self._calculate_comprehensive_quality_metrics(
|
|
core_persona, platform_personas, linguistic_analysis, user_preferences
|
|
)
|
|
|
|
# Generate detailed recommendations
|
|
recommendations = self._generate_comprehensive_recommendations(quality_metrics, linguistic_analysis)
|
|
|
|
return {
|
|
"overall_score": quality_metrics.get('overall_score', 0),
|
|
"core_completeness": quality_metrics.get('core_completeness', 0),
|
|
"platform_consistency": quality_metrics.get('platform_consistency', 0),
|
|
"platform_optimization": quality_metrics.get('platform_optimization', 0),
|
|
"linguistic_quality": quality_metrics.get('linguistic_quality', 0),
|
|
"recommendations": recommendations,
|
|
"assessment_method": "comprehensive_ai_based",
|
|
"linguistic_insights": linguistic_analysis,
|
|
"detailed_metrics": quality_metrics
|
|
}
|
|
|
|
except Exception as e:
|
|
logger.error(f"Comprehensive quality assessment error: {str(e)}")
|
|
return {
|
|
"overall_score": 75,
|
|
"core_completeness": 75,
|
|
"platform_consistency": 75,
|
|
"platform_optimization": 75,
|
|
"linguistic_quality": 75,
|
|
"recommendations": ["Quality assessment completed with default metrics"],
|
|
"error": str(e)
|
|
}
|
|
|
|
def improve_persona_quality(
|
|
self,
|
|
core_persona: Dict[str, Any],
|
|
platform_personas: Dict[str, Any],
|
|
quality_metrics: Dict[str, Any]
|
|
) -> Dict[str, Any]:
|
|
"""
|
|
Improve persona quality based on assessment results.
|
|
"""
|
|
try:
|
|
logger.info("Improving persona quality based on assessment results...")
|
|
|
|
improved_core_persona = self._improve_core_persona(core_persona, quality_metrics)
|
|
improved_platform_personas = self._improve_platform_personas(platform_personas, quality_metrics)
|
|
|
|
return {
|
|
"core_persona": improved_core_persona,
|
|
"platform_personas": improved_platform_personas,
|
|
"improvement_applied": True,
|
|
"improvement_details": "Quality improvements applied based on assessment results"
|
|
}
|
|
|
|
except Exception as e:
|
|
logger.error(f"Persona quality improvement error: {str(e)}")
|
|
return {"error": f"Failed to improve persona quality: {str(e)}"}
|
|
|
|
def _calculate_comprehensive_quality_metrics(
|
|
self,
|
|
core_persona: Dict[str, Any],
|
|
platform_personas: Dict[str, Any],
|
|
linguistic_analysis: Dict[str, Any],
|
|
user_preferences: Optional[Dict[str, Any]] = None
|
|
) -> Dict[str, Any]:
|
|
"""Calculate comprehensive quality metrics."""
|
|
try:
|
|
# Core completeness (30% weight)
|
|
core_completeness = self._assess_core_completeness(core_persona, linguistic_analysis)
|
|
|
|
# Platform consistency (25% weight)
|
|
platform_consistency = self._assess_platform_consistency(core_persona, platform_personas)
|
|
|
|
# Platform optimization (25% weight)
|
|
platform_optimization = self._assess_platform_optimization_dict(platform_personas)
|
|
|
|
# Linguistic quality (20% weight)
|
|
linguistic_quality = self._assess_linguistic_quality(linguistic_analysis)
|
|
|
|
# Calculate weighted overall score
|
|
overall_score = int((
|
|
core_completeness * 0.30 +
|
|
platform_consistency * 0.25 +
|
|
platform_optimization * 0.25 +
|
|
linguistic_quality * 0.20
|
|
))
|
|
|
|
return {
|
|
"overall_score": overall_score,
|
|
"core_completeness": core_completeness,
|
|
"platform_consistency": platform_consistency,
|
|
"platform_optimization": platform_optimization,
|
|
"linguistic_quality": linguistic_quality,
|
|
"weights": {
|
|
"core_completeness": 0.30,
|
|
"platform_consistency": 0.25,
|
|
"platform_optimization": 0.25,
|
|
"linguistic_quality": 0.20
|
|
}
|
|
}
|
|
|
|
except Exception as e:
|
|
logger.error(f"Error calculating comprehensive quality metrics: {str(e)}")
|
|
return {
|
|
"overall_score": 75,
|
|
"core_completeness": 75,
|
|
"platform_consistency": 75,
|
|
"platform_optimization": 75,
|
|
"linguistic_quality": 75
|
|
}
|
|
|
|
def _assess_core_completeness(self, core_persona: Dict[str, Any], linguistic_analysis: Dict[str, Any]) -> int:
|
|
"""Assess core persona completeness."""
|
|
required_sections = ['writing_style', 'content_characteristics', 'brand_voice', 'target_audience']
|
|
present_sections = sum(1 for section in required_sections if section in core_persona and core_persona[section])
|
|
|
|
base_score = int((present_sections / len(required_sections)) * 100)
|
|
|
|
# Boost if linguistic analysis provides additional insights
|
|
if linguistic_analysis and linguistic_analysis.get('analysis_completeness', 0) > 0.8:
|
|
base_score = min(base_score + 10, 100)
|
|
|
|
return base_score
|
|
|
|
def _assess_platform_consistency(self, core_persona: Dict[str, Any], platform_personas: Dict[str, Any]) -> int:
|
|
"""Assess consistency across platform personas."""
|
|
if not platform_personas:
|
|
return 50
|
|
|
|
core_voice = core_persona.get('brand_voice', {}).get('keywords', [])
|
|
consistency_scores = []
|
|
|
|
for platform, persona in platform_personas.items():
|
|
if 'error' not in persona:
|
|
platform_voice = persona.get('brand_voice', {}).get('keywords', [])
|
|
overlap = len(set(core_voice) & set(platform_voice))
|
|
consistency_scores.append(min(overlap * 10, 100))
|
|
|
|
return int(sum(consistency_scores) / len(consistency_scores)) if consistency_scores else 75
|
|
|
|
def _assess_platform_optimization_dict(self, platform_personas: Dict[str, Any]) -> int:
|
|
"""Assess platform-specific optimization quality for dictionary input."""
|
|
if not platform_personas:
|
|
return 50
|
|
|
|
optimization_scores = []
|
|
for platform, persona in platform_personas.items():
|
|
if 'error' not in persona:
|
|
has_optimizations = any(key in persona for key in [
|
|
'platform_optimizations', 'content_guidelines', 'engagement_strategies'
|
|
])
|
|
optimization_scores.append(90 if has_optimizations else 60)
|
|
|
|
return int(sum(optimization_scores) / len(optimization_scores)) if optimization_scores else 75
|
|
|
|
def _assess_linguistic_quality(self, linguistic_analysis: Dict[str, Any]) -> int:
|
|
"""Assess linguistic analysis quality."""
|
|
if not linguistic_analysis:
|
|
return 50
|
|
|
|
quality_indicators = [
|
|
'analysis_completeness',
|
|
'style_consistency',
|
|
'vocabulary_sophistication',
|
|
'content_coherence'
|
|
]
|
|
|
|
scores = [linguistic_analysis.get(indicator, 0.5) for indicator in quality_indicators]
|
|
return int(sum(scores) / len(scores) * 100)
|
|
|
|
def _generate_comprehensive_recommendations(self, quality_metrics: Dict[str, Any], linguistic_analysis: Dict[str, Any]) -> List[str]:
|
|
"""Generate comprehensive quality recommendations."""
|
|
recommendations = []
|
|
|
|
if quality_metrics.get('core_completeness', 0) < 85:
|
|
recommendations.append("Enhance core persona with more detailed writing style characteristics and brand voice elements")
|
|
|
|
if quality_metrics.get('platform_consistency', 0) < 80:
|
|
recommendations.append("Improve brand voice consistency across all platform adaptations")
|
|
|
|
if quality_metrics.get('platform_optimization', 0) < 85:
|
|
recommendations.append("Strengthen platform-specific optimizations and engagement strategies")
|
|
|
|
if quality_metrics.get('linguistic_quality', 0) < 80:
|
|
recommendations.append("Improve linguistic quality and writing sophistication")
|
|
|
|
# Add linguistic-specific recommendations
|
|
if linguistic_analysis:
|
|
if linguistic_analysis.get('style_consistency', 0) < 0.7:
|
|
recommendations.append("Enhance writing style consistency across content samples")
|
|
|
|
if linguistic_analysis.get('vocabulary_sophistication', 0) < 0.7:
|
|
recommendations.append("Increase vocabulary sophistication for better audience engagement")
|
|
|
|
if not recommendations:
|
|
recommendations.append("Your personas demonstrate excellent quality across all assessment criteria!")
|
|
|
|
return recommendations
|
|
|
|
def _improve_core_persona(self, core_persona: Dict[str, Any], quality_metrics: Dict[str, Any]) -> Dict[str, Any]:
|
|
"""Improve core persona based on quality metrics."""
|
|
improved_persona = core_persona.copy()
|
|
|
|
# Enhance based on quality gaps
|
|
if quality_metrics.get('core_completeness', 0) < 85:
|
|
# Add more detailed characteristics
|
|
if 'writing_style' not in improved_persona:
|
|
improved_persona['writing_style'] = {}
|
|
|
|
if 'sentence_structure' not in improved_persona['writing_style']:
|
|
improved_persona['writing_style']['sentence_structure'] = 'Varied and engaging'
|
|
|
|
if 'vocabulary_level' not in improved_persona['writing_style']:
|
|
improved_persona['writing_style']['vocabulary_level'] = 'Professional with accessible language'
|
|
|
|
return improved_persona
|
|
|
|
def _improve_platform_personas(self, platform_personas: Dict[str, Any], quality_metrics: Dict[str, Any]) -> Dict[str, Any]:
|
|
"""Improve platform personas based on quality metrics."""
|
|
improved_personas = platform_personas.copy()
|
|
|
|
# Enhance each platform persona
|
|
for platform, persona in improved_personas.items():
|
|
if 'error' not in persona:
|
|
# Add platform-specific optimizations if missing
|
|
if 'platform_optimizations' not in persona:
|
|
persona['platform_optimizations'] = self._get_default_platform_optimizations(platform)
|
|
|
|
# Enhance engagement strategies
|
|
if 'engagement_strategies' not in persona:
|
|
persona['engagement_strategies'] = self._get_default_engagement_strategies(platform)
|
|
|
|
return improved_personas
|
|
|
|
def _get_default_platform_optimizations(self, platform: str) -> Dict[str, Any]:
|
|
"""Get default platform optimizations."""
|
|
optimizations = {
|
|
'linkedin': {
|
|
'professional_networking': True,
|
|
'thought_leadership': True,
|
|
'industry_insights': True
|
|
},
|
|
'facebook': {
|
|
'community_building': True,
|
|
'social_engagement': True,
|
|
'visual_storytelling': True
|
|
},
|
|
'twitter': {
|
|
'real_time_updates': True,
|
|
'hashtag_optimization': True,
|
|
'concise_messaging': True
|
|
},
|
|
'blog': {
|
|
'seo_optimization': True,
|
|
'long_form_content': True,
|
|
'storytelling': True
|
|
}
|
|
}
|
|
return optimizations.get(platform, {})
|
|
|
|
def _get_default_engagement_strategies(self, platform: str) -> Dict[str, Any]:
|
|
"""Get default engagement strategies."""
|
|
strategies = {
|
|
'linkedin': {
|
|
'call_to_action': 'Connect with me to discuss',
|
|
'engagement_style': 'Professional networking'
|
|
},
|
|
'facebook': {
|
|
'call_to_action': 'Join our community',
|
|
'engagement_style': 'Social interaction'
|
|
},
|
|
'twitter': {
|
|
'call_to_action': 'Follow for updates',
|
|
'engagement_style': 'Real-time conversation'
|
|
},
|
|
'blog': {
|
|
'call_to_action': 'Subscribe for more insights',
|
|
'engagement_style': 'Educational content'
|
|
}
|
|
}
|
|
return strategies.get(platform, {})
|
|
|
|
def assess_persona_quality(self, persona_id: int, user_feedback: Optional[Dict[str, Any]] = None) -> Dict[str, Any]:
|
|
"""
|
|
Assess the quality of a persona and provide improvement suggestions.
|
|
|
|
Args:
|
|
persona_id: ID of the persona to assess
|
|
user_feedback: Optional user feedback data
|
|
|
|
Returns:
|
|
Quality assessment results
|
|
"""
|
|
try:
|
|
session = get_db_session()
|
|
|
|
# Get persona data
|
|
persona = session.query(EnhancedWritingPersona).filter(
|
|
EnhancedWritingPersona.id == persona_id
|
|
).first()
|
|
|
|
if not persona:
|
|
return {"error": "Persona not found"}
|
|
|
|
# Perform quality assessment
|
|
quality_metrics = self._perform_quality_assessment(persona, user_feedback)
|
|
|
|
# Save quality metrics
|
|
self._save_quality_metrics(session, persona_id, quality_metrics, user_feedback)
|
|
|
|
# Generate improvement suggestions
|
|
improvement_suggestions = self._generate_improvement_suggestions(quality_metrics)
|
|
|
|
session.close()
|
|
|
|
return {
|
|
"persona_id": persona_id,
|
|
"quality_metrics": quality_metrics,
|
|
"improvement_suggestions": improvement_suggestions,
|
|
"assessment_date": datetime.utcnow().isoformat()
|
|
}
|
|
|
|
except Exception as e:
|
|
logger.error(f"Error assessing persona quality: {str(e)}")
|
|
return {"error": f"Failed to assess persona quality: {str(e)}"}
|
|
|
|
def improve_persona_from_feedback(self, persona_id: int, feedback_data: Dict[str, Any]) -> Dict[str, Any]:
|
|
"""
|
|
Improve persona based on user feedback and performance data.
|
|
|
|
Args:
|
|
persona_id: ID of the persona to improve
|
|
feedback_data: User feedback and performance data
|
|
|
|
Returns:
|
|
Improvement results
|
|
"""
|
|
try:
|
|
session = get_db_session()
|
|
|
|
# Get current persona
|
|
persona = session.query(EnhancedWritingPersona).filter(
|
|
EnhancedWritingPersona.id == persona_id
|
|
).first()
|
|
|
|
if not persona:
|
|
return {"error": "Persona not found"}
|
|
|
|
# Analyze feedback
|
|
feedback_analysis = self._analyze_feedback(feedback_data)
|
|
|
|
# Generate improvements
|
|
improvements = self._generate_persona_improvements(persona, feedback_analysis)
|
|
|
|
# Apply improvements
|
|
updated_persona = self._apply_improvements(session, persona, improvements)
|
|
|
|
# Save learning data
|
|
self._save_learning_data(session, persona_id, feedback_data, improvements)
|
|
|
|
session.commit()
|
|
session.close()
|
|
|
|
return {
|
|
"persona_id": persona_id,
|
|
"improvements_applied": improvements,
|
|
"updated_persona": updated_persona.to_dict(),
|
|
"improvement_date": datetime.utcnow().isoformat()
|
|
}
|
|
|
|
except Exception as e:
|
|
logger.error(f"Error improving persona: {str(e)}")
|
|
return {"error": f"Failed to improve persona: {str(e)}"}
|
|
|
|
def learn_from_content_performance(self, persona_id: int, content_performance: List[Dict[str, Any]]) -> Dict[str, Any]:
|
|
"""
|
|
Learn from content performance data to improve persona.
|
|
|
|
Args:
|
|
persona_id: ID of the persona to improve
|
|
content_performance: List of content performance data
|
|
|
|
Returns:
|
|
Learning results
|
|
"""
|
|
try:
|
|
session = get_db_session()
|
|
|
|
# Analyze performance patterns
|
|
performance_analysis = self._analyze_performance_patterns(content_performance)
|
|
|
|
# Identify successful patterns
|
|
successful_patterns = self._identify_successful_patterns(content_performance)
|
|
|
|
# Generate learning insights
|
|
learning_insights = self._generate_learning_insights(performance_analysis, successful_patterns)
|
|
|
|
# Apply learning to persona
|
|
persona_updates = self._apply_performance_learning(persona_id, learning_insights)
|
|
|
|
# Save learning data
|
|
self._save_performance_learning(session, persona_id, content_performance, learning_insights)
|
|
|
|
session.commit()
|
|
session.close()
|
|
|
|
return {
|
|
"persona_id": persona_id,
|
|
"learning_insights": learning_insights,
|
|
"persona_updates": persona_updates,
|
|
"learning_date": datetime.utcnow().isoformat()
|
|
}
|
|
|
|
except Exception as e:
|
|
logger.error(f"Error learning from performance: {str(e)}")
|
|
return {"error": f"Failed to learn from performance: {str(e)}"}
|
|
|
|
def _perform_quality_assessment(self, persona: EnhancedWritingPersona, user_feedback: Optional[Dict[str, Any]]) -> Dict[str, Any]:
|
|
"""Perform comprehensive quality assessment of a persona."""
|
|
|
|
# Linguistic analysis quality
|
|
linguistic_quality = self._assess_linguistic_quality(persona)
|
|
|
|
# Consistency assessment
|
|
consistency_score = self._assess_consistency(persona)
|
|
|
|
# Authenticity assessment
|
|
authenticity_score = self._assess_authenticity(persona)
|
|
|
|
# User satisfaction (if feedback provided)
|
|
user_satisfaction = self._assess_user_satisfaction(user_feedback) if user_feedback else None
|
|
|
|
# Platform optimization quality
|
|
platform_quality = self._assess_platform_optimization(persona)
|
|
|
|
# Overall quality score
|
|
quality_scores = [linguistic_quality, consistency_score, authenticity_score, platform_quality]
|
|
if user_satisfaction is not None:
|
|
quality_scores.append(user_satisfaction)
|
|
|
|
overall_quality = sum(quality_scores) / len(quality_scores)
|
|
|
|
return {
|
|
"overall_quality_score": overall_quality,
|
|
"linguistic_quality": linguistic_quality,
|
|
"consistency_score": consistency_score,
|
|
"authenticity_score": authenticity_score,
|
|
"user_satisfaction": user_satisfaction,
|
|
"platform_optimization_quality": platform_quality,
|
|
"quality_breakdown": {
|
|
"linguistic_analysis_completeness": self._assess_analysis_completeness(persona),
|
|
"style_consistency": consistency_score,
|
|
"brand_alignment": authenticity_score,
|
|
"platform_adaptation_quality": platform_quality
|
|
}
|
|
}
|
|
|
|
def _assess_linguistic_quality(self, persona: EnhancedWritingPersona) -> float:
|
|
"""Assess the quality of linguistic analysis."""
|
|
linguistic_fingerprint = persona.linguistic_fingerprint or {}
|
|
|
|
# Check completeness of linguistic analysis
|
|
required_fields = [
|
|
'sentence_analysis', 'vocabulary_analysis', 'rhetorical_analysis',
|
|
'style_patterns', 'readability_analysis'
|
|
]
|
|
|
|
completeness_score = 0
|
|
for field in required_fields:
|
|
if field in linguistic_fingerprint and linguistic_fingerprint[field]:
|
|
completeness_score += 20
|
|
|
|
# Check quality of analysis
|
|
quality_indicators = 0
|
|
if linguistic_fingerprint.get('sentence_analysis', {}).get('sentence_length_distribution'):
|
|
quality_indicators += 1
|
|
if linguistic_fingerprint.get('vocabulary_analysis', {}).get('lexical_diversity'):
|
|
quality_indicators += 1
|
|
if linguistic_fingerprint.get('rhetorical_analysis', {}).get('questions'):
|
|
quality_indicators += 1
|
|
if linguistic_fingerprint.get('style_patterns', {}).get('formality_level'):
|
|
quality_indicators += 1
|
|
|
|
quality_score = (quality_indicators / 4) * 100
|
|
|
|
return (completeness_score + quality_score) / 2
|
|
|
|
def _assess_consistency(self, persona: EnhancedWritingPersona) -> float:
|
|
"""Assess consistency of the persona."""
|
|
consistency_analysis = persona.linguistic_fingerprint.get('consistency_analysis', {})
|
|
|
|
if not consistency_analysis:
|
|
return 50.0 # Default score if no consistency data
|
|
|
|
return consistency_analysis.get('consistency_score', 50.0)
|
|
|
|
def _assess_authenticity(self, persona: EnhancedWritingPersona) -> float:
|
|
"""Assess authenticity of the persona."""
|
|
# Check if persona reflects real user characteristics
|
|
source_data = persona.source_website_analysis or {}
|
|
|
|
# Authenticity indicators
|
|
authenticity_indicators = 0
|
|
total_indicators = 5
|
|
|
|
# Check for brand voice alignment
|
|
if persona.brand_voice_description:
|
|
authenticity_indicators += 1
|
|
|
|
# Check for core belief definition
|
|
if persona.core_belief:
|
|
authenticity_indicators += 1
|
|
|
|
# Check for archetype definition
|
|
if persona.archetype:
|
|
authenticity_indicators += 1
|
|
|
|
# Check for source data quality
|
|
if source_data.get('writing_style'):
|
|
authenticity_indicators += 1
|
|
|
|
# Check for confidence score
|
|
if persona.confidence_score and persona.confidence_score > 70:
|
|
authenticity_indicators += 1
|
|
|
|
return (authenticity_indicators / total_indicators) * 100
|
|
|
|
def _assess_user_satisfaction(self, user_feedback: Dict[str, Any]) -> float:
|
|
"""Assess user satisfaction from feedback."""
|
|
if not user_feedback:
|
|
return None
|
|
|
|
# Extract satisfaction metrics
|
|
satisfaction_score = user_feedback.get('satisfaction_score', 0)
|
|
content_quality_rating = user_feedback.get('content_quality_rating', 0)
|
|
style_match_rating = user_feedback.get('style_match_rating', 0)
|
|
|
|
# Calculate weighted average
|
|
if satisfaction_score and content_quality_rating and style_match_rating:
|
|
return (satisfaction_score + content_quality_rating + style_match_rating) / 3
|
|
elif satisfaction_score:
|
|
return satisfaction_score
|
|
else:
|
|
return 50.0 # Default if no clear satisfaction data
|
|
|
|
def _assess_platform_optimization(self, persona) -> float:
|
|
"""Assess platform optimization quality."""
|
|
# Handle both EnhancedWritingPersona objects and dictionaries
|
|
if hasattr(persona, 'platform_personas'):
|
|
platform_personas = persona.platform_personas
|
|
elif isinstance(persona, dict):
|
|
# For dictionary input, use the simpler assessment method
|
|
return float(self._assess_platform_optimization_dict(persona))
|
|
else:
|
|
logger.warning(f"Unexpected persona type: {type(persona)}")
|
|
return 0.0
|
|
|
|
if not platform_personas:
|
|
return 0.0
|
|
|
|
total_score = 0
|
|
platform_count = 0
|
|
|
|
for platform_persona in platform_personas:
|
|
if platform_persona.is_active:
|
|
# Check platform-specific optimization completeness
|
|
platform_score = 0
|
|
|
|
if platform_persona.platform_linguistic_adaptation:
|
|
platform_score += 25
|
|
if platform_persona.platform_engagement_patterns:
|
|
platform_score += 25
|
|
if platform_persona.platform_content_optimization:
|
|
platform_score += 25
|
|
if platform_persona.platform_algorithm_insights:
|
|
platform_score += 25
|
|
|
|
total_score += platform_score
|
|
platform_count += 1
|
|
|
|
return total_score / platform_count if platform_count > 0 else 0.0
|
|
|
|
def _assess_analysis_completeness(self, persona: EnhancedWritingPersona) -> float:
|
|
"""Assess completeness of the persona analysis."""
|
|
completeness_indicators = 0
|
|
total_indicators = 8
|
|
|
|
# Core persona fields
|
|
if persona.persona_name:
|
|
completeness_indicators += 1
|
|
if persona.archetype:
|
|
completeness_indicators += 1
|
|
if persona.core_belief:
|
|
completeness_indicators += 1
|
|
if persona.brand_voice_description:
|
|
completeness_indicators += 1
|
|
|
|
# Linguistic analysis
|
|
if persona.linguistic_fingerprint:
|
|
completeness_indicators += 1
|
|
if persona.writing_style_signature:
|
|
completeness_indicators += 1
|
|
if persona.vocabulary_profile:
|
|
completeness_indicators += 1
|
|
if persona.sentence_patterns:
|
|
completeness_indicators += 1
|
|
|
|
return (completeness_indicators / total_indicators) * 100
|
|
|
|
def _generate_improvement_suggestions(self, quality_metrics: Dict[str, Any]) -> List[Dict[str, Any]]:
|
|
"""Generate improvement suggestions based on quality metrics."""
|
|
suggestions = []
|
|
|
|
overall_score = quality_metrics.get('overall_quality_score', 0)
|
|
|
|
# Linguistic quality improvements
|
|
if quality_metrics.get('linguistic_quality', 0) < 70:
|
|
suggestions.append({
|
|
"category": "linguistic_analysis",
|
|
"priority": "high",
|
|
"suggestion": "Enhance linguistic analysis with more detailed sentence patterns and vocabulary analysis",
|
|
"action": "reanalyze_source_content"
|
|
})
|
|
|
|
# Consistency improvements
|
|
if quality_metrics.get('consistency_score', 0) < 70:
|
|
suggestions.append({
|
|
"category": "consistency",
|
|
"priority": "high",
|
|
"suggestion": "Improve consistency by analyzing more writing samples",
|
|
"action": "collect_additional_samples"
|
|
})
|
|
|
|
# Authenticity improvements
|
|
if quality_metrics.get('authenticity_score', 0) < 70:
|
|
suggestions.append({
|
|
"category": "authenticity",
|
|
"priority": "medium",
|
|
"suggestion": "Strengthen brand voice alignment and core belief definition",
|
|
"action": "refine_brand_analysis"
|
|
})
|
|
|
|
# Platform optimization improvements
|
|
if quality_metrics.get('platform_optimization_quality', 0) < 70:
|
|
suggestions.append({
|
|
"category": "platform_optimization",
|
|
"priority": "medium",
|
|
"suggestion": "Enhance platform-specific adaptations and algorithm insights",
|
|
"action": "update_platform_adaptations"
|
|
})
|
|
|
|
# User satisfaction improvements
|
|
user_satisfaction = quality_metrics.get('user_satisfaction')
|
|
if user_satisfaction is not None and user_satisfaction < 70:
|
|
suggestions.append({
|
|
"category": "user_satisfaction",
|
|
"priority": "high",
|
|
"suggestion": "Address user feedback and adjust persona based on preferences",
|
|
"action": "incorporate_user_feedback"
|
|
})
|
|
|
|
return suggestions
|
|
|
|
def _analyze_feedback(self, feedback_data: Dict[str, Any]) -> Dict[str, Any]:
|
|
"""Analyze user feedback to extract improvement insights."""
|
|
return {
|
|
"satisfaction_level": feedback_data.get('satisfaction_score', 0),
|
|
"content_quality_rating": feedback_data.get('content_quality_rating', 0),
|
|
"style_match_rating": feedback_data.get('style_match_rating', 0),
|
|
"specific_complaints": feedback_data.get('complaints', []),
|
|
"specific_praises": feedback_data.get('praises', []),
|
|
"improvement_requests": feedback_data.get('improvement_requests', []),
|
|
"preferred_adjustments": feedback_data.get('preferred_adjustments', {})
|
|
}
|
|
|
|
def _generate_persona_improvements(self, persona: EnhancedWritingPersona, feedback_analysis: Dict[str, Any]) -> Dict[str, Any]:
|
|
"""Generate specific improvements based on feedback analysis."""
|
|
improvements = {}
|
|
|
|
# Style adjustments based on feedback
|
|
if feedback_analysis.get('style_match_rating', 0) < 70:
|
|
improvements['style_adjustments'] = {
|
|
"tone_adjustment": feedback_analysis.get('preferred_adjustments', {}).get('tone'),
|
|
"formality_adjustment": feedback_analysis.get('preferred_adjustments', {}).get('formality'),
|
|
"vocabulary_adjustment": feedback_analysis.get('preferred_adjustments', {}).get('vocabulary')
|
|
}
|
|
|
|
# Content quality improvements
|
|
if feedback_analysis.get('content_quality_rating', 0) < 70:
|
|
improvements['content_quality'] = {
|
|
"clarity_improvement": True,
|
|
"engagement_enhancement": True,
|
|
"structure_optimization": True
|
|
}
|
|
|
|
# Specific complaint addressing
|
|
complaints = feedback_analysis.get('specific_complaints', [])
|
|
if complaints:
|
|
improvements['complaint_resolutions'] = {
|
|
"addressed_complaints": complaints,
|
|
"resolution_strategies": self._generate_complaint_resolutions(complaints)
|
|
}
|
|
|
|
return improvements
|
|
|
|
def _generate_complaint_resolutions(self, complaints: List[str]) -> List[Dict[str, Any]]:
|
|
"""Generate resolution strategies for specific complaints."""
|
|
resolutions = []
|
|
|
|
for complaint in complaints:
|
|
complaint_lower = complaint.lower()
|
|
|
|
if 'too formal' in complaint_lower:
|
|
resolutions.append({
|
|
"complaint": complaint,
|
|
"resolution": "Reduce formality level and increase conversational tone",
|
|
"action": "adjust_formality_metrics"
|
|
})
|
|
elif 'too casual' in complaint_lower:
|
|
resolutions.append({
|
|
"complaint": complaint,
|
|
"resolution": "Increase formality level and professional tone",
|
|
"action": "adjust_formality_metrics"
|
|
})
|
|
elif 'too long' in complaint_lower:
|
|
resolutions.append({
|
|
"complaint": complaint,
|
|
"resolution": "Reduce average sentence length and improve conciseness",
|
|
"action": "adjust_sentence_length"
|
|
})
|
|
elif 'too short' in complaint_lower:
|
|
resolutions.append({
|
|
"complaint": complaint,
|
|
"resolution": "Increase sentence complexity and add more detail",
|
|
"action": "adjust_sentence_length"
|
|
})
|
|
elif 'boring' in complaint_lower or 'dull' in complaint_lower:
|
|
resolutions.append({
|
|
"complaint": complaint,
|
|
"resolution": "Add more engaging language and rhetorical devices",
|
|
"action": "enhance_engagement_patterns"
|
|
})
|
|
else:
|
|
resolutions.append({
|
|
"complaint": complaint,
|
|
"resolution": "General style adjustment based on feedback",
|
|
"action": "general_style_refinement"
|
|
})
|
|
|
|
return resolutions
|
|
|
|
def _apply_improvements(self, session: Session, persona: EnhancedWritingPersona, improvements: Dict[str, Any]) -> EnhancedWritingPersona:
|
|
"""Apply improvements to the persona."""
|
|
|
|
# Apply style adjustments
|
|
if 'style_adjustments' in improvements:
|
|
self._apply_style_adjustments(persona, improvements['style_adjustments'])
|
|
|
|
# Apply content quality improvements
|
|
if 'content_quality' in improvements:
|
|
self._apply_content_quality_improvements(persona, improvements['content_quality'])
|
|
|
|
# Apply complaint resolutions
|
|
if 'complaint_resolutions' in improvements:
|
|
self._apply_complaint_resolutions(persona, improvements['complaint_resolutions'])
|
|
|
|
# Update persona metadata
|
|
persona.updated_at = datetime.utcnow()
|
|
|
|
session.add(persona)
|
|
return persona
|
|
|
|
def _apply_style_adjustments(self, persona: EnhancedWritingPersona, style_adjustments: Dict[str, Any]):
|
|
"""Apply style adjustments to persona."""
|
|
# Update linguistic fingerprint based on adjustments
|
|
if not persona.linguistic_fingerprint:
|
|
persona.linguistic_fingerprint = {}
|
|
|
|
# Tone adjustment
|
|
if style_adjustments.get('tone_adjustment'):
|
|
persona.linguistic_fingerprint['adjusted_tone'] = style_adjustments['tone_adjustment']
|
|
|
|
# Formality adjustment
|
|
if style_adjustments.get('formality_adjustment'):
|
|
persona.linguistic_fingerprint['adjusted_formality'] = style_adjustments['formality_adjustment']
|
|
|
|
# Vocabulary adjustment
|
|
if style_adjustments.get('vocabulary_adjustment'):
|
|
persona.linguistic_fingerprint['adjusted_vocabulary'] = style_adjustments['vocabulary_adjustment']
|
|
|
|
def _apply_content_quality_improvements(self, persona: EnhancedWritingPersona, quality_improvements: Dict[str, Any]):
|
|
"""Apply content quality improvements to persona."""
|
|
if not persona.linguistic_fingerprint:
|
|
persona.linguistic_fingerprint = {}
|
|
|
|
# Add quality improvement markers
|
|
persona.linguistic_fingerprint['quality_improvements'] = {
|
|
"clarity_enhanced": quality_improvements.get('clarity_improvement', False),
|
|
"engagement_enhanced": quality_improvements.get('engagement_enhancement', False),
|
|
"structure_optimized": quality_improvements.get('structure_optimization', False),
|
|
"improvement_date": datetime.utcnow().isoformat()
|
|
}
|
|
|
|
def _apply_complaint_resolutions(self, persona: EnhancedWritingPersona, complaint_resolutions: Dict[str, Any]):
|
|
"""Apply complaint resolutions to persona."""
|
|
if not persona.linguistic_fingerprint:
|
|
persona.linguistic_fingerprint = {}
|
|
|
|
# Add complaint resolution tracking
|
|
persona.linguistic_fingerprint['complaint_resolutions'] = {
|
|
"addressed_complaints": complaint_resolutions.get('addressed_complaints', []),
|
|
"resolution_strategies": complaint_resolutions.get('resolution_strategies', []),
|
|
"resolution_date": datetime.utcnow().isoformat()
|
|
}
|
|
|
|
def _analyze_performance_patterns(self, content_performance: List[Dict[str, Any]]) -> Dict[str, Any]:
|
|
"""Analyze content performance patterns."""
|
|
if not content_performance:
|
|
return {}
|
|
|
|
# Calculate average performance metrics
|
|
total_content = len(content_performance)
|
|
|
|
avg_engagement = sum(item.get('engagement_rate', 0) for item in content_performance) / total_content
|
|
avg_reach = sum(item.get('reach', 0) for item in content_performance) / total_content
|
|
avg_clicks = sum(item.get('clicks', 0) for item in content_performance) / total_content
|
|
|
|
# Identify top performing content
|
|
top_performers = sorted(content_performance,
|
|
key=lambda x: x.get('engagement_rate', 0),
|
|
reverse=True)[:3]
|
|
|
|
# Analyze content characteristics of top performers
|
|
top_performer_analysis = self._analyze_top_performers(top_performers)
|
|
|
|
return {
|
|
"average_engagement_rate": avg_engagement,
|
|
"average_reach": avg_reach,
|
|
"average_clicks": avg_clicks,
|
|
"total_content_analyzed": total_content,
|
|
"top_performers": top_performer_analysis,
|
|
"performance_trends": self._identify_performance_trends(content_performance)
|
|
}
|
|
|
|
def _analyze_top_performers(self, top_performers: List[Dict[str, Any]]) -> Dict[str, Any]:
|
|
"""Analyze characteristics of top performing content."""
|
|
if not top_performers:
|
|
return {}
|
|
|
|
# Analyze common characteristics
|
|
content_types = [item.get('content_type') for item in top_performers]
|
|
topics = [item.get('topic') for item in top_performers]
|
|
lengths = [item.get('content_length') for item in top_performers]
|
|
|
|
return {
|
|
"common_content_types": list(set(content_types)),
|
|
"common_topics": list(set(topics)),
|
|
"average_length": sum(lengths) / len(lengths) if lengths else 0,
|
|
"performance_characteristics": {
|
|
"high_engagement_keywords": self._extract_high_engagement_keywords(top_performers),
|
|
"optimal_posting_times": self._extract_optimal_posting_times(top_performers),
|
|
"successful_formats": self._extract_successful_formats(top_performers)
|
|
}
|
|
}
|
|
|
|
def _extract_high_engagement_keywords(self, top_performers: List[Dict[str, Any]]) -> List[str]:
|
|
"""Extract keywords that appear in high-performing content."""
|
|
# This would analyze the content text for common keywords
|
|
# For now, return a placeholder
|
|
return ["innovation", "strategy", "growth", "success"]
|
|
|
|
def _extract_optimal_posting_times(self, top_performers: List[Dict[str, Any]]) -> List[str]:
|
|
"""Extract optimal posting times from top performers."""
|
|
posting_times = [item.get('posting_time') for item in top_performers if item.get('posting_time')]
|
|
return list(set(posting_times))
|
|
|
|
def _extract_successful_formats(self, top_performers: List[Dict[str, Any]]) -> List[str]:
|
|
"""Extract successful content formats from top performers."""
|
|
formats = [item.get('format') for item in top_performers if item.get('format')]
|
|
return list(set(formats))
|
|
|
|
def _identify_performance_trends(self, content_performance: List[Dict[str, Any]]) -> Dict[str, Any]:
|
|
"""Identify performance trends over time."""
|
|
# Sort by date if available
|
|
sorted_performance = sorted(content_performance,
|
|
key=lambda x: x.get('date', ''),
|
|
reverse=True)
|
|
|
|
if len(sorted_performance) < 2:
|
|
return {"trend": "insufficient_data"}
|
|
|
|
# Calculate trend
|
|
recent_performance = sorted_performance[:len(sorted_performance)//2]
|
|
older_performance = sorted_performance[len(sorted_performance)//2:]
|
|
|
|
recent_avg = sum(item.get('engagement_rate', 0) for item in recent_performance) / len(recent_performance)
|
|
older_avg = sum(item.get('engagement_rate', 0) for item in older_performance) / len(older_performance)
|
|
|
|
if recent_avg > older_avg * 1.1:
|
|
trend = "improving"
|
|
elif recent_avg < older_avg * 0.9:
|
|
trend = "declining"
|
|
else:
|
|
trend = "stable"
|
|
|
|
return {
|
|
"trend": trend,
|
|
"recent_average": recent_avg,
|
|
"older_average": older_avg,
|
|
"change_percentage": ((recent_avg - older_avg) / older_avg * 100) if older_avg > 0 else 0
|
|
}
|
|
|
|
def _identify_successful_patterns(self, content_performance: List[Dict[str, Any]]) -> Dict[str, Any]:
|
|
"""Identify patterns in successful content."""
|
|
# Filter for high-performing content (top 25%)
|
|
sorted_performance = sorted(content_performance,
|
|
key=lambda x: x.get('engagement_rate', 0),
|
|
reverse=True)
|
|
|
|
top_quarter = sorted_performance[:max(1, len(sorted_performance) // 4)]
|
|
|
|
return {
|
|
"high_performing_content_count": len(top_quarter),
|
|
"common_characteristics": self._analyze_top_performers(top_quarter),
|
|
"success_patterns": {
|
|
"optimal_length_range": self._calculate_optimal_length_range(top_quarter),
|
|
"preferred_content_types": self._get_preferred_content_types(top_quarter),
|
|
"successful_topic_categories": self._get_successful_topic_categories(top_quarter)
|
|
}
|
|
}
|
|
|
|
def _calculate_optimal_length_range(self, top_performers: List[Dict[str, Any]]) -> Dict[str, int]:
|
|
"""Calculate optimal content length range from top performers."""
|
|
lengths = [item.get('content_length', 0) for item in top_performers if item.get('content_length')]
|
|
|
|
if not lengths:
|
|
return {"min": 0, "max": 0, "average": 0}
|
|
|
|
return {
|
|
"min": min(lengths),
|
|
"max": max(lengths),
|
|
"average": sum(lengths) / len(lengths)
|
|
}
|
|
|
|
def _get_preferred_content_types(self, top_performers: List[Dict[str, Any]]) -> List[str]:
|
|
"""Get preferred content types from top performers."""
|
|
content_types = [item.get('content_type') for item in top_performers if item.get('content_type')]
|
|
return list(set(content_types))
|
|
|
|
def _get_successful_topic_categories(self, top_performers: List[Dict[str, Any]]) -> List[str]:
|
|
"""Get successful topic categories from top performers."""
|
|
topics = [item.get('topic_category') for item in top_performers if item.get('topic_category')]
|
|
return list(set(topics))
|
|
|
|
def _generate_learning_insights(self, performance_analysis: Dict[str, Any], successful_patterns: Dict[str, Any]) -> Dict[str, Any]:
|
|
"""Generate learning insights from performance analysis."""
|
|
return {
|
|
"performance_insights": {
|
|
"average_engagement": performance_analysis.get('average_engagement_rate', 0),
|
|
"performance_trend": performance_analysis.get('performance_trends', {}).get('trend', 'unknown'),
|
|
"top_performing_characteristics": performance_analysis.get('top_performers', {})
|
|
},
|
|
"success_patterns": successful_patterns,
|
|
"recommendations": {
|
|
"content_length_optimization": successful_patterns.get('success_patterns', {}).get('optimal_length_range', {}),
|
|
"content_type_preferences": successful_patterns.get('success_patterns', {}).get('preferred_content_types', []),
|
|
"topic_focus_areas": successful_patterns.get('success_patterns', {}).get('successful_topic_categories', [])
|
|
},
|
|
"learning_confidence": self._calculate_learning_confidence(performance_analysis, successful_patterns)
|
|
}
|
|
|
|
def _calculate_learning_confidence(self, performance_analysis: Dict[str, Any], successful_patterns: Dict[str, Any]) -> float:
|
|
"""Calculate confidence in learning insights."""
|
|
# Base confidence on amount of data
|
|
total_content = performance_analysis.get('total_content_analyzed', 0)
|
|
high_performers = successful_patterns.get('high_performing_content_count', 0)
|
|
|
|
# Confidence increases with more data
|
|
data_confidence = min(100, (total_content / 20) * 100) # 20 pieces of content = 100% confidence
|
|
|
|
# Confidence increases with more high performers
|
|
pattern_confidence = min(100, (high_performers / 5) * 100) # 5 high performers = 100% confidence
|
|
|
|
return (data_confidence + pattern_confidence) / 2
|
|
|
|
def _apply_performance_learning(self, persona_id: int, learning_insights: Dict[str, Any]) -> Dict[str, Any]:
|
|
"""Apply performance learning to persona."""
|
|
# This would update the persona based on learning insights
|
|
# For now, return the insights that would be applied
|
|
return {
|
|
"applied_insights": learning_insights,
|
|
"persona_updates": {
|
|
"content_length_preferences": learning_insights.get('recommendations', {}).get('content_length_optimization', {}),
|
|
"preferred_content_types": learning_insights.get('recommendations', {}).get('content_type_preferences', []),
|
|
"successful_topic_areas": learning_insights.get('recommendations', {}).get('topic_focus_areas', []),
|
|
"learning_confidence": learning_insights.get('learning_confidence', 0)
|
|
}
|
|
}
|
|
|
|
def _save_quality_metrics(self, session: Session, persona_id: int, quality_metrics: Dict[str, Any], user_feedback: Optional[Dict[str, Any]]):
|
|
"""Save quality metrics to database."""
|
|
quality_record = PersonaQualityMetrics(
|
|
writing_persona_id=persona_id,
|
|
style_accuracy=quality_metrics.get('linguistic_quality', 0),
|
|
content_quality=quality_metrics.get('overall_quality_score', 0),
|
|
engagement_rate=quality_metrics.get('platform_optimization_quality', 0),
|
|
consistency_score=quality_metrics.get('consistency_score', 0),
|
|
user_satisfaction=quality_metrics.get('user_satisfaction'),
|
|
user_feedback=json.dumps(user_feedback) if user_feedback else None,
|
|
ai_quality_assessment=json.dumps(quality_metrics),
|
|
improvement_suggestions=json.dumps(quality_metrics.get('improvement_suggestions', [])),
|
|
assessor_type="ai_automated"
|
|
)
|
|
|
|
session.add(quality_record)
|
|
|
|
def _save_learning_data(self, session: Session, persona_id: int, feedback_data: Dict[str, Any], improvements: Dict[str, Any]):
|
|
"""Save learning data to database."""
|
|
learning_record = PersonaLearningData(
|
|
writing_persona_id=persona_id,
|
|
user_writing_samples=json.dumps(feedback_data.get('writing_samples', [])),
|
|
successful_content_examples=json.dumps(feedback_data.get('successful_content', [])),
|
|
user_preferences=json.dumps(feedback_data.get('preferences', {})),
|
|
style_refinements=json.dumps(improvements.get('style_adjustments', {})),
|
|
vocabulary_updates=json.dumps(improvements.get('vocabulary_adjustments', {})),
|
|
pattern_adjustments=json.dumps(improvements.get('pattern_adjustments', {})),
|
|
learning_type="feedback"
|
|
)
|
|
|
|
session.add(learning_record)
|
|
|
|
def _save_performance_learning(self, session: Session, persona_id: int, content_performance: List[Dict[str, Any]], learning_insights: Dict[str, Any]):
|
|
"""Save performance learning data to database."""
|
|
learning_record = PersonaLearningData(
|
|
writing_persona_id=persona_id,
|
|
user_writing_samples=json.dumps(content_performance),
|
|
successful_content_examples=json.dumps(learning_insights.get('success_patterns', {})),
|
|
user_preferences=json.dumps(learning_insights.get('recommendations', {})),
|
|
style_refinements=json.dumps(learning_insights.get('persona_updates', {})),
|
|
learning_type="performance"
|
|
)
|
|
|
|
session.add(learning_record)
|