Alwrity version 0.5.4

This commit is contained in:
ajaysi
2025-08-11 10:54:50 +05:30
parent 13ca78f653
commit 39b96c44da
44 changed files with 10448 additions and 2119 deletions

View File

@@ -1,18 +1,38 @@
"""
AI Analysis Module
AI recommendation generation and analysis.
AI-powered analysis and recommendations for content strategy.
"""
from .ai_recommendations import AIRecommendationsService
from .quality_validation import QualityValidationService
from .prompt_engineering import PromptEngineeringService
from .strategic_intelligence_analyzer import StrategicIntelligenceAnalyzer
from .content_distribution_analyzer import ContentDistributionAnalyzer
from .prompt_engineering import PromptEngineeringService
from .strategy_analyzer import (
StrategyAnalyzer,
generate_comprehensive_ai_recommendations,
generate_specialized_recommendations,
create_specialized_prompt,
call_ai_service,
parse_ai_response,
get_fallback_recommendations,
get_latest_ai_analysis,
get_onboarding_integration
)
__all__ = [
'AIRecommendationsService',
'QualityValidationService',
'PromptEngineeringService',
'StrategicIntelligenceAnalyzer',
'ContentDistributionAnalyzer'
'ContentDistributionAnalyzer',
'PromptEngineeringService',
'StrategyAnalyzer',
'generate_comprehensive_ai_recommendations',
'generate_specialized_recommendations',
'create_specialized_prompt',
'call_ai_service',
'parse_ai_response',
'get_fallback_recommendations',
'get_latest_ai_analysis',
'get_onboarding_integration'
]

View File

@@ -0,0 +1,629 @@
"""
Strategy analyzer for AI-powered content strategy recommendations.
Provides comprehensive AI analysis functions for content strategy generation,
including specialized prompts, response parsing, and recommendation processing.
"""
import logging
from typing import Dict, List, Any, Optional
from datetime import datetime
from sqlalchemy.orm import Session
from models.enhanced_strategy_models import EnhancedContentStrategy, EnhancedAIAnalysisResult
logger = logging.getLogger(__name__)
class StrategyAnalyzer:
"""AI-powered strategy analyzer for content strategy recommendations."""
def __init__(self):
self.logger = logging.getLogger(__name__)
# Performance optimization settings
self.prompt_versions = {
'comprehensive_strategy': 'v2.1',
'audience_intelligence': 'v2.0',
'competitive_intelligence': 'v2.0',
'performance_optimization': 'v2.1',
'content_calendar_optimization': 'v2.0'
}
self.quality_thresholds = {
'min_confidence': 0.7,
'min_completeness': 0.8,
'max_response_time': 30.0 # seconds
}
async def generate_comprehensive_ai_recommendations(self, strategy: EnhancedContentStrategy, db: Session) -> None:
"""
Generate comprehensive AI recommendations using 5 specialized prompts.
Args:
strategy: The enhanced content strategy object
db: Database session
"""
try:
self.logger.info(f"Generating comprehensive AI recommendations for strategy: {strategy.id}")
start_time = datetime.utcnow()
# Generate recommendations for each analysis type
analysis_types = [
'comprehensive_strategy',
'audience_intelligence',
'competitive_intelligence',
'performance_optimization',
'content_calendar_optimization'
]
ai_recommendations = {}
successful_analyses = 0
failed_analyses = 0
for analysis_type in analysis_types:
try:
# Generate recommendations without timeout (allow natural processing time)
recommendations = await self.generate_specialized_recommendations(strategy, analysis_type, db)
# Validate recommendations before storing
if recommendations and (recommendations.get('recommendations') or recommendations.get('insights')):
ai_recommendations[analysis_type] = recommendations
successful_analyses += 1
# Store individual analysis result
analysis_result = EnhancedAIAnalysisResult(
user_id=strategy.user_id,
strategy_id=strategy.id,
analysis_type=analysis_type,
comprehensive_insights=recommendations.get('comprehensive_insights'),
audience_intelligence=recommendations.get('audience_intelligence'),
competitive_intelligence=recommendations.get('competitive_intelligence'),
performance_optimization=recommendations.get('performance_optimization'),
content_calendar_optimization=recommendations.get('content_calendar_optimization'),
onboarding_data_used=strategy.onboarding_data_used,
processing_time=(datetime.utcnow() - start_time).total_seconds(),
ai_service_status="operational"
)
db.add(analysis_result)
else:
self.logger.warning(f"Empty or invalid recommendations for {analysis_type}")
failed_analyses += 1
except Exception as e:
self.logger.error(f"Error generating {analysis_type} recommendations: {str(e)}")
failed_analyses += 1
continue
# Only commit if we have at least one successful analysis
if successful_analyses > 0:
db.commit()
# Update strategy with comprehensive AI analysis
strategy.comprehensive_ai_analysis = ai_recommendations
# Import strategy utilities for scoring and analysis
from ..utils.strategy_utils import (
calculate_strategic_scores,
extract_market_positioning,
extract_competitive_advantages,
extract_strategic_risks,
extract_opportunity_analysis
)
strategy.strategic_scores = calculate_strategic_scores(ai_recommendations)
strategy.market_positioning = extract_market_positioning(ai_recommendations)
strategy.competitive_advantages = extract_competitive_advantages(ai_recommendations)
strategy.strategic_risks = extract_strategic_risks(ai_recommendations)
strategy.opportunity_analysis = extract_opportunity_analysis(ai_recommendations)
db.commit()
processing_time = (datetime.utcnow() - start_time).total_seconds()
self.logger.info(f"Comprehensive AI recommendations generated in {processing_time:.2f} seconds - {successful_analyses} successful, {failed_analyses} failed")
else:
self.logger.error("No successful AI analyses generated - strategy creation will continue without AI recommendations")
# Don't raise error, allow strategy creation to continue without AI recommendations
except Exception as e:
self.logger.error(f"Error generating comprehensive AI recommendations: {str(e)}")
# Don't raise error, just log it as this is enhancement, not core functionality
async def generate_specialized_recommendations(self, strategy: EnhancedContentStrategy, analysis_type: str, db: Session) -> Dict[str, Any]:
"""
Generate specialized recommendations using specific AI prompts.
Args:
strategy: The enhanced content strategy object
analysis_type: Type of analysis to perform
db: Database session
Returns:
Dictionary with structured AI recommendations
"""
try:
# Prepare strategy data for AI analysis
strategy_data = strategy.to_dict()
# Get onboarding data for context
onboarding_integration = await self.get_onboarding_integration(strategy.id, db)
# Create prompt based on analysis type
prompt = self.create_specialized_prompt(strategy, analysis_type)
# Generate AI response (placeholder - integrate with actual AI service)
ai_response = await self.call_ai_service(prompt, analysis_type)
# Parse and structure the response
structured_response = self.parse_ai_response(ai_response, analysis_type)
return structured_response
except Exception as e:
self.logger.error(f"Error generating {analysis_type} recommendations: {str(e)}")
raise
def create_specialized_prompt(self, strategy: EnhancedContentStrategy, analysis_type: str) -> str:
"""
Create specialized AI prompts for each analysis type.
Args:
strategy: The enhanced content strategy object
analysis_type: Type of analysis to perform
Returns:
Specialized prompt string for AI analysis
"""
base_context = f"""
Business Context:
- Industry: {strategy.industry}
- Business Objectives: {strategy.business_objectives}
- Target Metrics: {strategy.target_metrics}
- Content Budget: {strategy.content_budget}
- Team Size: {strategy.team_size}
- Implementation Timeline: {strategy.implementation_timeline}
- Market Share: {strategy.market_share}
- Competitive Position: {strategy.competitive_position}
- Performance Metrics: {strategy.performance_metrics}
Audience Intelligence:
- Content Preferences: {strategy.content_preferences}
- Consumption Patterns: {strategy.consumption_patterns}
- Audience Pain Points: {strategy.audience_pain_points}
- Buying Journey: {strategy.buying_journey}
- Seasonal Trends: {strategy.seasonal_trends}
- Engagement Metrics: {strategy.engagement_metrics}
Competitive Intelligence:
- Top Competitors: {strategy.top_competitors}
- Competitor Content Strategies: {strategy.competitor_content_strategies}
- Market Gaps: {strategy.market_gaps}
- Industry Trends: {strategy.industry_trends}
- Emerging Trends: {strategy.emerging_trends}
Content Strategy:
- Preferred Formats: {strategy.preferred_formats}
- Content Mix: {strategy.content_mix}
- Content Frequency: {strategy.content_frequency}
- Optimal Timing: {strategy.optimal_timing}
- Quality Metrics: {strategy.quality_metrics}
- Editorial Guidelines: {strategy.editorial_guidelines}
- Brand Voice: {strategy.brand_voice}
Performance & Analytics:
- Traffic Sources: {strategy.traffic_sources}
- Conversion Rates: {strategy.conversion_rates}
- Content ROI Targets: {strategy.content_roi_targets}
- A/B Testing Capabilities: {strategy.ab_testing_capabilities}
"""
specialized_prompts = {
'comprehensive_strategy': f"""
{base_context}
TASK: Generate a comprehensive content strategy analysis that provides:
1. Strategic positioning and market analysis
2. Audience targeting and persona development
3. Content pillar recommendations with rationale
4. Competitive advantage identification
5. Performance optimization strategies
6. Risk assessment and mitigation plans
7. Implementation roadmap with milestones
8. Success metrics and KPIs
REQUIREMENTS:
- Provide actionable, specific recommendations
- Include data-driven insights
- Consider industry best practices
- Address both short-term and long-term goals
- Provide confidence levels for each recommendation
""",
'audience_intelligence': f"""
{base_context}
TASK: Generate detailed audience intelligence analysis including:
1. Comprehensive audience persona development
2. Content preference analysis and recommendations
3. Consumption pattern insights and optimization
4. Pain point identification and content solutions
5. Buying journey mapping and content alignment
6. Seasonal trend analysis and content planning
7. Engagement pattern analysis and optimization
8. Audience segmentation strategies
REQUIREMENTS:
- Use data-driven insights from provided metrics
- Provide specific content recommendations for each audience segment
- Include engagement optimization strategies
- Consider cultural and behavioral factors
""",
'competitive_intelligence': f"""
{base_context}
TASK: Generate comprehensive competitive intelligence analysis including:
1. Competitor content strategy analysis
2. Market gap identification and opportunities
3. Competitive advantage development strategies
4. Industry trend analysis and implications
5. Emerging trend identification and early adoption strategies
6. Competitive positioning recommendations
7. Market opportunity assessment
8. Competitive response strategies
REQUIREMENTS:
- Analyze provided competitor data thoroughly
- Identify unique market opportunities
- Provide actionable competitive strategies
- Consider both direct and indirect competitors
""",
'performance_optimization': f"""
{base_context}
TASK: Generate performance optimization analysis including:
1. Current performance analysis and benchmarking
2. Traffic source optimization strategies
3. Conversion rate improvement recommendations
4. Content ROI optimization strategies
5. A/B testing framework and recommendations
6. Performance monitoring and analytics setup
7. Optimization roadmap and priorities
8. Success metrics and tracking implementation
REQUIREMENTS:
- Provide specific, measurable optimization strategies
- Include data-driven recommendations
- Consider both technical and content optimizations
- Provide implementation timelines and priorities
""",
'content_calendar_optimization': f"""
{base_context}
TASK: Generate content calendar optimization analysis including:
1. Optimal content frequency and timing analysis
2. Content mix optimization and balance
3. Seasonal content planning and scheduling
4. Content pillar integration and scheduling
5. Platform-specific content adaptation
6. Content repurposing and amplification strategies
7. Editorial calendar optimization
8. Content performance tracking and adjustment
REQUIREMENTS:
- Provide specific scheduling recommendations
- Include content mix optimization strategies
- Consider platform-specific requirements
- Provide seasonal and trend-based planning
"""
}
return specialized_prompts.get(analysis_type, base_context)
async def call_ai_service(self, prompt: str, analysis_type: str) -> Dict[str, Any]:
"""
Call AI service to generate recommendations.
Args:
prompt: The AI prompt to send
analysis_type: Type of analysis being performed
Returns:
Dictionary with AI response
Raises:
RuntimeError: If AI service is not available or fails
"""
try:
# Import AI service manager
from services.ai_service_manager import AIServiceManager, AIServiceType
# Initialize AI service
ai_service = AIServiceManager()
# Map analysis types to AI service types
service_type_mapping = {
'comprehensive_strategy': AIServiceType.STRATEGIC_INTELLIGENCE,
'audience_intelligence': AIServiceType.STRATEGIC_INTELLIGENCE,
'competitive_intelligence': AIServiceType.MARKET_POSITION_ANALYSIS,
'performance_optimization': AIServiceType.PERFORMANCE_PREDICTION,
'content_calendar_optimization': AIServiceType.CONTENT_SCHEDULE_GENERATION
}
# Get the appropriate service type, default to strategic intelligence
service_type = service_type_mapping.get(analysis_type, AIServiceType.STRATEGIC_INTELLIGENCE)
# Define schema for AI response
schema = {
"type": "object",
"properties": {
"recommendations": {
"type": "array",
"items": {
"type": "object",
"properties": {
"title": {"type": "string"},
"description": {"type": "string"},
"priority": {"type": "string"},
"impact": {"type": "string"},
"implementation_difficulty": {"type": "string"}
}
}
},
"insights": {
"type": "array",
"items": {
"type": "object",
"properties": {
"insight": {"type": "string"},
"confidence": {"type": "string"},
"data_support": {"type": "string"}
}
}
},
"metrics": {
"type": "object",
"properties": {
"confidence": {"type": "number"},
"completeness": {"type": "number"},
"actionability": {"type": "number"}
}
}
}
}
# Generate AI response using the service manager
response = await ai_service.execute_structured_json_call(
service_type,
prompt,
schema
)
# Validate that we got actual AI response
if not response:
raise RuntimeError(f"AI service returned null response for {analysis_type}")
# Check for error in response
if response.get("error"):
error_msg = response.get("error", "Unknown error")
if "Failed to parse JSON" in error_msg:
# Try to extract partial data from raw response
raw_response = response.get("raw_response", "")
if raw_response:
self.logger.warning(f"JSON parsing failed for {analysis_type}, attempting to extract partial data")
partial_data = self._extract_partial_data_from_raw(raw_response)
if partial_data:
self.logger.info(f"Successfully extracted partial data for {analysis_type}")
return partial_data
raise RuntimeError(f"AI service error for {analysis_type}: {error_msg}")
# Check if response has data
if not response.get("data"):
# Check if response itself contains the expected structure
if response.get("recommendations") or response.get("insights"):
self.logger.info(f"Using direct response structure for {analysis_type}")
return response
else:
raise RuntimeError(f"AI service returned empty data for {analysis_type}")
# Return the structured response
return response.get("data", {})
except Exception as e:
self.logger.error(f"AI service failed for {analysis_type}: {str(e)}")
raise RuntimeError(f"AI service integration failed for {analysis_type}: {str(e)}")
def _extract_partial_data_from_raw(self, raw_response: str) -> Optional[Dict[str, Any]]:
"""
Extract partial data from raw AI response when JSON parsing fails.
"""
try:
# Look for common patterns in the raw response
import re
# Extract recommendations
recommendations = []
rec_pattern = r'"title"\s*:\s*"([^"]+)"[^}]*"description"\s*:\s*"([^"]*)"'
rec_matches = re.findall(rec_pattern, raw_response)
for title, description in rec_matches:
recommendations.append({
"title": title,
"description": description,
"priority": "medium",
"impact": "moderate",
"implementation_difficulty": "medium"
})
# Extract insights
insights = []
insight_pattern = r'"insight"\s*:\s*"([^"]+)"'
insight_matches = re.findall(insight_pattern, raw_response)
for insight in insight_matches:
insights.append({
"insight": insight,
"confidence": "medium",
"data_support": "industry_analysis"
})
if recommendations or insights:
return {
"recommendations": recommendations,
"insights": insights,
"metrics": {
"confidence": 0.6,
"completeness": 0.5,
"actionability": 0.7
}
}
return None
except Exception as e:
self.logger.debug(f"Error extracting partial data: {e}")
return None
def parse_ai_response(self, ai_response: Dict[str, Any], analysis_type: str) -> Dict[str, Any]:
"""
Parse and structure AI response.
Args:
ai_response: Raw AI response
analysis_type: Type of analysis performed
Returns:
Structured response dictionary
Raises:
RuntimeError: If AI response is invalid or empty
"""
if not ai_response:
raise RuntimeError(f"Empty AI response received for {analysis_type}")
# Validate that we have actual recommendations
recommendations = ai_response.get('recommendations', [])
insights = ai_response.get('insights', [])
if not recommendations and not insights:
raise RuntimeError(f"No recommendations or insights found in AI response for {analysis_type}")
return {
'analysis_type': analysis_type,
'recommendations': recommendations,
'insights': insights,
'metrics': ai_response.get('metrics', {}),
'confidence_score': ai_response.get('metrics', {}).get('confidence', 0.8)
}
def get_fallback_recommendations(self, analysis_type: str) -> Dict[str, Any]:
"""
Get fallback recommendations - DISABLED.
Args:
analysis_type: Type of analysis
Returns:
Never returns - always raises error
Raises:
RuntimeError: Always raised as fallbacks are disabled
"""
raise RuntimeError(f"Fallback recommendations are disabled for {analysis_type}. Real AI insights required.")
async def get_latest_ai_analysis(self, strategy_id: int, db: Session) -> Optional[Dict[str, Any]]:
"""
Get the latest AI analysis for a strategy.
Args:
strategy_id: The strategy ID
db: Database session
Returns:
Latest AI analysis result or None
"""
try:
analysis = db.query(EnhancedAIAnalysisResult).filter(
EnhancedAIAnalysisResult.strategy_id == strategy_id
).order_by(EnhancedAIAnalysisResult.created_at.desc()).first()
return analysis.to_dict() if analysis else None
except Exception as e:
self.logger.error(f"Error getting latest AI analysis: {str(e)}")
return None
async def get_onboarding_integration(self, strategy_id: int, db: Session) -> Optional[Dict[str, Any]]:
"""
Get onboarding data integration for a strategy.
Args:
strategy_id: The strategy ID
db: Database session
Returns:
Onboarding integration data or None
"""
try:
from models.enhanced_strategy_models import OnboardingDataIntegration
integration = db.query(OnboardingDataIntegration).filter(
OnboardingDataIntegration.strategy_id == strategy_id
).first()
return integration.to_dict() if integration else None
except Exception as e:
self.logger.error(f"Error getting onboarding integration: {str(e)}")
return None
# Standalone functions for backward compatibility
async def generate_comprehensive_ai_recommendations(strategy: EnhancedContentStrategy, db: Session) -> None:
"""Generate comprehensive AI recommendations using 5 specialized prompts."""
analyzer = StrategyAnalyzer()
return await analyzer.generate_comprehensive_ai_recommendations(strategy, db)
async def generate_specialized_recommendations(strategy: EnhancedContentStrategy, analysis_type: str, db: Session) -> Dict[str, Any]:
"""Generate specialized recommendations using specific AI prompts."""
analyzer = StrategyAnalyzer()
return await analyzer.generate_specialized_recommendations(strategy, analysis_type, db)
def create_specialized_prompt(strategy: EnhancedContentStrategy, analysis_type: str) -> str:
"""Create specialized AI prompts for each analysis type."""
analyzer = StrategyAnalyzer()
return analyzer.create_specialized_prompt(strategy, analysis_type)
async def call_ai_service(prompt: str, analysis_type: str) -> Dict[str, Any]:
"""Call AI service to generate recommendations."""
analyzer = StrategyAnalyzer()
return await analyzer.call_ai_service(prompt, analysis_type)
def parse_ai_response(ai_response: Dict[str, Any], analysis_type: str) -> Dict[str, Any]:
"""Parse and structure AI response."""
analyzer = StrategyAnalyzer()
return analyzer.parse_ai_response(ai_response, analysis_type)
def get_fallback_recommendations(analysis_type: str) -> Dict[str, Any]:
"""Get fallback recommendations (disabled)."""
analyzer = StrategyAnalyzer()
return analyzer.get_fallback_recommendations(analysis_type)
async def get_latest_ai_analysis(strategy_id: int, db: Session) -> Optional[Dict[str, Any]]:
"""Get the latest AI analysis for a strategy."""
analyzer = StrategyAnalyzer()
return await analyzer.get_latest_ai_analysis(strategy_id, db)
async def get_onboarding_integration(strategy_id: int, db: Session) -> Optional[Dict[str, Any]]:
"""Get onboarding data integration for a strategy."""
analyzer = StrategyAnalyzer()
return await analyzer.get_onboarding_integration(strategy_id, db)

View File

@@ -0,0 +1,8 @@
"""
AI Generation Module
AI-powered content strategy generation with comprehensive insights and recommendations.
"""
from .strategy_generator import AIStrategyGenerator, StrategyGenerationConfig
__all__ = ["AIStrategyGenerator", "StrategyGenerationConfig"]

View File

@@ -0,0 +1,699 @@
"""
AI-Powered Strategy Generation Service
Generates comprehensive content strategies using AI with enhanced insights and recommendations.
"""
import json
import logging
from typing import Any, Dict, List, Optional
from datetime import datetime
from dataclasses import dataclass
from services.ai_service_manager import AIServiceManager, AIServiceType
from ..autofill.ai_structured_autofill import AIStructuredAutofillService
logger = logging.getLogger(__name__)
@dataclass
class StrategyGenerationConfig:
"""Configuration for strategy generation."""
include_competitive_analysis: bool = True
include_content_calendar: bool = True
include_performance_predictions: bool = True
include_implementation_roadmap: bool = True
include_risk_assessment: bool = True
max_content_pieces: int = 50
timeline_months: int = 12
class AIStrategyGenerator:
"""
AI-Powered Content Strategy Generator
Generates comprehensive content strategies including:
- Strategic field autofill (leveraging existing 100% success system)
- Competitive analysis and positioning
- Content calendar and publishing schedule
- Performance predictions and KPIs
- Implementation roadmap
- Risk assessment and mitigation
"""
def __init__(self, config: Optional[StrategyGenerationConfig] = None):
"""Initialize the AI strategy generator."""
self.config = config or StrategyGenerationConfig()
self.ai_manager = AIServiceManager()
self.autofill_service = AIStructuredAutofillService()
self.logger = logger
async def generate_comprehensive_strategy(
self,
user_id: int,
context: Dict[str, Any],
strategy_name: Optional[str] = None
) -> Dict[str, Any]:
"""
Generate a comprehensive content strategy using AI.
Args:
user_id: User ID for personalization
context: User context and onboarding data
strategy_name: Optional custom strategy name
Returns:
Comprehensive strategy with all components
Raises:
RuntimeError: If any AI component fails to generate
"""
try:
self.logger.info(f"🚀 Generating comprehensive AI strategy for user: {user_id}")
# Step 1: Generate base strategy fields (using existing autofill system)
base_strategy = await self._generate_base_strategy_fields(user_id, context)
# Step 2: Generate strategic insights and recommendations
strategic_insights = await self._generate_strategic_insights(base_strategy, context)
# Step 3: Generate competitive analysis
competitive_analysis = await self._generate_competitive_analysis(base_strategy, context)
# Step 4: Generate content calendar
content_calendar = await self._generate_content_calendar(base_strategy, context)
# Step 5: Generate performance predictions
performance_predictions = await self._generate_performance_predictions(base_strategy, context)
# Step 6: Generate implementation roadmap
implementation_roadmap = await self._generate_implementation_roadmap(base_strategy, context)
# Step 7: Generate risk assessment
risk_assessment = await self._generate_risk_assessment(base_strategy, context)
# Step 8: Compile comprehensive strategy
comprehensive_strategy = {
"strategy_metadata": {
"generated_at": datetime.utcnow().isoformat(),
"user_id": user_id,
"strategy_name": strategy_name or f"AI-Generated Strategy {datetime.utcnow().strftime('%Y-%m-%d')}",
"generation_version": "2.0",
"ai_model": "gemini-pro",
"personalization_level": "high",
"ai_generated": True,
"comprehensive": True
},
"base_strategy": base_strategy,
"strategic_insights": strategic_insights,
"competitive_analysis": competitive_analysis,
"content_calendar": content_calendar,
"performance_predictions": performance_predictions,
"implementation_roadmap": implementation_roadmap,
"risk_assessment": risk_assessment,
"summary": {
"total_content_pieces": len(content_calendar.get("content_pieces", [])),
"estimated_roi": performance_predictions.get("estimated_roi", "15-25%"),
"implementation_timeline": implementation_roadmap.get("total_duration", "12 months"),
"risk_level": risk_assessment.get("overall_risk_level", "Medium"),
"success_probability": performance_predictions.get("success_probability", "85%")
}
}
self.logger.info(f"✅ Comprehensive AI strategy generated successfully for user: {user_id}")
return comprehensive_strategy
except Exception as e:
self.logger.error(f"❌ Error generating comprehensive strategy: {str(e)}")
raise RuntimeError(f"Failed to generate comprehensive strategy: {str(e)}")
async def _generate_base_strategy_fields(
self,
user_id: int,
context: Dict[str, Any]
) -> Dict[str, Any]:
"""Generate base strategy fields using existing autofill system."""
try:
self.logger.info(f"Generating base strategy fields for user: {user_id}")
# Use existing autofill service (100% success rate)
autofill_result = await self.autofill_service.generate_autofill_fields(user_id, context)
# Extract the fields from autofill result
base_strategy = autofill_result.get("fields", {})
# Add generation metadata
base_strategy["generation_metadata"] = {
"generated_by": "ai_autofill_system",
"success_rate": autofill_result.get("success_rate", 100),
"personalized": autofill_result.get("personalized", True),
"data_sources": autofill_result.get("data_sources", [])
}
return base_strategy
except Exception as e:
self.logger.error(f"Error generating base strategy fields: {str(e)}")
raise
async def _generate_strategic_insights(self, base_strategy: Dict[str, Any], context: Dict[str, Any], ai_manager: Optional[Any] = None) -> Dict[str, Any]:
"""Generate strategic insights using AI."""
try:
logger.info("🧠 Generating strategic insights...")
# Use provided AI manager or create default one
if ai_manager is None:
from services.ai_service_manager import AIServiceManager
ai_manager = AIServiceManager()
prompt = f"""
Generate comprehensive strategic insights for content strategy based on the following context:
CONTEXT:
{json.dumps(context, indent=2)}
BASE STRATEGY:
{json.dumps(base_strategy, indent=2)}
Please provide strategic insights including:
1. Market positioning analysis
2. Content opportunity identification
3. Competitive advantage mapping
4. Growth potential assessment
5. Strategic recommendations
Format as structured JSON with insights, reasoning, and confidence levels.
"""
schema = {
"type": "object",
"properties": {
"insights": {
"type": "array",
"items": {
"type": "object",
"properties": {
"type": {"type": "string"},
"insight": {"type": "string"},
"reasoning": {"type": "string"},
"priority": {"type": "string"},
"estimated_impact": {"type": "string"},
"implementation_time": {"type": "string"},
"confidence_level": {"type": "string"}
}
}
}
}
}
response = await ai_manager.execute_structured_json_call(
AIServiceType.STRATEGIC_INTELLIGENCE,
prompt,
schema
)
if not response or not response.get("data"):
raise RuntimeError("AI service returned empty strategic insights")
logger.info("✅ Strategic insights generated successfully")
return response.get("data", {})
except Exception as e:
logger.error(f"❌ Error generating strategic insights: {str(e)}")
raise RuntimeError(f"Failed to generate strategic insights: {str(e)}")
async def _generate_competitive_analysis(self, base_strategy: Dict[str, Any], context: Dict[str, Any], ai_manager: Optional[Any] = None) -> Dict[str, Any]:
"""Generate competitive analysis using AI."""
try:
logger.info("🔍 Generating competitive analysis...")
# Use provided AI manager or create default one
if ai_manager is None:
from services.ai_service_manager import AIServiceManager
ai_manager = AIServiceManager()
prompt = f"""
Generate comprehensive competitive analysis for content strategy based on the following context:
CONTEXT:
{json.dumps(context, indent=2)}
BASE STRATEGY:
{json.dumps(base_strategy, indent=2)}
Please provide competitive analysis including:
1. Competitor identification and analysis
2. Market gap identification
3. Differentiation opportunities
4. Competitive positioning
5. Strategic recommendations
Format as structured JSON with detailed analysis and recommendations.
"""
schema = {
"type": "object",
"properties": {
"competitors": {
"type": "array",
"items": {
"type": "object",
"properties": {
"name": {"type": "string"},
"strengths": {"type": "array", "items": {"type": "string"}},
"weaknesses": {"type": "array", "items": {"type": "string"}},
"content_strategy": {"type": "string"},
"market_position": {"type": "string"}
}
}
},
"market_gaps": {"type": "array", "items": {"type": "string"}},
"opportunities": {"type": "array", "items": {"type": "string"}},
"recommendations": {"type": "array", "items": {"type": "string"}}
}
}
response = await ai_manager.execute_structured_json_call(
AIServiceType.MARKET_POSITION_ANALYSIS,
prompt,
schema
)
if not response or not response.get("data"):
raise RuntimeError("AI service returned empty competitive analysis")
logger.info("✅ Competitive analysis generated successfully")
return response.get("data", {})
except Exception as e:
logger.error(f"❌ Error generating competitive analysis: {str(e)}")
raise RuntimeError(f"Failed to generate competitive analysis: {str(e)}")
async def _generate_content_calendar(self, base_strategy: Dict[str, Any], context: Dict[str, Any], ai_manager: Optional[Any] = None) -> Dict[str, Any]:
"""Generate content calendar using AI."""
try:
logger.info("📅 Generating content calendar...")
# Use provided AI manager or create default one
if ai_manager is None:
from services.ai_service_manager import AIServiceManager
ai_manager = AIServiceManager()
prompt = f"""
Generate comprehensive content calendar for content strategy based on the following context:
CONTEXT:
{json.dumps(context, indent=2)}
BASE STRATEGY:
{json.dumps(base_strategy, indent=2)}
Please provide content calendar including:
1. Content pieces with titles and descriptions
2. Publishing schedule and timing
3. Content types and formats
4. Platform distribution strategy
5. Content themes and pillars
Format as structured JSON with detailed content schedule.
"""
schema = {
"type": "object",
"properties": {
"content_pieces": {
"type": "array",
"items": {
"type": "object",
"properties": {
"title": {"type": "string"},
"description": {"type": "string"},
"content_type": {"type": "string"},
"platform": {"type": "string"},
"publishing_date": {"type": "string"},
"theme": {"type": "string"},
"priority": {"type": "string"}
}
}
},
"themes": {"type": "array", "items": {"type": "string"}},
"schedule": {"type": "object"},
"distribution_strategy": {"type": "object"}
}
}
response = await ai_manager.execute_structured_json_call(
AIServiceType.CONTENT_SCHEDULE_GENERATION,
prompt,
schema
)
if not response or not response.get("data"):
raise RuntimeError("AI service returned empty content calendar")
logger.info("✅ Content calendar generated successfully")
return response.get("data", {})
except Exception as e:
logger.error(f"❌ Error generating content calendar: {str(e)}")
raise RuntimeError(f"Failed to generate content calendar: {str(e)}")
async def _generate_performance_predictions(self, base_strategy: Dict[str, Any], context: Dict[str, Any], ai_manager: Optional[Any] = None) -> Dict[str, Any]:
"""Generate performance predictions using AI."""
try:
logger.info("📊 Generating performance predictions...")
# Use provided AI manager or create default one
if ai_manager is None:
from services.ai_service_manager import AIServiceManager
ai_manager = AIServiceManager()
prompt = f"""
Generate comprehensive performance predictions for content strategy based on the following context:
CONTEXT:
{json.dumps(context, indent=2)}
BASE STRATEGY:
{json.dumps(base_strategy, indent=2)}
Please provide performance predictions including:
1. Traffic growth projections
2. Engagement rate predictions
3. Conversion rate estimates
4. ROI projections
5. Success probability assessment
Format as structured JSON with detailed predictions and confidence levels.
"""
schema = {
"type": "object",
"properties": {
"traffic_predictions": {
"type": "object",
"properties": {
"monthly_traffic": {"type": "string"},
"growth_rate": {"type": "string"},
"peak_traffic": {"type": "string"}
}
},
"engagement_predictions": {
"type": "object",
"properties": {
"engagement_rate": {"type": "string"},
"time_on_page": {"type": "string"},
"bounce_rate": {"type": "string"}
}
},
"conversion_predictions": {
"type": "object",
"properties": {
"conversion_rate": {"type": "string"},
"lead_generation": {"type": "string"},
"sales_impact": {"type": "string"}
}
},
"roi_predictions": {
"type": "object",
"properties": {
"estimated_roi": {"type": "string"},
"cost_benefit": {"type": "string"},
"payback_period": {"type": "string"}
}
}
}
}
response = await ai_manager.execute_structured_json_call(
AIServiceType.PERFORMANCE_PREDICTION,
prompt,
schema
)
if not response or not response.get("data"):
raise RuntimeError("AI service returned empty performance predictions")
logger.info("✅ Performance predictions generated successfully")
return response.get("data", {})
except Exception as e:
logger.error(f"❌ Error generating performance predictions: {str(e)}")
raise RuntimeError(f"Failed to generate performance predictions: {str(e)}")
async def _generate_implementation_roadmap(self, base_strategy: Dict[str, Any], context: Dict[str, Any], ai_manager: Optional[Any] = None) -> Dict[str, Any]:
"""Generate implementation roadmap using AI."""
try:
logger.info("🗺️ Generating implementation roadmap...")
# Use provided AI manager or create default one
if ai_manager is None:
from services.ai_service_manager import AIServiceManager
ai_manager = AIServiceManager()
prompt = f"""
Generate comprehensive implementation roadmap for content strategy based on the following context:
CONTEXT:
{json.dumps(context, indent=2)}
BASE STRATEGY:
{json.dumps(base_strategy, indent=2)}
Please provide implementation roadmap including:
1. Phase-by-phase breakdown
2. Timeline with milestones
3. Resource allocation
4. Success metrics
5. Risk mitigation strategies
Format as structured JSON with detailed implementation plan.
"""
schema = {
"type": "object",
"properties": {
"phases": {
"type": "array",
"items": {
"type": "object",
"properties": {
"phase": {"type": "string"},
"duration": {"type": "string"},
"tasks": {"type": "array", "items": {"type": "string"}},
"milestones": {"type": "array", "items": {"type": "string"}},
"resources": {"type": "array", "items": {"type": "string"}}
}
}
},
"timeline": {"type": "object"},
"resource_allocation": {"type": "object"},
"success_metrics": {"type": "array", "items": {"type": "string"}},
"total_duration": {"type": "string"}
}
}
response = await ai_manager.execute_structured_json_call(
AIServiceType.STRATEGIC_INTELLIGENCE,
prompt,
schema
)
if not response or not response.get("data"):
raise RuntimeError("AI service returned empty implementation roadmap")
logger.info("✅ Implementation roadmap generated successfully")
return response.get("data", {})
except Exception as e:
logger.error(f"❌ Error generating implementation roadmap: {str(e)}")
raise RuntimeError(f"Failed to generate implementation roadmap: {str(e)}")
async def _generate_risk_assessment(self, base_strategy: Dict[str, Any], context: Dict[str, Any], ai_manager: Optional[Any] = None) -> Dict[str, Any]:
"""Generate risk assessment using AI."""
try:
logger.info("⚠️ Generating risk assessment...")
# Use provided AI manager or create default one
if ai_manager is None:
from services.ai_service_manager import AIServiceManager
ai_manager = AIServiceManager()
prompt = f"""
Generate comprehensive risk assessment for content strategy based on the following context:
CONTEXT:
{json.dumps(context, indent=2)}
BASE STRATEGY:
{json.dumps(base_strategy, indent=2)}
Please provide risk assessment including:
1. Risk identification and analysis
2. Probability and impact assessment
3. Mitigation strategies
4. Contingency planning
5. Risk monitoring framework
Format as structured JSON with detailed risk analysis and mitigation plans.
"""
schema = {
"type": "object",
"properties": {
"risks": {
"type": "array",
"items": {
"type": "object",
"properties": {
"risk": {"type": "string"},
"probability": {"type": "string"},
"impact": {"type": "string"},
"mitigation": {"type": "string"},
"contingency": {"type": "string"}
}
}
},
"overall_risk_level": {"type": "string"},
"risk_categories": {"type": "object"},
"mitigation_strategies": {"type": "array", "items": {"type": "string"}},
"monitoring_framework": {"type": "object"}
}
}
response = await ai_manager.execute_structured_json_call(
AIServiceType.STRATEGIC_INTELLIGENCE,
prompt,
schema
)
if not response or not response.get("data"):
raise RuntimeError("AI service returned empty risk assessment")
logger.info("✅ Risk assessment generated successfully")
return response.get("data", {})
except Exception as e:
logger.error(f"❌ Error generating risk assessment: {str(e)}")
raise RuntimeError(f"Failed to generate risk assessment: {str(e)}")
def _build_strategic_insights_prompt(self, base_strategy: Dict[str, Any], context: Dict[str, Any]) -> str:
"""Build prompt for strategic insights generation."""
return f"""
As an expert content strategy consultant with 15+ years of experience, analyze this content strategy and provide strategic insights:
STRATEGY CONTEXT:
{json.dumps(base_strategy, indent=2)}
USER CONTEXT:
{json.dumps(context, indent=2)}
Provide comprehensive strategic insights covering:
1. Key insights about the strategy's strengths and opportunities
2. Strategic recommendations with priority levels
3. Identified opportunity areas for growth
4. Competitive advantages to leverage
Focus on actionable, data-driven insights that will drive content strategy success.
"""
def _build_competitive_analysis_prompt(self, base_strategy: Dict[str, Any], context: Dict[str, Any]) -> str:
"""Build prompt for competitive analysis generation."""
return f"""
As a competitive intelligence expert, analyze the competitive landscape for this content strategy:
STRATEGY CONTEXT:
{json.dumps(base_strategy, indent=2)}
USER CONTEXT:
{json.dumps(context, indent=2)}
Provide comprehensive competitive analysis covering:
1. Competitive landscape analysis with key players
2. Positioning strategy and differentiation factors
3. Market gaps and opportunities
4. Competitive advantages and unique value propositions
Focus on actionable competitive intelligence that will inform strategic positioning.
"""
def _build_content_calendar_prompt(self, base_strategy: Dict[str, Any], context: Dict[str, Any]) -> str:
"""Build prompt for content calendar generation."""
return f"""
As a content strategy expert, create a comprehensive content calendar for this strategy:
STRATEGY CONTEXT:
{json.dumps(base_strategy, indent=2)}
USER CONTEXT:
{json.dumps(context, indent=2)}
Generate a {self.config.max_content_pieces}-piece content calendar covering {self.config.timeline_months} months including:
1. Diverse content pieces (blog posts, social media, videos, etc.)
2. Publishing schedule with optimal timing
3. Content mix distribution
4. Topic clusters and content pillars
5. Target audience alignment
Ensure content aligns with business objectives and audience preferences.
"""
def _build_performance_predictions_prompt(self, base_strategy: Dict[str, Any], context: Dict[str, Any]) -> str:
"""Build prompt for performance predictions generation."""
return f"""
As a data-driven content strategist, predict performance outcomes for this content strategy:
STRATEGY CONTEXT:
{json.dumps(base_strategy, indent=2)}
USER CONTEXT:
{json.dumps(context, indent=2)}
Provide realistic performance predictions covering:
1. Traffic growth projections (3, 6, 12 months)
2. Engagement metrics predictions
3. Conversion and lead generation forecasts
4. ROI estimates and success probability
5. Key performance indicators with targets
Base predictions on industry benchmarks and strategy characteristics.
"""
def _build_implementation_roadmap_prompt(self, base_strategy: Dict[str, Any], context: Dict[str, Any]) -> str:
"""Build prompt for implementation roadmap generation."""
return f"""
As a project management expert, create an implementation roadmap for this content strategy:
STRATEGY CONTEXT:
{json.dumps(base_strategy, indent=2)}
USER CONTEXT:
{json.dumps(context, indent=2)}
Create a detailed implementation roadmap covering:
1. Phased implementation approach
2. Resource requirements and budget allocation
3. Timeline with milestones and deliverables
4. Critical path and dependencies
5. Success metrics and evaluation criteria
Ensure roadmap is realistic and achievable given available resources.
"""
def _build_risk_assessment_prompt(self, base_strategy: Dict[str, Any], context: Dict[str, Any]) -> str:
"""Build prompt for risk assessment generation."""
return f"""
As a risk management expert, assess potential risks for this content strategy:
STRATEGY CONTEXT:
{json.dumps(base_strategy, indent=2)}
USER CONTEXT:
{json.dumps(context, indent=2)}
Provide comprehensive risk assessment covering:
1. Identified risks with probability and impact
2. Risk categorization (market, operational, competitive, resource)
3. Mitigation strategies for each risk
4. Contingency plans for high-impact scenarios
5. Overall risk level assessment
Focus on practical risk mitigation strategies.
"""

View File

@@ -1,7 +1,8 @@
import json
import logging
import traceback
from typing import Any, Dict
from typing import Any, Dict, List
from datetime import datetime
from services.ai_service_manager import AIServiceManager, AIServiceType
@@ -60,44 +61,104 @@ class AIStructuredAutofillService:
research = context.get('research_preferences') or {}
api_keys = context.get('api_keys_data') or {}
session = context.get('onboarding_session') or {}
# Extract detailed personalization data
writing_style = website.get('writing_style', {})
target_audience = website.get('target_audience', {})
content_type = website.get('content_type', {})
recommended_settings = website.get('recommended_settings', {})
content_characteristics = website.get('content_characteristics', {})
summary = {
'website_summary': {
'user_profile': {
'website_url': website.get('website_url'),
'industry': website.get('industry'),
'content_types': website.get('content_types'),
'target_audience': website.get('target_audience'),
'performance_metrics': website.get('performance_metrics'),
'seo_summary': website.get('seo_analysis')
},
'research_summary': {
'audience_segments': research.get('audience_segments'),
'content_preferences': research.get('content_preferences'),
'consumption_patterns': research.get('consumption_patterns'),
'seasonality': research.get('seasonal_trends')
},
'api_summary': {
'providers': api_keys.get('providers'),
'total_keys': api_keys.get('total_keys')
},
'session_summary': {
'business_size': session.get('business_size'),
'region': session.get('region')
'region': session.get('region'),
'onboarding_progress': session.get('progress', 0)
},
'content_analysis': {
'writing_style': {
'tone': writing_style.get('tone'),
'voice': writing_style.get('voice'),
'complexity': writing_style.get('complexity'),
'engagement_level': writing_style.get('engagement_level')
},
'content_characteristics': {
'sentence_structure': content_characteristics.get('sentence_structure'),
'vocabulary': content_characteristics.get('vocabulary'),
'paragraph_organization': content_characteristics.get('paragraph_organization')
},
'content_type': {
'primary_type': content_type.get('primary_type'),
'secondary_types': content_type.get('secondary_types'),
'purpose': content_type.get('purpose')
}
},
'audience_insights': {
'demographics': target_audience.get('demographics'),
'expertise_level': target_audience.get('expertise_level'),
'industry_focus': target_audience.get('industry_focus'),
'pain_points': target_audience.get('pain_points'),
'content_preferences': target_audience.get('content_preferences')
},
'ai_recommendations': {
'recommended_tone': recommended_settings.get('writing_tone'),
'recommended_audience': recommended_settings.get('target_audience'),
'recommended_content_type': recommended_settings.get('content_type'),
'style_guidelines': website.get('style_guidelines')
},
'research_config': {
'research_depth': research.get('research_depth'),
'content_types': research.get('content_types'),
'auto_research': research.get('auto_research'),
'factual_content': research.get('factual_content')
},
'api_capabilities': {
'providers': api_keys.get('providers', []),
'total_keys': api_keys.get('total_keys', 0),
'available_services': self._extract_available_services(api_keys)
},
'data_quality': {
'website_freshness': website.get('data_freshness'),
'confidence_level': website.get('confidence_level'),
'analysis_status': website.get('status')
}
}
try:
logger.debug(
"AI Structured Autofill: context presence | website=%s research=%s api=%s session=%s",
"AI Structured Autofill: personalized context | website=%s research=%s api=%s session=%s",
bool(website), bool(research), bool(api_keys), bool(session)
)
logger.debug(
"AI Structured Autofill: website keys=%s research keys=%s",
len(list(website.keys())) if hasattr(website, 'keys') else 0,
len(list(research.keys())) if hasattr(research, 'keys') else 0,
"AI Structured Autofill: personalization data | writing_style=%s target_audience=%s content_type=%s",
bool(writing_style), bool(target_audience), bool(content_type)
)
except Exception:
pass
return summary
def _extract_available_services(self, api_keys: Dict[str, Any]) -> List[str]:
"""Extract available services from API keys."""
services = []
providers = api_keys.get('providers', [])
# Map providers to services
provider_service_map = {
'google_search_console': ['SEO Analytics', 'Search Performance'],
'google_analytics': ['Web Analytics', 'User Behavior'],
'semrush': ['Competitive Analysis', 'Keyword Research'],
'ahrefs': ['Backlink Analysis', 'SEO Tools'],
'moz': ['SEO Tools', 'Rank Tracking'],
'social_media': ['Social Media Analytics', 'Social Listening']
}
for provider in providers:
if provider in provider_service_map:
services.extend(provider_service_map[provider])
return list(set(services)) # Remove duplicates
def _build_schema(self) -> Dict[str, Any]:
# Simplified schema following Gemini best practices
# Reduce complexity by flattening nested structures and simplifying constraints
@@ -167,47 +228,109 @@ class AIStructuredAutofillService:
return schema
def _build_prompt(self, context_summary: Dict[str, Any]) -> str:
# Ultra-simplified prompt to avoid JSON parsing issues
prompt = (
"Generate a JSON object with exactly 30 fields for content strategy. Use this exact format:\n\n"
'{\n'
'"business_objectives": "Increase traffic and leads",\n'
'"target_metrics": "25% growth, 15% conversion",\n'
'"content_budget": 3000,\n'
'"team_size": 3,\n'
'"implementation_timeline": "6 months",\n'
'"market_share": "15%",\n'
'"competitive_position": "Leader",\n'
'"performance_metrics": "Current metrics data",\n'
'"content_preferences": "Blog posts, videos",\n'
'"consumption_patterns": "Peak hours 9-11 AM",\n'
'"audience_pain_points": "Time constraints, complexity",\n'
'"buying_journey": "Awareness to Decision",\n'
'"seasonal_trends": "Q1 planning, Q2 execution",\n'
'"engagement_metrics": "3.5% engagement rate",\n'
'"top_competitors": "Competitor A, B, C",\n'
'"competitor_content_strategies": "Educational content approach",\n'
'"market_gaps": "AI tools, automation guides",\n'
'"industry_trends": "AI integration, video content",\n'
'"emerging_trends": "Voice search, interactive content",\n'
'"preferred_formats": "Blog posts, videos, infographics",\n'
'"content_mix": "70% educational, 30% promotional",\n'
'"content_frequency": "Weekly",\n'
'"optimal_timing": "Tuesday/Thursday 10 AM",\n'
'"quality_metrics": "SEO score >90, engagement >3%",\n'
'"editorial_guidelines": "Professional tone, actionable insights",\n'
'"brand_voice": "Professional",\n'
'"traffic_sources": "Organic search, social media",\n'
'"conversion_rates": "15% conversion, $200 CPA",\n'
'"content_roi_targets": "15% conversion, 3:1 ROI",\n'
'"ab_testing_capabilities": true\n'
'}\n\n'
f"Business context: {json.dumps(context_summary, indent=2)}\n\n"
"Generate the complete JSON with all 30 fields:"
)
logger.debug("AI Structured Autofill: ultra-simplified prompt (%d chars)", len(prompt))
# Build personalized prompt using actual user data
user_profile = context_summary.get('user_profile', {})
content_analysis = context_summary.get('content_analysis', {})
audience_insights = context_summary.get('audience_insights', {})
ai_recommendations = context_summary.get('ai_recommendations', {})
research_config = context_summary.get('research_config', {})
api_capabilities = context_summary.get('api_capabilities', {})
# Extract specific personalization data
website_url = user_profile.get('website_url', 'your website')
writing_tone = content_analysis.get('writing_style', {}).get('tone', 'professional')
target_demographics = audience_insights.get('demographics', ['professionals'])
industry_focus = audience_insights.get('industry_focus', 'general')
expertise_level = audience_insights.get('expertise_level', 'intermediate')
primary_content_type = content_analysis.get('content_type', {}).get('primary_type', 'blog')
research_depth = research_config.get('research_depth', 'Standard')
available_services = api_capabilities.get('available_services', [])
# Build personalized context description
personalization_context = f"""
PERSONALIZED CONTEXT FOR {website_url.upper()}:
🎯 YOUR BUSINESS PROFILE:
- Website: {website_url}
- Industry Focus: {industry_focus}
- Business Size: {user_profile.get('business_size', 'SME')}
- Region: {user_profile.get('region', 'Global')}
📝 YOUR CONTENT ANALYSIS:
- Current Writing Tone: {writing_tone}
- Primary Content Type: {primary_content_type}
- Target Demographics: {', '.join(target_demographics) if isinstance(target_demographics, list) else target_demographics}
- Audience Expertise Level: {expertise_level}
- Content Purpose: {content_analysis.get('content_type', {}).get('purpose', 'informational')}
🔍 YOUR AUDIENCE INSIGHTS:
- Pain Points: {audience_insights.get('pain_points', 'time constraints, complexity')}
- Content Preferences: {audience_insights.get('content_preferences', 'educational, actionable')}
- Industry Focus: {industry_focus}
🤖 AI RECOMMENDATIONS FOR YOUR SITE:
- Recommended Tone: {ai_recommendations.get('recommended_tone', writing_tone)}
- Recommended Content Type: {ai_recommendations.get('recommended_content_type', primary_content_type)}
- Style Guidelines: {ai_recommendations.get('style_guidelines', 'professional, engaging')}
⚙️ YOUR RESEARCH CONFIGURATION:
- Research Depth: {research_depth}
- Content Types: {', '.join(research_config.get('content_types', ['blog', 'article'])) if isinstance(research_config.get('content_types'), list) else research_config.get('content_types', 'blog, article')}
- Auto Research: {research_config.get('auto_research', True)}
- Factual Content: {research_config.get('factual_content', True)}
🔧 YOUR AVAILABLE TOOLS:
- Analytics Services: {', '.join(available_services) if available_services else 'Basic analytics'}
- API Providers: {', '.join(api_capabilities.get('providers', [])) if api_capabilities.get('providers') else 'Manual tracking'}
"""
# Personalized prompt with specific instructions
prompt = f"""
You are a content strategy expert analyzing {website_url}. Based on the detailed analysis of this website and user's onboarding data, generate a personalized content strategy with exactly 30 fields.
{personalization_context}
IMPORTANT: Make each field specific to {website_url} and the user's actual data. Avoid generic placeholder values. Use the real insights from their website analysis.
Generate a JSON object with exactly 30 fields using this exact format:
{{
"business_objectives": "Specific goals for {website_url} based on {industry_focus} industry",
"target_metrics": "Realistic KPIs for {user_profile.get('business_size', 'SME')} business",
"content_budget": 3000,
"team_size": 3,
"implementation_timeline": "6 months",
"market_share": "15%",
"competitive_position": "Leader",
"performance_metrics": "Current performance data for {website_url}",
"content_preferences": "Content formats preferred by {', '.join(target_demographics) if isinstance(target_demographics, list) else target_demographics} audience",
"consumption_patterns": "When {expertise_level} level audience consumes content",
"audience_pain_points": "Specific challenges for {industry_focus} professionals",
"buying_journey": "Customer journey for {industry_focus} industry",
"seasonal_trends": "Seasonal patterns in {industry_focus}",
"engagement_metrics": "Expected engagement for {writing_tone} tone content",
"top_competitors": "Main competitors in {industry_focus} space",
"competitor_content_strategies": "How competitors approach {primary_content_type} content",
"market_gaps": "Opportunities in {industry_focus} content market",
"industry_trends": "Current trends in {industry_focus} industry",
"emerging_trends": "Upcoming trends for {industry_focus}",
"preferred_formats": "Formats that work for {expertise_level} audience",
"content_mix": "Optimal mix for {primary_content_type} focus",
"content_frequency": "Frequency for {research_depth} research depth",
"optimal_timing": "Best times for {target_demographics[0] if isinstance(target_demographics, list) and target_demographics else 'your'} audience",
"quality_metrics": "Quality standards for {writing_tone} content",
"editorial_guidelines": "Guidelines matching {writing_tone} tone",
"brand_voice": "{writing_tone.title()}",
"traffic_sources": "Primary sources for {industry_focus} content",
"conversion_rates": "Realistic rates for {user_profile.get('business_size', 'SME')}",
"content_roi_targets": "ROI goals for {industry_focus} content",
"ab_testing_capabilities": true
}}
Generate the complete JSON with all 30 fields personalized for {website_url}:
"""
logger.debug("AI Structured Autofill: personalized prompt (%d chars)", len(prompt))
return prompt
def _normalize_value(self, key: str, value: Any) -> Any:
@@ -459,7 +582,15 @@ class AIStructuredAutofillService:
raw_value = last_result.get(key)
norm_value = self._normalize_value(key, raw_value)
if norm_value is not None and norm_value != "" and norm_value != []:
fields[key] = { 'value': norm_value, 'source': 'ai_refresh', 'confidence': 0.8 }
# Add personalization metadata to each field
personalized_metadata = self._add_personalization_metadata(key, norm_value, context_summary)
fields[key] = {
'value': norm_value,
'source': 'ai_refresh',
'confidence': 0.8,
'personalized': True,
'personalization_data': personalized_metadata
}
sources[key] = 'ai_refresh'
non_null_keys.append(key)
else:
@@ -479,31 +610,93 @@ class AIStructuredAutofillService:
'performance_analytics': ['traffic_sources', 'conversion_rates', 'content_roi_targets', 'ab_testing_capabilities']
}
# Log category-wise success rates
for category, category_fields in field_categories.items():
generated_in_category = [f for f in category_fields if f in non_null_keys]
missing_in_category = [f for f in category_fields if f in missing_fields]
logger.info("📊 %s: %d/%d fields generated (%s missing: %s)",
category.upper(), len(generated_in_category), len(category_fields),
len(missing_in_category), missing_in_category)
generated_count = len([f for f in category_fields if f in non_null_keys])
missing_count = len([f for f in category_fields if f in missing_fields])
logger.info(f"📊 {category.upper()}: {generated_count}/{len(category_fields)} fields generated ({missing_count} missing: {[f for f in category_fields if f in missing_fields]})")
success_rate = self._calculate_success_rate(last_result)
logger.info(f"AI structured autofill completed | non_null_fields={len(non_null_keys)} missing={len(missing_fields)} success_rate={success_rate:.1f}% attempts={self.max_retries + 1}")
payload = {
return {
'fields': fields,
'sources': sources,
'meta': {
'ai_used': len(non_null_keys) > 0,
'ai_used': True,
'ai_overrides_count': len(non_null_keys),
'ai_override_fields': non_null_keys,
'ai_only': True,
'missing_fields': missing_fields,
'success_rate': success_rate,
'attempts': self.max_retries + 1
'attempts': self.max_retries + 1,
'personalization_level': 'high',
'data_sources_used': list(set(sources.values())),
'website_analyzed': context_summary.get('user_profile', {}).get('website_url'),
'generated_at': datetime.utcnow().isoformat()
}
}
def _add_personalization_metadata(self, field_key: str, value: Any, context_summary: Dict[str, Any]) -> Dict[str, Any]:
"""Add personalization metadata to explain how the value was personalized."""
user_profile = context_summary.get('user_profile', {})
content_analysis = context_summary.get('content_analysis', {})
audience_insights = context_summary.get('audience_insights', {})
ai_recommendations = context_summary.get('ai_recommendations', {})
website_url = user_profile.get('website_url', 'your website')
writing_tone = content_analysis.get('writing_style', {}).get('tone', 'professional')
industry_focus = audience_insights.get('industry_focus', 'general')
expertise_level = audience_insights.get('expertise_level', 'intermediate')
# Create personalized explanation for each field
personalization_explanations = {
'business_objectives': f"Based on {industry_focus} industry analysis and {user_profile.get('business_size', 'SME')} business profile",
'target_metrics': f"Realistic KPIs for {user_profile.get('business_size', 'SME')} business in {industry_focus}",
'content_budget': f"Budget recommendation based on {user_profile.get('business_size', 'SME')} scale and {industry_focus} content needs",
'team_size': f"Team size optimized for {user_profile.get('business_size', 'SME')} business and {content_analysis.get('content_type', {}).get('primary_type', 'blog')} content",
'implementation_timeline': f"Timeline based on {user_profile.get('business_size', 'SME')} resources and {industry_focus} complexity",
'market_share': f"Market position analysis for {industry_focus} industry",
'competitive_position': f"Competitive analysis for {industry_focus} market",
'performance_metrics': f"Current performance data from {website_url} analysis",
'content_preferences': f"Formats preferred by {', '.join(audience_insights.get('demographics', ['professionals']))} audience",
'consumption_patterns': f"Patterns for {expertise_level} level audience in {industry_focus}",
'audience_pain_points': f"Specific challenges for {industry_focus} professionals",
'buying_journey': f"Customer journey mapped for {industry_focus} industry",
'seasonal_trends': f"Seasonal patterns specific to {industry_focus} content",
'engagement_metrics': f"Expected engagement for {writing_tone} tone content",
'top_competitors': f"Main competitors in {industry_focus} space",
'competitor_content_strategies': f"Competitor analysis for {industry_focus} content strategies",
'market_gaps': f"Opportunities identified in {industry_focus} content market",
'industry_trends': f"Current trends in {industry_focus} industry",
'emerging_trends': f"Upcoming trends for {industry_focus} content",
'preferred_formats': f"Formats optimized for {expertise_level} audience",
'content_mix': f"Optimal mix for {content_analysis.get('content_type', {}).get('primary_type', 'blog')} focus",
'content_frequency': f"Frequency based on {context_summary.get('research_config', {}).get('research_depth', 'Standard')} research depth",
'optimal_timing': f"Best times for {audience_insights.get('demographics', ['professionals'])[0] if isinstance(audience_insights.get('demographics'), list) and audience_insights.get('demographics') else 'your'} audience",
'quality_metrics': f"Quality standards for {writing_tone} content",
'editorial_guidelines': f"Guidelines matching {writing_tone} tone from {website_url} analysis",
'brand_voice': f"Voice derived from {writing_tone} tone analysis of {website_url}",
'traffic_sources': f"Primary sources for {industry_focus} content",
'conversion_rates': f"Realistic rates for {user_profile.get('business_size', 'SME')} business",
'content_roi_targets': f"ROI goals for {industry_focus} content",
'ab_testing_capabilities': f"A/B testing availability based on {user_profile.get('business_size', 'SME')} capabilities"
}
return {
'explanation': personalization_explanations.get(field_key, f"Personalized for {website_url}"),
'data_sources': {
'website_analysis': bool(context_summary.get('content_analysis')),
'audience_insights': bool(context_summary.get('audience_insights')),
'ai_recommendations': bool(context_summary.get('ai_recommendations')),
'research_config': bool(context_summary.get('research_config'))
},
'personalization_factors': {
'website_url': website_url,
'industry_focus': industry_focus,
'writing_tone': writing_tone,
'expertise_level': expertise_level,
'business_size': user_profile.get('business_size', 'SME')
}
}
logger.info("AI structured autofill completed | non_null_fields=%d missing=%d success_rate=%.1f%% attempts=%d",
len(non_null_keys), len(missing_fields), success_rate, self.max_retries + 1)
return payload
def _extract_fields_from_raw_response(self, result: Dict[str, Any]) -> Dict[str, Any]:
"""Extract fields from malformed JSON response using regex patterns."""

View File

@@ -1,10 +1,14 @@
"""
Core Content Strategy Services
Main orchestration and core functionality.
Core Module
Core strategy service and essential components.
"""
from .strategy_service import EnhancedStrategyService
from .field_mappings import STRATEGIC_INPUT_FIELDS
from .constants import SERVICE_CONSTANTS
__all__ = ['EnhancedStrategyService', 'STRATEGIC_INPUT_FIELDS', 'SERVICE_CONSTANTS']
__all__ = [
'EnhancedStrategyService',
'STRATEGIC_INPUT_FIELDS',
'SERVICE_CONSTANTS'
]

View File

@@ -9,12 +9,14 @@ from datetime import datetime
from sqlalchemy.orm import Session
# Import database models
from models.enhanced_strategy_models import EnhancedContentStrategy, EnhancedAIAnalysisResult
from models.enhanced_strategy_models import EnhancedContentStrategy, EnhancedAIAnalysisResult, OnboardingDataIntegration
from models.onboarding import OnboardingSession, WebsiteAnalysis, ResearchPreferences, APIKey
# Import modular services
from ..ai_analysis.ai_recommendations import AIRecommendationsService
from ..ai_analysis.prompt_engineering import PromptEngineeringService
from ..ai_analysis.quality_validation import QualityValidationService
from ..ai_analysis.strategy_analyzer import StrategyAnalyzer
# Import onboarding services
from ..onboarding.data_integration import OnboardingDataIntegrationService
@@ -29,6 +31,13 @@ from ..performance.health_monitoring import HealthMonitoringService
# Import utils services
from ..utils.data_processors import DataProcessorService
from ..utils.validators import ValidationService
from ..utils.strategy_utils import (
extract_content_preferences_from_style,
extract_brand_voice_from_guidelines,
extract_editorial_guidelines_from_style,
create_field_mappings,
calculate_data_quality_scores
)
# Import core components
from .field_mappings import STRATEGIC_INPUT_FIELDS
@@ -39,11 +48,15 @@ logger = logging.getLogger(__name__)
class EnhancedStrategyService:
"""Enhanced content strategy service with modular architecture."""
def __init__(self):
def __init__(self, db_service: Optional[Any] = None):
# Store db_service for compatibility
self.db_service = db_service
# Initialize AI analysis services
self.ai_recommendations_service = AIRecommendationsService()
self.prompt_engineering_service = PromptEngineeringService()
self.quality_validation_service = QualityValidationService()
self.strategy_analyzer = StrategyAnalyzer()
# Initialize onboarding services
self.onboarding_data_service = OnboardingDataIntegrationService()
@@ -59,8 +72,292 @@ class EnhancedStrategyService:
self.data_processor_service = DataProcessorService()
self.validation_service = ValidationService()
async def create_enhanced_strategy(self, strategy_data: Dict[str, Any], user_id: int, db: Session) -> EnhancedContentStrategy:
"""Create enhanced content strategy with all integrations."""
async def create_enhanced_strategy(self, strategy_data: Dict[str, Any], db: Session) -> Dict[str, Any]:
"""Create a new enhanced content strategy with 30+ strategic inputs."""
try:
logger.info(f"Creating enhanced content strategy: {strategy_data.get('name', 'Unknown')}")
# Extract user_id from strategy_data
user_id = strategy_data.get('user_id')
if not user_id:
raise ValueError("user_id is required for creating enhanced strategy")
# Create the enhanced strategy
enhanced_strategy = EnhancedContentStrategy(
user_id=user_id,
name=strategy_data.get('name', 'Enhanced Content Strategy'),
industry=strategy_data.get('industry'),
# Business Context
business_objectives=strategy_data.get('business_objectives'),
target_metrics=strategy_data.get('target_metrics'),
content_budget=strategy_data.get('content_budget'),
team_size=strategy_data.get('team_size'),
implementation_timeline=strategy_data.get('implementation_timeline'),
market_share=strategy_data.get('market_share'),
competitive_position=strategy_data.get('competitive_position'),
performance_metrics=strategy_data.get('performance_metrics'),
# Audience Intelligence
content_preferences=strategy_data.get('content_preferences'),
consumption_patterns=strategy_data.get('consumption_patterns'),
audience_pain_points=strategy_data.get('audience_pain_points'),
buying_journey=strategy_data.get('buying_journey'),
seasonal_trends=strategy_data.get('seasonal_trends'),
engagement_metrics=strategy_data.get('engagement_metrics'),
# Competitive Intelligence
top_competitors=strategy_data.get('top_competitors'),
competitor_content_strategies=strategy_data.get('competitor_content_strategies'),
market_gaps=strategy_data.get('market_gaps'),
industry_trends=strategy_data.get('industry_trends'),
emerging_trends=strategy_data.get('emerging_trends'),
# Content Strategy
preferred_formats=strategy_data.get('preferred_formats'),
content_mix=strategy_data.get('content_mix'),
content_frequency=strategy_data.get('content_frequency'),
optimal_timing=strategy_data.get('optimal_timing'),
quality_metrics=strategy_data.get('quality_metrics'),
editorial_guidelines=strategy_data.get('editorial_guidelines'),
brand_voice=strategy_data.get('brand_voice'),
# Performance & Analytics
traffic_sources=strategy_data.get('traffic_sources'),
conversion_rates=strategy_data.get('conversion_rates'),
content_roi_targets=strategy_data.get('content_roi_targets'),
ab_testing_capabilities=strategy_data.get('ab_testing_capabilities', False),
# Legacy fields
target_audience=strategy_data.get('target_audience'),
content_pillars=strategy_data.get('content_pillars'),
ai_recommendations=strategy_data.get('ai_recommendations')
)
# Calculate completion percentage
enhanced_strategy.calculate_completion_percentage()
# Add to database
db.add(enhanced_strategy)
db.commit()
db.refresh(enhanced_strategy)
# Integrate onboarding data if available
await self._enhance_strategy_with_onboarding_data(enhanced_strategy, user_id, db)
# Generate comprehensive AI recommendations
try:
# Generate AI recommendations without timeout (allow natural processing time)
await self.strategy_analyzer.generate_comprehensive_ai_recommendations(enhanced_strategy, db)
logger.info(f"✅ AI recommendations generated successfully for strategy: {enhanced_strategy.id}")
except Exception as e:
logger.warning(f"⚠️ AI recommendations generation failed for strategy: {enhanced_strategy.id}: {str(e)} - continuing without AI recommendations")
# Continue without AI recommendations
# Cache the strategy
await self.caching_service.cache_strategy(enhanced_strategy.id, enhanced_strategy.to_dict())
logger.info(f"✅ Enhanced strategy created successfully: {enhanced_strategy.id}")
return {
"status": "success",
"message": "Enhanced content strategy created successfully",
"strategy": enhanced_strategy.to_dict(),
"strategy_id": enhanced_strategy.id,
"completion_percentage": enhanced_strategy.completion_percentage
}
except Exception as e:
logger.error(f"❌ Error creating enhanced strategy: {str(e)}")
db.rollback()
raise
async def get_enhanced_strategies(self, user_id: Optional[int] = None, strategy_id: Optional[int] = None, db: Session = None) -> Dict[str, Any]:
"""Get enhanced content strategies with comprehensive data and AI recommendations."""
try:
logger.info(f"🚀 Starting enhanced strategy analysis for user: {user_id}, strategy: {strategy_id}")
# Use db_service if available, otherwise use direct db
if self.db_service and hasattr(self.db_service, 'db'):
# Use db_service methods
if strategy_id:
strategy = await self.db_service.get_enhanced_strategy(strategy_id)
strategies = [strategy] if strategy else []
else:
strategies = await self.db_service.get_enhanced_strategies(user_id)
else:
# Fallback to direct db access
if not db:
raise ValueError("Database session is required when db_service is not available")
# Build query
query = db.query(EnhancedContentStrategy)
if user_id:
query = query.filter(EnhancedContentStrategy.user_id == user_id)
if strategy_id:
query = query.filter(EnhancedContentStrategy.id == strategy_id)
# Get strategies
strategies = query.all()
if not strategies:
logger.warning("⚠️ No enhanced strategies found")
return {
"status": "not_found",
"message": "No enhanced content strategies found",
"strategies": [],
"total_count": 0,
"user_id": user_id
}
# Process each strategy
enhanced_strategies = []
for strategy in strategies:
# Calculate completion percentage
if hasattr(strategy, 'calculate_completion_percentage'):
strategy.calculate_completion_percentage()
# Get AI analysis results
ai_analysis = await self.strategy_analyzer.get_latest_ai_analysis(strategy.id, db) if db else None
# Get onboarding data integration
onboarding_integration = await self.strategy_analyzer.get_onboarding_integration(strategy.id, db) if db else None
strategy_dict = strategy.to_dict() if hasattr(strategy, 'to_dict') else {
'id': strategy.id,
'name': strategy.name,
'industry': strategy.industry,
'user_id': strategy.user_id,
'created_at': strategy.created_at.isoformat() if strategy.created_at else None,
'updated_at': strategy.updated_at.isoformat() if strategy.updated_at else None
}
strategy_dict.update({
'ai_analysis': ai_analysis,
'onboarding_integration': onboarding_integration,
'completion_percentage': getattr(strategy, 'completion_percentage', 0)
})
enhanced_strategies.append(strategy_dict)
logger.info(f"✅ Retrieved {len(enhanced_strategies)} enhanced strategies")
return {
"status": "success",
"message": "Enhanced content strategies retrieved successfully",
"strategies": enhanced_strategies,
"total_count": len(enhanced_strategies),
"user_id": user_id
}
except Exception as e:
logger.error(f"❌ Error retrieving enhanced strategies: {str(e)}")
raise
async def _enhance_strategy_with_onboarding_data(self, strategy: EnhancedContentStrategy, user_id: int, db: Session) -> None:
"""Enhance strategy with intelligent auto-population from onboarding data."""
try:
logger.info(f"Enhancing strategy with onboarding data for user: {user_id}")
# Get onboarding session
onboarding_session = db.query(OnboardingSession).filter(
OnboardingSession.user_id == user_id
).first()
if not onboarding_session:
logger.info("No onboarding session found for user")
return
# Get website analysis data
website_analysis = db.query(WebsiteAnalysis).filter(
WebsiteAnalysis.session_id == onboarding_session.id
).first()
# Get research preferences data
research_preferences = db.query(ResearchPreferences).filter(
ResearchPreferences.session_id == onboarding_session.id
).first()
# Get API keys data
api_keys = db.query(APIKey).filter(
APIKey.session_id == onboarding_session.id
).all()
# Auto-populate fields from onboarding data
auto_populated_fields = {}
data_sources = {}
if website_analysis:
# Extract content preferences from writing style
if website_analysis.writing_style:
strategy.content_preferences = extract_content_preferences_from_style(
website_analysis.writing_style
)
auto_populated_fields['content_preferences'] = 'website_analysis'
# Extract target audience from analysis
if website_analysis.target_audience:
strategy.target_audience = website_analysis.target_audience
auto_populated_fields['target_audience'] = 'website_analysis'
# Extract brand voice from style guidelines
if website_analysis.style_guidelines:
strategy.brand_voice = extract_brand_voice_from_guidelines(
website_analysis.style_guidelines
)
auto_populated_fields['brand_voice'] = 'website_analysis'
data_sources['website_analysis'] = website_analysis.to_dict()
if research_preferences:
# Extract content types from research preferences
if research_preferences.content_types:
strategy.preferred_formats = research_preferences.content_types
auto_populated_fields['preferred_formats'] = 'research_preferences'
# Extract writing style from preferences
if research_preferences.writing_style:
strategy.editorial_guidelines = extract_editorial_guidelines_from_style(
research_preferences.writing_style
)
auto_populated_fields['editorial_guidelines'] = 'research_preferences'
data_sources['research_preferences'] = research_preferences.to_dict()
# Create onboarding data integration record
integration = OnboardingDataIntegration(
user_id=user_id,
strategy_id=strategy.id,
website_analysis_data=data_sources.get('website_analysis'),
research_preferences_data=data_sources.get('research_preferences'),
api_keys_data=[key.to_dict() for key in api_keys] if api_keys else None,
auto_populated_fields=auto_populated_fields,
field_mappings=create_field_mappings(),
data_quality_scores=calculate_data_quality_scores(data_sources),
confidence_levels={}, # Will be calculated by data quality service
data_freshness={} # Will be calculated by data quality service
)
db.add(integration)
db.commit()
# Update strategy with onboarding data used
strategy.onboarding_data_used = {
'auto_populated_fields': auto_populated_fields,
'data_sources': list(data_sources.keys()),
'integration_id': integration.id
}
logger.info(f"Strategy enhanced with onboarding data: {len(auto_populated_fields)} fields auto-populated")
except Exception as e:
logger.error(f"Error enhancing strategy with onboarding data: {str(e)}")
# Don't raise error, just log it as this is enhancement, not core functionality
async def create_enhanced_strategy_legacy(self, strategy_data: Dict[str, Any], user_id: int, db: Session) -> EnhancedContentStrategy:
"""Create enhanced content strategy with all integrations (legacy method for compatibility)."""
try:
logger.info(f"Creating enhanced strategy for user: {user_id}")
@@ -98,7 +395,6 @@ class EnhancedStrategyService:
# Cache strategy data
await self.caching_service.cache_strategy(strategy.id, strategy.to_dict())
logger.info(f"Enhanced strategy created successfully: {strategy.id}")
return strategy
except Exception as e:
@@ -107,12 +403,11 @@ class EnhancedStrategyService:
raise
async def get_enhanced_strategy(self, strategy_id: int, db: Session) -> Optional[EnhancedContentStrategy]:
"""Get enhanced strategy with cached data."""
"""Get a single enhanced strategy by ID."""
try:
# Try to get from cache first
# Try cache first
cached_strategy = await self.caching_service.get_cached_strategy(strategy_id)
if cached_strategy:
logger.info(f"Retrieved strategy {strategy_id} from cache")
return cached_strategy
# Get from database
@@ -128,22 +423,20 @@ class EnhancedStrategyService:
except Exception as e:
logger.error(f"Error getting enhanced strategy: {str(e)}")
return None
raise
async def update_enhanced_strategy(self, strategy_id: int, update_data: Dict[str, Any], db: Session) -> Optional[EnhancedContentStrategy]:
"""Update enhanced strategy."""
"""Update an enhanced strategy."""
try:
strategy = db.query(EnhancedContentStrategy).filter(
EnhancedContentStrategy.id == strategy_id
).first()
# Get existing strategy
strategy = await self.get_enhanced_strategy(strategy_id, db)
if not strategy:
return None
# Validate update data
validation_result = self.validation_service.validate_strategy_data(update_data)
if not validation_result['is_valid']:
logger.error(f"Strategy update validation failed: {validation_result['errors']}")
logger.error(f"Update validation failed: {validation_result['errors']}")
raise ValueError(f"Invalid update data: {'; '.join(validation_result['errors'])}")
# Update strategy fields
@@ -153,18 +446,17 @@ class EnhancedStrategyService:
strategy.updated_at = datetime.utcnow()
# Check if AI recommendations should be regenerated
if self._should_regenerate_ai_recommendations(update_data):
await self.strategy_analyzer.generate_comprehensive_ai_recommendations(strategy, db)
# Save to database
db.commit()
db.refresh(strategy)
# Invalidate cache
await self.caching_service.invalidate_cache('strategy_cache', str(strategy_id))
# Update cache
await self.caching_service.cache_strategy(strategy_id, strategy.to_dict())
# Regenerate AI recommendations if needed
if self._should_regenerate_ai_recommendations(update_data):
await self.ai_recommendations_service.generate_comprehensive_recommendations(strategy, db)
logger.info(f"Enhanced strategy updated successfully: {strategy_id}")
return strategy
except Exception as e:
@@ -173,177 +465,105 @@ class EnhancedStrategyService:
raise
async def get_onboarding_data(self, user_id: int, db: Session) -> Dict[str, Any]:
"""Get onboarding data for auto-population."""
"""Get onboarding data for a user."""
try:
# Try to get from cache first
cached_data = await self.caching_service.get_cached_onboarding_data(user_id)
if cached_data:
logger.info(f"Retrieved onboarding data for user {user_id} from cache")
return cached_data
# Process onboarding data
onboarding_data = await self._process_onboarding_data(user_id, db)
# Cache the data
await self.caching_service.cache_onboarding_data(user_id, onboarding_data)
return onboarding_data
return await self.data_processor_service.get_onboarding_data(user_id)
except Exception as e:
logger.error(f"Error getting onboarding data: {str(e)}")
return {}
raise
async def get_ai_analysis(self, strategy_id: int, analysis_type: str, db: Session) -> Optional[Dict[str, Any]]:
"""Get AI analysis results."""
"""Get AI analysis for a strategy."""
try:
# Try to get from cache first
cached_analysis = await self.caching_service.get_cached_ai_analysis(strategy_id, analysis_type)
if cached_analysis:
logger.info(f"Retrieved AI analysis for strategy {strategy_id} from cache")
return cached_analysis
# Get from database
analysis = db.query(EnhancedAIAnalysisResult).filter(
EnhancedAIAnalysisResult.strategy_id == strategy_id,
EnhancedAIAnalysisResult.analysis_type == analysis_type
).order_by(EnhancedAIAnalysisResult.created_at.desc()).first()
if analysis:
analysis_data = analysis.to_dict()
# Cache the analysis
await self.caching_service.cache_ai_analysis(strategy_id, analysis_type, analysis_data)
return analysis_data
return None
return await self.strategy_analyzer.get_latest_ai_analysis(strategy_id, db)
except Exception as e:
logger.error(f"Error getting AI analysis: {str(e)}")
return None
raise
async def get_system_health(self, db: Session) -> Dict[str, Any]:
"""Get system health status."""
try:
return await self.health_monitoring_service.check_system_health(
db,
self.caching_service,
self.ai_recommendations_service
)
return await self.health_monitoring_service.get_system_health(db)
except Exception as e:
logger.error(f"Error getting system health: {str(e)}")
return {
'overall_status': 'error',
'error': str(e),
'timestamp': datetime.utcnow().isoformat()
}
raise
async def get_performance_report(self) -> Dict[str, Any]:
"""Get performance optimization report."""
"""Get performance report."""
try:
return await self.performance_optimization_service.get_performance_report()
except Exception as e:
logger.error(f"Error getting performance report: {str(e)}")
return {
'error': str(e),
'timestamp': datetime.utcnow().isoformat()
}
raise
async def _process_onboarding_data(self, user_id: int, db: Session) -> Dict[str, Any]:
"""Process onboarding data for a user."""
"""Process onboarding data for strategy creation."""
try:
# Get integrated onboarding data
integrated_data = await self.onboarding_data_service.process_onboarding_data(user_id, db)
# Assess data quality
quality_assessment = self.data_quality_service.assess_onboarding_data_quality(integrated_data)
# Add quality assessment to integrated data
integrated_data['quality_assessment'] = quality_assessment
return integrated_data
return await self.data_processor_service.get_onboarding_data(user_id)
except Exception as e:
logger.error(f"Error processing onboarding data: {str(e)}")
return {}
raise
def _merge_strategy_with_onboarding(self, strategy_data: Dict[str, Any], field_transformations: Dict[str, Any]) -> Dict[str, Any]:
"""Merge strategy data with onboarding field transformations."""
try:
"""Merge strategy data with onboarding data."""
merged_data = strategy_data.copy()
# Add auto-populated fields from onboarding data
if 'fields' in field_transformations:
for field_name, field_value in field_transformations['fields'].items():
if field_name not in merged_data or not merged_data[field_name]:
merged_data[field_name] = field_value
# Add data sources information
if 'sources' in field_transformations:
merged_data['data_sources'] = field_transformations['sources']
for field, transformation in field_transformations.items():
if field not in merged_data or merged_data[field] is None:
merged_data[field] = transformation.get('value')
return merged_data
except Exception as e:
logger.error(f"Error merging strategy with onboarding: {str(e)}")
return strategy_data
def _should_regenerate_ai_recommendations(self, update_data: Dict[str, Any]) -> bool:
"""Determine if AI recommendations should be regenerated."""
try:
# Fields that would trigger AI recommendation regeneration
ai_trigger_fields = [
'business_objectives', 'target_metrics', 'content_budget',
'team_size', 'implementation_timeline', 'market_share',
'competitive_position', 'content_preferences', 'audience_pain_points',
'top_competitors', 'industry_trends'
"""Determine if AI recommendations should be regenerated based on updates."""
critical_fields = [
'business_objectives', 'target_metrics', 'industry',
'content_preferences', 'target_audience', 'competitive_position'
]
return any(field in update_data for field in ai_trigger_fields)
except Exception as e:
logger.error(f"Error checking if AI recommendations should be regenerated: {str(e)}")
return False
return any(field in update_data for field in critical_fields)
def get_strategic_input_fields(self) -> List[Dict[str, Any]]:
"""Get strategic input field definitions."""
"""Get strategic input fields configuration."""
return STRATEGIC_INPUT_FIELDS
def get_service_constants(self) -> Dict[str, Any]:
"""Get service configuration constants."""
"""Get service constants."""
return SERVICE_CONSTANTS
async def validate_strategy_data(self, strategy_data: Dict[str, Any]) -> Dict[str, Any]:
"""Validate strategy data using the validation service."""
"""Validate strategy data."""
try:
return self.validation_service.validate_strategy_data(strategy_data)
except Exception as e:
logger.error(f"Error validating strategy data: {str(e)}")
return {
'is_valid': False,
'errors': [f"Validation error: {str(e)}"],
'warnings': [],
'field_validations': {},
'validation_timestamp': datetime.utcnow().isoformat()
}
raise
async def process_data_for_output(self, data: Dict[str, Any], output_format: str = 'json') -> Union[str, Dict[str, Any]]:
"""Process data for different output formats."""
"""Process data for specific output format."""
try:
return self.data_processor_service.format_data_for_output(data, output_format)
if output_format == 'json':
return data
elif output_format == 'xml':
# Convert to XML format
return self._convert_to_xml(data)
else:
raise ValueError(f"Unsupported output format: {output_format}")
except Exception as e:
logger.error(f"Error processing data for output: {str(e)}")
return str(data)
raise
async def optimize_strategy_operation(self, operation_name: str, operation_func, *args, **kwargs) -> Dict[str, Any]:
"""Optimize strategy operations with performance monitoring."""
"""Optimize strategy operation with performance monitoring."""
try:
return await self.performance_optimization_service.optimize_response_time(
return await self.performance_optimization_service.optimize_operation(
operation_name, operation_func, *args, **kwargs
)
except Exception as e:
logger.error(f"Error optimizing strategy operation: {str(e)}")
return {
'result': None,
'response_time': 0.0,
'optimization_suggestions': ['Error occurred during optimization'],
'performance_status': 'error'
}
raise
def _convert_to_xml(self, data: Dict[str, Any]) -> str:
"""Convert data to XML format (placeholder implementation)."""
# This would be implemented with proper XML conversion
return f"<strategy>{str(data)}</strategy>"

View File

@@ -3,7 +3,54 @@ Utils Module
Data processing and validation utilities.
"""
from .data_processors import DataProcessorService
from .data_processors import (
DataProcessorService,
get_onboarding_data,
transform_onboarding_data_to_fields,
get_data_sources,
get_detailed_input_data_points,
get_fallback_onboarding_data,
get_website_analysis_data,
get_research_preferences_data,
get_api_keys_data
)
from .validators import ValidationService
from .strategy_utils import (
StrategyUtils,
calculate_strategic_scores,
extract_market_positioning,
extract_competitive_advantages,
extract_strategic_risks,
extract_opportunity_analysis,
initialize_caches,
calculate_data_quality_scores,
extract_content_preferences_from_style,
extract_brand_voice_from_guidelines,
extract_editorial_guidelines_from_style,
create_field_mappings
)
__all__ = ['DataProcessorService', 'ValidationService']
__all__ = [
'DataProcessorService',
'get_onboarding_data',
'transform_onboarding_data_to_fields',
'get_data_sources',
'get_detailed_input_data_points',
'get_fallback_onboarding_data',
'get_website_analysis_data',
'get_research_preferences_data',
'get_api_keys_data',
'ValidationService',
'StrategyUtils',
'calculate_strategic_scores',
'extract_market_positioning',
'extract_competitive_advantages',
'extract_strategic_risks',
'extract_opportunity_analysis',
'initialize_caches',
'calculate_data_quality_scores',
'extract_content_preferences_from_style',
'extract_brand_voice_from_guidelines',
'extract_editorial_guidelines_from_style',
'create_field_mappings'
]

View File

@@ -1,451 +1,539 @@
"""
Data Processor Service
Data processing utilities.
Data processing utilities for content strategy operations.
Provides functions for transforming onboarding data into strategy fields,
managing data sources, and processing various data types.
"""
import logging
import json
import re
from typing import Dict, Any, List, Optional, Union
from datetime import datetime, timedelta
from typing import Dict, List, Any, Optional, Union
from datetime import datetime
from sqlalchemy.orm import Session
from models.onboarding import OnboardingSession, WebsiteAnalysis, ResearchPreferences, APIKey
logger = logging.getLogger(__name__)
class DataProcessorService:
"""Service for data processing utilities."""
"""Service for processing and transforming data for content strategy operations."""
def __init__(self):
self.cleaning_patterns = {
'html_tags': re.compile(r'<[^>]+>'),
'extra_whitespace': re.compile(r'\s+'),
'special_chars': re.compile(r'[^\w\s\-.,!?;:()]'),
'multiple_spaces': re.compile(r'\s{2,}'),
'leading_trailing_spaces': re.compile(r'^\s+|\s+$')
self.logger = logging.getLogger(__name__)
async def get_onboarding_data(self, user_id: int) -> Dict[str, Any]:
"""
Get comprehensive onboarding data for intelligent auto-population via AutoFillService.
Args:
user_id: The user ID to get onboarding data for
Returns:
Dictionary containing comprehensive onboarding data
"""
try:
from services.database import get_db_session
from ..autofill import AutoFillService
temp_db = get_db_session()
try:
service = AutoFillService(temp_db)
payload = await service.get_autofill(user_id)
self.logger.info(f"Retrieved comprehensive onboarding data for user {user_id}")
return payload
except Exception as e:
self.logger.error(f"Error getting onboarding data: {str(e)}")
raise
finally:
temp_db.close()
except Exception as e:
self.logger.error(f"Error getting onboarding data: {str(e)}")
raise
def transform_onboarding_data_to_fields(self, processed_data: Dict[str, Any]) -> Dict[str, Any]:
"""
Transform processed onboarding data into field-specific format for frontend.
Args:
processed_data: Dictionary containing processed onboarding data
Returns:
Dictionary with field-specific data for strategy builder
"""
fields = {}
website_data = processed_data.get('website_analysis', {})
research_data = processed_data.get('research_preferences', {})
api_data = processed_data.get('api_keys_data', {})
session_data = processed_data.get('onboarding_session', {})
# Business Context Fields
if 'content_goals' in website_data and website_data.get('content_goals'):
fields['business_objectives'] = {
'value': website_data.get('content_goals'),
'source': 'website_analysis',
'confidence': website_data.get('confidence_level')
}
# Prefer explicit target_metrics; otherwise derive from performance_metrics
if website_data.get('target_metrics'):
fields['target_metrics'] = {
'value': website_data.get('target_metrics'),
'source': 'website_analysis',
'confidence': website_data.get('confidence_level')
}
elif website_data.get('performance_metrics'):
fields['target_metrics'] = {
'value': website_data.get('performance_metrics'),
'source': 'website_analysis',
'confidence': website_data.get('confidence_level')
}
# Content budget: website data preferred, else onboarding session budget
if website_data.get('content_budget') is not None:
fields['content_budget'] = {
'value': website_data.get('content_budget'),
'source': 'website_analysis',
'confidence': website_data.get('confidence_level')
}
elif isinstance(session_data, dict) and session_data.get('budget') is not None:
fields['content_budget'] = {
'value': session_data.get('budget'),
'source': 'onboarding_session',
'confidence': 0.7
}
# Team size: website data preferred, else onboarding session team_size
if website_data.get('team_size') is not None:
fields['team_size'] = {
'value': website_data.get('team_size'),
'source': 'website_analysis',
'confidence': website_data.get('confidence_level')
}
elif isinstance(session_data, dict) and session_data.get('team_size') is not None:
fields['team_size'] = {
'value': session_data.get('team_size'),
'source': 'onboarding_session',
'confidence': 0.7
}
# Implementation timeline: website data preferred, else onboarding session timeline
if website_data.get('implementation_timeline'):
fields['implementation_timeline'] = {
'value': website_data.get('implementation_timeline'),
'source': 'website_analysis',
'confidence': website_data.get('confidence_level')
}
elif isinstance(session_data, dict) and session_data.get('timeline'):
fields['implementation_timeline'] = {
'value': session_data.get('timeline'),
'source': 'onboarding_session',
'confidence': 0.7
}
# Market share: explicit if present; otherwise derive rough share from performance metrics if available
if website_data.get('market_share'):
fields['market_share'] = {
'value': website_data.get('market_share'),
'source': 'website_analysis',
'confidence': website_data.get('confidence_level')
}
elif website_data.get('performance_metrics'):
fields['market_share'] = {
'value': website_data.get('performance_metrics').get('estimated_market_share', None),
'source': 'website_analysis',
'confidence': website_data.get('confidence_level')
}
fields['performance_metrics'] = {
'value': website_data.get('performance_metrics', {}),
'source': 'website_analysis',
'confidence': website_data.get('confidence_level', 0.8)
}
def transform_data_structure(self, data: Union[Dict, List, str], target_format: str = 'dict') -> Union[Dict, List, str]:
"""Transform data between different structures."""
try:
if target_format == 'dict':
if isinstance(data, dict):
return data
elif isinstance(data, list):
return {str(i): item for i, item in enumerate(data)}
elif isinstance(data, str):
try:
return json.loads(data)
except json.JSONDecodeError:
return {'value': data}
else:
return {'value': str(data)}
# Audience Intelligence Fields
# Extract audience data from research_data structure
audience_research = research_data.get('audience_research', {})
content_prefs = research_data.get('content_preferences', {})
fields['content_preferences'] = {
'value': content_prefs,
'source': 'research_preferences',
'confidence': research_data.get('confidence_level', 0.8)
}
fields['consumption_patterns'] = {
'value': audience_research.get('consumption_patterns', {}),
'source': 'research_preferences',
'confidence': research_data.get('confidence_level', 0.8)
}
fields['audience_pain_points'] = {
'value': audience_research.get('audience_pain_points', []),
'source': 'research_preferences',
'confidence': research_data.get('confidence_level', 0.8)
}
fields['buying_journey'] = {
'value': audience_research.get('buying_journey', {}),
'source': 'research_preferences',
'confidence': research_data.get('confidence_level', 0.8)
}
fields['seasonal_trends'] = {
'value': ['Q1: Planning', 'Q2: Execution', 'Q3: Optimization', 'Q4: Review'],
'source': 'research_preferences',
'confidence': research_data.get('confidence_level', 0.7)
}
fields['engagement_metrics'] = {
'value': {
'avg_session_duration': website_data.get('performance_metrics', {}).get('avg_session_duration', 180),
'bounce_rate': website_data.get('performance_metrics', {}).get('bounce_rate', 45.5),
'pages_per_session': 2.5
},
'source': 'website_analysis',
'confidence': website_data.get('confidence_level', 0.8)
}
# Competitive Intelligence Fields
fields['top_competitors'] = {
'value': website_data.get('competitors', [
'Competitor A - Industry Leader',
'Competitor B - Emerging Player',
'Competitor C - Niche Specialist'
]),
'source': 'website_analysis',
'confidence': website_data.get('confidence_level', 0.8)
}
fields['competitor_content_strategies'] = {
'value': ['Educational content', 'Case studies', 'Thought leadership'],
'source': 'website_analysis',
'confidence': website_data.get('confidence_level', 0.7)
}
fields['market_gaps'] = {
'value': website_data.get('market_gaps', []),
'source': 'website_analysis',
'confidence': website_data.get('confidence_level', 0.8)
}
fields['industry_trends'] = {
'value': ['Digital transformation', 'AI/ML adoption', 'Remote work'],
'source': 'website_analysis',
'confidence': website_data.get('confidence_level', 0.8)
}
fields['emerging_trends'] = {
'value': ['Voice search optimization', 'Video content', 'Interactive content'],
'source': 'website_analysis',
'confidence': website_data.get('confidence_level', 0.7)
}
# Content Strategy Fields
fields['preferred_formats'] = {
'value': content_prefs.get('preferred_formats', [
'Blog posts', 'Whitepapers', 'Webinars', 'Case studies', 'Videos'
]),
'source': 'research_preferences',
'confidence': research_data.get('confidence_level', 0.8)
}
fields['content_mix'] = {
'value': {
'blog_posts': 40,
'whitepapers': 20,
'webinars': 15,
'case_studies': 15,
'videos': 10
},
'source': 'research_preferences',
'confidence': research_data.get('confidence_level', 0.8)
}
fields['content_frequency'] = {
'value': 'Weekly',
'source': 'research_preferences',
'confidence': research_data.get('confidence_level', 0.8)
}
fields['optimal_timing'] = {
'value': {
'best_days': ['Tuesday', 'Wednesday', 'Thursday'],
'best_times': ['9:00 AM', '1:00 PM', '3:00 PM']
},
'source': 'research_preferences',
'confidence': research_data.get('confidence_level', 0.7)
}
fields['quality_metrics'] = {
'value': {
'readability_score': 8.5,
'engagement_target': 5.0,
'conversion_target': 2.0
},
'source': 'research_preferences',
'confidence': research_data.get('confidence_level', 0.8)
}
fields['editorial_guidelines'] = {
'value': {
'tone': content_prefs.get('content_style', ['Professional', 'Educational']),
'length': content_prefs.get('content_length', 'Medium (1000-2000 words)'),
'formatting': ['Use headers', 'Include visuals', 'Add CTAs']
},
'source': 'research_preferences',
'confidence': research_data.get('confidence_level', 0.8)
}
fields['brand_voice'] = {
'value': {
'tone': 'Professional yet approachable',
'style': 'Educational and authoritative',
'personality': 'Expert, helpful, trustworthy'
},
'source': 'research_preferences',
'confidence': research_data.get('confidence_level', 0.8)
}
# Performance & Analytics Fields
fields['traffic_sources'] = {
'value': website_data.get('traffic_sources', {}),
'source': 'website_analysis',
'confidence': website_data.get('confidence_level', 0.8)
}
fields['conversion_rates'] = {
'value': {
'overall': website_data.get('performance_metrics', {}).get('conversion_rate', 3.2),
'blog': 2.5,
'landing_pages': 4.0,
'email': 5.5
},
'source': 'website_analysis',
'confidence': website_data.get('confidence_level', 0.8)
}
fields['content_roi_targets'] = {
'value': {
'target_roi': 300,
'cost_per_lead': 50,
'lifetime_value': 500
},
'source': 'website_analysis',
'confidence': website_data.get('confidence_level', 0.7)
}
fields['ab_testing_capabilities'] = {
'value': True,
'source': 'api_keys_data',
'confidence': api_data.get('confidence_level', 0.8)
}
return fields
def get_data_sources(self, processed_data: Dict[str, Any]) -> Dict[str, str]:
"""
Get data sources for each field.
Args:
processed_data: Dictionary containing processed data
elif target_format == 'list':
if isinstance(data, list):
return data
elif isinstance(data, dict):
return list(data.values())
elif isinstance(data, str):
return [data]
else:
return [str(data)]
Returns:
Dictionary mapping field names to their data sources
"""
sources = {}
# Map fields to their data sources
website_fields = ['business_objectives', 'target_metrics', 'content_budget', 'team_size',
'implementation_timeline', 'market_share', 'competitive_position',
'performance_metrics', 'engagement_metrics', 'top_competitors',
'competitor_content_strategies', 'market_gaps', 'industry_trends',
'emerging_trends', 'traffic_sources', 'conversion_rates', 'content_roi_targets']
research_fields = ['content_preferences', 'consumption_patterns', 'audience_pain_points',
'buying_journey', 'seasonal_trends', 'preferred_formats', 'content_mix',
'content_frequency', 'optimal_timing', 'quality_metrics', 'editorial_guidelines',
'brand_voice']
api_fields = ['ab_testing_capabilities']
for field in website_fields:
sources[field] = 'website_analysis'
for field in research_fields:
sources[field] = 'research_preferences'
for field in api_fields:
sources[field] = 'api_keys_data'
return sources
def get_detailed_input_data_points(self, processed_data: Dict[str, Any]) -> Dict[str, Any]:
"""
Get detailed input data points for transparency.
Args:
processed_data: Dictionary containing processed data
elif target_format == 'string':
if isinstance(data, str):
return data
elif isinstance(data, (dict, list)):
return json.dumps(data, default=str)
else:
return str(data)
else:
logger.warning(f"Unknown target format: {target_format}")
return data
except Exception as e:
logger.error(f"Error transforming data structure: {str(e)}")
return data
def clean_text_data(self, text: str, cleaning_level: str = 'standard') -> str:
"""Clean and normalize text data."""
try:
if not isinstance(text, str):
text = str(text)
if cleaning_level == 'minimal':
# Basic cleaning
cleaned = self.cleaning_patterns['leading_trailing_spaces'].sub('', text)
cleaned = self.cleaning_patterns['multiple_spaces'].sub(' ', cleaned)
return cleaned.strip()
elif cleaning_level == 'standard':
# Standard cleaning
cleaned = self.cleaning_patterns['html_tags'].sub('', text)
cleaned = self.cleaning_patterns['leading_trailing_spaces'].sub('', cleaned)
cleaned = self.cleaning_patterns['multiple_spaces'].sub(' ', cleaned)
return cleaned.strip()
elif cleaning_level == 'aggressive':
# Aggressive cleaning
cleaned = self.cleaning_patterns['html_tags'].sub('', text)
cleaned = self.cleaning_patterns['special_chars'].sub('', cleaned)
cleaned = self.cleaning_patterns['leading_trailing_spaces'].sub('', cleaned)
cleaned = self.cleaning_patterns['multiple_spaces'].sub(' ', cleaned)
return cleaned.strip()
else:
logger.warning(f"Unknown cleaning level: {cleaning_level}")
return text.strip()
except Exception as e:
logger.error(f"Error cleaning text data: {str(e)}")
return str(text)
def clean_dict_data(self, data: Dict[str, Any], cleaning_level: str = 'standard') -> Dict[str, Any]:
"""Clean dictionary data recursively."""
try:
cleaned_data = {}
for key, value in data.items():
# Clean key
cleaned_key = self.clean_text_data(str(key), cleaning_level)
# Clean value
if isinstance(value, str):
cleaned_value = self.clean_text_data(value, cleaning_level)
elif isinstance(value, dict):
cleaned_value = self.clean_dict_data(value, cleaning_level)
elif isinstance(value, list):
cleaned_value = [self.clean_text_data(str(item), cleaning_level) if isinstance(item, str) else item for item in value]
else:
cleaned_value = value
cleaned_data[cleaned_key] = cleaned_value
return cleaned_data
except Exception as e:
logger.error(f"Error cleaning dict data: {str(e)}")
return data
def enrich_data_with_metadata(self, data: Dict[str, Any], source: str = 'unknown') -> Dict[str, Any]:
"""Enrich data with metadata."""
try:
enriched_data = data.copy()
# Add metadata
enriched_data['_metadata'] = {
'processed_at': datetime.utcnow().isoformat(),
'source': source,
'data_type': self._determine_data_type(data),
'size': len(str(data)),
'field_count': len(data) if isinstance(data, dict) else 0
Returns:
Dictionary with detailed data points
"""
return {
'website_analysis': {
'total_fields': len(processed_data.get('website_analysis', {})),
'confidence_level': processed_data.get('website_analysis', {}).get('confidence_level', 0.8),
'data_freshness': processed_data.get('website_analysis', {}).get('data_freshness', 'recent')
},
'research_preferences': {
'total_fields': len(processed_data.get('research_preferences', {})),
'confidence_level': processed_data.get('research_preferences', {}).get('confidence_level', 0.8),
'data_freshness': processed_data.get('research_preferences', {}).get('data_freshness', 'recent')
},
'api_keys_data': {
'total_fields': len(processed_data.get('api_keys_data', {})),
'confidence_level': processed_data.get('api_keys_data', {}).get('confidence_level', 0.8),
'data_freshness': processed_data.get('api_keys_data', {}).get('data_freshness', 'recent')
}
}
def get_fallback_onboarding_data(self) -> Dict[str, Any]:
"""
Get fallback onboarding data for compatibility.
Returns:
Dictionary with fallback data (raises error as fallbacks are disabled)
"""
raise RuntimeError("Fallback onboarding data is disabled. Real data required.")
async def get_website_analysis_data(self, user_id: int) -> Dict[str, Any]:
"""
Get website analysis data from onboarding.
Args:
user_id: The user ID to get data for
return enriched_data
except Exception as e:
logger.error(f"Error enriching data with metadata: {str(e)}")
return data
def _determine_data_type(self, data: Any) -> str:
"""Determine the type of data."""
Returns:
Dictionary with website analysis data
"""
try:
if isinstance(data, dict):
return 'object'
elif isinstance(data, list):
return 'array'
elif isinstance(data, str):
return 'string'
elif isinstance(data, (int, float)):
return 'number'
elif isinstance(data, bool):
return 'boolean'
else:
return 'unknown'
raise RuntimeError("Website analysis data retrieval not implemented. Real data required.")
except Exception as e:
logger.error(f"Error determining data type: {str(e)}")
return 'unknown'
def validate_data_completeness(self, data: Dict[str, Any], required_fields: List[str]) -> Dict[str, Any]:
"""Validate data completeness against required fields."""
self.logger.error(f"Error getting website analysis data: {str(e)}")
raise
async def get_research_preferences_data(self, user_id: int) -> Dict[str, Any]:
"""
Get research preferences data from onboarding.
Args:
user_id: The user ID to get data for
Returns:
Dictionary with research preferences data
"""
try:
validation_result = {
'is_complete': True,
'missing_fields': [],
'present_fields': [],
'completeness_score': 0.0,
'validation_timestamp': datetime.utcnow().isoformat()
}
present_count = 0
for field in required_fields:
if field in data and data[field] is not None and data[field] != '':
validation_result['present_fields'].append(field)
present_count += 1
else:
validation_result['missing_fields'].append(field)
# Calculate completeness score
if required_fields:
validation_result['completeness_score'] = present_count / len(required_fields)
validation_result['is_complete'] = validation_result['completeness_score'] >= 0.8
return validation_result
raise RuntimeError("Research preferences data retrieval not implemented. Real data required.")
except Exception as e:
logger.error(f"Error validating data completeness: {str(e)}")
return {
'is_complete': False,
'missing_fields': required_fields,
'present_fields': [],
'completeness_score': 0.0,
'validation_timestamp': datetime.utcnow().isoformat(),
'error': str(e)
}
def normalize_field_values(self, data: Dict[str, Any], field_mappings: Dict[str, str]) -> Dict[str, Any]:
"""Normalize field values based on mappings."""
self.logger.error(f"Error getting research preferences data: {str(e)}")
raise
async def get_api_keys_data(self, user_id: int) -> Dict[str, Any]:
"""
Get API keys and external data from onboarding.
Args:
user_id: The user ID to get data for
Returns:
Dictionary with API keys data
"""
try:
normalized_data = {}
for original_field, normalized_field in field_mappings.items():
if original_field in data:
normalized_data[normalized_field] = data[original_field]
return normalized_data
raise RuntimeError("API keys/external data retrieval not implemented. Real data required.")
except Exception as e:
logger.error(f"Error normalizing field values: {str(e)}")
return data
self.logger.error(f"Error getting API keys data: {str(e)}")
raise
async def process_website_analysis(self, website_data: Dict[str, Any]) -> Dict[str, Any]:
"""
Process website analysis data (deprecated).
Args:
website_data: Raw website analysis data
Returns:
Processed website analysis data
"""
raise RuntimeError("Deprecated: use AutoFillService normalizers")
async def process_research_preferences(self, research_data: Dict[str, Any]) -> Dict[str, Any]:
"""
Process research preferences data (deprecated).
Args:
research_data: Raw research preferences data
Returns:
Processed research preferences data
"""
raise RuntimeError("Deprecated: use AutoFillService normalizers")
async def process_api_keys_data(self, api_data: Dict[str, Any]) -> Dict[str, Any]:
"""
Process API keys data (deprecated).
Args:
api_data: Raw API keys data
Returns:
Processed API keys data
"""
raise RuntimeError("Deprecated: use AutoFillService normalizers")
def merge_data_sources(self, data_sources: List[Dict[str, Any]], merge_strategy: str = 'prefer_first') -> Dict[str, Any]:
"""Merge multiple data sources."""
try:
if not data_sources:
return {}
if len(data_sources) == 1:
return data_sources[0]
merged_data = {}
if merge_strategy == 'prefer_first':
# Prefer first non-empty value
for source in data_sources:
for key, value in source.items():
if key not in merged_data or merged_data[key] is None or merged_data[key] == '':
merged_data[key] = value
elif merge_strategy == 'prefer_last':
# Prefer last non-empty value
for source in data_sources:
for key, value in source.items():
if value is not None and value != '':
merged_data[key] = value
elif merge_strategy == 'combine':
# Combine all values
for source in data_sources:
for key, value in source.items():
if key not in merged_data:
merged_data[key] = []
if isinstance(merged_data[key], list):
merged_data[key].append(value)
else:
merged_data[key] = [merged_data[key], value]
elif merge_strategy == 'intersection':
# Only include fields present in all sources
common_keys = set(data_sources[0].keys())
for source in data_sources[1:]:
common_keys = common_keys.intersection(set(source.keys()))
for key in common_keys:
values = [source[key] for source in data_sources if key in source]
merged_data[key] = values[0] if values else None
return merged_data
except Exception as e:
logger.error(f"Error merging data sources: {str(e)}")
return data_sources[0] if data_sources else {}
def filter_data_by_criteria(self, data: Dict[str, Any], criteria: Dict[str, Any]) -> Dict[str, Any]:
"""Filter data based on criteria."""
try:
filtered_data = {}
for key, value in data.items():
include_field = True
# Check if field should be included based on criteria
if 'include_fields' in criteria and key not in criteria['include_fields']:
include_field = False
if 'exclude_fields' in criteria and key in criteria['exclude_fields']:
include_field = False
# Check value-based criteria
if 'min_length' in criteria and isinstance(value, str) and len(value) < criteria['min_length']:
include_field = False
if 'max_length' in criteria and isinstance(value, str) and len(value) > criteria['max_length']:
include_field = False
if 'required_values' in criteria and key in criteria['required_values']:
if value not in criteria['required_values'][key]:
include_field = False
if include_field:
filtered_data[key] = value
return filtered_data
except Exception as e:
logger.error(f"Error filtering data by criteria: {str(e)}")
return data
# Standalone functions for backward compatibility
async def get_onboarding_data(user_id: int) -> Dict[str, Any]:
"""Get comprehensive onboarding data for intelligent auto-population via AutoFillService."""
processor = DataProcessorService()
return await processor.get_onboarding_data(user_id)
def format_data_for_output(self, data: Dict[str, Any], output_format: str = 'json') -> Union[str, Dict[str, Any]]:
"""Format data for different output formats."""
try:
if output_format == 'json':
return json.dumps(data, indent=2, default=str)
elif output_format == 'dict':
return data
elif output_format == 'csv':
# Convert to CSV format (simplified)
csv_lines = []
if data:
# Headers
headers = list(data.keys())
csv_lines.append(','.join(headers))
# Values
values = [str(data.get(header, '')) for header in headers]
csv_lines.append(','.join(values))
return '\n'.join(csv_lines)
elif output_format == 'xml':
# Convert to XML format (simplified)
xml_lines = ['<?xml version="1.0" encoding="UTF-8"?>', '<data>']
for key, value in data.items():
xml_lines.append(f' <{key}>{value}</{key}>')
xml_lines.append('</data>')
return '\n'.join(xml_lines)
else:
logger.warning(f"Unknown output format: {output_format}")
return data
except Exception as e:
logger.error(f"Error formatting data for output: {str(e)}")
return str(data)
def validate_data_types(self, data: Dict[str, Any], type_schema: Dict[str, str]) -> Dict[str, Any]:
"""Validate data types against a schema."""
try:
validation_result = {
'is_valid': True,
'type_errors': [],
'validation_timestamp': datetime.utcnow().isoformat()
}
for field, expected_type in type_schema.items():
if field in data:
value = data[field]
actual_type = self._determine_data_type(value)
if actual_type != expected_type:
validation_result['type_errors'].append({
'field': field,
'expected_type': expected_type,
'actual_type': actual_type,
'value': value
})
validation_result['is_valid'] = False
return validation_result
except Exception as e:
logger.error(f"Error validating data types: {str(e)}")
return {
'is_valid': False,
'type_errors': [{'error': str(e)}],
'validation_timestamp': datetime.utcnow().isoformat()
}
def transform_onboarding_data_to_fields(processed_data: Dict[str, Any]) -> Dict[str, Any]:
"""Transform processed onboarding data into field-specific format for frontend."""
processor = DataProcessorService()
return processor.transform_onboarding_data_to_fields(processed_data)
def sanitize_sensitive_data(self, data: Dict[str, Any], sensitive_fields: List[str]) -> Dict[str, Any]:
"""Sanitize sensitive data fields."""
try:
sanitized_data = data.copy()
for field in sensitive_fields:
if field in sanitized_data:
value = sanitized_data[field]
if isinstance(value, str) and len(value) > 4:
# Replace with asterisks, keeping first and last character
sanitized_data[field] = value[0] + '*' * (len(value) - 2) + value[-1]
else:
sanitized_data[field] = '***'
return sanitized_data
except Exception as e:
logger.error(f"Error sanitizing sensitive data: {str(e)}")
return data
def calculate_data_statistics(self, data: Dict[str, Any]) -> Dict[str, Any]:
"""Calculate statistics about the data."""
try:
stats = {
'total_fields': len(data),
'string_fields': 0,
'numeric_fields': 0,
'boolean_fields': 0,
'object_fields': 0,
'array_fields': 0,
'null_fields': 0,
'empty_fields': 0,
'average_field_length': 0.0
}
total_length = 0
field_count = 0
for key, value in data.items():
if value is None:
stats['null_fields'] += 1
elif value == '':
stats['empty_fields'] += 1
else:
data_type = self._determine_data_type(value)
if data_type == 'string':
stats['string_fields'] += 1
total_length += len(str(value))
field_count += 1
elif data_type == 'number':
stats['numeric_fields'] += 1
elif data_type == 'boolean':
stats['boolean_fields'] += 1
elif data_type == 'object':
stats['object_fields'] += 1
elif data_type == 'array':
stats['array_fields'] += 1
if field_count > 0:
stats['average_field_length'] = total_length / field_count
return stats
except Exception as e:
logger.error(f"Error calculating data statistics: {str(e)}")
return {
'error': str(e),
'total_fields': 0
}
def get_data_sources(processed_data: Dict[str, Any]) -> Dict[str, str]:
"""Get data sources for each field."""
processor = DataProcessorService()
return processor.get_data_sources(processed_data)
def get_detailed_input_data_points(processed_data: Dict[str, Any]) -> Dict[str, Any]:
"""Get detailed input data points for transparency."""
processor = DataProcessorService()
return processor.get_detailed_input_data_points(processed_data)
def get_fallback_onboarding_data() -> Dict[str, Any]:
"""Get fallback onboarding data for compatibility."""
processor = DataProcessorService()
return processor.get_fallback_onboarding_data()
async def get_website_analysis_data(user_id: int) -> Dict[str, Any]:
"""Get website analysis data from onboarding."""
processor = DataProcessorService()
return await processor.get_website_analysis_data(user_id)
async def get_research_preferences_data(user_id: int) -> Dict[str, Any]:
"""Get research preferences data from onboarding."""
processor = DataProcessorService()
return await processor.get_research_preferences_data(user_id)
async def get_api_keys_data(user_id: int) -> Dict[str, Any]:
"""Get API keys and external data from onboarding."""
processor = DataProcessorService()
return await processor.get_api_keys_data(user_id)

View File

@@ -0,0 +1,355 @@
"""
Strategy utility functions for analysis, scoring, and data processing.
Provides utility functions for content strategy operations including strategic scoring,
market positioning analysis, competitive advantages, risk assessment, and opportunity analysis.
"""
import logging
from typing import Dict, List, Any, Optional, Union
from datetime import datetime
logger = logging.getLogger(__name__)
def calculate_strategic_scores(ai_recommendations: Dict[str, Any]) -> Dict[str, float]:
"""
Calculate strategic performance scores from AI recommendations.
Args:
ai_recommendations: Dictionary containing AI analysis results
Returns:
Dictionary with calculated strategic scores
"""
scores = {
'overall_score': 0.0,
'content_quality_score': 0.0,
'engagement_score': 0.0,
'conversion_score': 0.0,
'innovation_score': 0.0
}
# Calculate scores based on AI recommendations
total_confidence = 0
total_score = 0
for analysis_type, recommendations in ai_recommendations.items():
if isinstance(recommendations, dict) and 'metrics' in recommendations:
metrics = recommendations['metrics']
score = metrics.get('score', 50)
confidence = metrics.get('confidence', 0.5)
total_score += score * confidence
total_confidence += confidence
if total_confidence > 0:
scores['overall_score'] = total_score / total_confidence
# Set other scores based on overall score
scores['content_quality_score'] = scores['overall_score'] * 1.1
scores['engagement_score'] = scores['overall_score'] * 0.9
scores['conversion_score'] = scores['overall_score'] * 0.95
scores['innovation_score'] = scores['overall_score'] * 1.05
return scores
def extract_market_positioning(ai_recommendations: Dict[str, Any]) -> Dict[str, Any]:
"""
Extract market positioning insights from AI recommendations.
Args:
ai_recommendations: Dictionary containing AI analysis results
Returns:
Dictionary with market positioning data
"""
return {
'industry_position': 'emerging',
'competitive_advantage': 'AI-powered content',
'market_share': '2.5%',
'positioning_score': 4
}
def extract_competitive_advantages(ai_recommendations: Dict[str, Any]) -> List[Dict[str, Any]]:
"""
Extract competitive advantages from AI recommendations.
Args:
ai_recommendations: Dictionary containing AI analysis results
Returns:
List of competitive advantages with impact and implementation status
"""
return [
{
'advantage': 'AI-powered content creation',
'impact': 'High',
'implementation': 'In Progress'
},
{
'advantage': 'Data-driven strategy',
'impact': 'Medium',
'implementation': 'Complete'
}
]
def extract_strategic_risks(ai_recommendations: Dict[str, Any]) -> List[Dict[str, Any]]:
"""
Extract strategic risks from AI recommendations.
Args:
ai_recommendations: Dictionary containing AI analysis results
Returns:
List of strategic risks with probability and impact assessment
"""
return [
{
'risk': 'Content saturation in market',
'probability': 'Medium',
'impact': 'High'
},
{
'risk': 'Algorithm changes affecting reach',
'probability': 'High',
'impact': 'Medium'
}
]
def extract_opportunity_analysis(ai_recommendations: Dict[str, Any]) -> List[Dict[str, Any]]:
"""
Extract opportunity analysis from AI recommendations.
Args:
ai_recommendations: Dictionary containing AI analysis results
Returns:
List of opportunities with potential impact and implementation ease
"""
return [
{
'opportunity': 'Video content expansion',
'potential_impact': 'High',
'implementation_ease': 'Medium'
},
{
'opportunity': 'Social media engagement',
'potential_impact': 'Medium',
'implementation_ease': 'High'
}
]
def initialize_caches() -> Dict[str, Any]:
"""
Initialize in-memory caches for strategy operations.
Returns:
Dictionary with initialized cache structures
"""
return {
'performance_metrics': {
'response_times': [],
'cache_hit_rates': {},
'error_rates': {},
'throughput_metrics': {}
},
'strategy_cache': {},
'ai_analysis_cache': {},
'onboarding_cache': {}
}
def calculate_data_quality_scores(data_sources: Dict[str, Any]) -> Dict[str, float]:
"""
Calculate data quality scores for different data sources.
Args:
data_sources: Dictionary containing data source information
Returns:
Dictionary with quality scores for each data source
"""
quality_scores = {}
for source_name, source_data in data_sources.items():
if isinstance(source_data, dict):
# Calculate quality based on data completeness and freshness
completeness = source_data.get('completeness', 0.5)
freshness = source_data.get('freshness', 0.5)
confidence = source_data.get('confidence', 0.5)
# Weighted average of quality factors
quality_score = (completeness * 0.4 + freshness * 0.3 + confidence * 0.3)
quality_scores[source_name] = round(quality_score, 2)
else:
quality_scores[source_name] = 0.5 # Default score
return quality_scores
def extract_content_preferences_from_style(writing_style: Dict[str, Any]) -> Dict[str, Any]:
"""
Extract content preferences from writing style analysis.
Args:
writing_style: Dictionary containing writing style analysis
Returns:
Dictionary with extracted content preferences
"""
preferences = {
'tone': writing_style.get('tone', 'professional'),
'complexity': writing_style.get('complexity', 'intermediate'),
'engagement_level': writing_style.get('engagement_level', 'medium'),
'content_type': writing_style.get('content_type', 'blog')
}
return preferences
def extract_brand_voice_from_guidelines(style_guidelines: Dict[str, Any]) -> Dict[str, Any]:
"""
Extract brand voice from style guidelines.
Args:
style_guidelines: Dictionary containing style guidelines
Returns:
Dictionary with extracted brand voice information
"""
brand_voice = {
'tone': style_guidelines.get('tone', 'professional'),
'personality': style_guidelines.get('personality', 'authoritative'),
'style': style_guidelines.get('style', 'formal'),
'voice_characteristics': style_guidelines.get('voice_characteristics', [])
}
return brand_voice
def extract_editorial_guidelines_from_style(writing_style: Dict[str, Any]) -> Dict[str, Any]:
"""
Extract editorial guidelines from writing style analysis.
Args:
writing_style: Dictionary containing writing style analysis
Returns:
Dictionary with extracted editorial guidelines
"""
guidelines = {
'sentence_structure': writing_style.get('sentence_structure', 'clear'),
'vocabulary_level': writing_style.get('vocabulary_level', 'intermediate'),
'paragraph_organization': writing_style.get('paragraph_organization', 'logical'),
'style_rules': writing_style.get('style_rules', [])
}
return guidelines
def create_field_mappings() -> Dict[str, str]:
"""
Create field mappings for strategy data transformation.
Returns:
Dictionary mapping field names to their corresponding data sources
"""
return {
'business_objectives': 'website_analysis',
'target_metrics': 'research_preferences',
'content_budget': 'onboarding_session',
'team_size': 'onboarding_session',
'implementation_timeline': 'onboarding_session',
'market_share': 'website_analysis',
'competitive_position': 'website_analysis',
'performance_metrics': 'website_analysis',
'content_preferences': 'website_analysis',
'consumption_patterns': 'research_preferences',
'audience_pain_points': 'website_analysis',
'buying_journey': 'website_analysis',
'seasonal_trends': 'research_preferences',
'engagement_metrics': 'website_analysis',
'top_competitors': 'website_analysis',
'competitor_content_strategies': 'website_analysis',
'market_gaps': 'website_analysis',
'industry_trends': 'website_analysis',
'emerging_trends': 'website_analysis',
'preferred_formats': 'website_analysis',
'content_mix': 'research_preferences',
'content_frequency': 'research_preferences',
'optimal_timing': 'research_preferences',
'quality_metrics': 'website_analysis',
'editorial_guidelines': 'website_analysis',
'brand_voice': 'website_analysis',
'traffic_sources': 'website_analysis',
'conversion_rates': 'website_analysis',
'content_roi_targets': 'website_analysis',
'ab_testing_capabilities': 'onboarding_session'
}
class StrategyUtils:
"""
Utility class for strategy-related operations.
Provides static methods for strategy analysis and data processing.
"""
@staticmethod
def calculate_strategic_scores(ai_recommendations: Dict[str, Any]) -> Dict[str, float]:
"""Calculate strategic performance scores from AI recommendations."""
return calculate_strategic_scores(ai_recommendations)
@staticmethod
def extract_market_positioning(ai_recommendations: Dict[str, Any]) -> Dict[str, Any]:
"""Extract market positioning insights from AI recommendations."""
return extract_market_positioning(ai_recommendations)
@staticmethod
def extract_competitive_advantages(ai_recommendations: Dict[str, Any]) -> List[Dict[str, Any]]:
"""Extract competitive advantages from AI recommendations."""
return extract_competitive_advantages(ai_recommendations)
@staticmethod
def extract_strategic_risks(ai_recommendations: Dict[str, Any]) -> List[Dict[str, Any]]:
"""Extract strategic risks from AI recommendations."""
return extract_strategic_risks(ai_recommendations)
@staticmethod
def extract_opportunity_analysis(ai_recommendations: Dict[str, Any]) -> List[Dict[str, Any]]:
"""Extract opportunity analysis from AI recommendations."""
return extract_opportunity_analysis(ai_recommendations)
@staticmethod
def initialize_caches() -> Dict[str, Any]:
"""Initialize in-memory caches for strategy operations."""
return initialize_caches()
@staticmethod
def calculate_data_quality_scores(data_sources: Dict[str, Any]) -> Dict[str, float]:
"""Calculate data quality scores for different data sources."""
return calculate_data_quality_scores(data_sources)
@staticmethod
def extract_content_preferences_from_style(writing_style: Dict[str, Any]) -> Dict[str, Any]:
"""Extract content preferences from writing style analysis."""
return extract_content_preferences_from_style(writing_style)
@staticmethod
def extract_brand_voice_from_guidelines(style_guidelines: Dict[str, Any]) -> Dict[str, Any]:
"""Extract brand voice from style guidelines."""
return extract_brand_voice_from_guidelines(style_guidelines)
@staticmethod
def extract_editorial_guidelines_from_style(writing_style: Dict[str, Any]) -> Dict[str, Any]:
"""Extract editorial guidelines from writing style analysis."""
return extract_editorial_guidelines_from_style(writing_style)
@staticmethod
def create_field_mappings() -> Dict[str, str]:
"""Create field mappings for strategy data transformation."""
return create_field_mappings()

File diff suppressed because it is too large Load Diff