ALwrity LinkedIn Writer: Billing Dashboard: Compact View, Billing Overview, System Health Indicator, Cost Breakdown, Usage Trends, Usage Alerts, Comprehensive API Breakdown

This commit is contained in:
ajaysi
2025-09-11 11:09:10 +05:30
parent b156298e82
commit 1b65a9487b
84 changed files with 10143 additions and 156 deletions

View File

@@ -0,0 +1,101 @@
#!/usr/bin/env python3
"""
Debug Database Data
This script checks what data is actually in the database for debugging.
"""
import asyncio
import sys
import os
from loguru import logger
# Add the backend directory to the path
backend_dir = os.path.dirname(os.path.abspath(__file__))
if backend_dir not in sys.path:
sys.path.insert(0, backend_dir)
# Add the services directory to the path
services_dir = os.path.join(backend_dir, "services")
if services_dir not in sys.path:
sys.path.insert(0, services_dir)
async def debug_database_data():
"""Debug what data is in the database."""
try:
logger.info("🔍 Debugging database data")
# Initialize database
from services.database import init_database, get_db_session
try:
init_database()
logger.info("✅ Database initialized successfully")
except Exception as e:
logger.error(f"❌ Database initialization failed: {str(e)}")
return False
# Get database session
db_session = get_db_session()
if not db_session:
logger.error("❌ Failed to get database session")
return False
from services.content_planning_db import ContentPlanningDBService
db_service = ContentPlanningDBService(db_session)
# Check content strategies
logger.info("📋 Checking content strategies...")
strategies = await db_service.get_user_content_strategies(1)
logger.info(f"Found {len(strategies)} strategies for user 1")
for strategy in strategies:
logger.info(f"Strategy ID: {strategy.id}, Name: {strategy.name}")
logger.info(f" Content Pillars: {strategy.content_pillars}")
logger.info(f" Target Audience: {strategy.target_audience}")
# Check gap analyses
logger.info("📋 Checking gap analyses...")
gap_analyses = await db_service.get_user_content_gap_analyses(1)
logger.info(f"Found {len(gap_analyses)} gap analyses for user 1")
for gap_analysis in gap_analyses:
logger.info(f"Gap Analysis ID: {gap_analysis.id}")
logger.info(f" Website URL: {gap_analysis.website_url}")
logger.info(f" Analysis Results: {gap_analysis.analysis_results}")
logger.info(f" Recommendations: {gap_analysis.recommendations}")
logger.info(f" Opportunities: {gap_analysis.opportunities}")
# Check if analysis_results has content_gaps
if gap_analysis.analysis_results:
content_gaps = gap_analysis.analysis_results.get("content_gaps", [])
logger.info(f" Content Gaps in analysis_results: {len(content_gaps)} items")
for gap in content_gaps:
logger.info(f" - {gap}")
else:
logger.info(" Analysis Results is None or empty")
db_session.close()
logger.info("✅ Database debugging completed")
return True
except Exception as e:
logger.error(f"❌ Debug failed with error: {str(e)}")
return False
if __name__ == "__main__":
# Configure logging
logger.remove()
logger.add(sys.stderr, level="INFO", format="<green>{time:HH:mm:ss}</green> | <level>{level: <8}</level> | <cyan>{name}</cyan>:<cyan>{function}</cyan>:<cyan>{line}</cyan> - <level>{message}</level>")
# Run the debug
success = asyncio.run(debug_database_data())
if success:
logger.info("✅ Debug completed successfully!")
sys.exit(0)
else:
logger.error("❌ Debug failed!")
sys.exit(1)

175
backend/test/debug_step8.py Normal file
View File

@@ -0,0 +1,175 @@
#!/usr/bin/env python3
"""
Debug script for Step 8 (Daily Content Planning) to isolate data type issues.
"""
import asyncio
import logging
import sys
import os
# Add the project root to the Python path
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
from services.calendar_generation_datasource_framework.prompt_chaining.steps.phase3.step8_daily_content_planning.daily_schedule_generator import DailyScheduleGenerator
# Configure logging
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s | %(levelname)-8s | %(name)s:%(funcName)s:%(lineno)d - %(message)s',
datefmt='%H:%M:%S'
)
logger = logging.getLogger(__name__)
async def debug_step8():
"""Debug Step 8 with controlled test data."""
logger.info("🔍 Starting Step 8 Debug Session")
# Create test data with known types
test_weekly_themes = [
{
"title": "Week 1 Theme: AI Implementation",
"description": "Focus on AI tools and implementation",
"primary_pillar": "AI and Machine Learning",
"content_angles": ["AI tools", "Implementation guide", "Best practices"],
"target_platforms": ["LinkedIn", "Blog", "Twitter"],
"strategic_alignment": "High alignment with business goals",
"gap_addressal": "Addresses AI implementation gap",
"priority": "high",
"estimated_impact": "High",
"ai_confidence": 0.9,
"week_number": 1
},
{
"title": "Week 2 Theme: Digital Transformation",
"description": "Digital transformation strategies",
"primary_pillar": "Digital Transformation",
"content_angles": ["Strategy", "Case studies", "ROI"],
"target_platforms": ["LinkedIn", "Blog", "YouTube"],
"strategic_alignment": "Medium alignment with business goals",
"gap_addressal": "Addresses transformation gap",
"priority": "medium",
"estimated_impact": "Medium",
"ai_confidence": 0.8,
"week_number": 2
}
]
test_platform_strategies = {
"LinkedIn": {
"content_type": "professional",
"posting_frequency": "daily",
"engagement_strategy": "thought_leadership"
},
"Blog": {
"content_type": "educational",
"posting_frequency": "weekly",
"engagement_strategy": "seo_optimized"
},
"Twitter": {
"content_type": "conversational",
"posting_frequency": "daily",
"engagement_strategy": "community_building"
}
}
test_content_pillars = [
{
"name": "AI and Machine Learning",
"weight": 0.4,
"description": "AI tools and implementation"
},
{
"name": "Digital Transformation",
"weight": 0.3,
"description": "Digital strategy and transformation"
},
{
"name": "Business Strategy",
"weight": 0.3,
"description": "Strategic business insights"
}
]
test_calendar_framework = {
"type": "monthly",
"total_weeks": 4,
"posting_frequency": "daily",
"posting_days": ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday"],
"industry": "technology",
"business_size": "sme"
}
test_posting_preferences = {
"preferred_times": ["09:00", "12:00", "15:00"],
"posting_frequency": "daily",
"content_count_per_day": 2
}
test_business_goals = [
"Increase brand awareness by 40%",
"Generate 500 qualified leads per month",
"Establish thought leadership"
]
test_target_audience = {
"primary": "Tech professionals",
"secondary": "Business leaders",
"demographics": {
"age_range": "25-45",
"location": "Global"
}
}
# Test data type validation
logger.info("🔍 Validating test data types:")
logger.info(f" weekly_themes: {type(test_weekly_themes)} (length: {len(test_weekly_themes)})")
logger.info(f" platform_strategies: {type(test_platform_strategies)}")
logger.info(f" content_pillars: {type(test_content_pillars)}")
logger.info(f" calendar_framework: {type(test_calendar_framework)}")
logger.info(f" posting_preferences: {type(test_posting_preferences)}")
logger.info(f" business_goals: {type(test_business_goals)}")
logger.info(f" target_audience: {type(test_target_audience)}")
# Validate weekly themes structure
for i, theme in enumerate(test_weekly_themes):
logger.info(f" Theme {i+1}: {type(theme)} - keys: {list(theme.keys())}")
if not isinstance(theme, dict):
logger.error(f"❌ Theme {i+1} is not a dictionary: {type(theme)}")
return
try:
# Initialize the daily schedule generator
generator = DailyScheduleGenerator()
logger.info("✅ DailyScheduleGenerator initialized successfully")
# Test the generate_daily_schedules method
logger.info("🚀 Testing generate_daily_schedules method...")
daily_schedules = await generator.generate_daily_schedules(
weekly_themes=test_weekly_themes,
platform_strategies=test_platform_strategies,
business_goals=test_business_goals,
target_audience=test_target_audience,
posting_preferences=test_posting_preferences,
calendar_duration=28 # 4 weeks * 7 days
)
logger.info(f"✅ Successfully generated {len(daily_schedules)} daily schedules")
# Log first few schedules for inspection
for i, schedule in enumerate(daily_schedules[:3]):
logger.info(f" Schedule {i+1}: {type(schedule)} - keys: {list(schedule.keys())}")
except Exception as e:
logger.error(f"❌ Error in Step 8 debug: {str(e)}")
logger.error(f"📋 Error type: {type(e)}")
import traceback
logger.error(f"📋 Traceback: {traceback.format_exc()}")
return
logger.info("🎉 Step 8 debug completed successfully!")
if __name__ == "__main__":
asyncio.run(debug_step8())

View File

@@ -0,0 +1,118 @@
#!/usr/bin/env python3
"""
Debug script to test AI response parsing in Step 8.
"""
import asyncio
import logging
import sys
import os
# Add the project root to the Python path
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
from services.calendar_generation_datasource_framework.prompt_chaining.steps.phase3.step8_daily_content_planning.daily_schedule_generator import DailyScheduleGenerator
# Configure logging
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s | %(levelname)-8s | %(name)s:%(funcName)s:%(lineno)d - %(message)s',
datefmt='%H:%M:%S'
)
logger = logging.getLogger(__name__)
async def debug_ai_response_parsing():
"""Debug AI response parsing in Step 8."""
logger.info("🔍 Starting AI Response Parsing Debug")
# Create test data
test_posting_day = {
"day_number": 1,
"date": "2025-09-01",
"day_name": "monday",
"posting_times": ["09:00", "12:00"],
"content_count": 2,
"week_number": 1
}
test_weekly_theme = {
"title": "Week 1 Theme: AI Implementation",
"description": "Focus on AI tools and implementation",
"content_angles": ["AI tools", "Implementation guide", "Best practices"]
}
test_platform_strategies = {
"LinkedIn": {"approach": "professional"},
"Blog": {"approach": "educational"}
}
# Test different AI response formats
test_responses = [
# Format 1: List of recommendations (correct format)
[
{
"type": "Content Creation Opportunity",
"title": "AI Implementation Guide",
"description": "A comprehensive guide to AI implementation"
},
{
"type": "Content Creation Opportunity",
"title": "AI Tools Overview",
"description": "Overview of AI tools for business"
}
],
# Format 2: Dictionary with recommendations key
{
"recommendations": [
{
"type": "Content Creation Opportunity",
"title": "AI Implementation Guide",
"description": "A comprehensive guide to AI implementation"
},
{
"type": "Content Creation Opportunity",
"title": "AI Tools Overview",
"description": "Overview of AI tools for business"
}
]
},
# Format 3: Float (the problematic case)
0.95,
# Format 4: String
"AI Implementation Guide",
# Format 5: None
None
]
generator = DailyScheduleGenerator()
for i, test_response in enumerate(test_responses):
logger.info(f"🔍 Testing AI response format {i+1}: {type(test_response)} = {test_response}")
try:
content_pieces = generator._parse_content_response(
ai_response=test_response,
posting_day=test_posting_day,
weekly_theme=test_weekly_theme,
platform_strategies=test_platform_strategies
)
logger.info(f"✅ Format {i+1} parsed successfully: {len(content_pieces)} content pieces")
for j, piece in enumerate(content_pieces):
logger.info(f" Piece {j+1}: {piece.get('title', 'No title')}")
except Exception as e:
logger.error(f"❌ Format {i+1} failed: {str(e)}")
logger.error(f"📋 Error type: {type(e)}")
import traceback
logger.error(f"📋 Traceback: {traceback.format_exc()}")
logger.info("🎉 AI Response Parsing Debug completed!")
if __name__ == "__main__":
asyncio.run(debug_ai_response_parsing())

View File

@@ -0,0 +1,402 @@
#!/usr/bin/env python3
"""
Step 8 Debug Script - Isolated Testing
=====================================
This script tests Step 8 (Daily Content Planning) in isolation with controlled inputs
to identify which specific parameter is causing the 'float' object has no attribute 'get' error.
The script will:
1. Set up Step 8 with fixed, known dictionary inputs
2. Test the daily content generation in isolation
3. Identify which specific parameter is coming through as a float
4. Help pinpoint whether the issue is in weekly_theme, posting_day, platform_strategies, or other data
"""
import asyncio
import sys
import os
import logging
from typing import Dict, List, Any
# Add the project root to the path
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
# Configure logging
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger(__name__)
# Import Step 8 components
from services.calendar_generation_datasource_framework.prompt_chaining.steps.phase3.step8_daily_content_planning.step8_main import DailyContentPlanningStep
from services.calendar_generation_datasource_framework.prompt_chaining.steps.phase3.step8_daily_content_planning.daily_schedule_generator import DailyScheduleGenerator
def create_controlled_test_data():
"""Create controlled test data with known types for Step 8 testing."""
# 1. Weekly themes from Step 7 (should be list of dictionaries)
weekly_themes = [
{
"title": "Week 1 Theme: AI Implementation Guide",
"description": "Comprehensive guide on AI implementation for businesses",
"primary_pillar": "AI and Machine Learning",
"secondary_pillars": ["Digital Transformation", "Innovation"],
"strategic_alignment": "high",
"audience_alignment": "high",
"week_number": 1,
"content_count": 5,
"priority": "high",
"estimated_impact": "High",
"ai_confidence": 0.9
},
{
"title": "Week 2 Theme: Digital Transformation Strategies",
"description": "Strategic approaches to digital transformation",
"primary_pillar": "Digital Transformation",
"secondary_pillars": ["Business Strategy", "Innovation"],
"strategic_alignment": "high",
"audience_alignment": "medium",
"week_number": 2,
"content_count": 4,
"priority": "medium",
"estimated_impact": "Medium",
"ai_confidence": 0.8
}
]
# 2. Platform strategies from Step 6 (should be dictionary)
platform_strategies = {
"linkedin": {
"content_types": ["articles", "posts", "videos"],
"posting_times": ["09:00", "12:00", "15:00"],
"content_adaptation": "professional tone, industry insights",
"engagement_strategy": "thought leadership content"
},
"twitter": {
"content_types": ["tweets", "threads", "images"],
"posting_times": ["08:00", "11:00", "14:00", "17:00"],
"content_adaptation": "concise, engaging, hashtag optimization",
"engagement_strategy": "conversation starters"
}
}
# 3. Content pillars from Step 5 (should be list)
content_pillars = [
"AI and Machine Learning",
"Digital Transformation",
"Innovation and Technology Trends",
"Business Strategy and Growth"
]
# 4. Calendar framework from Step 4 (should be dictionary)
calendar_framework = {
"duration_weeks": 4,
"content_frequency": "daily",
"posting_schedule": {
"monday": ["09:00", "12:00", "15:00"],
"tuesday": ["09:00", "12:00", "15:00"],
"wednesday": ["09:00", "12:00", "15:00"],
"thursday": ["09:00", "12:00", "15:00"],
"friday": ["09:00", "12:00", "15:00"]
},
"theme_structure": "weekly_themes",
"content_mix": {
"blog_posts": 0.4,
"social_media": 0.3,
"videos": 0.2,
"infographics": 0.1
}
}
# 5. Business goals from Step 1 (should be list)
business_goals = [
"Increase brand awareness by 40%",
"Generate 500 qualified leads per month",
"Establish thought leadership"
]
# 6. Target audience from Step 1 (should be dictionary)
target_audience = {
"primary": "Tech professionals",
"secondary": "Business leaders",
"demographics": {
"age_range": "25-45",
"location": "Global",
"interests": ["technology", "innovation", "business growth"]
}
}
# 7. Keywords from Step 2 (should be list)
keywords = [
"AI implementation",
"digital transformation",
"machine learning",
"business automation",
"technology trends"
]
return {
"weekly_themes": weekly_themes,
"platform_strategies": platform_strategies,
"content_pillars": content_pillars,
"calendar_framework": calendar_framework,
"business_goals": business_goals,
"target_audience": target_audience,
"keywords": keywords
}
def validate_data_types(data: Dict[str, Any], test_name: str):
"""Validate that all data has the expected types."""
logger.info(f"🔍 Validating data types for {test_name}")
expected_types = {
"weekly_themes": list,
"platform_strategies": dict,
"content_pillars": list,
"calendar_framework": dict,
"business_goals": list,
"target_audience": dict,
"keywords": list
}
for key, expected_type in expected_types.items():
if key in data:
actual_type = type(data[key])
if actual_type != expected_type:
logger.error(f"❌ Type mismatch for {key}: expected {expected_type.__name__}, got {actual_type.__name__}")
logger.error(f" Value: {data[key]}")
return False
else:
logger.info(f"{key}: {actual_type.__name__} (correct)")
else:
logger.warning(f"⚠️ Missing key: {key}")
return True
async def test_daily_schedule_generator_isolated():
"""Test the DailyScheduleGenerator in isolation with controlled inputs."""
logger.info("🧪 Testing DailyScheduleGenerator in isolation")
# Create controlled test data
test_data = create_controlled_test_data()
# Validate data types
if not validate_data_types(test_data, "DailyScheduleGenerator"):
logger.error("❌ Data type validation failed")
return False
try:
# Create DailyScheduleGenerator instance
generator = DailyScheduleGenerator()
# Test the generate_daily_schedules method
logger.info("📅 Testing generate_daily_schedules method")
# Get posting preferences and calendar duration
posting_preferences = {
"preferred_times": ["09:00", "12:00", "15:00"],
"posting_frequency": "daily"
}
calendar_duration = test_data["calendar_framework"]["duration_weeks"] * 7
# Call the method with controlled inputs
daily_schedules = await generator.generate_daily_schedules(
test_data["weekly_themes"],
test_data["platform_strategies"],
test_data["content_pillars"],
test_data["calendar_framework"],
posting_preferences,
calendar_duration
)
logger.info(f"✅ DailyScheduleGenerator test successful")
logger.info(f" Generated {len(daily_schedules)} daily schedules")
# Validate the output
if isinstance(daily_schedules, list):
logger.info("✅ Output is a list (correct)")
for i, schedule in enumerate(daily_schedules[:3]): # Show first 3
logger.info(f" Schedule {i+1}: {type(schedule)} - {schedule.get('day_number', 'N/A')}")
else:
logger.error(f"❌ Output is not a list: {type(daily_schedules)}")
return False
return True
except Exception as e:
logger.error(f"❌ DailyScheduleGenerator test failed: {str(e)}")
logger.error(f" Exception type: {type(e).__name__}")
import traceback
logger.error(f" Traceback: {traceback.format_exc()}")
return False
async def test_step8_execute_method():
"""Test Step 8's execute method with controlled inputs."""
logger.info("🧪 Testing Step 8 execute method")
# Create controlled test data
test_data = create_controlled_test_data()
# Validate data types
if not validate_data_types(test_data, "Step 8 Execute"):
logger.error("❌ Data type validation failed")
return False
try:
# Create Step 8 instance
step8 = DailyContentPlanningStep()
# Create context with controlled data
context = {
"step_results": {
"step_07": {
"result": {
"weekly_themes": test_data["weekly_themes"]
}
},
"step_06": {
"result": {
"platform_strategies": test_data["platform_strategies"]
}
},
"step_05": {
"result": {
"content_pillars": test_data["content_pillars"]
}
},
"step_04": {
"result": {
"calendar_framework": test_data["calendar_framework"]
}
},
"step_01": {
"result": {
"business_goals": test_data["business_goals"],
"target_audience": test_data["target_audience"]
}
},
"step_02": {
"result": {
"keywords": test_data["keywords"]
}
}
},
"user_data": {
"business_goals": test_data["business_goals"],
"target_audience": test_data["target_audience"],
"keywords": test_data["keywords"]
}
}
# Test the execute method
logger.info("📅 Testing Step 8 execute method")
result = await step8.execute(context)
logger.info(f"✅ Step 8 execute test successful")
logger.info(f" Result type: {type(result)}")
logger.info(f" Result keys: {list(result.keys()) if isinstance(result, dict) else 'N/A'}")
return True
except Exception as e:
logger.error(f"❌ Step 8 execute test failed: {str(e)}")
logger.error(f" Exception type: {type(e).__name__}")
import traceback
logger.error(f" Traceback: {traceback.format_exc()}")
return False
async def test_specific_methods_with_debugging():
"""Test specific methods with detailed debugging to identify the float issue."""
logger.info("🔍 Testing specific methods with detailed debugging")
# Create controlled test data
test_data = create_controlled_test_data()
try:
# Create DailyScheduleGenerator instance
generator = DailyScheduleGenerator()
# Test _get_weekly_theme method specifically
logger.info("🔍 Testing _get_weekly_theme method")
for week_num in [1, 2]:
theme = generator._get_weekly_theme(test_data["weekly_themes"], week_num)
logger.info(f" Week {week_num} theme type: {type(theme)}")
logger.info(f" Week {week_num} theme: {theme}")
if not isinstance(theme, dict):
logger.error(f"❌ Week {week_num} theme is not a dictionary!")
return False
# Test _generate_daily_content method with controlled inputs
logger.info("🔍 Testing _generate_daily_content method")
# Create a controlled posting_day
posting_day = {
"day_number": 1,
"week_number": 1,
"content_count": 3,
"platforms": ["linkedin", "twitter"]
}
# Test with controlled weekly theme
weekly_theme = test_data["weekly_themes"][0] # First theme
# Test the method
content = await generator._generate_daily_content(
posting_day,
weekly_theme,
test_data["platform_strategies"],
test_data["content_pillars"],
test_data["calendar_framework"]
)
logger.info(f"✅ _generate_daily_content test successful")
logger.info(f" Content type: {type(content)}")
logger.info(f" Content: {content}")
return True
except Exception as e:
logger.error(f"❌ Specific method test failed: {str(e)}")
logger.error(f" Exception type: {type(e).__name__}")
import traceback
logger.error(f" Traceback: {traceback.format_exc()}")
return False
async def main():
"""Main debug function."""
logger.info("🚀 Starting Step 8 Debug Script")
logger.info("=" * 50)
# Test 1: DailyScheduleGenerator in isolation
logger.info("\n🧪 Test 1: DailyScheduleGenerator in isolation")
success1 = await test_daily_schedule_generator_isolated()
# Test 2: Step 8 execute method
logger.info("\n🧪 Test 2: Step 8 execute method")
success2 = await test_step8_execute_method()
# Test 3: Specific methods with debugging
logger.info("\n🧪 Test 3: Specific methods with debugging")
success3 = await test_specific_methods_with_debugging()
# Summary
logger.info("\n" + "=" * 50)
logger.info("📊 Debug Results Summary")
logger.info("=" * 50)
logger.info(f"✅ Test 1 (DailyScheduleGenerator): {'PASSED' if success1 else 'FAILED'}")
logger.info(f"✅ Test 2 (Step 8 Execute): {'PASSED' if success2 else 'FAILED'}")
logger.info(f"✅ Test 3 (Specific Methods): {'PASSED' if success3 else 'FAILED'}")
if success1 and success2 and success3:
logger.info("🎉 All tests passed! Step 8 is working correctly with controlled inputs.")
logger.info("💡 The issue might be in the data flow from previous steps.")
else:
logger.error("❌ Some tests failed. Check the logs above for specific issues.")
logger.info("=" * 50)
if __name__ == "__main__":
asyncio.run(main())

View File

@@ -0,0 +1,197 @@
#!/usr/bin/env python3
"""
Deployment script for the Persona System.
Sets up database tables and validates the complete system.
"""
import sys
import os
# Add the backend directory to the Python path
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
from loguru import logger
def deploy_persona_system():
"""Deploy the complete persona system."""
logger.info("🚀 Deploying Persona System")
try:
# Step 1: Create database tables
logger.info("📊 Step 1: Creating database tables...")
from scripts.create_persona_tables import create_persona_tables
create_persona_tables()
logger.info("✅ Database tables created")
# Step 2: Validate Gemini integration
logger.info("🤖 Step 2: Validating Gemini integration...")
from services.llm_providers.gemini_provider import gemini_structured_json_response
test_schema = {
"type": "object",
"properties": {
"status": {"type": "string"},
"timestamp": {"type": "string"}
},
"required": ["status"]
}
test_response = gemini_structured_json_response(
prompt="Return status='ready' and current timestamp",
schema=test_schema,
temperature=0.1,
max_tokens=1024
)
if "error" in test_response:
logger.warning(f"⚠️ Gemini test warning: {test_response['error']}")
else:
logger.info("✅ Gemini integration validated")
# Step 3: Test persona service
logger.info("🧠 Step 3: Testing persona service...")
from services.persona_analysis_service import PersonaAnalysisService
persona_service = PersonaAnalysisService()
logger.info("✅ Persona service initialized")
# Step 4: Test replication engine
logger.info("⚙️ Step 4: Testing replication engine...")
from services.persona_replication_engine import PersonaReplicationEngine
replication_engine = PersonaReplicationEngine()
logger.info("✅ Replication engine initialized")
# Step 5: Validate API endpoints
logger.info("🌐 Step 5: Validating API endpoints...")
from api.persona_routes import router
logger.info(f"✅ Persona router configured with {len(router.routes)} routes")
logger.info("🎉 Persona System deployed successfully!")
# Print deployment summary
print_deployment_summary()
return True
except Exception as e:
logger.error(f"❌ Deployment failed: {str(e)}")
return False
def print_deployment_summary():
"""Print deployment summary and next steps."""
logger.info("📋 PERSONA SYSTEM DEPLOYMENT SUMMARY")
logger.info("=" * 50)
logger.info("✅ Database Tables:")
logger.info(" - writing_personas")
logger.info(" - platform_personas")
logger.info(" - persona_analysis_results")
logger.info(" - persona_validation_results")
logger.info("✅ Services:")
logger.info(" - PersonaAnalysisService")
logger.info(" - PersonaReplicationEngine")
logger.info("✅ API Endpoints:")
logger.info(" - POST /api/personas/generate")
logger.info(" - GET /api/personas/user/{user_id}")
logger.info(" - GET /api/personas/platform/{platform}")
logger.info(" - GET /api/personas/export/{platform}")
logger.info("✅ Platform Support:")
logger.info(" - Twitter/X, LinkedIn, Instagram, Facebook")
logger.info(" - Blog, Medium, Substack")
logger.info("🔧 NEXT STEPS:")
logger.info("1. Complete onboarding with website analysis (Step 2)")
logger.info("2. Set research preferences (Step 3)")
logger.info("3. Generate persona in Final Step (Step 6)")
logger.info("4. Export hardened prompts for external AI systems")
logger.info("5. Use persona for consistent content generation")
logger.info("=" * 50)
def validate_deployment():
"""Validate that all components are working correctly."""
logger.info("🔍 Validating deployment...")
validation_results = {
"database": False,
"gemini": False,
"persona_service": False,
"replication_engine": False,
"api_routes": False
}
try:
# Test database
from services.database import get_db_session
session = get_db_session()
if session:
session.close()
validation_results["database"] = True
logger.info("✅ Database connection validated")
# Test Gemini
from services.llm_providers.gemini_provider import get_gemini_api_key
api_key = get_gemini_api_key()
if api_key and api_key != "your_gemini_api_key_here":
validation_results["gemini"] = True
logger.info("✅ Gemini API key configured")
else:
logger.warning("⚠️ Gemini API key not configured")
# Test services
from services.persona_analysis_service import PersonaAnalysisService
from services.persona_replication_engine import PersonaReplicationEngine
PersonaAnalysisService()
PersonaReplicationEngine()
validation_results["persona_service"] = True
validation_results["replication_engine"] = True
logger.info("✅ Services validated")
# Test API routes
from api.persona_routes import router
if len(router.routes) > 0:
validation_results["api_routes"] = True
logger.info("✅ API routes validated")
except Exception as e:
logger.error(f"❌ Validation error: {str(e)}")
# Summary
passed = sum(validation_results.values())
total = len(validation_results)
logger.info(f"📊 Validation Results: {passed}/{total} components validated")
if passed == total:
logger.info("🎉 All components validated successfully!")
return True
else:
logger.warning("⚠️ Some components failed validation")
for component, status in validation_results.items():
status_icon = "" if status else ""
logger.info(f" {status_icon} {component}")
return False
if __name__ == "__main__":
# Deploy system
deployment_success = deploy_persona_system()
if deployment_success:
# Validate deployment
validation_success = validate_deployment()
if validation_success:
logger.info("🎉 Persona System ready for production!")
sys.exit(0)
else:
logger.error("❌ Deployment validation failed")
sys.exit(1)
else:
logger.error("❌ Deployment failed")
sys.exit(1)

View File

@@ -0,0 +1,48 @@
#!/usr/bin/env python3
"""
Script to fix import paths in step files
"""
import os
import re
def fix_imports_in_file(file_path):
"""Fix import paths in a file."""
try:
with open(file_path, 'r', encoding='utf-8') as f:
content = f.read()
# Fix the base_step import path
# Change from ..base_step to ...base_step for subdirectories
if '/step9_content_recommendations/' in file_path or '/step10_performance_optimization/' in file_path or '/step11_strategy_alignment_validation/' in file_path or '/step12_final_calendar_assembly/' in file_path:
content = re.sub(r'from \.\.base_step import', 'from ...base_step import', content)
with open(file_path, 'w', encoding='utf-8') as f:
f.write(content)
print(f"✅ Fixed imports in {file_path}")
return True
except Exception as e:
print(f"❌ Error fixing {file_path}: {e}")
return False
def main():
"""Main function to fix all import paths."""
base_path = "services/calendar_generation_datasource_framework/prompt_chaining/steps"
# Files that need fixing
files_to_fix = [
f"{base_path}/phase3/step9_content_recommendations/step9_main.py",
f"{base_path}/phase4/step10_performance_optimization/step10_main.py",
f"{base_path}/phase4/step11_strategy_alignment_validation/step11_main.py",
f"{base_path}/phase4/step12_final_calendar_assembly/step12_main.py",
]
for file_path in files_to_fix:
if os.path.exists(file_path):
fix_imports_in_file(file_path)
else:
print(f"⚠️ File not found: {file_path}")
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,66 @@
#!/usr/bin/env python3
"""
Test script for calendar generation API
"""
import asyncio
import aiohttp
import json
async def test_calendar_generation():
"""Test the calendar generation API."""
url = "http://localhost:8000/api/content-planning/calendar-generation/start"
payload = {
"user_id": 1,
"strategy_id": 1,
"calendar_type": "monthly",
"industry": "technology",
"business_size": "sme"
}
async with aiohttp.ClientSession() as session:
try:
async with session.post(url, json=payload) as response:
if response.status == 200:
result = await response.json()
print("✅ Calendar generation started successfully!")
print(f"Session ID: {result.get('session_id')}")
# Test progress endpoint
session_id = result.get('session_id')
if session_id:
print(f"\n🔄 Testing progress for session: {session_id}")
progress_url = f"http://localhost:8000/api/content-planning/calendar-generation/progress/{session_id}"
async with session.get(progress_url) as progress_response:
if progress_response.status == 200:
progress_data = await progress_response.json()
print("✅ Progress endpoint working!")
print(f"Status: {progress_data.get('status')}")
print(f"Current Step: {progress_data.get('current_step')}")
print(f"Overall Progress: {progress_data.get('overall_progress')}%")
# Check for Step 4 specifically
step_results = progress_data.get('step_results', {})
if 'step_04' in step_results:
step4_result = step_results['step_04']
print(f"\n📊 Step 4 Status: {step4_result.get('status')}")
print(f"Step 4 Quality: {step4_result.get('quality_score')}")
if step4_result.get('status') == 'error':
print(f"Step 4 Error: {step4_result.get('error_message')}")
else:
print("⚠️ Step 4 results not yet available")
else:
print(f"❌ Progress endpoint failed: {progress_response.status}")
else:
print(f"❌ Calendar generation failed: {response.status}")
error_text = await response.text()
print(f"Error: {error_text}")
except Exception as e:
print(f"❌ Error testing calendar generation: {e}")
if __name__ == "__main__":
asyncio.run(test_calendar_generation())

View File

@@ -0,0 +1,383 @@
#!/usr/bin/env python3
"""
Test Script for Calendar Generation Data Source Framework
Demonstrates the functionality of the scalable framework for evolving data sources
in calendar generation without architectural changes.
"""
import asyncio
import sys
import os
from pathlib import Path
# Add the backend directory to the Python path
backend_dir = Path(__file__).parent
sys.path.insert(0, str(backend_dir))
from services.calendar_generation_datasource_framework import (
DataSourceRegistry,
StrategyAwarePromptBuilder,
QualityGateManager,
DataSourceEvolutionManager,
ContentStrategyDataSource,
GapAnalysisDataSource,
KeywordsDataSource,
ContentPillarsDataSource,
PerformanceDataSource,
AIAnalysisDataSource
)
async def test_framework_initialization():
"""Test framework initialization and component setup."""
print("🧪 Testing Framework Initialization...")
try:
# Initialize registry
registry = DataSourceRegistry()
print("✅ DataSourceRegistry initialized successfully")
# Initialize data sources
content_strategy = ContentStrategyDataSource()
gap_analysis = GapAnalysisDataSource()
keywords = KeywordsDataSource()
content_pillars = ContentPillarsDataSource()
performance_data = PerformanceDataSource()
ai_analysis = AIAnalysisDataSource()
print("✅ All data sources initialized successfully")
# Register data sources
registry.register_source(content_strategy)
registry.register_source(gap_analysis)
registry.register_source(keywords)
registry.register_source(content_pillars)
registry.register_source(performance_data)
registry.register_source(ai_analysis)
print("✅ All data sources registered successfully")
# Initialize framework components
prompt_builder = StrategyAwarePromptBuilder(registry)
quality_manager = QualityGateManager()
evolution_manager = DataSourceEvolutionManager(registry)
print("✅ Framework components initialized successfully")
return registry, prompt_builder, quality_manager, evolution_manager
except Exception as e:
print(f"❌ Framework initialization failed: {e}")
return None, None, None, None
async def test_data_source_registry(registry):
"""Test data source registry functionality."""
print("\n🧪 Testing Data Source Registry...")
try:
# Test registry status
status = registry.get_registry_status()
print(f"✅ Registry status: {status['total_sources']} sources, {status['active_sources']} active")
# Test source retrieval
content_strategy = registry.get_source("content_strategy")
if content_strategy:
print(f"✅ Content strategy source retrieved: {content_strategy}")
# Test active sources
active_sources = registry.get_active_sources()
print(f"✅ Active sources: {len(active_sources)}")
# Test source types
strategy_sources = registry.get_sources_by_type("strategy")
print(f"✅ Strategy sources: {len(strategy_sources)}")
# Test priorities
critical_sources = registry.get_sources_by_priority(1)
print(f"✅ Critical priority sources: {len(critical_sources)}")
return True
except Exception as e:
print(f"❌ Registry test failed: {e}")
return False
async def test_data_source_validation(registry):
"""Test data source validation functionality."""
print("\n🧪 Testing Data Source Validation...")
try:
# Validate all sources
validation_results = await registry.validate_all_sources()
print(f"✅ Validation completed for {len(validation_results)} sources")
# Check validation results
for source_id, result in validation_results.items():
if hasattr(result, 'quality_score'):
print(f" - {source_id}: {result.quality_score:.2f} quality score")
else:
print(f" - {source_id}: {result.get('quality_score', 0):.2f} quality score")
return True
except Exception as e:
print(f"❌ Validation test failed: {e}")
return False
async def test_prompt_builder(prompt_builder):
"""Test strategy-aware prompt builder functionality."""
print("\n🧪 Testing Strategy-Aware Prompt Builder...")
try:
# Test available steps
available_steps = prompt_builder.get_available_steps()
print(f"✅ Available steps: {len(available_steps)}")
# Test step dependencies
step_1_deps = prompt_builder.get_step_dependencies("step_1_content_strategy_analysis")
print(f"✅ Step 1 dependencies: {step_1_deps}")
# Test step requirements validation
step_validation = prompt_builder.validate_step_requirements("step_1_content_strategy_analysis")
print(f"✅ Step 1 validation: {step_validation['is_ready']}")
# Test prompt building (simplified)
try:
prompt = await prompt_builder.build_prompt("step_1_content_strategy_analysis", 1, 1)
print(f"✅ Prompt built successfully (length: {len(prompt)} characters)")
except Exception as e:
print(f"⚠️ Prompt building failed (expected for test): {e}")
return True
except Exception as e:
print(f"❌ Prompt builder test failed: {e}")
return False
async def test_quality_gates(quality_manager):
"""Test quality gate functionality."""
print("\n🧪 Testing Quality Gates...")
try:
# Test quality gate info
gate_info = quality_manager.get_gate_info()
print(f"✅ Quality gates: {len(gate_info)} gates available")
# Test specific gate validation
sample_calendar_data = {
"content_items": [
{"title": "Sample Content 1", "type": "blog", "theme": "technology"},
{"title": "Sample Content 2", "type": "video", "theme": "marketing"}
]
}
# Test all gates validation
validation_results = await quality_manager.validate_all_gates(sample_calendar_data, "test_step")
print(f"✅ All gates validation: {len(validation_results)} gates validated")
# Test specific gate validation
content_uniqueness_result = await quality_manager.validate_specific_gate("content_uniqueness", sample_calendar_data, "test_step")
print(f"✅ Content uniqueness validation: {content_uniqueness_result['passed']}")
return True
except Exception as e:
print(f"❌ Quality gates test failed: {e}")
return False
async def test_evolution_manager(evolution_manager):
"""Test evolution manager functionality."""
print("\n🧪 Testing Evolution Manager...")
try:
# Test evolution status
status = evolution_manager.get_evolution_status()
print(f"✅ Evolution status for {len(status)} sources")
# Test evolution summary
summary = evolution_manager.get_evolution_summary()
print(f"✅ Evolution summary: {summary['sources_needing_evolution']} need evolution")
# Test evolution plan
plan = evolution_manager.get_evolution_plan("content_strategy")
print(f"✅ Content strategy evolution plan: {plan['is_ready_for_evolution']}")
# Test evolution (simplified)
try:
success = await evolution_manager.evolve_data_source("content_strategy", "2.5.0")
print(f"✅ Evolution test: {'Success' if success else 'Failed'}")
except Exception as e:
print(f"⚠️ Evolution test failed (expected for test): {e}")
return True
except Exception as e:
print(f"❌ Evolution manager test failed: {e}")
return False
async def test_framework_integration(registry, prompt_builder, quality_manager, evolution_manager):
"""Test framework integration and end-to-end functionality."""
print("\n🧪 Testing Framework Integration...")
try:
# Test comprehensive workflow
print("📊 Testing comprehensive workflow...")
# 1. Get data from sources
print(" 1. Retrieving data from sources...")
for source_id in ["content_strategy", "gap_analysis", "keywords"]:
try:
data = await registry.get_data_with_dependencies(source_id, 1, 1)
print(f"{source_id}: Data retrieved")
except Exception as e:
print(f" ⚠️ {source_id}: Data retrieval failed (expected)")
# 2. Build enhanced prompts
print(" 2. Building enhanced prompts...")
for step in ["step_1_content_strategy_analysis", "step_2_gap_analysis"]:
try:
base_prompt = await prompt_builder.build_prompt(step, 1, 1)
print(f"{step}: Prompt built")
except Exception as e:
print(f" ⚠️ {step}: Prompt building failed (expected)")
# 3. Check evolution readiness
print(" 3. Checking evolution readiness...")
for source_id in ["content_strategy", "gap_analysis", "keywords"]:
plan = evolution_manager.get_evolution_plan(source_id)
print(f"{source_id}: Ready for evolution: {plan['is_ready_for_evolution']}")
print("✅ Framework integration test completed")
return True
except Exception as e:
print(f"❌ Framework integration test failed: {e}")
return False
async def test_scalability_features(registry, evolution_manager):
"""Test scalability features of the framework."""
print("\n🧪 Testing Scalability Features...")
try:
# Test adding custom data source
print("📈 Testing custom data source addition...")
# Create a custom data source (simplified)
from services.calendar_generation_datasource_framework.interfaces import DataSourceInterface, DataSourceType, DataSourcePriority
class CustomDataSource(DataSourceInterface):
def __init__(self):
super().__init__("custom_source", DataSourceType.CUSTOM, DataSourcePriority.LOW)
async def get_data(self, user_id: int, strategy_id: int):
return {"custom_data": "test"}
async def validate_data(self, data):
return {"is_valid": True, "quality_score": 0.8}
async def enhance_data(self, data):
return {**data, "enhanced": True}
# Register custom source
custom_source = CustomDataSource()
registry.register_source(custom_source)
print("✅ Custom data source registered successfully")
# Test evolution config addition
custom_config = {
"current_version": "1.0.0",
"target_version": "1.5.0",
"enhancement_plan": ["Custom enhancement"],
"implementation_steps": ["Implement custom enhancement"],
"priority": "low",
"estimated_effort": "low"
}
evolution_manager.add_evolution_config("custom_source", custom_config)
print("✅ Custom evolution config added successfully")
# Test framework status with new source
status = registry.get_registry_status()
print(f"✅ Framework now has {status['total_sources']} sources")
return True
except Exception as e:
print(f"❌ Scalability test failed: {e}")
return False
async def main():
"""Run all framework tests."""
print("🚀 Starting Calendar Generation Data Source Framework Tests...")
print("=" * 80)
# Initialize framework
registry, prompt_builder, quality_manager, evolution_manager = await test_framework_initialization()
if not all([registry, prompt_builder, quality_manager, evolution_manager]):
print("❌ Framework initialization failed. Exiting.")
return False
# Run individual component tests
tests = [
("Data Source Registry", test_data_source_registry, registry),
("Data Source Validation", test_data_source_validation, registry),
("Prompt Builder", test_prompt_builder, prompt_builder),
("Quality Gates", test_quality_gates, quality_manager),
("Evolution Manager", test_evolution_manager, evolution_manager),
("Framework Integration", test_framework_integration, registry, prompt_builder, quality_manager, evolution_manager),
("Scalability Features", test_scalability_features, registry, evolution_manager)
]
results = []
for test_name, test_func, *args in tests:
try:
result = await test_func(*args)
results.append((test_name, result))
except Exception as e:
print(f"{test_name} test failed with exception: {e}")
results.append((test_name, False))
# Print test summary
print("\n" + "=" * 80)
print("📋 Test Results Summary:")
passed = 0
total = len(results)
for test_name, result in results:
status = "✅ PASSED" if result else "❌ FAILED"
print(f" {status} - {test_name}")
if result:
passed += 1
print(f"\n🎯 Overall Results: {passed}/{total} tests passed")
if passed == total:
print("🎉 All tests passed! Framework is working correctly.")
print("\n✅ Framework Features Verified:")
print(" - Scalable data source management")
print(" - Strategy-aware prompt building")
print(" - Quality gate integration")
print(" - Evolution management")
print(" - Framework integration")
print(" - Scalability and extensibility")
return True
else:
print("⚠️ Some tests failed. Please check the implementation.")
return False
if __name__ == "__main__":
# Run the tests
success = asyncio.run(main())
sys.exit(0 if success else 1)

View File

@@ -0,0 +1,228 @@
#!/usr/bin/env python3
"""
Test Script for Enhanced LinkedIn Prompt Generation
This script demonstrates how the enhanced LinkedIn prompt generator analyzes
generated content and creates context-aware image prompts.
"""
import asyncio
import sys
import os
from pathlib import Path
# Add the backend directory to the Python path
backend_path = Path(__file__).parent
sys.path.insert(0, str(backend_path))
from loguru import logger
# Configure logging
logger.remove()
logger.add(sys.stdout, colorize=True, format="<level>{level}</level>| {message}")
async def test_enhanced_prompt_generation():
"""Test the enhanced LinkedIn prompt generation with content analysis."""
logger.info("🧪 Testing Enhanced LinkedIn Prompt Generation")
logger.info("=" * 70)
try:
# Import the enhanced prompt generator
from services.linkedin.image_prompts import LinkedInPromptGenerator
# Initialize the service
prompt_generator = LinkedInPromptGenerator()
logger.success("✅ LinkedIn Prompt Generator initialized successfully")
# Test cases with different types of LinkedIn content
test_cases = [
{
'name': 'AI Marketing Post',
'content': {
'topic': 'AI in Marketing',
'industry': 'Technology',
'content_type': 'post',
'content': """🚀 Exciting news! Artificial Intelligence is revolutionizing how we approach marketing strategies.
Here are 3 game-changing ways AI is transforming the industry:
1⃣ **Predictive Analytics**: AI algorithms can now predict customer behavior with 95% accuracy, allowing marketers to create hyper-personalized campaigns.
2⃣ **Content Optimization**: Machine learning models analyze engagement patterns to optimize content timing, format, and messaging for maximum impact.
3⃣ **Automated Personalization**: AI-powered tools automatically adjust marketing messages based on individual user preferences and behavior.
The future of marketing is here, and it's powered by AI! 🎯
What's your experience with AI in marketing? Share your thoughts below! 👇
#AIMarketing #DigitalTransformation #MarketingInnovation #TechTrends #FutureOfMarketing"""
}
},
{
'name': 'Leadership Article',
'content': {
'topic': 'Building High-Performance Teams',
'industry': 'Business',
'content_type': 'article',
'content': """Building High-Performance Teams: A Comprehensive Guide
In today's competitive business landscape, the ability to build and lead high-performance teams is not just a skill—it's a strategic imperative. After 15 years of leading teams across various industries, I've identified the key principles that consistently drive exceptional results.
**The Foundation: Clear Vision and Purpose**
Every high-performance team starts with a crystal-clear understanding of their mission. Team members need to know not just what they're doing, but why it matters. This creates intrinsic motivation that external rewards simply cannot match.
**Communication: The Lifeblood of Success**
Effective communication in high-performance teams goes beyond regular meetings. It involves creating an environment where feedback flows freely, ideas are shared without fear, and every voice is heard and valued.
**Trust and Psychological Safety**
High-performance teams operate in environments where team members feel safe to take risks, make mistakes, and learn from failures. This psychological safety is the bedrock of innovation and continuous improvement.
**Continuous Learning and Adaptation**
The best teams never rest on their laurels. They continuously seek new knowledge, adapt to changing circumstances, and evolve their approaches based on results and feedback.
**Results and Accountability**
While process matters, high-performance teams are ultimately measured by their results. Clear metrics, regular check-ins, and a culture of accountability ensure that the team stays focused on delivering value.
Building high-performance teams is both an art and a science. It requires patience, persistence, and a genuine commitment to developing people. The investment pays dividends not just in results, but in the satisfaction of seeing individuals grow and teams achieve what once seemed impossible.
What strategies have you found most effective in building high-performance teams? Share your insights in the comments below."""
}
},
{
'name': 'Data Analytics Carousel',
'content': {
'topic': 'Data-Driven Decision Making',
'industry': 'Finance',
'content_type': 'carousel',
'content': """📊 Data-Driven Decision Making: Your Competitive Advantage
Slide 1: The Power of Data
• 73% of companies using data-driven decision making report improved performance
• Data-driven organizations are 23x more likely to acquire customers
• 58% of executives say data analytics has improved their decision-making process
Slide 2: Key Metrics to Track
• Customer Acquisition Cost (CAC)
• Customer Lifetime Value (CLV)
• Conversion Rates
• Churn Rate
• Revenue Growth
Slide 3: Implementation Steps
1. Define clear objectives
2. Identify relevant data sources
3. Establish data quality standards
4. Build analytical capabilities
5. Create feedback loops
Slide 4: Common Pitfalls
• Analysis paralysis
• Ignoring qualitative insights
• Not validating assumptions
• Over-relying on historical data
• Poor data visualization
Slide 5: Success Stories
• Netflix: 75% of viewing decisions influenced by data
• Amazon: Dynamic pricing increases revenue by 25%
• Spotify: Personalized recommendations drive 40% of listening time
Slide 6: Getting Started
• Start small with key metrics
• Invest in data literacy training
• Use visualization tools
• Establish regular review cycles
• Celebrate data-driven wins
Ready to transform your decision-making process? Let's discuss your data strategy! 💬
#DataDriven #Analytics #BusinessIntelligence #DecisionMaking #Finance #Strategy"""
}
}
]
# Test each case
for i, test_case in enumerate(test_cases, 1):
logger.info(f"\n📝 Test Case {i}: {test_case['name']}")
logger.info("-" * 50)
# Generate prompts using the enhanced generator
prompts = await prompt_generator.generate_three_prompts(
test_case['content'],
aspect_ratio="1:1"
)
if prompts and len(prompts) >= 3:
logger.success(f"✅ Generated {len(prompts)} context-aware prompts")
# Display each prompt
for j, prompt in enumerate(prompts, 1):
logger.info(f"\n🎨 Prompt {j}: {prompt['style']}")
logger.info(f" Description: {prompt['description']}")
logger.info(f" Content Context: {prompt.get('content_context', 'N/A')}")
# Show a preview of the prompt
prompt_text = prompt['prompt']
if len(prompt_text) > 200:
prompt_text = prompt_text[:200] + "..."
logger.info(f" Prompt Preview: {prompt_text}")
# Validate prompt quality
quality_result = await prompt_generator.validate_prompt_quality(prompt)
if quality_result.get('valid'):
logger.success(f" ✅ Quality Score: {quality_result['overall_score']}/100")
else:
logger.warning(f" ⚠️ Quality Score: {quality_result.get('overall_score', 'N/A')}/100")
else:
logger.error(f"❌ Failed to generate prompts for {test_case['name']}")
# Test content analysis functionality directly
logger.info(f"\n🔍 Testing Content Analysis Functionality")
logger.info("-" * 50)
test_content = test_cases[0]['content']['content']
content_analysis = prompt_generator._analyze_content_for_image_context(
test_content,
test_cases[0]['content']['content_type']
)
logger.info("Content Analysis Results:")
for key, value in content_analysis.items():
logger.info(f" {key}: {value}")
logger.info("=" * 70)
logger.success("🎉 Enhanced LinkedIn Prompt Generation Test Completed Successfully!")
return True
except ImportError as e:
logger.error(f"❌ Import Error: {e}")
return False
except Exception as e:
logger.error(f"❌ Test Failed: {e}")
import traceback
logger.error(f"Traceback: {traceback.format_exc()}")
return False
async def main():
"""Main test function."""
logger.info("🚀 Starting Enhanced LinkedIn Prompt Generation Tests")
success = await test_enhanced_prompt_generation()
if success:
logger.success("✅ All tests passed! The enhanced prompt generation is working correctly.")
sys.exit(0)
else:
logger.error("❌ Some tests failed. Please check the errors above.")
sys.exit(1)
if __name__ == "__main__":
# Run the async test
asyncio.run(main())

View File

@@ -0,0 +1,201 @@
#!/usr/bin/env python3
"""
Test script for Enhanced Strategy Data Processing
Verifies that the enhanced strategy data processing is working correctly.
"""
import asyncio
import sys
import os
from pathlib import Path
# Add the backend directory to the Python path
backend_dir = Path(__file__).parent
sys.path.insert(0, str(backend_dir))
from services.content_planning_db import ContentPlanningDBService
async def test_enhanced_strategy_processing():
"""Test the enhanced strategy data processing functionality."""
print("🧪 Testing Enhanced Strategy Data Processing...")
try:
# Initialize the database service
db_service = ContentPlanningDBService()
# Test with a sample strategy ID
strategy_id = 1 # You can change this to test with different strategies
print(f"📊 Testing strategy data retrieval for strategy ID: {strategy_id}")
# Test the enhanced strategy data retrieval
strategy_data = await db_service.get_strategy_data(strategy_id)
if strategy_data:
print("✅ Strategy data retrieved successfully!")
print(f"📈 Strategy data contains {len(strategy_data)} fields")
# Check for enhanced fields
enhanced_fields = [
"strategy_analysis",
"quality_indicators",
"data_completeness",
"strategic_alignment",
"quality_gate_data",
"prompt_chain_data"
]
print("\n🔍 Checking for enhanced strategy fields:")
for field in enhanced_fields:
if field in strategy_data:
print(f"{field}: Present")
if isinstance(strategy_data[field], dict):
print(f" Contains {len(strategy_data[field])} sub-fields")
else:
print(f"{field}: Missing")
# Check strategy analysis
if "strategy_analysis" in strategy_data:
analysis = strategy_data["strategy_analysis"]
print(f"\n📊 Strategy Analysis:")
print(f" - Completion Percentage: {analysis.get('completion_percentage', 0)}%")
print(f" - Filled Fields: {analysis.get('filled_fields', 0)}/{analysis.get('total_fields', 30)}")
print(f" - Data Quality Score: {analysis.get('data_quality_score', 0)}%")
print(f" - Strategy Coherence: {analysis.get('strategy_coherence', {}).get('overall_coherence', 0)}%")
# Check quality indicators
if "quality_indicators" in strategy_data:
quality = strategy_data["quality_indicators"]
print(f"\n🎯 Quality Indicators:")
print(f" - Data Completeness: {quality.get('data_completeness', 0)}%")
print(f" - Strategic Alignment: {quality.get('strategic_alignment', 0)}%")
print(f" - Market Relevance: {quality.get('market_relevance', 0)}%")
print(f" - Audience Alignment: {quality.get('audience_alignment', 0)}%")
print(f" - Content Strategy Coherence: {quality.get('content_strategy_coherence', 0)}%")
print(f" - Overall Quality Score: {quality.get('overall_quality_score', 0)}%")
# Check quality gate data
if "quality_gate_data" in strategy_data:
quality_gates = strategy_data["quality_gate_data"]
print(f"\n🚪 Quality Gate Data:")
for gate_name, gate_data in quality_gates.items():
if isinstance(gate_data, dict):
print(f" - {gate_name}: {len(gate_data)} fields")
else:
print(f" - {gate_name}: {type(gate_data).__name__}")
# Check prompt chain data
if "prompt_chain_data" in strategy_data:
prompt_chain = strategy_data["prompt_chain_data"]
print(f"\n🔗 Prompt Chain Data:")
for step_name, step_data in prompt_chain.items():
if isinstance(step_data, dict):
print(f" - {step_name}: {len(step_data)} sub-sections")
else:
print(f" - {step_name}: {type(step_data).__name__}")
print(f"\n✅ Enhanced Strategy Data Processing Test PASSED!")
return True
else:
print("❌ No strategy data retrieved")
return False
except Exception as e:
print(f"❌ Error during enhanced strategy data processing test: {str(e)}")
import traceback
traceback.print_exc()
return False
async def test_comprehensive_user_data():
"""Test the comprehensive user data retrieval with enhanced strategy data."""
print("\n🧪 Testing Comprehensive User Data with Enhanced Strategy...")
try:
# Initialize the database service
db_service = ContentPlanningDBService()
# Test with a sample user ID and strategy ID
user_id = 1
strategy_id = 1
print(f"📊 Testing comprehensive user data for user {user_id} with strategy {strategy_id}")
# Test the comprehensive user data retrieval
user_data = await calendar_service._get_comprehensive_user_data(user_id, strategy_id)
if user_data:
print("✅ Comprehensive user data retrieved successfully!")
print(f"📈 User data contains {len(user_data)} fields")
# Check for enhanced strategy fields in user data
enhanced_fields = [
"strategy_analysis",
"quality_indicators",
"data_completeness",
"strategic_alignment",
"quality_gate_data",
"prompt_chain_data"
]
print("\n🔍 Checking for enhanced strategy fields in user data:")
for field in enhanced_fields:
if field in user_data:
print(f"{field}: Present")
if isinstance(user_data[field], dict):
print(f" Contains {len(user_data[field])} sub-fields")
else:
print(f"{field}: Missing")
# Check strategy data quality
if "strategy_data" in user_data:
strategy_data = user_data["strategy_data"]
print(f"\n📊 Strategy Data Quality:")
print(f" - Strategy ID: {strategy_data.get('strategy_id', 'N/A')}")
print(f" - Strategy Name: {strategy_data.get('strategy_name', 'N/A')}")
print(f" - Industry: {strategy_data.get('industry', 'N/A')}")
print(f" - Content Pillars: {len(strategy_data.get('content_pillars', []))} pillars")
print(f" - Target Audience: {len(strategy_data.get('target_audience', {}))} audience fields")
print(f"\n✅ Comprehensive User Data Test PASSED!")
return True
else:
print("❌ No comprehensive user data retrieved")
return False
except Exception as e:
print(f"❌ Error during comprehensive user data test: {str(e)}")
import traceback
traceback.print_exc()
return False
async def main():
"""Run all tests for enhanced strategy data processing."""
print("🚀 Starting Enhanced Strategy Data Processing Tests...")
print("=" * 60)
# Test 1: Enhanced Strategy Data Processing
test1_passed = await test_enhanced_strategy_processing()
# Test 2: Comprehensive User Data
test2_passed = await test_comprehensive_user_data()
print("\n" + "=" * 60)
print("📋 Test Results Summary:")
print(f" ✅ Enhanced Strategy Data Processing: {'PASSED' if test1_passed else 'FAILED'}")
print(f" ✅ Comprehensive User Data: {'PASSED' if test2_passed else 'FAILED'}")
if test1_passed and test2_passed:
print("\n🎉 All Enhanced Strategy Data Processing Tests PASSED!")
print("✅ The enhanced strategy data processing is working correctly.")
print("✅ Ready for 12-step prompt chaining and quality gates integration.")
return True
else:
print("\n❌ Some tests failed. Please check the implementation.")
return False
if __name__ == "__main__":
# Run the tests
success = asyncio.run(main())
sys.exit(0 if success else 1)

View File

@@ -0,0 +1,232 @@
"""Test script for Facebook Writer API endpoints."""
import requests
import json
from typing import Dict, Any
# Base URL for the API
BASE_URL = "http://localhost:8000"
def test_health_check():
"""Test the health check endpoint."""
try:
response = requests.get(f"{BASE_URL}/api/facebook-writer/health")
print(f"Health Check: {response.status_code}")
if response.status_code == 200:
print(f"Response: {response.json()}")
return response.status_code == 200
except Exception as e:
print(f"Health check failed: {e}")
return False
def test_get_tools():
"""Test getting available tools."""
try:
response = requests.get(f"{BASE_URL}/api/facebook-writer/tools")
print(f"Get Tools: {response.status_code}")
if response.status_code == 200:
data = response.json()
print(f"Available tools: {data['total_count']}")
for tool in data['tools'][:3]: # Show first 3 tools
print(f" - {tool['name']}: {tool['description']}")
return response.status_code == 200
except Exception as e:
print(f"Get tools failed: {e}")
return False
def test_generate_post():
"""Test Facebook post generation."""
payload = {
"business_type": "Fitness coach",
"target_audience": "Fitness enthusiasts aged 25-35",
"post_goal": "Increase engagement",
"post_tone": "Inspirational",
"include": "Success story, workout tips",
"avoid": "Generic advice",
"media_type": "Image",
"advanced_options": {
"use_hook": True,
"use_story": True,
"use_cta": True,
"use_question": True,
"use_emoji": True,
"use_hashtags": True
}
}
try:
response = requests.post(
f"{BASE_URL}/api/facebook-writer/post/generate",
json=payload,
headers={"Content-Type": "application/json"}
)
print(f"Generate Post: {response.status_code}")
if response.status_code == 200:
data = response.json()
if data['success']:
print(f"Post generated successfully!")
print(f"Content preview: {data['content'][:100]}...")
if data.get('analytics'):
print(f"Expected reach: {data['analytics']['expected_reach']}")
else:
print(f"Generation failed: {data.get('error', 'Unknown error')}")
else:
print(f"Request failed: {response.text}")
return response.status_code == 200
except Exception as e:
print(f"Generate post failed: {e}")
return False
def test_generate_story():
"""Test Facebook story generation."""
payload = {
"business_type": "Fashion brand",
"target_audience": "Fashion enthusiasts aged 18-30",
"story_type": "Product showcase",
"story_tone": "Fun",
"include": "Behind the scenes",
"avoid": "Too much text",
"visual_options": {
"background_type": "Gradient",
"text_overlay": True,
"stickers": True,
"interactive_elements": True
}
}
try:
response = requests.post(
f"{BASE_URL}/api/facebook-writer/story/generate",
json=payload,
headers={"Content-Type": "application/json"}
)
print(f"Generate Story: {response.status_code}")
if response.status_code == 200:
data = response.json()
if data['success']:
print(f"Story generated successfully!")
print(f"Content preview: {data['content'][:100]}...")
if data.get('visual_suggestions'):
print(f"Visual suggestions: {len(data['visual_suggestions'])} items")
else:
print(f"Generation failed: {data.get('error', 'Unknown error')}")
return response.status_code == 200
except Exception as e:
print(f"Generate story failed: {e}")
return False
def test_generate_ad_copy():
"""Test Facebook ad copy generation."""
payload = {
"business_type": "E-commerce store",
"product_service": "Wireless headphones",
"ad_objective": "Conversions",
"ad_format": "Single image",
"target_audience": "Tech enthusiasts and music lovers",
"targeting_options": {
"age_group": "25-34",
"interests": "Technology, Music, Audio equipment",
"location": "United States"
},
"unique_selling_proposition": "Premium sound quality at affordable prices",
"offer_details": "20% off for first-time buyers",
"budget_range": "Medium"
}
try:
response = requests.post(
f"{BASE_URL}/api/facebook-writer/ad-copy/generate",
json=payload,
headers={"Content-Type": "application/json"}
)
print(f"Generate Ad Copy: {response.status_code}")
if response.status_code == 200:
data = response.json()
if data['success']:
print(f"Ad copy generated successfully!")
if data.get('primary_ad_copy'):
print(f"Headline: {data['primary_ad_copy'].get('headline', 'N/A')}")
if data.get('performance_predictions'):
print(f"Estimated reach: {data['performance_predictions']['estimated_reach']}")
else:
print(f"Generation failed: {data.get('error', 'Unknown error')}")
return response.status_code == 200
except Exception as e:
print(f"Generate ad copy failed: {e}")
return False
def test_analyze_engagement():
"""Test engagement analysis."""
payload = {
"content": "🚀 Ready to transform your fitness journey? Our new 30-day challenge is here! Join thousands who've already seen amazing results. What's your biggest fitness goal? 💪 #FitnessMotivation #Challenge #Transformation",
"content_type": "Post",
"analysis_type": "Performance prediction",
"business_type": "Fitness coach",
"target_audience": "Fitness enthusiasts"
}
try:
response = requests.post(
f"{BASE_URL}/api/facebook-writer/engagement/analyze",
json=payload,
headers={"Content-Type": "application/json"}
)
print(f"Analyze Engagement: {response.status_code}")
if response.status_code == 200:
data = response.json()
if data['success']:
print(f"Analysis completed successfully!")
print(f"Content score: {data.get('content_score', 'N/A')}/100")
if data.get('engagement_metrics'):
print(f"Predicted engagement: {data['engagement_metrics']['predicted_engagement_rate']}")
else:
print(f"Analysis failed: {data.get('error', 'Unknown error')}")
return response.status_code == 200
except Exception as e:
print(f"Analyze engagement failed: {e}")
return False
def main():
"""Run all tests."""
print("🧪 Testing Facebook Writer API Endpoints")
print("=" * 50)
tests = [
("Health Check", test_health_check),
("Get Tools", test_get_tools),
("Generate Post", test_generate_post),
("Generate Story", test_generate_story),
("Generate Ad Copy", test_generate_ad_copy),
("Analyze Engagement", test_analyze_engagement)
]
results = []
for test_name, test_func in tests:
print(f"\n🔍 Running {test_name}...")
try:
success = test_func()
results.append((test_name, success))
status = "✅ PASS" if success else "❌ FAIL"
print(f"{status}")
except Exception as e:
print(f"❌ FAIL - {e}")
results.append((test_name, False))
print(f"\n📊 Test Results Summary")
print("=" * 50)
passed = sum(1 for _, success in results if success)
total = len(results)
for test_name, success in results:
status = "✅ PASS" if success else "❌ FAIL"
print(f"{status} {test_name}")
print(f"\nOverall: {passed}/{total} tests passed ({passed/total*100:.1f}%)")
if passed == total:
print("🎉 All tests passed! Facebook Writer API is ready to use.")
else:
print("⚠️ Some tests failed. Check the server logs for details.")
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,140 @@
#!/usr/bin/env python3
"""
Test the full 12-step calendar generation process to verify Step 5 fix.
"""
import asyncio
import time
from loguru import logger
import sys
import os
# Add the backend directory to the path
backend_dir = os.path.dirname(os.path.abspath(__file__))
if backend_dir not in sys.path:
sys.path.insert(0, backend_dir)
from services.calendar_generation_datasource_framework.prompt_chaining.orchestrator import PromptChainOrchestrator
async def test_full_12_step_process():
"""Test the complete 12-step process to verify Step 5 fix."""
try:
logger.info("🧪 Testing full 12-step calendar generation process")
# Create orchestrator
logger.info("✅ Creating orchestrator...")
orchestrator = PromptChainOrchestrator()
# Test parameters
user_id = 1
strategy_id = 1
calendar_type = "monthly"
industry = "technology"
business_size = "sme"
logger.info(f"🎯 Starting calendar generation for user {user_id}, strategy {strategy_id}")
logger.info(f"📋 Parameters: {calendar_type}, {industry}, {business_size}")
# Start the full process
start_time = time.time()
# Generate calendar using the orchestrator's main method
logger.info("🚀 Executing full 12-step process...")
final_calendar = await orchestrator.generate_calendar(
user_id=user_id,
strategy_id=strategy_id,
calendar_type=calendar_type,
industry=industry,
business_size=business_size
)
# Extract context from the result for analysis
context = {
"step_results": final_calendar.get("step_results", {}),
"quality_scores": final_calendar.get("quality_scores", {})
}
execution_time = time.time() - start_time
logger.info(f"✅ Full 12-step process completed in {execution_time:.2f} seconds")
# Analyze results
step_results = context.get("step_results", {})
quality_scores = context.get("quality_scores", {})
logger.info("📊 Step Results Analysis:")
logger.info(f" Total steps executed: {len(step_results)}")
# Check each step
for step_key in sorted(step_results.keys()):
step_result = step_results[step_key]
status = step_result.get("status", "unknown")
quality_score = step_result.get("quality_score", 0.0)
validation_passed = step_result.get("validation_passed", False)
logger.info(f" {step_key}: status={status}, quality={quality_score:.2f}, validation_passed={validation_passed}")
if status == "failed" or status == "error":
logger.error(f"{step_key} failed with status: {status}")
error_message = step_result.get("error_message", "No error message")
logger.error(f" Error: {error_message}")
# Check Step 5 specifically
step_05_result = step_results.get("step_05", {})
if step_05_result:
step_05_status = step_05_result.get("status", "unknown")
step_05_quality = step_05_result.get("quality_score", 0.0)
step_05_validation = step_05_result.get("validation_passed", False)
logger.info(f"🎯 Step 5 Analysis:")
logger.info(f" Status: {step_05_status}")
logger.info(f" Quality Score: {step_05_quality:.2f}")
logger.info(f" Validation Passed: {step_05_validation}")
if step_05_status == "completed" and step_05_validation:
logger.info("✅ Step 5 FIX VERIFIED - Working correctly in full process!")
else:
logger.error("❌ Step 5 still has issues in full process")
else:
logger.error("❌ Step 5 result not found in step_results")
# Overall quality
overall_quality = sum(quality_scores.values()) / len(quality_scores) if quality_scores else 0.0
logger.info(f"📊 Overall Quality Score: {overall_quality:.2f}")
# Success criteria
completed_steps = sum(1 for result in step_results.values() if result.get("status") == "completed")
total_steps = len(step_results)
logger.info(f"📊 Process Summary:")
logger.info(f" Completed Steps: {completed_steps}/{total_steps}")
logger.info(f" Success Rate: {(completed_steps/total_steps)*100:.1f}%")
logger.info(f" Overall Quality: {overall_quality:.2f}")
if completed_steps == total_steps and overall_quality > 0.8:
logger.info("🎉 SUCCESS: Full 12-step process completed successfully!")
return True
else:
logger.error("❌ FAILURE: Full 12-step process had issues")
return False
except Exception as e:
logger.error(f"❌ Error in full 12-step process test: {str(e)}")
import traceback
logger.error(f"📋 Traceback: {traceback.format_exc()}")
return False
if __name__ == "__main__":
# Configure logging
logger.remove()
logger.add(sys.stderr, level="INFO", format="<green>{time:HH:mm:ss}</green> | <level>{level: <8}</level> | <cyan>{name}</cyan>:<cyan>{function}</cyan>:<cyan>{line}</cyan> - <level>{message}</level>")
# Run the test
success = asyncio.run(test_full_12_step_process())
if success:
print("\n🎉 Test completed successfully!")
sys.exit(0)
else:
print("\n❌ Test failed!")
sys.exit(1)

View File

@@ -0,0 +1,62 @@
#!/usr/bin/env python3
"""
Test script to debug the grounding data flow
"""
import asyncio
import sys
import os
# Add the backend directory to the path
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
from services.linkedin_service import LinkedInService
from models.linkedin_models import LinkedInPostRequest, GroundingLevel
async def test_grounding_flow():
"""Test the grounding data flow"""
try:
print("🔍 Testing grounding data flow...")
# Initialize the service
service = LinkedInService()
print("✅ LinkedInService initialized")
# Create a test request
request = LinkedInPostRequest(
topic="AI in healthcare transformation",
industry="Healthcare",
grounding_level=GroundingLevel.ENHANCED,
include_citations=True,
research_enabled=True,
search_engine="google",
max_length=2000
)
print("✅ Test request created")
# Generate post
print("🚀 Generating LinkedIn post...")
response = await service.generate_linkedin_post(request)
if response.success:
print("✅ Post generated successfully!")
print(f"📊 Research sources count: {len(response.research_sources) if response.research_sources else 0}")
print(f"📝 Citations count: {len(response.data.citations) if response.data.citations else 0}")
print(f"🔗 Source list: {response.data.source_list[:200] if response.data.source_list else 'None'}")
if response.research_sources:
print(f"📚 First research source: {response.research_sources[0]}")
print(f"📚 Research source types: {[type(s) for s in response.research_sources[:3]]}")
if response.data.citations:
print(f"📝 First citation: {response.data.citations[0]}")
else:
print(f"❌ Post generation failed: {response.error}")
except Exception as e:
print(f"❌ Error during test: {str(e)}")
import traceback
traceback.print_exc()
if __name__ == "__main__":
asyncio.run(test_grounding_flow())

View File

@@ -0,0 +1,228 @@
"""
Test script for LinkedIn grounding integration.
This script tests the integration of the new grounding services:
- GoogleSearchService
- GeminiGroundedProvider
- CitationManager
- ContentQualityAnalyzer
- Enhanced LinkedInService
"""
import asyncio
import os
from datetime import datetime
from loguru import logger
# Set up environment variables for testing
os.environ.setdefault('GOOGLE_SEARCH_API_KEY', 'test_key')
os.environ.setdefault('GOOGLE_SEARCH_ENGINE_ID', 'test_engine_id')
os.environ.setdefault('GEMINI_API_KEY', 'test_gemini_key')
from services.linkedin_service import LinkedInService
from models.linkedin_models import (
LinkedInPostRequest, LinkedInArticleRequest, LinkedInCarouselRequest,
LinkedInVideoScriptRequest, LinkedInCommentResponseRequest,
GroundingLevel, SearchEngine, LinkedInTone, LinkedInPostType
)
async def test_grounding_integration():
"""Test the complete grounding integration."""
logger.info("Starting LinkedIn grounding integration test")
try:
# Initialize the enhanced LinkedIn service
linkedin_service = LinkedInService()
logger.info("LinkedIn service initialized successfully")
# Test 1: Basic post generation with grounding disabled
logger.info("\n=== Test 1: Basic Post Generation (No Grounding) ===")
basic_request = LinkedInPostRequest(
topic="AI in Marketing",
industry="Marketing",
post_type=LinkedInPostType.PROFESSIONAL,
tone=LinkedInTone.PROFESSIONAL,
research_enabled=False,
grounding_level=GroundingLevel.NONE,
include_citations=False
)
basic_response = await linkedin_service.generate_linkedin_post(basic_request)
logger.info(f"Basic post generation: {'SUCCESS' if basic_response.success else 'FAILED'}")
if basic_response.success:
logger.info(f"Content length: {basic_response.data.character_count}")
logger.info(f"Grounding enabled: {basic_response.data.grounding_enabled}")
# Test 2: Enhanced post generation with grounding enabled
logger.info("\n=== Test 2: Enhanced Post Generation (With Grounding) ===")
enhanced_request = LinkedInPostRequest(
topic="Digital Transformation in Healthcare",
industry="Healthcare",
post_type=LinkedInPostType.THOUGHT_LEADERSHIP,
tone=LinkedInTone.AUTHORITATIVE,
research_enabled=True,
search_engine=SearchEngine.GOOGLE,
grounding_level=GroundingLevel.ENHANCED,
include_citations=True,
max_length=2000
)
enhanced_response = await linkedin_service.generate_linkedin_post(enhanced_request)
logger.info(f"Enhanced post generation: {'SUCCESS' if enhanced_response.success else 'FAILED'}")
if enhanced_response.success:
logger.info(f"Content length: {enhanced_response.data.character_count}")
logger.info(f"Grounding enabled: {enhanced_response.data.grounding_enabled}")
logger.info(f"Research sources: {len(enhanced_response.research_sources)}")
logger.info(f"Citations: {len(enhanced_response.data.citations)}")
if enhanced_response.data.quality_metrics:
logger.info(f"Quality score: {enhanced_response.data.quality_metrics.overall_score:.2f}")
if enhanced_response.grounding_status:
logger.info(f"Grounding status: {enhanced_response.grounding_status['status']}")
# Test 3: Article generation with grounding
logger.info("\n=== Test 3: Article Generation (With Grounding) ===")
article_request = LinkedInArticleRequest(
topic="Future of Remote Work",
industry="Technology",
tone=LinkedInTone.EDUCATIONAL,
research_enabled=True,
search_engine=SearchEngine.GOOGLE,
grounding_level=GroundingLevel.ENHANCED,
include_citations=True,
word_count=1500
)
article_response = await linkedin_service.generate_linkedin_article(article_request)
logger.info(f"Article generation: {'SUCCESS' if article_response.success else 'FAILED'}")
if article_response.success:
logger.info(f"Word count: {article_response.data.word_count}")
logger.info(f"Grounding enabled: {article_response.data.grounding_enabled}")
logger.info(f"Research sources: {len(article_response.research_sources)}")
logger.info(f"Citations: {len(article_response.data.citations)}")
# Test 4: Carousel generation with grounding
logger.info("\n=== Test 4: Carousel Generation (With Grounding) ===")
carousel_request = LinkedInCarouselRequest(
topic="Cybersecurity Best Practices",
industry="Technology",
tone=LinkedInTone.EDUCATIONAL,
research_enabled=True,
search_engine=SearchEngine.GOOGLE,
grounding_level=GroundingLevel.ENHANCED,
include_citations=True,
number_of_slides=5
)
carousel_response = await linkedin_service.generate_linkedin_carousel(carousel_request)
logger.info(f"Carousel generation: {'SUCCESS' if carousel_response.success else 'FAILED'}")
if carousel_response.success:
logger.info(f"Number of slides: {len(carousel_response.data.slides)}")
logger.info(f"Grounding enabled: {carousel_response.data.grounding_enabled}")
logger.info(f"Research sources: {len(carousel_response.research_sources)}")
# Test 5: Video script generation with grounding
logger.info("\n=== Test 5: Video Script Generation (With Grounding) ===")
video_request = LinkedInVideoScriptRequest(
topic="AI Ethics in Business",
industry="Technology",
tone=LinkedInTone.EDUCATIONAL,
research_enabled=True,
search_engine=SearchEngine.GOOGLE,
grounding_level=GroundingLevel.ENHANCED,
include_citations=True,
video_duration=90
)
video_response = await linkedin_service.generate_linkedin_video_script(video_request)
logger.info(f"Video script generation: {'SUCCESS' if video_response.success else 'FAILED'}")
if video_response.success:
logger.info(f"Grounding enabled: {video_response.data.grounding_enabled}")
logger.info(f"Research sources: {len(video_response.research_sources)}")
logger.info(f"Citations: {len(video_response.data.citations)}")
# Test 6: Comment response generation
logger.info("\n=== Test 6: Comment Response Generation ===")
comment_request = LinkedInCommentResponseRequest(
original_comment="Great insights on AI implementation!",
post_context="Post about AI transformation in healthcare",
industry="Healthcare",
tone=LinkedInTone.FRIENDLY,
response_length="medium",
include_questions=True,
research_enabled=False,
grounding_level=GroundingLevel.BASIC
)
comment_response = await linkedin_service.generate_linkedin_comment_response(comment_request)
logger.info(f"Comment response generation: {'SUCCESS' if comment_response.success else 'FAILED'}")
if comment_response.success:
logger.info(f"Response length: {len(comment_response.response) if comment_response.response else 0}")
logger.info(f"Grounding enabled: {comment_response.grounding_status['status'] if comment_response.grounding_status else 'N/A'}")
logger.info("\n=== Integration Test Summary ===")
logger.info("All tests completed successfully!")
except Exception as e:
logger.error(f"Integration test failed: {str(e)}")
raise
async def test_individual_services():
"""Test individual service components."""
logger.info("\n=== Testing Individual Service Components ===")
try:
# Test Google Search Service
from services.research import GoogleSearchService
google_search = GoogleSearchService()
logger.info("GoogleSearchService initialized successfully")
# Test Citation Manager
from services.citation import CitationManager
citation_manager = CitationManager()
logger.info("CitationManager initialized successfully")
# Test Content Quality Analyzer
from services.quality import ContentQualityAnalyzer
quality_analyzer = ContentQualityAnalyzer()
logger.info("ContentQualityAnalyzer initialized successfully")
# Test Gemini Grounded Provider
from services.llm_providers.gemini_grounded_provider import GeminiGroundedProvider
gemini_grounded = GeminiGroundedProvider()
logger.info("GeminiGroundedProvider initialized successfully")
logger.info("All individual services initialized successfully!")
except Exception as e:
logger.error(f"Service component test failed: {str(e)}")
raise
async def main():
"""Main test function."""
logger.info("Starting LinkedIn Grounding Integration Tests")
logger.info(f"Test timestamp: {datetime.now().isoformat()}")
try:
# Test individual services first
await test_individual_services()
# Test complete integration
await test_grounding_integration()
logger.info("\n🎉 All tests completed successfully!")
except Exception as e:
logger.error(f"Test suite failed: {str(e)}")
logger.error("Please check the error details above and ensure all services are properly configured.")
return 1
return 0
if __name__ == "__main__":
# Run the tests
exit_code = asyncio.run(main())
exit(exit_code)

View File

@@ -0,0 +1,134 @@
#!/usr/bin/env python3
"""
Test script for the hallucination detector service.
This script tests the hallucination detector functionality
without requiring the full FastAPI server to be running.
"""
import asyncio
import os
import sys
from pathlib import Path
# Add the backend directory to the Python path
backend_dir = Path(__file__).parent
sys.path.insert(0, str(backend_dir))
from services.hallucination_detector import HallucinationDetector
async def test_hallucination_detector():
"""Test the hallucination detector with sample text."""
print("🧪 Testing Hallucination Detector")
print("=" * 50)
# Initialize detector
detector = HallucinationDetector()
# Test text with various types of claims
test_text = """
The Eiffel Tower is located in Paris, France. It was built in 1889 and stands 330 meters tall.
The tower was designed by Gustave Eiffel and is one of the most visited monuments in the world.
Our company increased sales by 25% last quarter and launched three new products.
The weather today is sunny with a temperature of 22 degrees Celsius.
"""
print(f"📝 Test Text:\n{test_text.strip()}\n")
try:
# Test claim extraction
print("🔍 Testing claim extraction...")
claims = await detector._extract_claims(test_text)
print(f"✅ Extracted {len(claims)} claims:")
for i, claim in enumerate(claims, 1):
print(f" {i}. {claim}")
print()
# Test full hallucination detection
print("🔍 Testing full hallucination detection...")
result = await detector.detect_hallucinations(test_text)
print(f"✅ Analysis completed:")
print(f" Overall Confidence: {result.overall_confidence:.2f}")
print(f" Total Claims: {result.total_claims}")
print(f" Supported: {result.supported_claims}")
print(f" Refuted: {result.refuted_claims}")
print(f" Insufficient: {result.insufficient_claims}")
print()
# Display individual claims
print("📊 Individual Claim Analysis:")
for i, claim in enumerate(result.claims, 1):
print(f"\n Claim {i}: {claim.text}")
print(f" Assessment: {claim.assessment}")
print(f" Confidence: {claim.confidence:.2f}")
print(f" Supporting Sources: {len(claim.supporting_sources)}")
print(f" Refuting Sources: {len(claim.refuting_sources)}")
if claim.supporting_sources:
print(" Supporting Sources:")
for j, source in enumerate(claim.supporting_sources[:2], 1): # Show first 2
print(f" {j}. {source.get('title', 'Untitled')} (Score: {source.get('score', 0):.2f})")
if claim.refuting_sources:
print(" Refuting Sources:")
for j, source in enumerate(claim.refuting_sources[:2], 1): # Show first 2
print(f" {j}. {source.get('title', 'Untitled')} (Score: {source.get('score', 0):.2f})")
print("\n✅ Test completed successfully!")
except Exception as e:
print(f"❌ Test failed with error: {str(e)}")
import traceback
traceback.print_exc()
async def test_health_check():
"""Test the health check functionality."""
print("\n🏥 Testing Health Check")
print("=" * 30)
detector = HallucinationDetector()
# Check API availability
exa_available = bool(detector.exa_api_key)
openai_available = bool(detector.openai_api_key)
print(f"Exa.ai API Available: {'' if exa_available else ''}")
print(f"OpenAI API Available: {'' if openai_available else ''}")
if not exa_available:
print("⚠️ Exa.ai API key not found. Set EXA_API_KEY environment variable.")
if not openai_available:
print("⚠️ OpenAI API key not found. Set OPENAI_API_KEY environment variable.")
if exa_available and openai_available:
print("✅ All APIs are available for full functionality.")
elif openai_available:
print("⚠️ Limited functionality available (claim extraction only).")
else:
print("❌ No APIs available. Only fallback functionality will work.")
def main():
"""Main test function."""
print("🚀 Hallucination Detector Test Suite")
print("=" * 50)
# Check environment variables
print("🔧 Environment Check:")
exa_key = os.getenv('EXA_API_KEY')
openai_key = os.getenv('OPENAI_API_KEY')
print(f"EXA_API_KEY: {'✅ Set' if exa_key else '❌ Not set'}")
print(f"OPENAI_API_KEY: {'✅ Set' if openai_key else '❌ Not set'}")
print()
# Run tests
asyncio.run(test_health_check())
asyncio.run(test_hallucination_detector())
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,95 @@
#!/usr/bin/env python3
"""
Test script for LinkedIn Image Generation API endpoints
"""
import asyncio
import aiohttp
import json
async def test_image_generation_api():
"""Test the LinkedIn image generation API endpoints"""
base_url = "http://localhost:8000"
print("🧪 Testing LinkedIn Image Generation API...")
print("=" * 50)
# Test 1: Health Check
print("\n1⃣ Testing Health Check...")
async with aiohttp.ClientSession() as session:
async with session.get(f"{base_url}/api/linkedin/image-generation-health") as response:
if response.status == 200:
health_data = await response.json()
print(f"✅ Health Check: {health_data['status']}")
print(f" Services: {health_data['services']}")
print(f" Test Prompts: {health_data['test_prompts_generated']}")
else:
print(f"❌ Health Check Failed: {response.status}")
return
# Test 2: Generate Image Prompts
print("\n2⃣ Testing Image Prompt Generation...")
prompt_data = {
"content_type": "post",
"topic": "AI in Marketing",
"industry": "Technology",
"content": "This is a test LinkedIn post about AI in marketing. It demonstrates the image generation capabilities."
}
async with aiohttp.ClientSession() as session:
async with session.post(
f"{base_url}/api/linkedin/generate-image-prompts",
json=prompt_data
) as response:
if response.status == 200:
prompts = await response.json()
print(f"✅ Generated {len(prompts)} image prompts:")
for i, prompt in enumerate(prompts, 1):
print(f" {i}. {prompt['style']}: {prompt['description']}")
# Test 3: Generate Image from First Prompt
print("\n3⃣ Testing Image Generation...")
image_data = {
"prompt": prompts[0]['prompt'],
"content_context": {
"topic": prompt_data["topic"],
"industry": prompt_data["industry"],
"content_type": prompt_data["content_type"],
"content": prompt_data["content"],
"style": prompts[0]['style']
},
"aspect_ratio": "1:1"
}
async with session.post(
f"{base_url}/api/linkedin/generate-image",
json=image_data
) as img_response:
if img_response.status == 200:
result = await img_response.json()
if result.get('success'):
print(f"✅ Image Generated Successfully!")
print(f" Image ID: {result.get('image_id')}")
print(f" Style: {result.get('style')}")
print(f" Aspect Ratio: {result.get('aspect_ratio')}")
else:
print(f"❌ Image Generation Failed: {result.get('error')}")
else:
print(f"❌ Image Generation Request Failed: {img_response.status}")
error_text = await img_response.text()
print(f" Error: {error_text}")
else:
print(f"❌ Prompt Generation Failed: {response.status}")
error_text = await response.text()
print(f" Error: {error_text}")
if __name__ == "__main__":
print("🚀 Starting LinkedIn Image Generation API Tests...")
try:
asyncio.run(test_image_generation_api())
print("\n🎉 All tests completed!")
except Exception as e:
print(f"\n💥 Test failed with error: {e}")
import traceback
traceback.print_exc()

View File

@@ -0,0 +1,139 @@
#!/usr/bin/env python3
"""
Simple test script to verify import issues are fixed.
This script tests that all the required services can be imported and initialized
without import errors.
Usage:
python test_imports.py
"""
import sys
import os
from pathlib import Path
# Add the backend directory to the Python path
backend_dir = Path(__file__).parent
sys.path.insert(0, str(backend_dir))
def test_imports():
"""Test that all required modules can be imported."""
print("🧪 Testing Imports...")
try:
print("📦 Testing LinkedIn Models...")
from models.linkedin_models import (
LinkedInPostRequest, LinkedInPostResponse, PostContent, ResearchSource,
LinkedInArticleRequest, LinkedInArticleResponse, ArticleContent,
LinkedInCarouselRequest, LinkedInCarouselResponse, CarouselContent, CarouselSlide,
LinkedInVideoScriptRequest, LinkedInVideoScriptResponse, VideoScript,
LinkedInCommentResponseRequest, LinkedInCommentResponseResult,
HashtagSuggestion, ImageSuggestion, Citation, ContentQualityMetrics,
GroundingLevel
)
print("✅ LinkedIn Models imported successfully")
except Exception as e:
print(f"❌ LinkedIn Models import failed: {e}")
return False
try:
print("📦 Testing Research Service...")
from services.research import GoogleSearchService
print("✅ Research Service imported successfully")
except Exception as e:
print(f"❌ Research Service import failed: {e}")
return False
try:
print("📦 Testing Citation Service...")
from services.citation import CitationManager
print("✅ Citation Service imported successfully")
except Exception as e:
print(f"❌ Citation Service import failed: {e}")
return False
try:
print("📦 Testing Quality Service...")
from services.quality import ContentQualityAnalyzer
print("✅ Quality Service imported successfully")
except Exception as e:
print(f"❌ Quality Service import failed: {e}")
return False
try:
print("📦 Testing LLM Providers...")
from services.llm_providers.gemini_provider import gemini_structured_json_response, gemini_text_response
print("✅ LLM Providers imported successfully")
except Exception as e:
print(f"❌ LLM Providers import failed: {e}")
return False
try:
print("📦 Testing Gemini Grounded Provider...")
from services.llm_providers.gemini_grounded_provider import GeminiGroundedProvider
print("✅ Gemini Grounded Provider imported successfully")
except Exception as e:
print(f"❌ Gemini Grounded Provider import failed: {e}")
return False
try:
print("📦 Testing LinkedIn Service...")
from services.linkedin_service import LinkedInService
print("✅ LinkedIn Service imported successfully")
except Exception as e:
print(f"❌ LinkedIn Service import failed: {e}")
return False
print("\n🎉 All imports successful!")
return True
def test_service_initialization():
"""Test that services can be initialized without errors."""
print("\n🔧 Testing Service Initialization...")
try:
print("📦 Initializing LinkedIn Service...")
from services.linkedin_service import LinkedInService
service = LinkedInService()
print("✅ LinkedIn Service initialized successfully")
# Check which services are available
print(f" - Google Search: {'' if service.google_search else ''}")
print(f" - Gemini Grounded: {'' if service.gemini_grounded else ''}")
print(f" - Citation Manager: {'' if service.citation_manager else ''}")
print(f" - Quality Analyzer: {'' if service.quality_analyzer else ''}")
print(f" - Fallback Provider: {'' if service.fallback_provider else ''}")
return True
except Exception as e:
print(f"❌ LinkedIn Service initialization failed: {e}")
return False
def main():
"""Main test function."""
print("🚀 Starting Import Tests")
print("=" * 50)
# Test imports
import_success = test_imports()
if import_success:
# Test service initialization
init_success = test_service_initialization()
if init_success:
print("\n🎉 SUCCESS: All tests passed!")
print("✅ Import issues have been resolved")
print("✅ Services can be initialized")
print("✅ Ready for testing native grounding")
else:
print("\n⚠️ PARTIAL SUCCESS: Imports work but initialization failed")
print("💡 This may be due to missing dependencies or configuration")
else:
print("\n❌ FAILURE: Import tests failed")
print("💡 There are still import issues to resolve")
sys.exit(1)
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,341 @@
"""
Test script for LinkedIn content generation endpoints.
This script tests the LinkedIn content generation functionality
to ensure proper integration and validation.
"""
import asyncio
import json
import time
from typing import Dict, Any
import sys
import os
# Add the backend directory to Python path
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
from models.linkedin_models import (
LinkedInPostRequest, LinkedInArticleRequest, LinkedInCarouselRequest,
LinkedInVideoScriptRequest, LinkedInCommentResponseRequest
)
from services.linkedin_service import linkedin_service
from loguru import logger
# Configure logger
logger.remove()
logger.add(sys.stdout, level="INFO", format="<level>{level}</level> | {message}")
async def test_post_generation():
"""Test LinkedIn post generation."""
logger.info("🧪 Testing LinkedIn Post Generation")
try:
request = LinkedInPostRequest(
topic="Artificial Intelligence in Healthcare",
industry="Healthcare",
post_type="thought_leadership",
tone="professional",
target_audience="Healthcare executives and AI professionals",
key_points=["AI diagnostics", "Patient outcomes", "Cost reduction", "Implementation challenges"],
include_hashtags=True,
include_call_to_action=True,
research_enabled=True,
search_engine="metaphor",
max_length=2000
)
start_time = time.time()
response = await linkedin_service.generate_post(request)
duration = time.time() - start_time
logger.info(f"✅ Post generation completed in {duration:.2f} seconds")
logger.info(f"Success: {response.success}")
if response.success and response.data:
logger.info(f"Content length: {response.data.character_count} characters")
logger.info(f"Hashtags generated: {len(response.data.hashtags)}")
logger.info(f"Call-to-action: {response.data.call_to_action is not None}")
logger.info(f"Research sources: {len(response.research_sources)}")
# Preview content (first 200 chars)
content_preview = response.data.content[:200] + "..." if len(response.data.content) > 200 else response.data.content
logger.info(f"Content preview: {content_preview}")
else:
logger.error(f"Post generation failed: {response.error}")
return response.success
except Exception as e:
logger.error(f"❌ Error testing post generation: {str(e)}")
return False
async def test_article_generation():
"""Test LinkedIn article generation."""
logger.info("🧪 Testing LinkedIn Article Generation")
try:
request = LinkedInArticleRequest(
topic="Digital Transformation in Manufacturing",
industry="Manufacturing",
tone="professional",
target_audience="Manufacturing leaders and technology professionals",
key_sections=["Current challenges", "Technology solutions", "Implementation strategies", "Future outlook"],
include_images=True,
seo_optimization=True,
research_enabled=True,
search_engine="metaphor",
word_count=1500
)
start_time = time.time()
response = await linkedin_service.generate_article(request)
duration = time.time() - start_time
logger.info(f"✅ Article generation completed in {duration:.2f} seconds")
logger.info(f"Success: {response.success}")
if response.success and response.data:
logger.info(f"Word count: {response.data.word_count}")
logger.info(f"Sections: {len(response.data.sections)}")
logger.info(f"Reading time: {response.data.reading_time} minutes")
logger.info(f"Image suggestions: {len(response.data.image_suggestions)}")
logger.info(f"SEO metadata: {response.data.seo_metadata is not None}")
logger.info(f"Research sources: {len(response.research_sources)}")
# Preview title
logger.info(f"Article title: {response.data.title}")
else:
logger.error(f"Article generation failed: {response.error}")
return response.success
except Exception as e:
logger.error(f"❌ Error testing article generation: {str(e)}")
return False
async def test_carousel_generation():
"""Test LinkedIn carousel generation."""
logger.info("🧪 Testing LinkedIn Carousel Generation")
try:
request = LinkedInCarouselRequest(
topic="5 Ways to Improve Team Productivity",
industry="Business Management",
slide_count=8,
tone="professional",
target_audience="Team leaders and managers",
key_takeaways=["Clear communication", "Goal setting", "Tool optimization", "Regular feedback", "Work-life balance"],
include_cover_slide=True,
include_cta_slide=True,
visual_style="modern"
)
start_time = time.time()
response = await linkedin_service.generate_carousel(request)
duration = time.time() - start_time
logger.info(f"✅ Carousel generation completed in {duration:.2f} seconds")
logger.info(f"Success: {response.success}")
if response.success and response.data:
logger.info(f"Slide count: {len(response.data.slides)}")
logger.info(f"Carousel title: {response.data.title}")
logger.info(f"Design guidelines: {bool(response.data.design_guidelines)}")
# Preview first slide
if response.data.slides:
first_slide = response.data.slides[0]
logger.info(f"First slide title: {first_slide.title}")
else:
logger.error(f"Carousel generation failed: {response.error}")
return response.success
except Exception as e:
logger.error(f"❌ Error testing carousel generation: {str(e)}")
return False
async def test_video_script_generation():
"""Test LinkedIn video script generation."""
logger.info("🧪 Testing LinkedIn Video Script Generation")
try:
request = LinkedInVideoScriptRequest(
topic="Quick tips for remote team management",
industry="Human Resources",
video_length=90,
tone="conversational",
target_audience="Remote team managers",
key_messages=["Communication tools", "Regular check-ins", "Team building", "Performance tracking"],
include_hook=True,
include_captions=True
)
start_time = time.time()
response = await linkedin_service.generate_video_script(request)
duration = time.time() - start_time
logger.info(f"✅ Video script generation completed in {duration:.2f} seconds")
logger.info(f"Success: {response.success}")
if response.success and response.data:
logger.info(f"Hook: {bool(response.data.hook)}")
logger.info(f"Main content scenes: {len(response.data.main_content)}")
logger.info(f"Conclusion: {bool(response.data.conclusion)}")
logger.info(f"Thumbnail suggestions: {len(response.data.thumbnail_suggestions)}")
logger.info(f"Captions: {bool(response.data.captions)}")
# Preview hook
if response.data.hook:
hook_preview = response.data.hook[:100] + "..." if len(response.data.hook) > 100 else response.data.hook
logger.info(f"Hook preview: {hook_preview}")
else:
logger.error(f"Video script generation failed: {response.error}")
return response.success
except Exception as e:
logger.error(f"❌ Error testing video script generation: {str(e)}")
return False
async def test_comment_response_generation():
"""Test LinkedIn comment response generation."""
logger.info("🧪 Testing LinkedIn Comment Response Generation")
try:
request = LinkedInCommentResponseRequest(
original_post="Just published an article about AI transformation in healthcare. The potential for improving patient outcomes while reducing costs is incredible. Healthcare leaders need to start preparing for this shift now.",
comment="Great insights! How do you see this affecting smaller healthcare providers who might not have the resources for large AI implementations?",
response_type="value_add",
tone="professional",
include_question=True,
brand_voice="Expert but approachable, data-driven and helpful"
)
start_time = time.time()
response = await linkedin_service.generate_comment_response(request)
duration = time.time() - start_time
logger.info(f"✅ Comment response generation completed in {duration:.2f} seconds")
logger.info(f"Success: {response.success}")
if response.success and response.response:
logger.info(f"Primary response length: {len(response.response)} characters")
logger.info(f"Alternative responses: {len(response.alternative_responses)}")
logger.info(f"Tone analysis: {bool(response.tone_analysis)}")
# Preview response
response_preview = response.response[:150] + "..." if len(response.response) > 150 else response.response
logger.info(f"Response preview: {response_preview}")
if response.tone_analysis:
logger.info(f"Detected sentiment: {response.tone_analysis.get('sentiment', 'unknown')}")
else:
logger.error(f"Comment response generation failed: {response.error}")
return response.success
except Exception as e:
logger.error(f"❌ Error testing comment response generation: {str(e)}")
return False
async def test_error_handling():
"""Test error handling with invalid requests."""
logger.info("🧪 Testing Error Handling")
try:
# Test with empty topic
request = LinkedInPostRequest(
topic="", # Empty topic should trigger validation error
industry="Technology",
)
response = await linkedin_service.generate_post(request)
# Should still handle gracefully
if not response.success:
logger.info("✅ Error handling working correctly for invalid input")
return True
else:
logger.warning("⚠️ Expected error handling but got successful response")
return False
except Exception as e:
logger.error(f"❌ Error in error handling test: {str(e)}")
return False
async def run_all_tests():
"""Run all LinkedIn content generation tests."""
logger.info("🚀 Starting LinkedIn Content Generation Tests")
logger.info("=" * 60)
test_results = {}
# Run individual tests
test_results["post_generation"] = await test_post_generation()
logger.info("-" * 40)
test_results["article_generation"] = await test_article_generation()
logger.info("-" * 40)
test_results["carousel_generation"] = await test_carousel_generation()
logger.info("-" * 40)
test_results["video_script_generation"] = await test_video_script_generation()
logger.info("-" * 40)
test_results["comment_response_generation"] = await test_comment_response_generation()
logger.info("-" * 40)
test_results["error_handling"] = await test_error_handling()
logger.info("-" * 40)
# Summary
logger.info("📊 Test Results Summary")
logger.info("=" * 60)
passed = sum(test_results.values())
total = len(test_results)
for test_name, result in test_results.items():
status = "✅ PASSED" if result else "❌ FAILED"
logger.info(f"{test_name}: {status}")
logger.info(f"\nOverall: {passed}/{total} tests passed ({(passed/total)*100:.1f}%)")
if passed == total:
logger.info("🎉 All tests passed! LinkedIn content generation is working correctly.")
else:
logger.warning(f"⚠️ {total - passed} test(s) failed. Please check the implementation.")
return passed == total
if __name__ == "__main__":
# Run the tests
success = asyncio.run(run_all_tests())
if success:
logger.info("\n✅ LinkedIn content generation migration completed successfully!")
logger.info("The FastAPI endpoints are ready for use.")
else:
logger.error("\n❌ Some tests failed. Please review the implementation.")
# Print API endpoint information
logger.info("\n📡 Available LinkedIn Content Generation Endpoints:")
logger.info("- POST /api/linkedin/generate-post")
logger.info("- POST /api/linkedin/generate-article")
logger.info("- POST /api/linkedin/generate-carousel")
logger.info("- POST /api/linkedin/generate-video-script")
logger.info("- POST /api/linkedin/generate-comment-response")
logger.info("- GET /api/linkedin/health")
logger.info("- GET /api/linkedin/content-types")
logger.info("- GET /api/linkedin/usage-stats")

View File

@@ -0,0 +1,191 @@
#!/usr/bin/env python3
"""
Test Script for LinkedIn Image Generation Infrastructure
This script tests the basic functionality of the LinkedIn image generation services
to ensure they are properly initialized and can perform basic operations.
"""
import asyncio
import sys
import os
from pathlib import Path
# Add the backend directory to the Python path
backend_path = Path(__file__).parent
sys.path.insert(0, str(backend_path))
from loguru import logger
# Configure logging
logger.remove()
logger.add(sys.stdout, colorize=True, format="<level>{level}</level>| {message}")
async def test_linkedin_image_infrastructure():
"""Test the LinkedIn image generation infrastructure."""
logger.info("🧪 Testing LinkedIn Image Generation Infrastructure")
logger.info("=" * 60)
try:
# Test 1: Import LinkedIn Image Services
logger.info("📦 Test 1: Importing LinkedIn Image Services...")
from services.linkedin.image_generation import (
LinkedInImageGenerator,
LinkedInImageEditor,
LinkedInImageStorage
)
from services.linkedin.image_prompts import LinkedInPromptGenerator
logger.success("✅ All LinkedIn image services imported successfully")
# Test 2: Initialize Services
logger.info("🔧 Test 2: Initializing LinkedIn Image Services...")
# Initialize services (without API keys for testing)
image_generator = LinkedInImageGenerator()
image_editor = LinkedInImageEditor()
image_storage = LinkedInImageStorage()
prompt_generator = LinkedInPromptGenerator()
logger.success("✅ All LinkedIn image services initialized successfully")
# Test 3: Test Prompt Generation (without API calls)
logger.info("📝 Test 3: Testing Prompt Generation Logic...")
# Test content context
test_content = {
'topic': 'AI in Marketing',
'industry': 'Technology',
'content_type': 'post',
'content': 'Exploring how artificial intelligence is transforming modern marketing strategies.'
}
# Test fallback prompt generation
fallback_prompts = prompt_generator._get_fallback_prompts(test_content, "1:1")
if len(fallback_prompts) == 3:
logger.success(f"✅ Fallback prompt generation working: {len(fallback_prompts)} prompts created")
for i, prompt in enumerate(fallback_prompts):
logger.info(f" Prompt {i+1}: {prompt['style']} - {prompt['description']}")
else:
logger.error(f"❌ Fallback prompt generation failed: expected 3, got {len(fallback_prompts)}")
# Test 4: Test Image Storage Directory Creation
logger.info("📁 Test 4: Testing Image Storage Directory Creation...")
# Check if storage directories were created
storage_path = image_storage.base_storage_path
if storage_path.exists():
logger.success(f"✅ Storage base directory created: {storage_path}")
# Check subdirectories
for subdir in ['images', 'metadata', 'temp']:
subdir_path = storage_path / subdir
if subdir_path.exists():
logger.info(f"{subdir} directory exists: {subdir_path}")
else:
logger.warning(f" ⚠️ {subdir} directory missing: {subdir_path}")
else:
logger.error(f"❌ Storage base directory not created: {storage_path}")
# Test 5: Test Service Methods
logger.info("⚙️ Test 5: Testing Service Method Signatures...")
# Test image generator methods
if hasattr(image_generator, 'generate_image'):
logger.success("✅ LinkedInImageGenerator.generate_image method exists")
else:
logger.error("❌ LinkedInImageGenerator.generate_image method missing")
if hasattr(image_editor, 'edit_image_conversationally'):
logger.success("✅ LinkedInImageEditor.edit_image_conversationally method exists")
else:
logger.error("❌ LinkedInImageEditor.edit_image_conversationally method missing")
if hasattr(image_storage, 'store_image'):
logger.success("✅ LinkedInImageStorage.store_image method exists")
else:
logger.error("❌ LinkedInImageStorage.store_image method missing")
if hasattr(prompt_generator, 'generate_three_prompts'):
logger.success("✅ LinkedInPromptGenerator.generate_three_prompts method exists")
else:
logger.error("❌ LinkedInPromptGenerator.generate_three_prompts method missing")
# Test 6: Test Prompt Enhancement
logger.info("🎨 Test 6: Testing Prompt Enhancement Logic...")
test_prompt = {
'style': 'Professional',
'prompt': 'Create a business image',
'description': 'Professional style'
}
enhanced_prompt = prompt_generator._enhance_prompt_for_linkedin(
test_prompt, test_content, "1:1", 0
)
if enhanced_prompt and 'enhanced_at' in enhanced_prompt:
logger.success("✅ Prompt enhancement working")
logger.info(f" Enhanced prompt length: {len(enhanced_prompt['prompt'])} characters")
else:
logger.error("❌ Prompt enhancement failed")
# Test 7: Test Image Validation Logic
logger.info("🔍 Test 7: Testing Image Validation Logic...")
# Test aspect ratio validation
valid_ratios = [(1024, 1024), (1600, 900), (1200, 1600)]
invalid_ratios = [(500, 500), (2000, 500)]
for width, height in valid_ratios:
if image_generator._is_aspect_ratio_suitable(width, height):
logger.info(f" ✅ Valid ratio {width}:{height} correctly identified")
else:
logger.warning(f" ⚠️ Valid ratio {width}:{height} incorrectly rejected")
for width, height in invalid_ratios:
if not image_generator._is_aspect_ratio_suitable(width, height):
logger.info(f" ✅ Invalid ratio {width}:{height} correctly rejected")
else:
logger.warning(f" ⚠️ Invalid ratio {width}:{height} incorrectly accepted")
logger.info("=" * 60)
logger.success("🎉 LinkedIn Image Generation Infrastructure Test Completed Successfully!")
return True
except ImportError as e:
logger.error(f"❌ Import Error: {e}")
logger.error("This usually means there's an issue with the module structure or dependencies")
return False
except Exception as e:
logger.error(f"❌ Test Failed: {e}")
logger.error(f"Error type: {type(e).__name__}")
import traceback
logger.error(f"Traceback: {traceback.format_exc()}")
return False
async def main():
"""Main test function."""
logger.info("🚀 Starting LinkedIn Image Generation Infrastructure Tests")
success = await test_linkedin_image_infrastructure()
if success:
logger.success("✅ All tests passed! The infrastructure is ready for use.")
sys.exit(0)
else:
logger.error("❌ Some tests failed. Please check the errors above.")
sys.exit(1)
if __name__ == "__main__":
# Run the async test
asyncio.run(main())

View File

@@ -0,0 +1,105 @@
#!/usr/bin/env python3
"""
Test script for LinkedIn service functionality.
This script tests that the LinkedIn service can be initialized and
basic functionality works without errors.
Usage:
python test_linkedin_service.py
"""
import asyncio
import sys
import os
from pathlib import Path
# Add the backend directory to the Python path
backend_dir = Path(__file__).parent
sys.path.insert(0, str(backend_dir))
from loguru import logger
from models.linkedin_models import LinkedInPostRequest, GroundingLevel
from services.linkedin_service import LinkedInService
async def test_linkedin_service():
"""Test the LinkedIn service functionality."""
try:
logger.info("🧪 Testing LinkedIn Service Functionality")
# Initialize the service
logger.info("📦 Initializing LinkedIn Service...")
service = LinkedInService()
logger.info("✅ LinkedIn Service initialized successfully")
# Create a test request
test_request = LinkedInPostRequest(
topic="AI in Marketing",
industry="Technology",
tone="professional",
max_length=500,
target_audience="Marketing professionals",
key_points=["AI automation", "Personalization", "ROI improvement"],
research_enabled=True,
search_engine="google",
grounding_level=GroundingLevel.BASIC,
include_citations=True
)
logger.info("📝 Testing LinkedIn Post Generation...")
# Test post generation
response = await service.generate_linkedin_post(test_request)
if response.success:
logger.info("✅ LinkedIn post generation successful")
logger.info(f"📊 Content length: {len(response.data.content)} characters")
logger.info(f"🔗 Sources: {len(response.research_sources)}")
logger.info(f"📚 Citations: {len(response.data.citations)}")
logger.info(f"🏆 Quality score: {response.data.quality_metrics.overall_score if response.data.quality_metrics else 'N/A'}")
# Display a snippet of the generated content
content_preview = response.data.content[:200] + "..." if len(response.data.content) > 200 else response.data.content
logger.info(f"📄 Content preview: {content_preview}")
else:
logger.error(f"❌ LinkedIn post generation failed: {response.error}")
return False
logger.info("🎉 LinkedIn service test completed successfully!")
return True
except Exception as e:
logger.error(f"❌ LinkedIn service test failed: {str(e)}")
return False
async def main():
"""Main test function."""
logger.info("🚀 Starting LinkedIn Service Test")
logger.info("=" * 50)
success = await test_linkedin_service()
if success:
logger.info("\n🎉 SUCCESS: LinkedIn service is working correctly!")
logger.info("✅ Service initialization successful")
logger.info("✅ Post generation working")
logger.info("✅ Ready for production use")
else:
logger.error("\n❌ FAILURE: LinkedIn service test failed")
sys.exit(1)
if __name__ == "__main__":
# Configure logging
logger.remove()
logger.add(
sys.stderr,
format="<green>{time:YYYY-MM-DD HH:mm:ss}</green> | <level>{level: <8}</level> | <cyan>{name}</cyan>:<cyan>{function}</cyan>:<cyan>{line}</cyan> - <level>{message}</level>",
level="INFO"
)
# Run the test
asyncio.run(main())

View File

@@ -0,0 +1,239 @@
#!/usr/bin/env python3
"""
Test script for native Google Search grounding implementation.
This script tests the new GeminiGroundedProvider that uses native Google Search
grounding instead of custom search implementation.
Usage:
python test_native_grounding.py
"""
import asyncio
import os
import sys
from pathlib import Path
# Add the backend directory to the Python path
backend_dir = Path(__file__).parent
sys.path.insert(0, str(backend_dir))
from loguru import logger
from services.llm_providers.gemini_grounded_provider import GeminiGroundedProvider
async def test_native_grounding():
"""Test the native Google Search grounding functionality."""
try:
logger.info("🧪 Testing Native Google Search Grounding")
# Check if GEMINI_API_KEY is set
if not os.getenv('GEMINI_API_KEY'):
logger.error("❌ GEMINI_API_KEY environment variable not set")
logger.info("Please set GEMINI_API_KEY to test native grounding")
return False
# Initialize the grounded provider
logger.info("🔧 Initializing Gemini Grounded Provider...")
provider = GeminiGroundedProvider()
logger.info("✅ Provider initialized successfully")
# Test 1: Basic grounded content generation
logger.info("\n📝 Test 1: Basic LinkedIn Post Generation")
test_prompt = "Write a professional LinkedIn post about the latest AI trends in 2025"
result = await provider.generate_grounded_content(
prompt=test_prompt,
content_type="linkedin_post",
temperature=0.7,
max_tokens=500
)
if result and 'content' in result:
logger.info("✅ Content generated successfully")
logger.info(f"📊 Content length: {len(result['content'])} characters")
logger.info(f"🔗 Sources found: {len(result.get('sources', []))}")
logger.info(f"📚 Citations found: {len(result.get('citations', []))}")
# Display the generated content
logger.info("\n📄 Generated Content:")
logger.info("-" * 50)
logger.info(result['content'][:500] + "..." if len(result['content']) > 500 else result['content'])
logger.info("-" * 50)
# Display sources if available
if result.get('sources'):
logger.info("\n🔗 Sources:")
for i, source in enumerate(result['sources']):
logger.info(f" {i+1}. {source.get('title', 'Unknown')}")
logger.info(f" URL: {source.get('url', 'N/A')}")
# Display search queries if available
if result.get('search_queries'):
logger.info(f"\n🔍 Search Queries Used: {result['search_queries']}")
# Display grounding metadata info
if result.get('grounding_metadata'):
logger.info("✅ Grounding metadata found")
else:
logger.warning("⚠️ No grounding metadata found")
else:
logger.error("❌ Content generation failed")
if 'error' in result:
logger.error(f"Error: {result['error']}")
return False
# Test 2: Article generation
logger.info("\n📝 Test 2: LinkedIn Article Generation")
article_prompt = "Create a comprehensive article about sustainable business practices in tech companies"
article_result = await provider.generate_grounded_content(
prompt=article_prompt,
content_type="linkedin_article",
temperature=0.7,
max_tokens=1000
)
if article_result and 'content' in article_result:
logger.info("✅ Article generated successfully")
logger.info(f"📊 Article length: {len(article_result['content'])} characters")
logger.info(f"🔗 Sources: {len(article_result.get('sources', []))}")
# Check for article-specific processing
if 'title' in article_result:
logger.info(f"📰 Article title: {article_result['title']}")
if 'word_count' in article_result:
logger.info(f"📊 Word count: {article_result['word_count']}")
else:
logger.error("❌ Article generation failed")
return False
# Test 3: Content quality assessment
logger.info("\n📝 Test 3: Content Quality Assessment")
if result.get('content') and result.get('sources'):
quality_metrics = provider.assess_content_quality(
content=result['content'],
sources=result['sources']
)
logger.info("✅ Quality assessment completed")
logger.info(f"📊 Overall score: {quality_metrics.get('overall_score', 'N/A')}")
logger.info(f"🔗 Source coverage: {quality_metrics.get('source_coverage', 'N/A')}")
logger.info(f"🎯 Tone score: {quality_metrics.get('tone_score', 'N/A')}")
logger.info(f"📝 Word count: {quality_metrics.get('word_count', 'N/A')}")
logger.info(f"🏆 Quality level: {quality_metrics.get('quality_level', 'N/A')}")
# Test 4: Citation extraction
logger.info("\n📝 Test 4: Citation Extraction")
if result.get('content'):
citations = provider.extract_citations(result['content'])
logger.info(f"✅ Extracted {len(citations)} citations")
for i, citation in enumerate(citations):
logger.info(f" Citation {i+1}: {citation.get('reference', 'Unknown')}")
logger.info("\n🎉 All tests completed successfully!")
return True
except ImportError as e:
logger.error(f"❌ Import error: {str(e)}")
logger.info("💡 Make sure to install required dependencies:")
logger.info(" pip install google-genai loguru")
return False
except Exception as e:
logger.error(f"❌ Test failed with error: {str(e)}")
return False
async def test_individual_components():
"""Test individual components of the native grounding system."""
try:
logger.info("🔧 Testing Individual Components")
# Test 1: Provider initialization
logger.info("\n📋 Test 1: Provider Initialization")
if not os.getenv('GEMINI_API_KEY'):
logger.warning("⚠️ Skipping provider test - no API key")
return False
provider = GeminiGroundedProvider()
logger.info("✅ Provider initialized successfully")
# Test 2: Prompt building
logger.info("\n📋 Test 2: Prompt Building")
test_prompt = "Test prompt for LinkedIn post"
grounded_prompt = provider._build_grounded_prompt(test_prompt, "linkedin_post")
if grounded_prompt and len(grounded_prompt) > len(test_prompt):
logger.info("✅ Grounded prompt built successfully")
logger.info(f"📊 Original length: {len(test_prompt)}")
logger.info(f"📊 Enhanced length: {len(grounded_prompt)}")
else:
logger.error("❌ Prompt building failed")
return False
# Test 3: Content processing methods
logger.info("\n📋 Test 3: Content Processing Methods")
# Test post processing
test_content = "This is a test LinkedIn post #AI #Technology"
post_processing = provider._process_post_content(test_content)
if post_processing:
logger.info("✅ Post processing works")
logger.info(f"🔖 Hashtags found: {len(post_processing.get('hashtags', []))}")
# Test article processing
test_article = "# Test Article\n\nThis is test content for an article."
article_processing = provider._process_article_content(test_article)
if article_processing:
logger.info("✅ Article processing works")
logger.info(f"📊 Word count: {article_processing.get('word_count', 'N/A')}")
logger.info("✅ All component tests passed")
return True
except Exception as e:
logger.error(f"❌ Component test failed: {str(e)}")
return False
async def main():
"""Main test function."""
logger.info("🚀 Starting Native Grounding Tests")
logger.info("=" * 60)
# Test individual components first
component_success = await test_individual_components()
if component_success:
# Test the full integration
integration_success = await test_native_grounding()
if integration_success:
logger.info("\n🎉 SUCCESS: All tests passed!")
logger.info("✅ Native Google Search grounding is working correctly")
logger.info("✅ Gemini API integration successful")
logger.info("✅ Grounding metadata processing working")
logger.info("✅ Content generation with sources successful")
else:
logger.error("\n❌ FAILURE: Integration tests failed")
sys.exit(1)
else:
logger.error("\n❌ FAILURE: Component tests failed")
sys.exit(1)
if __name__ == "__main__":
# Configure logging
logger.remove()
logger.add(
sys.stderr,
format="<green>{time:YYYY-MM-DD HH:mm:ss}</green> | <level>{level: <8}</level> | <cyan>{name}</cyan>:<cyan>{function}</cyan>:<cyan>{line}</cyan> - <level>{message}</level>",
level="INFO"
)
# Run the tests
asyncio.run(main())

View File

@@ -0,0 +1,106 @@
#!/usr/bin/env python3
"""
Test script to verify the calendar generation progress endpoint.
This script tests the progress endpoint to ensure it returns the correct data structure.
"""
import asyncio
import sys
import os
import json
from datetime import datetime
# Add the current directory to the Python path
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
def test_progress_endpoint():
"""Test the progress endpoint with a mock session."""
try:
from api.content_planning.services.calendar_generation_service import CalendarGenerationService
print("🧪 Testing Progress Endpoint")
print("=" * 50)
# Initialize service
service = CalendarGenerationService()
# Create a test session
session_id = f"test-session-{int(datetime.now().timestamp())}"
test_request_data = {
"user_id": 1,
"strategy_id": 1,
"calendar_type": "monthly",
"industry": "technology",
"business_size": "sme"
}
print(f"📋 Creating test session: {session_id}")
# Initialize session
success = service.initialize_orchestrator_session(session_id, test_request_data)
if not success:
print("❌ Failed to initialize session")
return False
print("✅ Session initialized successfully")
# Test progress retrieval
print(f"🔍 Testing progress retrieval for session: {session_id}")
progress = service.get_orchestrator_progress(session_id)
if not progress:
print("❌ No progress data returned")
return False
print("✅ Progress data retrieved successfully")
print(f"📊 Progress data structure:")
print(json.dumps(progress, indent=2, default=str))
# Verify required fields
required_fields = [
"status", "current_step", "step_progress", "overall_progress",
"step_results", "quality_scores", "errors", "warnings"
]
missing_fields = [field for field in required_fields if field not in progress]
if missing_fields:
print(f"❌ Missing required fields: {missing_fields}")
return False
print("✅ All required fields present")
# Test data types
if not isinstance(progress["current_step"], int):
print("❌ current_step should be int")
return False
if not isinstance(progress["step_progress"], (int, float)):
print("❌ step_progress should be numeric")
return False
if not isinstance(progress["overall_progress"], (int, float)):
print("❌ overall_progress should be numeric")
return False
print("✅ All data types correct")
# Test quality scores
quality_scores = progress["quality_scores"]
if not isinstance(quality_scores, dict):
print("❌ quality_scores should be dict")
return False
print("✅ Quality scores structure correct")
print("\n🎉 All tests passed! Progress endpoint is working correctly.")
return True
except Exception as e:
print(f"❌ Test failed with error: {str(e)}")
import traceback
print(f"📋 Traceback: {traceback.format_exc()}")
return False
if __name__ == "__main__":
success = test_progress_endpoint()
sys.exit(0 if success else 1)

View File

@@ -0,0 +1,304 @@
#!/usr/bin/env python3
"""
Real Database Integration Test for Steps 1-8
This script tests the calendar generation framework with real database services,
replacing all mock data with actual database operations.
"""
import asyncio
import sys
import os
from typing import Dict, Any
from loguru import logger
# Add the backend directory to the path
backend_dir = os.path.dirname(os.path.abspath(__file__))
if backend_dir not in sys.path:
sys.path.insert(0, backend_dir)
# Add the services directory to the path
services_dir = os.path.join(backend_dir, "services")
if services_dir not in sys.path:
sys.path.insert(0, services_dir)
async def test_real_database_integration():
"""Test Steps 1-8 with real database services."""
try:
logger.info("🚀 Starting real database integration test")
# Initialize database
logger.info("🗄️ Initializing database connection")
from services.database import init_database, get_db_session
try:
init_database()
logger.info("✅ Database initialized successfully")
except Exception as e:
logger.error(f"❌ Database initialization failed: {str(e)}")
return False
# Get database session
db_session = get_db_session()
if not db_session:
logger.error("❌ Failed to get database session")
return False
logger.info("✅ Database session created successfully")
# Test data
test_context = {
"user_id": 1,
"strategy_id": 1,
"calendar_duration": 7,
"posting_preferences": {
"posting_frequency": "daily",
"preferred_days": ["monday", "wednesday", "friday"],
"preferred_times": ["09:00", "12:00", "15:00"],
"content_per_day": 2
}
}
# Create test data in database
logger.info("📝 Creating test data in database")
await create_test_data(db_session, test_context)
# Test Step 1: Content Strategy Analysis with Real Database
logger.info("📋 Testing Step 1: Content Strategy Analysis (Real Database)")
try:
from services.calendar_generation_datasource_framework.prompt_chaining.steps.phase1.phase1_steps import ContentStrategyAnalysisStep
from services.calendar_generation_datasource_framework.data_processing.strategy_data import StrategyDataProcessor
from services.content_planning_db import ContentPlanningDBService
# Create real database service
content_planning_db = ContentPlanningDBService(db_session)
# Create strategy processor with real database service
strategy_processor = StrategyDataProcessor()
strategy_processor.content_planning_db_service = content_planning_db
step1 = ContentStrategyAnalysisStep()
step1.strategy_processor = strategy_processor
result1 = await step1.execute(test_context)
logger.info(f"✅ Step 1 completed: {result1.get('status')}")
logger.info(f" Quality Score: {result1.get('quality_score')}")
except Exception as e:
logger.error(f"❌ Step 1 failed: {str(e)}")
return False
# Test Step 2: Gap Analysis with Real Database
logger.info("📋 Testing Step 2: Gap Analysis (Real Database)")
try:
from services.calendar_generation_datasource_framework.prompt_chaining.steps.phase1.phase1_steps import GapAnalysisStep
from services.calendar_generation_datasource_framework.data_processing.gap_analysis_data import GapAnalysisDataProcessor
# Create gap processor with real database service
gap_processor = GapAnalysisDataProcessor()
gap_processor.content_planning_db_service = content_planning_db
step2 = GapAnalysisStep()
step2.gap_processor = gap_processor
result2 = await step2.execute(test_context)
logger.info(f"✅ Step 2 completed: {result2.get('status')}")
logger.info(f" Quality Score: {result2.get('quality_score')}")
except Exception as e:
logger.error(f"❌ Step 2 failed: {str(e)}")
return False
# Test Step 3: Audience & Platform Strategy with Real Database
logger.info("📋 Testing Step 3: Audience & Platform Strategy (Real Database)")
try:
from services.calendar_generation_datasource_framework.prompt_chaining.steps.phase1.phase1_steps import AudiencePlatformStrategyStep
from services.calendar_generation_datasource_framework.data_processing.comprehensive_user_data import ComprehensiveUserDataProcessor
# Create comprehensive processor with real database service
comprehensive_processor = ComprehensiveUserDataProcessor(db_session)
comprehensive_processor.content_planning_db_service = content_planning_db
step3 = AudiencePlatformStrategyStep()
step3.comprehensive_processor = comprehensive_processor
result3 = await step3.execute(test_context)
logger.info(f"✅ Step 3 completed: {result3.get('status')}")
logger.info(f" Quality Score: {result3.get('quality_score')}")
except Exception as e:
logger.error(f"❌ Step 3 failed: {str(e)}")
return False
# Test Steps 4-8 with Real Database
logger.info("📋 Testing Steps 4-8: Calendar Framework to Daily Content Planning (Real Database)")
try:
# Test Step 4: Calendar Framework
from services.calendar_generation_datasource_framework.prompt_chaining.steps.phase2.step4_implementation import CalendarFrameworkStep
step4 = CalendarFrameworkStep()
result4 = await step4.execute(test_context)
logger.info(f"✅ Step 4 completed: {result4.get('status')}")
# Test Step 5: Content Pillar Distribution
from services.calendar_generation_datasource_framework.prompt_chaining.steps.phase2.step5_implementation import ContentPillarDistributionStep
step5 = ContentPillarDistributionStep()
result5 = await step5.execute(test_context)
logger.info(f"✅ Step 5 completed: {result5.get('status')}")
# Test Step 6: Platform-Specific Strategy
from services.calendar_generation_datasource_framework.prompt_chaining.steps.phase2.step6_implementation import PlatformSpecificStrategyStep
step6 = PlatformSpecificStrategyStep()
result6 = await step6.execute(test_context)
logger.info(f"✅ Step 6 completed: {result6.get('status')}")
# Test Step 7: Weekly Theme Development
from services.calendar_generation_datasource_framework.prompt_chaining.steps.phase3.step7_implementation import WeeklyThemeDevelopmentStep
step7 = WeeklyThemeDevelopmentStep()
result7 = await step7.execute(test_context)
logger.info(f"✅ Step 7 completed: {result7.get('status')}")
# Test Step 8: Daily Content Planning
from services.calendar_generation_datasource_framework.prompt_chaining.steps.phase3.step8_implementation import DailyContentPlanningStep
step8 = DailyContentPlanningStep()
result8 = await step8.execute(test_context)
logger.info(f"✅ Step 8 completed: {result8.get('status')}")
except Exception as e:
logger.error(f"❌ Steps 4-8 failed: {str(e)}")
return False
# Clean up test data
logger.info("🧹 Cleaning up test data")
await cleanup_test_data(db_session, test_context)
# Close database session
db_session.close()
logger.info("🎉 All Steps 1-8 completed successfully with real database!")
logger.info("📝 Real database integration working perfectly!")
return True
except Exception as e:
logger.error(f"❌ Test failed with error: {str(e)}")
return False
async def create_test_data(db_session, test_context: Dict[str, Any]):
"""Create test data in the database."""
try:
from services.content_planning_db import ContentPlanningDBService
from models.content_planning import ContentStrategy, ContentGapAnalysis
db_service = ContentPlanningDBService(db_session)
# Create test content strategy
strategy_data = {
"user_id": test_context["user_id"],
"name": "Test Strategy - Real Database",
"industry": "technology",
"target_audience": {
"primary": "Tech professionals",
"secondary": "Business leaders",
"demographics": {"age_range": "25-45", "location": "Global"}
},
"content_pillars": [
"AI and Machine Learning",
"Digital Transformation",
"Innovation and Technology Trends",
"Business Strategy and Growth"
],
"ai_recommendations": {
"strategic_insights": [
"Focus on deep-dive technical content",
"Emphasize practical implementation guides",
"Highlight ROI and business impact"
]
}
}
strategy = await db_service.create_content_strategy(strategy_data)
if strategy:
logger.info(f"✅ Created test strategy: {strategy.id}")
test_context["strategy_id"] = strategy.id
# Create test gap analysis
gap_data = {
"user_id": test_context["user_id"],
"website_url": "https://example.com",
"competitor_urls": ["https://competitor1.com", "https://competitor2.com"],
"target_keywords": [
{"keyword": "AI ethics in business", "search_volume": 5000, "competition": "low"},
{"keyword": "digital transformation ROI", "search_volume": 8000, "competition": "medium"}
],
"analysis_results": {
"content_gaps": [
{"topic": "AI Ethics", "priority": "high", "impact_score": 0.9},
{"topic": "Digital Transformation ROI", "priority": "medium", "impact_score": 0.7}
],
"keyword_opportunities": [
{"keyword": "AI ethics in business", "search_volume": 5000, "competition": "low"},
{"keyword": "digital transformation ROI", "search_volume": 8000, "competition": "medium"}
],
"competitor_insights": [
{"competitor": "Competitor A", "strength": "Technical content", "weakness": "Practical guides"},
{"competitor": "Competitor B", "strength": "Case studies", "weakness": "AI focus"}
],
"opportunities": [
{"type": "content", "topic": "AI Ethics", "priority": "high"},
{"type": "content", "topic": "ROI Analysis", "priority": "medium"}
]
},
"recommendations": [
"Create comprehensive AI ethics guide",
"Develop ROI calculator for digital transformation"
],
"opportunities": [
{"type": "content", "topic": "AI Ethics", "priority": "high"},
{"type": "content", "topic": "ROI Analysis", "priority": "medium"}
]
}
gap_analysis = await db_service.create_content_gap_analysis(gap_data)
if gap_analysis:
logger.info(f"✅ Created test gap analysis: {gap_analysis.id}")
logger.info("✅ Test data created successfully")
except Exception as e:
logger.error(f"❌ Error creating test data: {str(e)}")
raise
async def cleanup_test_data(db_session, test_context: Dict[str, Any]):
"""Clean up test data from the database."""
try:
from services.content_planning_db import ContentPlanningDBService
db_service = ContentPlanningDBService(db_session)
# Clean up gap analysis (get by user_id and delete)
gap_analyses = await db_service.get_user_content_gap_analyses(test_context["user_id"])
for gap_analysis in gap_analyses:
await db_service.delete_content_gap_analysis(gap_analysis.id)
# Clean up strategy
await db_service.delete_content_strategy(test_context["strategy_id"])
logger.info("✅ Test data cleaned up successfully")
except Exception as e:
logger.error(f"❌ Error cleaning up test data: {str(e)}")
if __name__ == "__main__":
# Configure logging
logger.remove()
logger.add(sys.stderr, level="INFO", format="<green>{time:HH:mm:ss}</green> | <level>{level: <8}</level> | <cyan>{name}</cyan>:<cyan>{function}</cyan>:<cyan>{line}</cyan> - <level>{message}</level>")
# Run the test
success = asyncio.run(test_real_database_integration())
if success:
logger.info("✅ Real database integration test completed successfully!")
sys.exit(0)
else:
logger.error("❌ Real database integration test failed!")
sys.exit(1)

View File

@@ -0,0 +1,179 @@
#!/usr/bin/env python3
"""
Test Script for AI SEO Tools API
This script tests all the migrated SEO tools endpoints to ensure
they are working correctly after migration to FastAPI.
"""
import asyncio
import aiohttp
import json
from datetime import datetime
BASE_URL = "http://localhost:8000"
async def test_endpoint(session, endpoint, method="GET", data=None):
"""Test a single endpoint"""
url = f"{BASE_URL}{endpoint}"
try:
if method == "POST":
async with session.post(url, json=data) as response:
result = await response.json()
return {
"endpoint": endpoint,
"status": response.status,
"success": response.status == 200,
"response": result
}
else:
async with session.get(url) as response:
result = await response.json()
return {
"endpoint": endpoint,
"status": response.status,
"success": response.status == 200,
"response": result
}
except Exception as e:
return {
"endpoint": endpoint,
"status": 0,
"success": False,
"error": str(e)
}
async def run_seo_tools_tests():
"""Run comprehensive tests for all SEO tools"""
print("🚀 Starting AI SEO Tools API Tests")
print("=" * 50)
async with aiohttp.ClientSession() as session:
# Test health endpoint
print("\n1. Testing Health Endpoints...")
health_tests = [
("/api/seo/health", "GET", None),
("/api/seo/tools/status", "GET", None)
]
for endpoint, method, data in health_tests:
result = await test_endpoint(session, endpoint, method, data)
status = "✅ PASS" if result["success"] else "❌ FAIL"
print(f" {status} {endpoint} - Status: {result['status']}")
# Test meta description generation
print("\n2. Testing Meta Description Generation...")
meta_desc_data = {
"keywords": ["SEO", "content marketing", "digital strategy"],
"tone": "Professional",
"search_intent": "Informational Intent",
"language": "English"
}
result = await test_endpoint(session, "/api/seo/meta-description", "POST", meta_desc_data)
status = "✅ PASS" if result["success"] else "❌ FAIL"
print(f" {status} Meta Description Generation - Status: {result['status']}")
if result["success"]:
data = result["response"].get("data", {})
descriptions = data.get("meta_descriptions", [])
print(f" Generated {len(descriptions)} meta descriptions")
# Test PageSpeed analysis
print("\n3. Testing PageSpeed Analysis...")
pagespeed_data = {
"url": "https://example.com",
"strategy": "DESKTOP",
"categories": ["performance"]
}
result = await test_endpoint(session, "/api/seo/pagespeed-analysis", "POST", pagespeed_data)
status = "✅ PASS" if result["success"] else "❌ FAIL"
print(f" {status} PageSpeed Analysis - Status: {result['status']}")
# Test sitemap analysis
print("\n4. Testing Sitemap Analysis...")
sitemap_data = {
"sitemap_url": "https://www.google.com/sitemap.xml",
"analyze_content_trends": False,
"analyze_publishing_patterns": False
}
result = await test_endpoint(session, "/api/seo/sitemap-analysis", "POST", sitemap_data)
status = "✅ PASS" if result["success"] else "❌ FAIL"
print(f" {status} Sitemap Analysis - Status: {result['status']}")
# Test OpenGraph generation
print("\n5. Testing OpenGraph Generation...")
og_data = {
"url": "https://example.com",
"title_hint": "Test Page",
"description_hint": "Test description",
"platform": "General"
}
result = await test_endpoint(session, "/api/seo/opengraph-tags", "POST", og_data)
status = "✅ PASS" if result["success"] else "❌ FAIL"
print(f" {status} OpenGraph Generation - Status: {result['status']}")
# Test on-page SEO analysis
print("\n6. Testing On-Page SEO Analysis...")
onpage_data = {
"url": "https://example.com",
"target_keywords": ["test", "example"],
"analyze_images": True,
"analyze_content_quality": True
}
result = await test_endpoint(session, "/api/seo/on-page-analysis", "POST", onpage_data)
status = "✅ PASS" if result["success"] else "❌ FAIL"
print(f" {status} On-Page SEO Analysis - Status: {result['status']}")
# Test technical SEO analysis
print("\n7. Testing Technical SEO Analysis...")
technical_data = {
"url": "https://example.com",
"crawl_depth": 2,
"include_external_links": True,
"analyze_performance": True
}
result = await test_endpoint(session, "/api/seo/technical-seo", "POST", technical_data)
status = "✅ PASS" if result["success"] else "❌ FAIL"
print(f" {status} Technical SEO Analysis - Status: {result['status']}")
# Test workflow endpoints
print("\n8. Testing Workflow Endpoints...")
# Website audit workflow
audit_data = {
"website_url": "https://example.com",
"workflow_type": "complete_audit",
"target_keywords": ["test", "example"]
}
result = await test_endpoint(session, "/api/seo/workflow/website-audit", "POST", audit_data)
status = "✅ PASS" if result["success"] else "❌ FAIL"
print(f" {status} Website Audit Workflow - Status: {result['status']}")
# Content analysis workflow
content_data = {
"website_url": "https://example.com",
"workflow_type": "content_analysis",
"target_keywords": ["content", "strategy"]
}
result = await test_endpoint(session, "/api/seo/workflow/content-analysis", "POST", content_data)
status = "✅ PASS" if result["success"] else "❌ FAIL"
print(f" {status} Content Analysis Workflow - Status: {result['status']}")
print("\n" + "=" * 50)
print("🎉 SEO Tools API Testing Completed!")
print("\nNote: Some tests may show connection errors if the server is not running.")
print("Start the server with: uvicorn app:app --reload --host 0.0.0.0 --port 8000")
if __name__ == "__main__":
asyncio.run(run_seo_tools_tests())

View File

@@ -0,0 +1,83 @@
#!/usr/bin/env python3
"""
Test script to verify session management and duplicate prevention.
This script tests the session cleanup and duplicate prevention features.
"""
import asyncio
import sys
import os
import json
from datetime import datetime
# Add the current directory to the Python path
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
def test_session_management():
"""Test session management features."""
try:
from api.content_planning.services.calendar_generation_service import CalendarGenerationService
print("🧪 Testing Session Management")
print("=" * 50)
# Initialize service
service = CalendarGenerationService(None) # No DB needed for this test
# Test 1: Initialize first session
print("\n📋 Test 1: Initialize first session")
request_data_1 = {
"user_id": 1,
"strategy_id": 1,
"calendar_type": "monthly",
"industry": "technology",
"business_size": "sme"
}
session_id_1 = f"test-session-{int(datetime.now().timestamp())}-1000"
success_1 = service.initialize_orchestrator_session(session_id_1, request_data_1)
print(f"✅ First session initialized: {success_1}")
print(f"📊 Available sessions: {list(service.orchestrator_sessions.keys())}")
# Test 2: Try to initialize second session for same user (should fail)
print("\n📋 Test 2: Try to initialize second session for same user")
session_id_2 = f"test-session-{int(datetime.now().timestamp())}-2000"
success_2 = service.initialize_orchestrator_session(session_id_2, request_data_1)
print(f"❌ Second session should fail: {success_2}")
print(f"📊 Available sessions: {list(service.orchestrator_sessions.keys())}")
# Test 3: Check active session for user
print("\n📋 Test 3: Check active session for user")
active_session = service._get_active_session_for_user(1)
print(f"✅ Active session for user 1: {active_session}")
# Test 4: Initialize session for different user (should succeed)
print("\n📋 Test 4: Initialize session for different user")
request_data_2 = {
"user_id": 2,
"strategy_id": 2,
"calendar_type": "weekly",
"industry": "finance",
"business_size": "enterprise"
}
session_id_3 = f"test-session-{int(datetime.now().timestamp())}-3000"
success_3 = service.initialize_orchestrator_session(session_id_3, request_data_2)
print(f"✅ Third session for different user: {success_3}")
print(f"📊 Available sessions: {list(service.orchestrator_sessions.keys())}")
# Test 5: Test session cleanup
print("\n📋 Test 5: Test session cleanup")
print(f"📊 Sessions before cleanup: {len(service.orchestrator_sessions)}")
service._cleanup_old_sessions(1)
print(f"📊 Sessions after cleanup: {len(service.orchestrator_sessions)}")
print("\n🎉 Session management tests completed successfully!")
except Exception as e:
print(f"❌ Test failed: {e}")
import traceback
traceback.print_exc()
if __name__ == "__main__":
test_session_management()

View File

@@ -0,0 +1,73 @@
#!/usr/bin/env python3
"""
Simple test script to verify basic grounding functionality.
This script tests the core components without triggering API overload.
"""
import asyncio
import sys
import os
from pathlib import Path
# Add the backend directory to the Python path
backend_dir = Path(__file__).parent
sys.path.insert(0, str(backend_dir))
from loguru import logger
from services.llm_providers.gemini_grounded_provider import GeminiGroundedProvider
async def test_basic_functionality():
"""Test basic grounding functionality."""
try:
logger.info("🧪 Testing Basic Grounding Functionality")
# Initialize provider
provider = GeminiGroundedProvider()
logger.info("✅ Provider initialized successfully")
# Test prompt building
prompt = "Write a short LinkedIn post about AI trends"
grounded_prompt = provider._build_grounded_prompt(prompt, "linkedin_post")
logger.info(f"✅ Grounded prompt built: {len(grounded_prompt)} characters")
# Test content processing
test_content = "AI is transforming industries #AI #Technology"
processed = provider._process_post_content(test_content)
logger.info(f"✅ Content processed: {len(processed.get('hashtags', []))} hashtags found")
logger.info("🎉 Basic functionality test completed successfully!")
return True
except Exception as e:
logger.error(f"❌ Basic functionality test failed: {str(e)}")
return False
async def main():
"""Main test function."""
logger.info("🚀 Starting Simple Grounding Test")
logger.info("=" * 50)
success = await test_basic_functionality()
if success:
logger.info("\n🎉 SUCCESS: Basic grounding functionality is working!")
logger.info("✅ Provider initialization successful")
logger.info("✅ Prompt building working")
logger.info("✅ Content processing working")
logger.info("✅ Ready for API integration")
else:
logger.error("\n❌ FAILURE: Basic functionality test failed")
sys.exit(1)
if __name__ == "__main__":
# Configure logging
logger.remove()
logger.add(
sys.stderr,
format="<green>{time:YYYY-MM-DD HH:mm:ss}</green> | <level>{level: <8}</level> | <cyan>{name}</cyan>:<cyan>{function}</cyan>:<cyan>{line}</cyan> - <level>{message}</level>",
level="INFO"
)
# Run the test
asyncio.run(main())

View File

@@ -0,0 +1,40 @@
import asyncio
from services.llm_providers.gemini_provider import gemini_structured_json_response
async def test_simple_schema():
"""Test with a very simple schema to see if structured output works at all"""
# Very simple schema
simple_schema = {
"type": "object",
"properties": {
"name": {"type": "string"},
"age": {"type": "integer"}
}
}
simple_prompt = "Generate a person with a name and age."
print("Testing simple schema...")
print(f"Schema: {simple_schema}")
print(f"Prompt: {simple_prompt}")
print("\n" + "="*50 + "\n")
try:
result = gemini_structured_json_response(
prompt=simple_prompt,
schema=simple_schema,
temperature=0.3,
max_tokens=100
)
print("Result:")
print(result)
except Exception as e:
print(f"Error: {e}")
import traceback
traceback.print_exc()
if __name__ == "__main__":
asyncio.run(test_simple_schema())

View File

@@ -0,0 +1,126 @@
#!/usr/bin/env python3
"""
Simple Test Script for Step 1 Only
This script tests only Step 1 to verify imports are working correctly.
"""
import asyncio
import sys
import os
from typing import Dict, Any
from loguru import logger
# Add the backend directory to the path
backend_dir = os.path.dirname(os.path.abspath(__file__))
if backend_dir not in sys.path:
sys.path.insert(0, backend_dir)
# Add the services directory to the path
services_dir = os.path.join(backend_dir, "services")
if services_dir not in sys.path:
sys.path.insert(0, services_dir)
async def test_step1_only():
"""Test only Step 1 to verify imports work."""
try:
logger.info("🚀 Starting test of Step 1 only")
# Test data
test_context = {
"user_id": 1,
"strategy_id": 1,
"calendar_duration": 7,
"posting_preferences": {
"posting_frequency": "daily",
"preferred_days": ["monday", "wednesday", "friday"],
"preferred_times": ["09:00", "12:00", "15:00"],
"content_per_day": 2
}
}
# Test Step 1: Content Strategy Analysis
logger.info("📋 Testing Step 1: Content Strategy Analysis")
try:
from services.calendar_generation_datasource_framework.prompt_chaining.steps.phase1.phase1_steps import ContentStrategyAnalysisStep
from services.calendar_generation_datasource_framework.data_processing.strategy_data import StrategyDataProcessor
logger.info("✅ Imports successful")
# Create strategy processor with mock data for testing
strategy_processor = StrategyDataProcessor()
# Mock strategy data
mock_strategy_data = {
"strategy_id": 1,
"strategy_name": "Test Strategy",
"industry": "technology",
"target_audience": {
"primary": "Tech professionals",
"secondary": "Business leaders",
"demographics": {"age_range": "25-45", "location": "Global"}
},
"content_pillars": [
"AI and Machine Learning",
"Digital Transformation",
"Innovation and Technology Trends",
"Business Strategy and Growth"
],
"business_objectives": [
"Increase brand awareness by 40%",
"Generate 500 qualified leads per month",
"Establish thought leadership"
],
"target_metrics": {"awareness": "website_traffic", "leads": "lead_generation"},
"quality_indicators": {"data_completeness": 0.8, "strategic_alignment": 0.9}
}
# Mock the get_strategy_data method for testing
async def mock_get_strategy_data(strategy_id):
return mock_strategy_data
strategy_processor.get_strategy_data = mock_get_strategy_data
# Mock the validate_data method
async def mock_validate_data(data):
return {
"quality_score": 0.85,
"missing_fields": [],
"recommendations": []
}
strategy_processor.validate_data = mock_validate_data
step1 = ContentStrategyAnalysisStep()
step1.strategy_processor = strategy_processor
result1 = await step1.execute(test_context)
logger.info(f"✅ Step 1 completed: {result1.get('status')}")
logger.info(f" Quality Score: {result1.get('quality_score')}")
except Exception as e:
logger.error(f"❌ Step 1 failed: {str(e)}")
return False
logger.info("🎉 Step 1 test completed successfully!")
return True
except Exception as e:
logger.error(f"❌ Test failed with error: {str(e)}")
return False
if __name__ == "__main__":
# Configure logging
logger.remove()
logger.add(sys.stderr, level="INFO", format="<green>{time:HH:mm:ss}</green> | <level>{level: <8}</level> | <cyan>{name}</cyan>:<cyan>{function}</cyan>:<cyan>{line}</cyan> - <level>{message}</level>")
# Run the test
success = asyncio.run(test_step1_only())
if success:
logger.info("✅ Test completed successfully!")
sys.exit(0)
else:
logger.error("❌ Test failed!")
sys.exit(1)

View File

@@ -0,0 +1,85 @@
#!/usr/bin/env python3
"""
Test script for Step 2 specifically
"""
import asyncio
import sys
import os
# Add the backend directory to the path
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
from services.calendar_generation_datasource_framework.prompt_chaining.steps.phase2.step2_implementation import Step2Implementation
async def test_step2():
"""Test Step 2 implementation."""
print("🧪 Testing Step 2: Gap Analysis & Opportunity Identification")
# Create test context
context = {
"user_id": 1,
"strategy_id": 1,
"calendar_type": "monthly",
"industry": "technology",
"business_size": "sme",
"user_data": {
"onboarding_data": {
"posting_preferences": {
"daily": 2,
"weekly": 10,
"monthly": 40
},
"posting_days": [
"Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"
],
"optimal_times": [
"09:00", "12:00", "15:00", "18:00", "20:00"
]
},
"strategy_data": {
"industry": "technology",
"target_audience": {
"primary": "Tech professionals",
"secondary": "Business leaders"
},
"business_objectives": [
"Increase brand awareness",
"Generate leads",
"Establish thought leadership"
]
}
},
"step_results": {},
"quality_scores": {}
}
try:
# Create Step 2 instance
step2 = Step2Implementation()
print("✅ Step 2 instance created successfully")
# Test Step 2 execution
print("🔄 Executing Step 2...")
result = await step2.run(context)
if result:
print("✅ Step 2 executed successfully!")
print(f"Status: {result.get('status')}")
print(f"Quality Score: {result.get('quality_score')}")
print(f"Execution Time: {result.get('execution_time')}")
if result.get('status') == 'error':
print(f"❌ Step 2 Error: {result.get('error_message')}")
else:
print("❌ Step 2 returned None")
except Exception as e:
print(f"❌ Error testing Step 2: {e}")
import traceback
print(f"📋 Traceback: {traceback.format_exc()}")
if __name__ == "__main__":
asyncio.run(test_step2())

View File

@@ -0,0 +1,50 @@
#!/usr/bin/env python3
"""
Test script for Step 4 data
"""
import asyncio
import sys
import os
# Add the backend directory to the path
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
async def test_step4_data():
"""Test Step 4 data processing."""
print("🧪 Testing Step 4: Calendar Framework & Timeline Data")
try:
# Test comprehensive user data
from services.calendar_generation_datasource_framework.data_processing.comprehensive_user_data import ComprehensiveUserDataProcessor
processor = ComprehensiveUserDataProcessor()
data = await processor.get_comprehensive_user_data(1, 1)
print("✅ Comprehensive user data retrieved successfully")
print(f"📊 Data keys: {list(data.keys())}")
onboarding_data = data.get('onboarding_data', {})
print(f"📋 Onboarding data keys: {list(onboarding_data.keys())}")
posting_preferences = onboarding_data.get('posting_preferences')
posting_days = onboarding_data.get('posting_days')
optimal_times = onboarding_data.get('optimal_times')
print(f"📅 Posting preferences: {posting_preferences}")
print(f"📅 Posting days: {posting_days}")
print(f"⏰ Optimal times: {optimal_times}")
if posting_preferences and posting_days:
print("✅ Step 4 data requirements met!")
else:
print("❌ Step 4 data requirements NOT met!")
except Exception as e:
print(f"❌ Error testing Step 4 data: {e}")
import traceback
print(f"📋 Traceback: {traceback.format_exc()}")
if __name__ == "__main__":
asyncio.run(test_step4_data())

View File

@@ -0,0 +1,168 @@
#!/usr/bin/env python3
"""
Debug Step 4 data issues - check what data is available from database.
"""
import asyncio
import time
from loguru import logger
import sys
import os
# Add the backend directory to the path
backend_dir = os.path.dirname(os.path.abspath(__file__))
if backend_dir not in sys.path:
sys.path.insert(0, backend_dir)
async def test_step4_data_sources():
"""Test what data Step 4 is actually receiving."""
try:
logger.info("🧪 Testing Step 4 data sources")
# Test 1: Onboarding Data Service
logger.info("📋 Test 1: Onboarding Data Service")
try:
from services.onboarding_data_service import OnboardingDataService
onboarding_service = OnboardingDataService()
# Test with user_id = 1
onboarding_data = onboarding_service.get_personalized_ai_inputs(1)
logger.info(f"📊 Onboarding data keys: {list(onboarding_data.keys()) if onboarding_data else 'None'}")
if onboarding_data:
# Check for posting preferences
posting_prefs = onboarding_data.get("posting_preferences")
posting_days = onboarding_data.get("posting_days")
optimal_times = onboarding_data.get("optimal_times")
logger.info(f"📅 Posting preferences: {posting_prefs}")
logger.info(f"📅 Posting days: {posting_days}")
logger.info(f"📅 Optimal times: {optimal_times}")
# Check website analysis
website_analysis = onboarding_data.get("website_analysis", {})
logger.info(f"🌐 Website analysis keys: {list(website_analysis.keys())}")
# Check competitor analysis
competitor_analysis = onboarding_data.get("competitor_analysis", {})
logger.info(f"🏢 Competitor analysis keys: {list(competitor_analysis.keys())}")
# Check keyword analysis
keyword_analysis = onboarding_data.get("keyword_analysis", {})
logger.info(f"🔍 Keyword analysis keys: {list(keyword_analysis.keys())}")
else:
logger.error("❌ No onboarding data returned")
except Exception as e:
logger.error(f"❌ Onboarding service error: {str(e)}")
# Test 2: Comprehensive User Data Processor
logger.info("\n📋 Test 2: Comprehensive User Data Processor")
try:
from services.calendar_generation_datasource_framework.data_processing.comprehensive_user_data import ComprehensiveUserDataProcessor
processor = ComprehensiveUserDataProcessor()
comprehensive_data = await processor.get_comprehensive_user_data(1, 1)
logger.info(f"📊 Comprehensive data keys: {list(comprehensive_data.keys()) if comprehensive_data else 'None'}")
if comprehensive_data:
# Check onboarding data
onboarding_data = comprehensive_data.get("onboarding_data", {})
logger.info(f"👤 Onboarding data keys: {list(onboarding_data.keys())}")
# Check for posting preferences (Step 4 requirement)
posting_prefs = onboarding_data.get("posting_preferences")
posting_days = onboarding_data.get("posting_days")
optimal_times = onboarding_data.get("optimal_times")
logger.info(f"📅 Posting preferences: {posting_prefs}")
logger.info(f"📅 Posting days: {posting_days}")
logger.info(f"📅 Optimal times: {optimal_times}")
# Check strategy data
strategy_data = comprehensive_data.get("strategy_data", {})
logger.info(f"🎯 Strategy data keys: {list(strategy_data.keys())}")
# Check gap analysis
gap_analysis = comprehensive_data.get("gap_analysis", {})
logger.info(f"📊 Gap analysis keys: {list(gap_analysis.keys())}")
else:
logger.error("❌ No comprehensive data returned")
except Exception as e:
logger.error(f"❌ Comprehensive data processor error: {str(e)}")
# Test 3: Database Connection
logger.info("\n📋 Test 3: Database Connection")
try:
from services.database import get_db_session
from models.onboarding import OnboardingSession, WebsiteAnalysis
session = get_db_session()
# Check for onboarding sessions
onboarding_sessions = session.query(OnboardingSession).all()
logger.info(f"📊 Found {len(onboarding_sessions)} onboarding sessions")
if onboarding_sessions:
for i, session_data in enumerate(onboarding_sessions):
logger.info(f" Session {i+1}: user_id={session_data.user_id}, created={session_data.created_at}")
# Check for website analysis
website_analyses = session.query(WebsiteAnalysis).filter(
WebsiteAnalysis.session_id == session_data.id
).all()
logger.info(f" Website analyses: {len(website_analyses)}")
else:
logger.warning("⚠️ No onboarding sessions found in database")
except Exception as e:
logger.error(f"❌ Database connection error: {str(e)}")
# Test 4: Step 4 Direct Test
logger.info("\n📋 Test 4: Step 4 Direct Test")
try:
from services.calendar_generation_datasource_framework.prompt_chaining.steps.phase2.step4_implementation import CalendarFrameworkStep
step4 = CalendarFrameworkStep()
# Create mock context
context = {
"user_id": 1,
"strategy_id": 1,
"calendar_type": "monthly",
"industry": "technology",
"business_size": "sme"
}
# Try to execute Step 4
logger.info("🔄 Executing Step 4...")
result = await step4.execute(context)
logger.info(f"✅ Step 4 executed successfully")
logger.info(f"📊 Result keys: {list(result.keys()) if result else 'None'}")
except Exception as e:
logger.error(f"❌ Step 4 execution error: {str(e)}")
import traceback
logger.error(f"📋 Traceback: {traceback.format_exc()}")
logger.info("\n🎯 Step 4 Data Debug Complete")
except Exception as e:
logger.error(f"❌ Error in data debug test: {str(e)}")
import traceback
logger.error(f"📋 Traceback: {traceback.format_exc()}")
if __name__ == "__main__":
# Configure logging
logger.remove()
logger.add(sys.stderr, level="INFO", format="<green>{time:HH:mm:ss}</green> | <level>{level: <8}</level> | <cyan>{name}</cyan>:<cyan>{function}</cyan>:<cyan>{line}</cyan> - <level>{message}</level>")
# Run the test
asyncio.run(test_step4_data_sources())

View File

@@ -0,0 +1,63 @@
#!/usr/bin/env python3
"""
Test script for Step 4 execution
"""
import asyncio
import sys
import os
# Add the backend directory to the path
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
async def test_step4_execution():
"""Test Step 4 execution directly."""
print("🧪 Testing Step 4: Calendar Framework & Timeline Execution")
try:
# Import Step 4
from services.calendar_generation_datasource_framework.prompt_chaining.steps.phase2.step4_implementation import CalendarFrameworkStep
# Create test context
context = {
"user_id": 1,
"strategy_id": 1,
"calendar_type": "monthly",
"industry": "technology",
"business_size": "sme",
"step_results": {},
"quality_scores": {}
}
# Create Step 4 instance
step4 = CalendarFrameworkStep()
print("✅ Step 4 instance created successfully")
# Test Step 4 execution
print("🔄 Executing Step 4...")
result = await step4.run(context)
if result:
print("✅ Step 4 executed successfully!")
print(f"Status: {result.get('status')}")
print(f"Quality Score: {result.get('quality_score')}")
print(f"Execution Time: {result.get('execution_time')}")
if result.get('status') == 'error':
print(f"❌ Step 4 Error: {result.get('error_message')}")
else:
print("📊 Step 4 Results:")
print(f" - Calendar Structure: {result.get('calendar_structure', {}).get('type')}")
print(f" - Timeline Config: {result.get('timeline_config', {}).get('total_weeks')} weeks")
print(f" - Duration Control: {result.get('duration_control', {}).get('validation_passed')}")
else:
print("❌ Step 4 returned None")
except Exception as e:
print(f"❌ Error testing Step 4 execution: {e}")
import traceback
print(f"📋 Traceback: {traceback.format_exc()}")
if __name__ == "__main__":
asyncio.run(test_step4_execution())

View File

@@ -0,0 +1,245 @@
#!/usr/bin/env python3
"""
Test Script for Step 4 Implementation
This script tests the Step 4 (Calendar Framework and Timeline) implementation
to ensure it works correctly with real AI services and data processing.
"""
import asyncio
import sys
import os
from pathlib import Path
# Add the backend directory to the Python path
backend_dir = Path(__file__).parent
sys.path.insert(0, str(backend_dir))
from services.calendar_generation_datasource_framework.prompt_chaining.steps.phase2.phase2_steps import CalendarFrameworkStep
from services.calendar_generation_datasource_framework.data_processing import ComprehensiveUserDataProcessor
async def test_step4_implementation():
"""Test Step 4 implementation with real data processing."""
print("🧪 Testing Step 4: Calendar Framework and Timeline Implementation")
try:
# Initialize Step 4
step4 = CalendarFrameworkStep()
print("✅ Step 4 initialized successfully")
# Initialize data processor
data_processor = ComprehensiveUserDataProcessor()
print("✅ Data processor initialized successfully")
# Test context data
context = {
"user_id": 1,
"strategy_id": 1,
"calendar_type": "monthly",
"industry": "technology",
"business_size": "sme"
}
print(f"📊 Testing with context: {context}")
# Execute Step 4
print("🔄 Executing Step 4...")
result = await step4.execute(context)
# Validate results
print("📋 Step 4 Results:")
print(f" - Step Number: {result.get('stepNumber')}")
print(f" - Step Name: {result.get('stepName')}")
print(f" - Quality Score: {result.get('qualityScore', 0):.2f}")
print(f" - Execution Time: {result.get('executionTime')}")
print(f" - Data Sources Used: {result.get('dataSourcesUsed')}")
# Validate calendar structure
calendar_structure = result.get('results', {}).get('calendarStructure', {})
print(f" - Calendar Type: {calendar_structure.get('type')}")
print(f" - Total Weeks: {calendar_structure.get('totalWeeks')}")
print(f" - Content Distribution: {calendar_structure.get('contentDistribution')}")
# Validate timeline configuration
timeline_config = result.get('results', {}).get('timelineConfiguration', {})
print(f" - Start Date: {timeline_config.get('startDate')}")
print(f" - End Date: {timeline_config.get('endDate')}")
print(f" - Total Days: {timeline_config.get('totalDays')}")
print(f" - Posting Days: {timeline_config.get('postingDays')}")
# Validate quality gates
duration_control = result.get('results', {}).get('durationControl', {})
strategic_alignment = result.get('results', {}).get('strategicAlignment', {})
print(f" - Duration Accuracy: {duration_control.get('accuracyScore', 0):.1%}")
print(f" - Strategic Alignment: {strategic_alignment.get('alignmentScore', 0):.1%}")
# Validate insights and recommendations
insights = result.get('insights', [])
recommendations = result.get('recommendations', [])
print(f" - Insights Count: {len(insights)}")
print(f" - Recommendations Count: {len(recommendations)}")
# Quality validation
quality_score = result.get('qualityScore', 0)
if quality_score >= 0.85:
print(f"✅ Quality Score: {quality_score:.2f} (Excellent)")
elif quality_score >= 0.75:
print(f"✅ Quality Score: {quality_score:.2f} (Good)")
else:
print(f"⚠️ Quality Score: {quality_score:.2f} (Needs Improvement)")
print("✅ Step 4 implementation test completed successfully!")
return True
except Exception as e:
print(f"❌ Error testing Step 4: {str(e)}")
import traceback
print(f"Traceback: {traceback.format_exc()}")
return False
async def test_step4_integration():
"""Test Step 4 integration with the orchestrator."""
print("\n🧪 Testing Step 4 Integration with Orchestrator")
try:
from services.calendar_generation_datasource_framework.prompt_chaining.orchestrator import PromptChainOrchestrator
# Initialize orchestrator
orchestrator = PromptChainOrchestrator()
print("✅ Orchestrator initialized successfully")
# Check if Step 4 is properly registered
step4 = orchestrator.steps.get("step_04")
if step4 and step4.name == "Calendar Framework & Timeline":
print("✅ Step 4 properly registered in orchestrator")
else:
print("❌ Step 4 not properly registered in orchestrator")
return False
# Test context initialization
context = await orchestrator._initialize_context(
user_id=1,
strategy_id=1,
calendar_type="monthly",
industry="technology",
business_size="sme"
)
print("✅ Context initialization successful")
# Test Step 4 execution through orchestrator
print("🔄 Testing Step 4 execution through orchestrator...")
step_result = await step4.execute(context)
if step_result and step_result.get('stepNumber') == 4:
print("✅ Step 4 execution through orchestrator successful")
print(f" - Quality Score: {step_result.get('qualityScore', 0):.2f}")
else:
print("❌ Step 4 execution through orchestrator failed")
return False
print("✅ Step 4 integration test completed successfully!")
return True
except Exception as e:
print(f"❌ Error testing Step 4 integration: {str(e)}")
import traceback
print(f"Traceback: {traceback.format_exc()}")
return False
async def test_step4_data_processing():
"""Test Step 4 data processing capabilities."""
print("\n🧪 Testing Step 4 Data Processing")
try:
from services.calendar_generation_datasource_framework.data_processing import ComprehensiveUserDataProcessor
# Initialize data processor
data_processor = ComprehensiveUserDataProcessor()
print("✅ Data processor initialized successfully")
# Test comprehensive user data retrieval
print("🔄 Testing comprehensive user data retrieval...")
user_data = await data_processor.get_comprehensive_user_data(1, 1)
if user_data:
print("✅ Comprehensive user data retrieved successfully")
print(f" - User ID: {user_data.get('user_id')}")
print(f" - Strategy ID: {user_data.get('strategy_id')}")
print(f" - Industry: {user_data.get('industry')}")
# Check for required data sections
required_sections = ['onboarding_data', 'strategy_data', 'gap_analysis', 'ai_analysis']
for section in required_sections:
if section in user_data:
print(f" - {section}: Available")
else:
print(f" - {section}: Missing")
else:
print("❌ Failed to retrieve comprehensive user data")
return False
print("✅ Step 4 data processing test completed successfully!")
return True
except Exception as e:
print(f"❌ Error testing Step 4 data processing: {str(e)}")
import traceback
print(f"Traceback: {traceback.format_exc()}")
return False
async def main():
"""Main test function."""
print("🚀 Starting Step 4 Implementation Tests")
print("=" * 50)
# Run all tests
tests = [
test_step4_implementation(),
test_step4_integration(),
test_step4_data_processing()
]
results = await asyncio.gather(*tests, return_exceptions=True)
# Summarize results
print("\n" + "=" * 50)
print("📊 Test Results Summary")
print("=" * 50)
test_names = [
"Step 4 Implementation",
"Step 4 Integration",
"Step 4 Data Processing"
]
passed = 0
total = len(results)
for i, result in enumerate(results):
if isinstance(result, Exception):
print(f"{test_names[i]}: Failed - {str(result)}")
elif result:
print(f"{test_names[i]}: Passed")
passed += 1
else:
print(f"{test_names[i]}: Failed")
print(f"\n🎯 Overall Results: {passed}/{total} tests passed")
if passed == total:
print("🎉 All tests passed! Step 4 implementation is ready for production.")
return True
else:
print("⚠️ Some tests failed. Please review the implementation.")
return False
if __name__ == "__main__":
success = asyncio.run(main())
sys.exit(0 if success else 1)

View File

@@ -0,0 +1,88 @@
#!/usr/bin/env python3
"""
Test script for Step 5 debugging
"""
import asyncio
import sys
import os
import time
# Add the backend directory to the path
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
async def test_step5_debug():
"""Debug Step 5 execution specifically."""
print("🧪 Debugging Step 5: Content Pillar Distribution")
try:
# Import Step 5
from services.calendar_generation_datasource_framework.prompt_chaining.steps.phase2.step5_implementation import ContentPillarDistributionStep
# Create test context with data from previous steps
context = {
"user_id": 1,
"strategy_id": 1,
"calendar_type": "monthly",
"industry": "technology",
"business_size": "sme",
"previous_step_results": {
4: {
"results": {
"calendarStructure": {
"type": "monthly",
"total_weeks": 4,
"posting_days": ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday"],
"posting_frequency": {
"daily": 2,
"weekly": 10,
"monthly": 40
}
}
}
}
},
"step_results": {},
"quality_scores": {}
}
# Create Step 5 instance
print("✅ Creating Step 5 instance...")
step5 = ContentPillarDistributionStep()
print("✅ Step 5 instance created successfully")
# Test Step 5 execution with timing
print("🔄 Executing Step 5...")
start_time = time.time()
result = await step5.run(context)
execution_time = time.time() - start_time
print(f"⏱️ Step 5 execution time: {execution_time:.2f} seconds")
if result:
print("✅ Step 5 executed successfully!")
print(f"Status: {result.get('status', 'unknown')}")
print(f"Quality Score: {result.get('quality_score', 0)}")
print(f"Execution Time: {result.get('execution_time', 'unknown')}")
if result.get('status') == 'error':
print(f"❌ Step 5 Error: {result.get('error_message', 'Unknown error')}")
else:
print("📊 Step 5 Results:")
results = result.get('results', {})
print(f" - Pillar Mapping: {results.get('pillarMapping', {}).get('distribution_balance', 0):.1%} balance")
print(f" - Theme Development: {results.get('themeDevelopment', {}).get('variety_score', 0):.1%} variety")
print(f" - Strategic Validation: {results.get('strategicValidation', {}).get('alignment_score', 0):.1%} alignment")
print(f" - Diversity Assurance: {results.get('diversityAssurance', {}).get('diversity_score', 0):.1%} diversity")
else:
print("❌ Step 5 returned None")
except Exception as e:
print(f"❌ Error testing Step 5: {e}")
import traceback
print(f"📋 Traceback: {traceback.format_exc()}")
if __name__ == "__main__":
asyncio.run(test_step5_debug())

View File

@@ -0,0 +1,122 @@
#!/usr/bin/env python3
"""
Test script for Step 5 with orchestrator context structure
"""
import asyncio
import sys
import os
import time
# Add the backend directory to the path
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
async def test_step5_orchestrator_context():
"""Test Step 5 with orchestrator context structure."""
print("🧪 Testing Step 5 with orchestrator context structure")
try:
# Import Step 5
from services.calendar_generation_datasource_framework.prompt_chaining.steps.phase2.step5_implementation import ContentPillarDistributionStep
# Create context exactly as the orchestrator does
context = {
"user_id": 1,
"strategy_id": 1,
"calendar_type": "monthly",
"industry": "technology",
"business_size": "sme",
"user_data": {
"user_id": 1,
"strategy_id": 1,
"industry": "technology",
"onboarding_data": {
"posting_preferences": {
"daily": 2,
"weekly": 10,
"monthly": 40
},
"posting_days": ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday"],
"optimal_times": ["09:00", "12:00", "15:00", "18:00", "20:00"]
},
"strategy_data": {
"content_pillars": [
"AI and Machine Learning",
"Digital Transformation",
"Innovation and Technology Trends",
"Business Strategy and Growth"
],
"business_objectives": [
"Increase brand awareness by 40%",
"Generate 500 qualified leads per month",
"Establish thought leadership in AI/ML space"
]
}
},
"step_results": {
"step_04": {
"stepNumber": 4,
"stepName": "Calendar Framework & Timeline",
"results": {
"calendarStructure": {
"type": "monthly",
"total_weeks": 4,
"posting_days": ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday"],
"posting_frequency": {
"daily": 2,
"weekly": 10,
"monthly": 40
},
"industry": "technology",
"business_size": "sme"
}
},
"qualityScore": 1.0,
"executionTime": "2.9s"
}
},
"quality_scores": {},
"current_step": 5,
"phase": "phase_2_structure"
}
# Create Step 5 instance
print("✅ Creating Step 5 instance...")
step5 = ContentPillarDistributionStep()
print("✅ Step 5 instance created successfully")
# Test Step 5 execution with timing
print("🔄 Executing Step 5...")
start_time = time.time()
result = await step5.run(context)
execution_time = time.time() - start_time
print(f"⏱️ Step 5 execution time: {execution_time:.2f} seconds")
if result:
print("✅ Step 5 executed successfully!")
print(f"Status: {result.get('status', 'unknown')}")
print(f"Quality Score: {result.get('quality_score', 0)}")
print(f"Execution Time: {result.get('execution_time', 'unknown')}")
if result.get('status') == 'error':
print(f"❌ Step 5 Error: {result.get('error_message', 'Unknown error')}")
else:
print("📊 Step 5 Results:")
results = result.get('results', {})
print(f" - Pillar Mapping: {results.get('pillarMapping', {}).get('distribution_balance', 0):.1%} balance")
print(f" - Theme Development: {results.get('themeDevelopment', {}).get('variety_score', 0):.1%} variety")
print(f" - Strategic Validation: {results.get('strategicValidation', {}).get('alignment_score', 0):.1%} alignment")
print(f" - Diversity Assurance: {results.get('diversityAssurance', {}).get('diversity_score', 0):.1%} diversity")
else:
print("❌ Step 5 returned None")
except Exception as e:
print(f"❌ Error testing Step 5: {e}")
import traceback
print(f"📋 Traceback: {traceback.format_exc()}")
if __name__ == "__main__":
asyncio.run(test_step5_orchestrator_context())

View File

@@ -0,0 +1,127 @@
#!/usr/bin/env python3
"""
Test script for Step 5 with orchestrator's direct step execution
"""
import asyncio
import sys
import os
import time
# Add the backend directory to the path
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
async def test_step5_orchestrator_direct():
"""Test Step 5 with orchestrator's direct step execution."""
print("🧪 Testing Step 5 with orchestrator's direct step execution")
try:
# Import orchestrator and Step 5
from services.calendar_generation_datasource_framework.prompt_chaining.orchestrator import PromptChainOrchestrator
from services.calendar_generation_datasource_framework.prompt_chaining.steps.phase2.step5_implementation import ContentPillarDistributionStep
# Create orchestrator
print("✅ Creating orchestrator...")
orchestrator = PromptChainOrchestrator()
print("✅ Orchestrator created successfully")
# Get Step 5 from orchestrator
step5 = orchestrator.steps["step_05"]
print(f"✅ Got Step 5 from orchestrator: {type(step5)}")
# Create context exactly as the orchestrator does
context = {
"user_id": 1,
"strategy_id": 1,
"calendar_type": "monthly",
"industry": "technology",
"business_size": "sme",
"user_data": {
"user_id": 1,
"strategy_id": 1,
"industry": "technology",
"onboarding_data": {
"posting_preferences": {
"daily": 2,
"weekly": 10,
"monthly": 40
},
"posting_days": ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday"],
"optimal_times": ["09:00", "12:00", "15:00", "18:00", "20:00"]
},
"strategy_data": {
"content_pillars": [
"AI and Machine Learning",
"Digital Transformation",
"Innovation and Technology Trends",
"Business Strategy and Growth"
],
"business_objectives": [
"Increase brand awareness by 40%",
"Generate 500 qualified leads per month",
"Establish thought leadership in AI/ML space"
]
}
},
"step_results": {
"step_04": {
"stepNumber": 4,
"stepName": "Calendar Framework & Timeline",
"results": {
"calendarStructure": {
"type": "monthly",
"total_weeks": 4,
"posting_days": ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday"],
"posting_frequency": {
"daily": 2,
"weekly": 10,
"monthly": 40
},
"industry": "technology",
"business_size": "sme"
}
},
"qualityScore": 1.0,
"executionTime": "2.9s"
}
},
"quality_scores": {},
"current_step": 5,
"phase": "phase_2_structure"
}
# Test Step 5 execution with timing
print("🔄 Executing Step 5 with orchestrator's step...")
start_time = time.time()
result = await step5.run(context)
execution_time = time.time() - start_time
print(f"⏱️ Step 5 execution time: {execution_time:.2f} seconds")
if result:
print("✅ Step 5 executed successfully!")
print(f"Status: {result.get('status', 'unknown')}")
print(f"Quality Score: {result.get('quality_score', 0)}")
print(f"Execution Time: {result.get('execution_time', 'unknown')}")
if result.get('status') == 'error':
print(f"❌ Step 5 Error: {result.get('error_message', 'Unknown error')}")
else:
print("📊 Step 5 Results:")
step_result = result.get('result', {})
print(f" - Pillar Mapping: {step_result.get('pillarMapping', {}).get('distribution_balance', 0):.1%} balance")
print(f" - Theme Development: {step_result.get('themeDevelopment', {}).get('variety_score', 0):.1%} variety")
print(f" - Strategic Validation: {step_result.get('strategicValidation', {}).get('alignment_score', 0):.1%} alignment")
print(f" - Diversity Assurance: {step_result.get('diversityAssurance', {}).get('diversity_score', 0):.1%} diversity")
else:
print("❌ Step 5 returned None")
except Exception as e:
print(f"❌ Error testing Step 5: {e}")
import traceback
print(f"📋 Traceback: {traceback.format_exc()}")
if __name__ == "__main__":
asyncio.run(test_step5_orchestrator_direct())

View File

@@ -0,0 +1,303 @@
#!/usr/bin/env python3
"""
Test Script for Steps 1-8 of Calendar Generation Framework
This script tests the first 8 steps of the calendar generation process
with real data sources and no fallbacks.
"""
import asyncio
import sys
import os
from typing import Dict, Any
from loguru import logger
# Add the backend directory to the path
backend_dir = os.path.dirname(os.path.abspath(__file__))
if backend_dir not in sys.path:
sys.path.insert(0, backend_dir)
# Add the services directory to the path
services_dir = os.path.join(backend_dir, "services")
if services_dir not in sys.path:
sys.path.insert(0, services_dir)
async def test_steps_1_8():
"""Test Steps 1-8 of the calendar generation framework."""
try:
logger.info("🚀 Starting test of Steps 1-8")
# Test data
test_context = {
"user_id": 1,
"strategy_id": 1,
"calendar_duration": 7, # 1 week
"posting_preferences": {
"posting_frequency": "daily",
"preferred_days": ["monday", "wednesday", "friday"],
"preferred_times": ["09:00", "12:00", "15:00"],
"content_per_day": 2
}
}
# Test Step 1: Content Strategy Analysis
logger.info("📋 Testing Step 1: Content Strategy Analysis")
try:
from services.calendar_generation_datasource_framework.prompt_chaining.steps.phase1.phase1_steps import ContentStrategyAnalysisStep
from services.calendar_generation_datasource_framework.data_processing.strategy_data import StrategyDataProcessor
# Create strategy processor with mock data for testing
strategy_processor = StrategyDataProcessor()
# For testing, we'll create a simple mock strategy data
# In a real scenario, this would come from the database
mock_strategy_data = {
"strategy_id": 1,
"strategy_name": "Test Strategy",
"industry": "technology",
"target_audience": {
"primary": "Tech professionals",
"secondary": "Business leaders",
"demographics": {"age_range": "25-45", "location": "Global"}
},
"content_pillars": [
"AI and Machine Learning",
"Digital Transformation",
"Innovation and Technology Trends",
"Business Strategy and Growth"
],
"business_objectives": [
"Increase brand awareness by 40%",
"Generate 500 qualified leads per month",
"Establish thought leadership"
],
"target_metrics": {"awareness": "website_traffic", "leads": "lead_generation"},
"quality_indicators": {"data_completeness": 0.8, "strategic_alignment": 0.9}
}
# Mock the get_strategy_data method for testing
async def mock_get_strategy_data(strategy_id):
return mock_strategy_data
strategy_processor.get_strategy_data = mock_get_strategy_data
# Mock the validate_data method
async def mock_validate_data(data):
return {
"quality_score": 0.85,
"missing_fields": [],
"recommendations": []
}
strategy_processor.validate_data = mock_validate_data
step1 = ContentStrategyAnalysisStep()
step1.strategy_processor = strategy_processor
result1 = await step1.execute(test_context)
logger.info(f"✅ Step 1 completed: {result1.get('status')}")
logger.info(f" Quality Score: {result1.get('quality_score')}")
except Exception as e:
logger.error(f"❌ Step 1 failed: {str(e)}")
return False
# Test Step 2: Gap Analysis
logger.info("📋 Testing Step 2: Gap Analysis")
try:
from services.calendar_generation_datasource_framework.prompt_chaining.steps.phase1.phase1_steps import GapAnalysisStep
from services.calendar_generation_datasource_framework.data_processing.gap_analysis_data import GapAnalysisDataProcessor
# Create gap processor with mock data for testing
gap_processor = GapAnalysisDataProcessor()
# Mock gap analysis data
mock_gap_data = {
"content_gaps": [
{"topic": "AI Ethics", "priority": "high", "impact_score": 0.9},
{"topic": "Digital Transformation ROI", "priority": "medium", "impact_score": 0.7},
{"topic": "Cloud Migration Strategies", "priority": "high", "impact_score": 0.8}
],
"keyword_opportunities": [
{"keyword": "AI ethics in business", "search_volume": 5000, "competition": "low"},
{"keyword": "digital transformation ROI", "search_volume": 8000, "competition": "medium"},
{"keyword": "cloud migration guide", "search_volume": 12000, "competition": "high"}
],
"competitor_insights": {
"top_competitors": ["Competitor A", "Competitor B"],
"content_gaps": ["AI Ethics", "Practical ROI"],
"opportunities": ["Case Studies", "Implementation Guides"]
},
"opportunities": [
{"type": "content", "topic": "AI Ethics", "priority": "high"},
{"type": "content", "topic": "ROI Analysis", "priority": "medium"}
],
"recommendations": [
"Create comprehensive AI ethics guide",
"Develop ROI calculator for digital transformation",
"Publish case studies on successful implementations"
]
}
# Mock the get_gap_analysis_data method
async def mock_get_gap_analysis_data(user_id):
return mock_gap_data
gap_processor.get_gap_analysis_data = mock_get_gap_analysis_data
step2 = GapAnalysisStep()
step2.gap_processor = gap_processor
result2 = await step2.execute(test_context)
logger.info(f"✅ Step 2 completed: {result2.get('status')}")
logger.info(f" Quality Score: {result2.get('quality_score')}")
except Exception as e:
logger.error(f"❌ Step 2 failed: {str(e)}")
return False
# Test Step 3: Audience & Platform Strategy
logger.info("📋 Testing Step 3: Audience & Platform Strategy")
try:
from services.calendar_generation_datasource_framework.prompt_chaining.steps.phase1.phase1_steps import AudiencePlatformStrategyStep
from services.calendar_generation_datasource_framework.data_processing.comprehensive_user_data import ComprehensiveUserDataProcessor
# Create comprehensive processor with mock data for testing
comprehensive_processor = ComprehensiveUserDataProcessor()
# Mock comprehensive user data
mock_user_data = {
"user_id": 1,
"onboarding_data": {
"industry": "technology",
"business_size": "enterprise",
"target_audience": {
"primary": "Tech professionals",
"secondary": "Business leaders",
"demographics": {"age_range": "25-45", "location": "Global"}
},
"platform_preferences": {
"LinkedIn": {"priority": "high", "content_focus": "professional"},
"Twitter": {"priority": "medium", "content_focus": "news"},
"Blog": {"priority": "high", "content_focus": "in-depth"}
}
},
"performance_data": {
"LinkedIn": {"engagement_rate": 0.08, "reach": 10000},
"Twitter": {"engagement_rate": 0.05, "reach": 5000},
"Blog": {"engagement_rate": 0.12, "reach": 8000}
},
"strategy_data": mock_strategy_data
}
# Mock the get_comprehensive_user_data method
async def mock_get_comprehensive_user_data(user_id, strategy_id):
return mock_user_data
comprehensive_processor.get_comprehensive_user_data = mock_get_comprehensive_user_data
step3 = AudiencePlatformStrategyStep()
step3.comprehensive_processor = comprehensive_processor
result3 = await step3.execute(test_context)
logger.info(f"✅ Step 3 completed: {result3.get('status')}")
logger.info(f" Quality Score: {result3.get('quality_score')}")
except Exception as e:
logger.error(f"❌ Step 3 failed: {str(e)}")
return False
# Test Step 4: Calendar Framework
logger.info("📋 Testing Step 4: Calendar Framework")
try:
from services.calendar_generation_datasource_framework.prompt_chaining.steps.phase2.step4_implementation import CalendarFrameworkStep
step4 = CalendarFrameworkStep()
result4 = await step4.execute(test_context)
logger.info(f"✅ Step 4 completed: {result4.get('status')}")
logger.info(f" Quality Score: {result4.get('quality_score')}")
except Exception as e:
logger.error(f"❌ Step 4 failed: {str(e)}")
return False
# Test Step 5: Content Pillar Distribution
logger.info("📋 Testing Step 5: Content Pillar Distribution")
try:
from services.calendar_generation_datasource_framework.prompt_chaining.steps.phase2.step5_implementation import ContentPillarDistributionStep
step5 = ContentPillarDistributionStep()
result5 = await step5.execute(test_context)
logger.info(f"✅ Step 5 completed: {result5.get('status')}")
logger.info(f" Quality Score: {result5.get('quality_score')}")
except Exception as e:
logger.error(f"❌ Step 5 failed: {str(e)}")
return False
# Test Step 6: Platform-Specific Strategy
logger.info("📋 Testing Step 6: Platform-Specific Strategy")
try:
from services.calendar_generation_datasource_framework.prompt_chaining.steps.phase2.step6_implementation import PlatformSpecificStrategyStep
step6 = PlatformSpecificStrategyStep()
result6 = await step6.execute(test_context)
logger.info(f"✅ Step 6 completed: {result6.get('status')}")
logger.info(f" Quality Score: {result6.get('quality_score')}")
except Exception as e:
logger.error(f"❌ Step 6 failed: {str(e)}")
return False
# Test Step 7: Weekly Theme Development
logger.info("📋 Testing Step 7: Weekly Theme Development")
try:
from services.calendar_generation_datasource_framework.prompt_chaining.steps.phase3.step7_implementation import WeeklyThemeDevelopmentStep
step7 = WeeklyThemeDevelopmentStep()
result7 = await step7.execute(test_context)
logger.info(f"✅ Step 7 completed: {result7.get('status')}")
logger.info(f" Quality Score: {result7.get('quality_score')}")
except Exception as e:
logger.error(f"❌ Step 7 failed: {str(e)}")
return False
# Test Step 8: Daily Content Planning
logger.info("📋 Testing Step 8: Daily Content Planning")
try:
from services.calendar_generation_datasource_framework.prompt_chaining.steps.phase3.step8_implementation import DailyContentPlanningStep
step8 = DailyContentPlanningStep()
result8 = await step8.execute(test_context)
logger.info(f"✅ Step 8 completed: {result8.get('status')}")
logger.info(f" Quality Score: {result8.get('quality_score')}")
except Exception as e:
logger.error(f"❌ Step 8 failed: {str(e)}")
return False
logger.info("🎉 All Steps 1-8 completed successfully!")
logger.info("📝 Note: This test uses mock data for database services.")
logger.info("📝 In production, real database services would be used.")
return True
except Exception as e:
logger.error(f"❌ Test failed with error: {str(e)}")
return False
if __name__ == "__main__":
# Configure logging
logger.remove()
logger.add(sys.stderr, level="INFO", format="<green>{time:HH:mm:ss}</green> | <level>{level: <8}</level> | <cyan>{name}</cyan>:<cyan>{function}</cyan>:<cyan>{line}</cyan> - <level>{message}</level>")
# Run the test
success = asyncio.run(test_steps_1_8())
if success:
logger.info("✅ Test completed successfully!")
sys.exit(0)
else:
logger.error("❌ Test failed!")
sys.exit(1)