ALwrity version 0.5.5

This commit is contained in:
ajaysi
2025-08-20 20:22:56 +05:30
parent 74e22b421a
commit 3f2f4d7b8c
43 changed files with 2938 additions and 690 deletions

View File

@@ -662,6 +662,16 @@ async def get_latest_generated_strategy(
logger.info(f"🔍 Querying database for strategies with user_id: {user_id}")
# Query for the most recent strategy with comprehensive AI analysis
# First, let's see all strategies for this user
all_strategies = db.query(EnhancedContentStrategy).filter(
EnhancedContentStrategy.user_id == user_id
).order_by(desc(EnhancedContentStrategy.created_at)).all()
logger.info(f"🔍 Found {len(all_strategies)} total strategies for user {user_id}")
for i, strategy in enumerate(all_strategies):
logger.info(f" Strategy {i+1}: ID={strategy.id}, name={strategy.name}, created_at={strategy.created_at}, has_comprehensive_ai_analysis={strategy.comprehensive_ai_analysis is not None}")
# Now query for the most recent strategy with comprehensive AI analysis
latest_db_strategy = db.query(EnhancedContentStrategy).filter(
EnhancedContentStrategy.user_id == user_id,
EnhancedContentStrategy.comprehensive_ai_analysis.isnot(None)
@@ -682,9 +692,31 @@ async def get_latest_generated_strategy(
}
)
else:
logger.info(f"⚠️ No strategy found in database for user: {user_id}")
if latest_db_strategy:
logger.info(f"🔍 Strategy found but no comprehensive_ai_analysis: {latest_db_strategy.id}")
logger.info(f"⚠️ No strategy with comprehensive_ai_analysis found in database for user: {user_id}")
# Fallback: Try to get the most recent strategy regardless of comprehensive_ai_analysis
fallback_strategy = db.query(EnhancedContentStrategy).filter(
EnhancedContentStrategy.user_id == user_id
).order_by(desc(EnhancedContentStrategy.created_at)).first()
if fallback_strategy:
logger.info(f"🔍 Found fallback strategy: ID={fallback_strategy.id}, name={fallback_strategy.name}")
logger.info(f"🔍 Fallback strategy has ai_recommendations: {fallback_strategy.ai_recommendations is not None}")
# Try to use ai_recommendations as the strategy data
if fallback_strategy.ai_recommendations:
logger.info(f"✅ Using ai_recommendations as strategy data for fallback strategy {fallback_strategy.id}")
return ResponseBuilder.create_success_response(
message="Latest generated strategy retrieved successfully from database (fallback)",
data={
"user_id": user_id,
"strategy": fallback_strategy.ai_recommendations,
"completed_at": fallback_strategy.created_at.isoformat(),
"strategy_id": fallback_strategy.id
}
)
else:
logger.info(f"⚠️ Fallback strategy has no ai_recommendations either")
else:
logger.info(f"🔍 No strategy record found at all for user: {user_id}")
except Exception as db_error:

View File

@@ -1141,7 +1141,7 @@ async def stream_autofill_refresh(
async def refresh_autofill(
user_id: Optional[int] = Query(None, description="User ID to build auto-fill for"),
use_ai: bool = Query(True, description="Use AI augmentation during refresh"),
ai_only: bool = Query(False, description="AI-first refresh: return AI overrides when available"),
ai_only: bool = Query(True, description="🚨 CRITICAL: Force AI-only generation to ensure real AI values"),
db: Session = Depends(get_db)
) -> Dict[str, Any]:
"""Non-stream endpoint to return a fresh auto-fill payload (no DB writes)."""
@@ -1149,7 +1149,8 @@ async def refresh_autofill(
actual_user_id = user_id or 1
started = datetime.utcnow()
refresh_service = AutoFillRefreshService(db)
payload = await refresh_service.build_fresh_payload_with_transparency(actual_user_id, use_ai=use_ai, ai_only=ai_only)
# 🚨 CRITICAL: Force AI-only generation for refresh to ensure real AI values
payload = await refresh_service.build_fresh_payload_with_transparency(actual_user_id, use_ai=True, ai_only=True)
total_ms = int((datetime.utcnow() - started).total_seconds() * 1000)
meta = payload.get('meta') or {}
meta.update({'http_total_ms': total_ms, 'http_started_at': started.isoformat()})

View File

@@ -68,23 +68,36 @@ class AIStrategyGenerator:
try:
self.logger.info(f"🚀 Generating comprehensive AI strategy for user: {user_id}")
# Track which components failed during generation
failed_components = []
# Step 1: Generate base strategy fields (using existing autofill system)
base_strategy = await self._generate_base_strategy_fields(user_id, context)
# Step 2: Generate strategic insights and recommendations
strategic_insights = await self._generate_strategic_insights(base_strategy, context)
if strategic_insights.get("ai_generation_failed"):
failed_components.append("strategic_insights")
# Step 3: Generate competitive analysis
competitive_analysis = await self._generate_competitive_analysis(base_strategy, context)
if competitive_analysis.get("ai_generation_failed"):
failed_components.append("competitive_analysis")
# Step 4: Generate performance predictions
performance_predictions = await self._generate_performance_predictions(base_strategy, context)
if performance_predictions.get("ai_generation_failed"):
failed_components.append("performance_predictions")
# Step 5: Generate implementation roadmap
implementation_roadmap = await self._generate_implementation_roadmap(base_strategy, context)
if implementation_roadmap.get("ai_generation_failed"):
failed_components.append("implementation_roadmap")
# Step 6: Generate risk assessment
risk_assessment = await self._generate_risk_assessment(base_strategy, context)
if risk_assessment.get("ai_generation_failed"):
failed_components.append("risk_assessment")
# Step 7: Compile comprehensive strategy (NO CONTENT CALENDAR)
comprehensive_strategy = {
@@ -97,7 +110,9 @@ class AIStrategyGenerator:
"personalization_level": "high",
"ai_generated": True,
"comprehensive": True,
"content_calendar_ready": False # Indicates calendar needs to be generated separately
"content_calendar_ready": False, # Indicates calendar needs to be generated separately
"failed_components": failed_components,
"generation_status": "partial" if failed_components else "complete"
},
"base_strategy": base_strategy,
"strategic_insights": strategic_insights,
@@ -114,7 +129,11 @@ class AIStrategyGenerator:
}
}
self.logger.info(f"✅ Comprehensive AI strategy generated successfully for user: {user_id}")
if failed_components:
self.logger.warning(f"⚠️ Strategy generated with partial AI components. Failed: {failed_components}")
self.logger.info(f"✅ Partial AI strategy generated successfully for user: {user_id}")
else:
self.logger.info(f"✅ Comprehensive AI strategy generated successfully for user: {user_id}")
return comprehensive_strategy
except Exception as e:
@@ -223,8 +242,15 @@ class AIStrategyGenerator:
return transformed_response
except Exception as e:
logger.error(f"❌ Error generating strategic insights: {str(e)}")
raise RuntimeError(f"Failed to generate strategic insights: {str(e)}")
logger.warning(f"⚠️ AI service overload or error during strategic insights: {str(e)}")
logger.info("🔄 Continuing strategy generation without strategic insights...")
# Return empty strategic insights to allow strategy generation to continue
return {
"insights": [],
"ai_generation_failed": True,
"failure_reason": str(e)
}
async def _generate_competitive_analysis(self, base_strategy: Dict[str, Any], context: Dict[str, Any], ai_manager: Optional[Any] = None) -> Dict[str, Any]:
"""Generate competitive analysis using AI."""
@@ -300,8 +326,18 @@ class AIStrategyGenerator:
return transformed_response
except Exception as e:
logger.error(f"❌ Error generating competitive analysis: {str(e)}")
raise RuntimeError(f"Failed to generate competitive analysis: {str(e)}")
logger.warning(f"⚠️ AI service overload or error during competitive analysis: {str(e)}")
logger.info("🔄 Continuing strategy generation without competitive analysis...")
# Return empty competitive analysis to allow strategy generation to continue
return {
"competitors": [],
"market_gaps": [],
"opportunities": [],
"recommendations": [],
"ai_generation_failed": True,
"failure_reason": str(e)
}
async def _generate_content_calendar(self, base_strategy: Dict[str, Any], context: Dict[str, Any], ai_manager: Optional[Any] = None) -> Dict[str, Any]:
"""Generate content calendar using AI."""
@@ -502,8 +538,18 @@ class AIStrategyGenerator:
return transformed_response
except Exception as e:
logger.error(f"❌ Error generating performance predictions: {str(e)}")
raise RuntimeError(f"Failed to generate performance predictions: {str(e)}")
logger.warning(f"⚠️ AI service overload or error during performance predictions: {str(e)}")
logger.info("🔄 Continuing strategy generation without performance predictions...")
# Return empty performance predictions to allow strategy generation to continue
return {
"traffic_predictions": {},
"engagement_predictions": {},
"conversion_predictions": {},
"roi_predictions": {},
"ai_generation_failed": True,
"failure_reason": str(e)
}
async def _generate_implementation_roadmap(self, base_strategy: Dict[str, Any], context: Dict[str, Any], ai_manager: Optional[Any] = None) -> Dict[str, Any]:
"""Generate implementation roadmap using AI."""
@@ -600,8 +646,19 @@ class AIStrategyGenerator:
return transformed_response
except Exception as e:
logger.error(f"❌ Error generating implementation roadmap: {str(e)}")
raise RuntimeError(f"Failed to generate implementation roadmap: {str(e)}")
logger.warning(f"⚠️ AI service overload or error during implementation roadmap: {str(e)}")
logger.info("🔄 Continuing strategy generation without implementation roadmap...")
# Return empty implementation roadmap to allow strategy generation to continue
return {
"phases": [],
"timeline": {},
"resource_allocation": {},
"success_metrics": [],
"total_duration": "TBD",
"ai_generation_failed": True,
"failure_reason": str(e)
}
async def _generate_risk_assessment(self, base_strategy: Dict[str, Any], context: Dict[str, Any], ai_manager: Optional[Any] = None) -> Dict[str, Any]:
"""Generate risk assessment using AI."""
@@ -738,8 +795,29 @@ class AIStrategyGenerator:
return transformed_response
except Exception as e:
logger.error(f"❌ Error generating risk assessment: {str(e)}")
raise RuntimeError(f"Failed to generate risk assessment: {str(e)}")
logger.warning(f"⚠️ AI service overload or error during risk assessment: {str(e)}")
logger.info("🔄 Continuing strategy generation without risk assessment...")
# Return empty risk assessment to allow strategy generation to continue
return {
"risks": [],
"overall_risk_level": "Medium",
"risk_categories": {
"technical_risks": [],
"market_risks": [],
"operational_risks": [],
"financial_risks": []
},
"mitigation_strategies": [],
"monitoring_framework": {
"key_indicators": [],
"monitoring_frequency": "Monthly",
"escalation_procedures": [],
"review_schedule": "Quarterly"
},
"ai_generation_failed": True,
"failure_reason": str(e)
}
def _build_strategic_insights_prompt(self, base_strategy: Dict[str, Any], context: Dict[str, Any]) -> str:
"""Build prompt for strategic insights generation."""