ALwrity version 0.5.5
This commit is contained in:
@@ -433,61 +433,61 @@ async def generate_comprehensive_strategy_polling(
|
||||
|
||||
# Step 5: Generate performance predictions
|
||||
generate_comprehensive_strategy_polling._task_status[task_id].update({
|
||||
"step": 4,
|
||||
"progress": 40,
|
||||
"step": 5,
|
||||
"progress": 50,
|
||||
"message": "Generating performance predictions...",
|
||||
"educational_content": EducationalContentManager.get_step_content(4)
|
||||
"educational_content": EducationalContentManager.get_step_content(5)
|
||||
})
|
||||
|
||||
performance_predictions = await strategy_generator._generate_performance_predictions({}, context)
|
||||
|
||||
generate_comprehensive_strategy_polling._task_status[task_id].update({
|
||||
"step": 4,
|
||||
"progress": 45,
|
||||
"step": 5,
|
||||
"progress": 55,
|
||||
"message": "Performance predictions generated successfully",
|
||||
"educational_content": EducationalContentManager.get_step_completion_content(4, performance_predictions)
|
||||
"educational_content": EducationalContentManager.get_step_completion_content(5, performance_predictions)
|
||||
})
|
||||
|
||||
# Step 5: Generate implementation roadmap
|
||||
# Step 6: Generate implementation roadmap
|
||||
generate_comprehensive_strategy_polling._task_status[task_id].update({
|
||||
"step": 5,
|
||||
"progress": 50,
|
||||
"step": 6,
|
||||
"progress": 60,
|
||||
"message": "Generating implementation roadmap...",
|
||||
"educational_content": EducationalContentManager.get_step_content(5)
|
||||
"educational_content": EducationalContentManager.get_step_content(6)
|
||||
})
|
||||
|
||||
implementation_roadmap = await strategy_generator._generate_implementation_roadmap({}, context)
|
||||
|
||||
generate_comprehensive_strategy_polling._task_status[task_id].update({
|
||||
"step": 5,
|
||||
"progress": 55,
|
||||
"step": 6,
|
||||
"progress": 65,
|
||||
"message": "Implementation roadmap generated successfully",
|
||||
"educational_content": EducationalContentManager.get_step_completion_content(5, implementation_roadmap)
|
||||
"educational_content": EducationalContentManager.get_step_completion_content(6, implementation_roadmap)
|
||||
})
|
||||
|
||||
# Step 6: Generate risk assessment
|
||||
# Step 7: Generate risk assessment
|
||||
generate_comprehensive_strategy_polling._task_status[task_id].update({
|
||||
"step": 6,
|
||||
"progress": 60,
|
||||
"step": 7,
|
||||
"progress": 70,
|
||||
"message": "Generating risk assessment...",
|
||||
"educational_content": EducationalContentManager.get_step_content(6)
|
||||
"educational_content": EducationalContentManager.get_step_content(7)
|
||||
})
|
||||
|
||||
risk_assessment = await strategy_generator._generate_risk_assessment({}, context)
|
||||
|
||||
generate_comprehensive_strategy_polling._task_status[task_id].update({
|
||||
"step": 6,
|
||||
"progress": 65,
|
||||
"step": 7,
|
||||
"progress": 75,
|
||||
"message": "Risk assessment generated successfully",
|
||||
"educational_content": EducationalContentManager.get_step_completion_content(6, risk_assessment)
|
||||
"educational_content": EducationalContentManager.get_step_completion_content(7, risk_assessment)
|
||||
})
|
||||
|
||||
# Step 7: Compile comprehensive strategy
|
||||
# Step 8: Compile comprehensive strategy
|
||||
generate_comprehensive_strategy_polling._task_status[task_id].update({
|
||||
"step": 7,
|
||||
"progress": 70,
|
||||
"step": 8,
|
||||
"progress": 80,
|
||||
"message": "Compiling comprehensive strategy...",
|
||||
"educational_content": EducationalContentManager.get_step_content(7)
|
||||
"educational_content": EducationalContentManager.get_step_content(8)
|
||||
})
|
||||
|
||||
# Compile the comprehensive strategy (NO CONTENT CALENDAR)
|
||||
@@ -553,7 +553,8 @@ async def generate_comprehensive_strategy_polling(
|
||||
logger.error(f"❌ Error saving strategy to database: {str(db_error)}")
|
||||
# Continue without database save, strategy is still available in memory
|
||||
|
||||
generate_comprehensive_strategy_polling._task_status[task_id].update({
|
||||
# Final completion update
|
||||
final_status = {
|
||||
"step": 8,
|
||||
"progress": 100,
|
||||
"status": "completed",
|
||||
@@ -561,7 +562,12 @@ async def generate_comprehensive_strategy_polling(
|
||||
"strategy": comprehensive_strategy,
|
||||
"completed_at": datetime.utcnow().isoformat(),
|
||||
"educational_content": completion_content
|
||||
})
|
||||
}
|
||||
|
||||
generate_comprehensive_strategy_polling._task_status[task_id].update(final_status)
|
||||
|
||||
logger.info(f"🎯 Final status update for task {task_id}: {final_status}")
|
||||
logger.info(f"🎯 Task status after update: {generate_comprehensive_strategy_polling._task_status[task_id]}")
|
||||
|
||||
# Store in global latest strategies for persistent access
|
||||
_latest_strategies[user_id] = {
|
||||
|
||||
@@ -210,7 +210,17 @@ class AIStrategyGenerator:
|
||||
raise RuntimeError("AI service returned empty strategic insights")
|
||||
|
||||
logger.info("✅ Strategic insights generated successfully")
|
||||
return response.get("data", {})
|
||||
|
||||
# Log the raw AI response for debugging
|
||||
logger.info(f"🔍 Raw AI response for strategic insights: {json.dumps(response.get('data', {}), indent=2)}")
|
||||
|
||||
# Transform AI response to frontend format
|
||||
transformed_response = self._transform_ai_response_to_frontend_format(response.get("data", {}), "strategic_insights")
|
||||
|
||||
# Log the transformed response for debugging
|
||||
logger.info(f"🔄 Transformed strategic insights: {json.dumps(transformed_response, indent=2)}")
|
||||
|
||||
return transformed_response
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"❌ Error generating strategic insights: {str(e)}")
|
||||
@@ -277,7 +287,17 @@ class AIStrategyGenerator:
|
||||
raise RuntimeError("AI service returned empty competitive analysis")
|
||||
|
||||
logger.info("✅ Competitive analysis generated successfully")
|
||||
return response.get("data", {})
|
||||
|
||||
# Log the raw AI response for debugging
|
||||
logger.info(f"🔍 Raw AI response for competitive analysis: {json.dumps(response.get('data', {}), indent=2)}")
|
||||
|
||||
# Transform AI response to frontend format
|
||||
transformed_response = self._transform_ai_response_to_frontend_format(response.get("data", {}), "competitive_analysis")
|
||||
|
||||
# Log the transformed response for debugging
|
||||
logger.info(f"🔄 Transformed competitive analysis: {json.dumps(transformed_response, indent=2)}")
|
||||
|
||||
return transformed_response
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"❌ Error generating competitive analysis: {str(e)}")
|
||||
@@ -476,7 +496,10 @@ class AIStrategyGenerator:
|
||||
raise RuntimeError("AI service returned empty performance predictions")
|
||||
|
||||
logger.info("✅ Performance predictions generated successfully")
|
||||
return response.get("data", {})
|
||||
|
||||
# Transform AI response to frontend format
|
||||
transformed_response = self._transform_ai_response_to_frontend_format(response.get("data", {}), "performance_predictions")
|
||||
return transformed_response
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"❌ Error generating performance predictions: {str(e)}")
|
||||
@@ -569,7 +592,10 @@ class AIStrategyGenerator:
|
||||
raise RuntimeError("AI service returned empty implementation roadmap")
|
||||
|
||||
logger.info("✅ Implementation roadmap generated successfully")
|
||||
return response.get("data", {})
|
||||
|
||||
# Transform AI response to frontend format
|
||||
transformed_response = self._transform_ai_response_to_frontend_format(response.get("data", {}), "implementation_roadmap")
|
||||
return transformed_response
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"❌ Error generating implementation roadmap: {str(e)}")
|
||||
@@ -653,7 +679,10 @@ class AIStrategyGenerator:
|
||||
raise RuntimeError("AI service returned empty risk assessment")
|
||||
|
||||
logger.info("✅ Risk assessment generated successfully")
|
||||
return response.get("data", {})
|
||||
|
||||
# Transform AI response to frontend format
|
||||
transformed_response = self._transform_ai_response_to_frontend_format(response.get("data", {}), "risk_assessment")
|
||||
return transformed_response
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"❌ Error generating risk assessment: {str(e)}")
|
||||
@@ -781,4 +810,260 @@ class AIStrategyGenerator:
|
||||
5. Overall risk level assessment
|
||||
|
||||
Focus on practical risk mitigation strategies.
|
||||
"""
|
||||
"""
|
||||
|
||||
def _transform_ai_response_to_frontend_format(self, ai_response: Dict[str, Any], response_type: str) -> Dict[str, Any]:
|
||||
"""
|
||||
Transform AI response to frontend-expected format to fix empty arrays issue.
|
||||
|
||||
Args:
|
||||
ai_response: Raw AI response
|
||||
response_type: Type of response (strategic_insights, competitive_analysis, etc.)
|
||||
|
||||
Returns:
|
||||
Transformed response in frontend-expected format
|
||||
"""
|
||||
try:
|
||||
if response_type == "strategic_insights":
|
||||
return self._transform_strategic_insights(ai_response)
|
||||
elif response_type == "competitive_analysis":
|
||||
return self._transform_competitive_analysis(ai_response)
|
||||
elif response_type == "performance_predictions":
|
||||
return self._transform_performance_predictions(ai_response)
|
||||
elif response_type == "implementation_roadmap":
|
||||
return self._transform_implementation_roadmap(ai_response)
|
||||
elif response_type == "risk_assessment":
|
||||
return self._transform_risk_assessment(ai_response)
|
||||
else:
|
||||
return ai_response
|
||||
except Exception as e:
|
||||
self.logger.error(f"Error transforming {response_type} response: {str(e)}")
|
||||
return ai_response
|
||||
|
||||
def _transform_strategic_insights(self, ai_response: Dict[str, Any]) -> Dict[str, Any]:
|
||||
"""Transform strategic insights to frontend format."""
|
||||
transformed = {
|
||||
"market_positioning": {
|
||||
"positioning_strength": 75,
|
||||
"current_position": "Emerging",
|
||||
"swot_analysis": {
|
||||
"strengths": [],
|
||||
"opportunities": []
|
||||
}
|
||||
},
|
||||
"content_opportunities": [],
|
||||
"growth_potential": {
|
||||
"market_size": "Growing",
|
||||
"growth_rate": "High",
|
||||
"key_drivers": [],
|
||||
"competitive_advantages": []
|
||||
},
|
||||
"swot_summary": {
|
||||
"overall_score": 75,
|
||||
"primary_strengths": [],
|
||||
"key_opportunities": []
|
||||
}
|
||||
}
|
||||
|
||||
# Extract insights from AI response
|
||||
insights = ai_response.get("insights", [])
|
||||
if insights:
|
||||
# Extract content opportunities
|
||||
content_opportunities = []
|
||||
key_drivers = []
|
||||
competitive_advantages = []
|
||||
strengths = []
|
||||
opportunities = []
|
||||
|
||||
for insight in insights:
|
||||
insight_type = insight.get("type", "").lower()
|
||||
insight_text = insight.get("insight", "")
|
||||
|
||||
# More flexible matching to capture different types of insights
|
||||
if any(keyword in insight_type for keyword in ["opportunity", "content", "market"]) or any(keyword in insight_text.lower() for keyword in ["opportunity", "content", "market"]):
|
||||
if any(keyword in insight_text.lower() for keyword in ["content", "blog", "article", "post", "video", "social"]):
|
||||
content_opportunities.append(insight_text)
|
||||
else:
|
||||
opportunities.append(insight_text)
|
||||
elif any(keyword in insight_type for keyword in ["strength", "advantage", "competitive"]) or any(keyword in insight_text.lower() for keyword in ["strength", "advantage", "competitive"]):
|
||||
if any(keyword in insight_text.lower() for keyword in ["competitive", "advantage", "differentiation"]):
|
||||
competitive_advantages.append(insight_text)
|
||||
else:
|
||||
strengths.append(insight_text)
|
||||
elif any(keyword in insight_type for keyword in ["driver", "growth", "trend"]) or any(keyword in insight_text.lower() for keyword in ["driver", "growth", "trend"]):
|
||||
key_drivers.append(insight_text)
|
||||
else:
|
||||
# Default categorization based on content
|
||||
if any(keyword in insight_text.lower() for keyword in ["opportunity", "potential", "growth"]):
|
||||
opportunities.append(insight_text)
|
||||
elif any(keyword in insight_text.lower() for keyword in ["strength", "advantage", "strong"]):
|
||||
strengths.append(insight_text)
|
||||
elif any(keyword in insight_text.lower() for keyword in ["driver", "trend", "factor"]):
|
||||
key_drivers.append(insight_text)
|
||||
|
||||
# Ensure we have some data even if categorization didn't work
|
||||
if not content_opportunities and insights:
|
||||
content_opportunities = [insight.get("insight", "") for insight in insights[:3]]
|
||||
if not opportunities and insights:
|
||||
opportunities = [insight.get("insight", "") for insight in insights[3:6]]
|
||||
if not strengths and insights:
|
||||
strengths = [insight.get("insight", "") for insight in insights[6:9]]
|
||||
if not key_drivers and insights:
|
||||
key_drivers = [insight.get("insight", "") for insight in insights[9:12]]
|
||||
|
||||
# Update transformed data
|
||||
transformed["content_opportunities"] = content_opportunities[:3] # Limit to 3
|
||||
transformed["growth_potential"]["key_drivers"] = key_drivers[:3]
|
||||
transformed["growth_potential"]["competitive_advantages"] = competitive_advantages[:3]
|
||||
transformed["market_positioning"]["swot_analysis"]["strengths"] = strengths[:3]
|
||||
transformed["market_positioning"]["swot_analysis"]["opportunities"] = opportunities[:3]
|
||||
transformed["swot_summary"]["primary_strengths"] = strengths[:3]
|
||||
transformed["swot_summary"]["key_opportunities"] = opportunities[:3]
|
||||
|
||||
return transformed
|
||||
|
||||
def _transform_competitive_analysis(self, ai_response: Dict[str, Any]) -> Dict[str, Any]:
|
||||
"""Transform competitive analysis to frontend format."""
|
||||
transformed = {
|
||||
"competitors": [],
|
||||
"market_gaps": [],
|
||||
"opportunities": [],
|
||||
"recommendations": [],
|
||||
"competitive_advantages": {
|
||||
"primary": [],
|
||||
"sustainable": [],
|
||||
"development_areas": []
|
||||
},
|
||||
"swot_competitive_insights": {
|
||||
"leverage_strengths": [],
|
||||
"address_weaknesses": [],
|
||||
"capitalize_opportunities": [],
|
||||
"mitigate_threats": []
|
||||
}
|
||||
}
|
||||
|
||||
# Extract competitive insights from AI response - handle both insights array and direct fields
|
||||
insights = ai_response.get("insights", [])
|
||||
competitors = ai_response.get("competitors", [])
|
||||
market_gaps = ai_response.get("market_gaps", [])
|
||||
opportunities = ai_response.get("opportunities", [])
|
||||
recommendations = ai_response.get("recommendations", [])
|
||||
|
||||
# Process insights array if available
|
||||
if insights:
|
||||
for insight in insights:
|
||||
insight_type = insight.get("type", "").lower()
|
||||
insight_text = insight.get("insight", "")
|
||||
|
||||
if any(keyword in insight_type for keyword in ["gap", "market"]) or any(keyword in insight_text.lower() for keyword in ["gap", "market", "missing"]):
|
||||
market_gaps.append(insight_text)
|
||||
elif any(keyword in insight_type for keyword in ["opportunity", "potential"]) or any(keyword in insight_text.lower() for keyword in ["opportunity", "potential", "growth"]):
|
||||
opportunities.append(insight_text)
|
||||
elif any(keyword in insight_type for keyword in ["recommendation", "strategy", "action"]) or any(keyword in insight_text.lower() for keyword in ["recommendation", "strategy", "action", "should"]):
|
||||
recommendations.append(insight_text)
|
||||
|
||||
# Ensure we have some data even if categorization didn't work
|
||||
if not market_gaps and insights:
|
||||
market_gaps = [insight.get("insight", "") for insight in insights[:3]]
|
||||
if not opportunities and insights:
|
||||
opportunities = [insight.get("insight", "") for insight in insights[3:6]]
|
||||
if not recommendations and insights:
|
||||
recommendations = [insight.get("insight", "") for insight in insights[6:9]]
|
||||
|
||||
# Update transformed data
|
||||
transformed["competitors"] = competitors[:3] if competitors else []
|
||||
transformed["market_gaps"] = market_gaps[:3]
|
||||
transformed["opportunities"] = opportunities[:3]
|
||||
transformed["recommendations"] = recommendations[:3]
|
||||
transformed["competitive_advantages"]["primary"] = opportunities[:3] # Use opportunities as primary advantages
|
||||
transformed["competitive_advantages"]["sustainable"] = recommendations[:3] # Use recommendations as sustainable advantages
|
||||
transformed["competitive_advantages"]["development_areas"] = market_gaps[:3] # Use market gaps as development areas
|
||||
transformed["swot_competitive_insights"]["leverage_strengths"] = opportunities[:2]
|
||||
transformed["swot_competitive_insights"]["capitalize_opportunities"] = opportunities[:2]
|
||||
transformed["swot_competitive_insights"]["address_weaknesses"] = market_gaps[:2]
|
||||
transformed["swot_competitive_insights"]["mitigate_threats"] = recommendations[:2]
|
||||
|
||||
return transformed
|
||||
|
||||
def _transform_performance_predictions(self, ai_response: Dict[str, Any]) -> Dict[str, Any]:
|
||||
"""Transform performance predictions to frontend format."""
|
||||
transformed = {
|
||||
"estimated_roi": "20-30%",
|
||||
"traffic_growth": {
|
||||
"month_3": "25%",
|
||||
"month_6": "50%",
|
||||
"month_12": "100%"
|
||||
},
|
||||
"engagement_metrics": {
|
||||
"time_on_page": "3-5 minutes",
|
||||
"bounce_rate": "35-45%",
|
||||
"social_shares": "15-25 per post"
|
||||
},
|
||||
"conversion_predictions": {
|
||||
"lead_generation": "5-8%",
|
||||
"email_signups": "3-5%",
|
||||
"content_downloads": "8-12%"
|
||||
},
|
||||
"success_probability": "85%"
|
||||
}
|
||||
|
||||
# Extract performance data from AI response
|
||||
predictions = ai_response.get("predictions", {})
|
||||
if predictions:
|
||||
if "roi" in predictions:
|
||||
transformed["estimated_roi"] = predictions["roi"]
|
||||
if "success_probability" in predictions:
|
||||
transformed["success_probability"] = predictions["success_probability"]
|
||||
|
||||
return transformed
|
||||
|
||||
def _transform_implementation_roadmap(self, ai_response: Dict[str, Any]) -> Dict[str, Any]:
|
||||
"""Transform implementation roadmap to frontend format."""
|
||||
transformed = {
|
||||
"phases": [],
|
||||
"timeline": "12 months",
|
||||
"resource_requirements": [],
|
||||
"milestones": [],
|
||||
"critical_path": [],
|
||||
"success_metrics": []
|
||||
}
|
||||
|
||||
# Extract roadmap data from AI response
|
||||
roadmap = ai_response.get("roadmap", {})
|
||||
if roadmap:
|
||||
if "phases" in roadmap:
|
||||
transformed["phases"] = roadmap["phases"][:4] # Limit to 4 phases
|
||||
if "timeline" in roadmap:
|
||||
transformed["timeline"] = roadmap["timeline"]
|
||||
if "milestones" in roadmap:
|
||||
transformed["milestones"] = roadmap["milestones"][:6] # Limit to 6 milestones
|
||||
|
||||
return transformed
|
||||
|
||||
def _transform_risk_assessment(self, ai_response: Dict[str, Any]) -> Dict[str, Any]:
|
||||
"""Transform risk assessment to frontend format."""
|
||||
transformed = {
|
||||
"risks": [],
|
||||
"overall_risk_level": "Medium",
|
||||
"risk_categories": {
|
||||
"technical_risks": [],
|
||||
"market_risks": [],
|
||||
"operational_risks": [],
|
||||
"financial_risks": []
|
||||
},
|
||||
"mitigation_strategies": [],
|
||||
"monitoring_framework": {
|
||||
"key_indicators": [],
|
||||
"monitoring_frequency": "Weekly",
|
||||
"escalation_procedures": [],
|
||||
"review_schedule": "Monthly"
|
||||
}
|
||||
}
|
||||
|
||||
# Extract risk data from AI response
|
||||
risks = ai_response.get("risks", [])
|
||||
if risks:
|
||||
transformed["risks"] = risks[:5] # Limit to 5 risks
|
||||
transformed["mitigation_strategies"] = [risk.get("mitigation", "") for risk in risks[:3]]
|
||||
|
||||
return transformed
|
||||
Reference in New Issue
Block a user