Files
ALwrity/backend/api/onboarding_utils/onboarding_summary_service.py

199 lines
9.5 KiB
Python

"""
Onboarding Summary Service
Handles the complex logic for generating comprehensive onboarding summaries.
"""
from typing import Dict, Any, Optional
from fastapi import HTTPException
from loguru import logger
from services.api_key_manager import get_api_key_manager
from services.database import get_db
from services.onboarding_database_service import OnboardingDatabaseService
from services.website_analysis_service import WebsiteAnalysisService
from services.research_preferences_service import ResearchPreferencesService
from services.persona_analysis_service import PersonaAnalysisService
class OnboardingSummaryService:
"""Service for handling onboarding summary generation with user isolation."""
def __init__(self, user_id: str):
"""
Initialize service with user-specific context.
Args:
user_id: Clerk user ID from authenticated request
"""
self.user_id = user_id # Store Clerk user ID (string)
self.db_service = OnboardingDatabaseService()
logger.info(f"OnboardingSummaryService initialized for user {user_id} (database mode)")
async def get_onboarding_summary(self) -> Dict[str, Any]:
"""Get comprehensive onboarding summary for FinalStep."""
try:
# Get API keys
api_keys = self._get_api_keys()
# Get website analysis data
website_analysis = self._get_website_analysis()
# Get research preferences
research_preferences = self._get_research_preferences()
# Get personalization settings
personalization_settings = self._get_personalization_settings(research_preferences)
# Check persona generation readiness
persona_readiness = self._check_persona_readiness(website_analysis)
# Determine capabilities
capabilities = self._determine_capabilities(api_keys, website_analysis, research_preferences, personalization_settings, persona_readiness)
return {
"api_keys": api_keys,
"website_url": website_analysis.get('website_url') if website_analysis else None,
"style_analysis": website_analysis.get('style_analysis') if website_analysis else None,
"research_preferences": research_preferences,
"personalization_settings": personalization_settings,
"persona_readiness": persona_readiness,
"integrations": {}, # TODO: Implement integrations data
"capabilities": capabilities
}
except Exception as e:
logger.error(f"Error getting onboarding summary: {str(e)}")
raise HTTPException(status_code=500, detail="Internal server error")
def _get_api_keys(self) -> Dict[str, Any]:
"""Get configured API keys from database."""
try:
db = next(get_db())
api_keys = self.db_service.get_api_keys(self.user_id, db)
logger.info(f"Retrieved {len(api_keys)} API keys from database for user {self.user_id}")
return api_keys
except Exception as e:
logger.error(f"Error getting API keys from database: {e}")
return {}
def _get_website_analysis(self) -> Optional[Dict[str, Any]]:
"""Get website analysis data from database (Step 2)."""
try:
db = next(get_db())
website_data = self.db_service.get_website_analysis(self.user_id, db)
if website_data:
logger.info(f"Retrieved website analysis from database for user {self.user_id}")
else:
logger.warning(f"No website analysis found in database for user {self.user_id}")
return website_data
except Exception as e:
logger.error(f"Error getting website analysis from database: {e}")
return None
def _get_research_preferences(self) -> Optional[Dict[str, Any]]:
"""Get research preferences data from database (Step 3)."""
try:
db = next(get_db())
research_data = self.db_service.get_research_preferences(self.user_id, db)
if research_data:
logger.info(f"Retrieved research preferences from database for user {self.user_id}")
else:
logger.warning(f"No research preferences found in database for user {self.user_id}")
return research_data
except Exception as e:
logger.error(f"Error getting research preferences from database: {e}")
return None
def _get_personalization_settings(self, research_preferences: Optional[Dict[str, Any]]) -> Optional[Dict[str, Any]]:
"""Get personalization settings from Step 4 (Persona) database."""
try:
# Try to get from Step 4 (Persona) in database
db = next(get_db())
persona_data = self.db_service.get_persona_data(self.user_id, db)
if persona_data:
logger.info(f"Retrieved persona data from database for user {self.user_id}")
# Extract personalization settings from persona data
if 'corePersona' in persona_data:
core_persona = persona_data.get('corePersona', {})
return {
'writing_style': core_persona.get('linguistic_fingerprint', {}).get('tone', 'Professional'),
'tone': core_persona.get('tonal_range', {}).get('primary_tone', 'Formal'),
'brand_voice': core_persona.get('identity', {}).get('voice', 'Trustworthy and Expert')
}
# Fallback to research preferences if persona data not available
if research_preferences:
logger.info(f"Using research preferences as fallback for personalization")
return {
'writing_style': research_preferences.get('writing_style', {}).get('tone', 'Professional'),
'tone': research_preferences.get('writing_style', {}).get('voice', 'Formal'),
'brand_voice': research_preferences.get('writing_style', {}).get('complexity', 'Trustworthy and Expert')
}
return None
except Exception as e:
logger.error(f"Error getting personalization settings from database: {e}")
return None
def _check_persona_readiness(self, website_analysis: Optional[Dict[str, Any]]) -> Optional[Dict[str, Any]]:
"""Check if persona can be generated."""
try:
persona_service = PersonaAnalysisService()
# Check if persona can be generated
onboarding_data = persona_service._collect_onboarding_data(self.user_id)
if onboarding_data:
data_sufficiency = persona_service._calculate_data_sufficiency(onboarding_data)
return {
"ready": data_sufficiency >= 50.0,
"data_sufficiency": data_sufficiency,
"can_generate": website_analysis is not None
}
return {"ready": False, "data_sufficiency": 0.0, "can_generate": False}
except Exception as e:
logger.warning(f"Could not check persona readiness: {str(e)}")
return {"ready": False, "error": str(e)}
def _determine_capabilities(self, api_keys: Dict[str, Any], website_analysis: Optional[Dict[str, Any]],
research_preferences: Optional[Dict[str, Any]],
personalization_settings: Optional[Dict[str, Any]],
persona_readiness: Optional[Dict[str, Any]]) -> Dict[str, bool]:
"""Determine user capabilities based on onboarding data."""
return {
"ai_content": len(api_keys) > 0,
"style_analysis": website_analysis is not None,
"research_tools": research_preferences is not None,
"personalization": personalization_settings is not None,
"persona_generation": persona_readiness.get("ready", False) if persona_readiness else False,
"integrations": False # TODO: Implement
}
async def get_website_analysis_data(self) -> Optional[Dict[str, Any]]:
"""Get website analysis data for FinalStep."""
try:
analysis = self._get_website_analysis()
if analysis:
return {
"website_url": analysis.get('website_url'),
"style_analysis": analysis.get('style_analysis'),
"style_patterns": analysis.get('style_patterns'),
"style_guidelines": analysis.get('style_guidelines'),
"status": analysis.get('status'),
"completed_at": analysis.get('created_at')
}
else:
return None
except Exception as e:
logger.error(f"Error getting website analysis data: {str(e)}")
raise HTTPException(status_code=500, detail="Internal server error")
async def get_research_preferences_data(self) -> Optional[Dict[str, Any]]:
"""Get research preferences data for FinalStep."""
try:
return self._get_research_preferences()
except Exception as e:
logger.error(f"Error getting research preferences data: {str(e)}")
raise HTTPException(status_code=500, detail="Internal server error")