AjaykumarPilla commited on
Commit
056c475
·
verified ·
1 Parent(s): eb03e55

Update model.py

Browse files
Files changed (1) hide show
  1. model.py +77 -55
model.py CHANGED
@@ -5,10 +5,25 @@ from typing import Dict, List
5
  logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
6
  logger = logging.getLogger(__name__)
7
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8
  def call_ai_model_for_insights(input_data: Dict, delay_risk: float) -> List[str]:
9
  """
10
- Generate detailed hardcoded insights based on input data and delay risk, bypassing T5-Small.
11
- Returns 3-5 prioritized, phase/task-specific insights tailored to conditions.
12
  """
13
  logger.info("Generating detailed hardcoded AI insights")
14
  phase = input_data.get("phase", "")
@@ -19,7 +34,9 @@ def call_ai_model_for_insights(input_data: Dict, delay_risk: float) -> List[str]
19
  workforce_gap = input_data.get("workforce_gap", 0)
20
  skill_level = input_data.get("workforce_skill_level", "").lower()
21
  shift_hours = input_data.get("workforce_shift_hours", 0)
22
- weather_condition = input_data.get("weather_condition", "").lower()
 
 
23
 
24
  # Initialize insights with scores for prioritization
25
  insights = []
@@ -30,30 +47,42 @@ def call_ai_model_for_insights(input_data: Dict, delay_risk: float) -> List[str]
30
 
31
  # Delay risk-based insights
32
  if delay_risk > 75:
33
- add_insight(f"Urgent: Accelerate {phase}: {task} to mitigate high delay risk", 1.0)
34
  elif delay_risk > 50:
35
- add_insight(f"Monitor {phase}: {task} closely to prevent delays", 0.9)
36
  elif delay_risk > 25:
37
- add_insight(f"Maintain current pace for {phase}: {task}", 0.7)
 
 
 
 
 
 
 
 
 
 
 
 
38
  else:
39
- add_insight(f"Optimize resource allocation for {phase}: {task}", 0.6)
40
 
41
  # Phase/task-specific insights
42
  task_specific = {
43
  "Planning": {
44
- "Define Scope": "Ensure clear stakeholder alignment for Planning: Define Scope",
45
- "Resource Allocation": "Secure budget approvals early for Planning: Resource Allocation",
46
- "Permit Acquisition": "Secure permits early for Planning: Permit Acquisition"
47
  },
48
  "Design": {
49
- "Architectural Drafting": "Engage architects early for Design: Architectural Drafting",
50
- "Engineering Analysis": "Hire additional engineers for Design: Engineering Analysis",
51
- "Design Review": "Schedule thorough reviews for Design: Design Review"
52
  },
53
  "Construction": {
54
- "Foundation Work": "Optimize material delivery for Construction: Foundation Work",
55
- "Structural Build": "Ensure equipment availability for Construction: Structural Build",
56
- "Utility Installation": "Coordinate subcontractors for Construction: Utility Installation"
57
  }
58
  }
59
  if phase in task_specific and task in task_specific[phase]:
@@ -61,68 +90,62 @@ def call_ai_model_for_insights(input_data: Dict, delay_risk: float) -> List[str]
61
 
62
  # Workforce-based insights
63
  if workforce_gap > 30:
64
- add_insight(f"Hire subcontractors immediately to address {workforce_gap}% workforce shortage", 1.0)
65
  elif workforce_gap > 15:
66
- add_insight(f"Hire additional workers to reduce {workforce_gap}% workforce gap", 0.9)
67
  elif workforce_gap > 5:
68
- add_insight("Consider temporary staff to address minor workforce gap", 0.7)
69
 
70
  if skill_level == "low":
71
- add_insight(f"Provide training to improve low skill levels for {phase}: {task}", 0.9)
72
  elif skill_level == "medium" and delay_risk > 50:
73
- add_insight(f"Upskill workforce for efficiency in {phase}: {task}", 0.8)
74
  elif skill_level == "high" and delay_risk < 25:
75
- add_insight("Leverage high skill levels to maintain progress", 0.6)
76
 
77
  if shift_hours < 6:
78
- add_insight(f"Extend shift hours beyond {shift_hours} to meet {phase}: {task} deadlines", 0.9)
79
  elif shift_hours < 8 and delay_risk > 50:
80
- add_insight(f"Increase shift hours to {8} for {phase}: {task}", 0.8)
81
  elif shift_hours > 10:
82
- add_insight("Balance shifts to prevent burnout", 0.7)
83
-
84
- # Weather-based insights
85
- if weather_condition in ["severe storm", "heavy rain"]:
86
- add_insight(f"Reschedule {phase}: {task} to avoid {weather_condition}", 1.0)
87
- elif weather_condition == "light rain":
88
- add_insight(f"Shift to indoor tasks during {weather_condition} for {phase}: {task}", 0.9)
89
- elif weather_condition in ["cloudy", "partly cloudy"]:
90
- add_insight(f"Continue monitoring {weather_condition} for {phase}: {task}", 0.7)
91
 
92
  # Progress and duration-based insights
93
  if expected_duration > 0 and actual_duration > expected_duration:
94
  overrun_pct = ((actual_duration - expected_duration) / expected_duration) * 100
95
  if overrun_pct > 20:
96
- add_insight(f"Address duration overrun urgently for {phase}: {task}", 1.0)
97
  elif overrun_pct > 10:
98
- add_insight(f"Review scheduling to address {overrun_pct:.1f}% overrun in {phase}: {task}", 0.8)
99
 
100
  if expected_duration > 0:
101
  expected_progress = min((actual_duration / expected_duration) * 100, 100)
102
  if current_progress < expected_progress * 0.8:
103
- add_insight(f"Accelerate task progress for {phase}: {task} to align with schedule", 0.9)
104
  elif current_progress < 50 and delay_risk > 50:
105
- add_insight(f"Increase resources to boost {current_progress}% progress in {phase}: {task}", 0.8)
106
 
107
  # Edge cases
108
  if workforce_gap >= 90:
109
- add_insight(f"Critical: Halt non-essential tasks until {phase}: {task} workforce gap is resolved", 1.1)
110
  if current_progress == 0 and delay_risk > 50:
111
- add_insight(f"Initiate {phase}: {task} immediately to avoid further delays", 1.0)
112
  if expected_duration == 0 or actual_duration == 0:
113
- add_insight("Provide accurate duration estimates for reliable predictions", 0.7)
 
 
114
 
115
  # Sort insights by priority and select top 3-5
116
  insights.sort(key=lambda x: x[1], reverse=True)
117
  selected_insights = [insight[0] for insight in insights[:5]]
118
 
119
  logger.info(f"Generated insights: {selected_insights}")
120
- return selected_insights or [f"No significant delay factors detected for {phase}: {task}"]
121
 
122
  def predict_delay(input_data: Dict) -> Dict:
123
  """
124
  Predict delay probability based on project task data.
125
- Uses task duration, progress, workforce info, and weather condition.
126
  Insights are generated using detailed hardcoded rules.
127
  """
128
  logger.info("Starting delay prediction")
@@ -130,11 +153,17 @@ def predict_delay(input_data: Dict) -> Dict:
130
  task = input_data.get("task", "")
131
  expected_duration = input_data.get("task_expected_duration", 0)
132
  actual_duration = input_data.get("task_actual_duration", 0)
133
- current_progress = input_data.get("current_progress", 0) # in %
134
- workforce_gap_pct = input_data.get("workforce_gap", 0) # in %
 
135
  skill_level = input_data.get("workforce_skill_level", "").lower()
136
  shift_hours = input_data.get("workforce_shift_hours", 0)
137
- weather_condition = input_data.get("weather_condition", "").lower()
 
 
 
 
 
138
 
139
  # Task options for phase (hardcoded to match app.py)
140
  task_options = {
@@ -173,16 +202,9 @@ def predict_delay(input_data: Dict) -> Dict:
173
  elif shift_hours > 8:
174
  delay_risk -= min((shift_hours - 8) * 2, 10)
175
 
176
- # 6. Weather condition effect
177
- weather_risk_map = {
178
- "severe storm": 20,
179
- "heavy rain": 15,
180
- "light rain": 10,
181
- "cloudy": 5,
182
- "partly cloudy": 2,
183
- "sunny": 0
184
- }
185
- delay_risk += weather_risk_map.get(weather_condition, 0)
186
 
187
  # Ensure delay_risk is between 0 and 100
188
  delay_risk = max(0, min(delay_risk, 100))
 
5
  logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
6
  logger = logging.getLogger(__name__)
7
 
8
+ def get_weather_condition(score: int) -> str:
9
+ """Map weather impact score (0-100) to descriptive weather condition."""
10
+ if score <= 10:
11
+ return "Sunny"
12
+ elif score <= 30:
13
+ return "Partly Cloudy"
14
+ elif score <= 50:
15
+ return "Cloudy"
16
+ elif score <= 70:
17
+ return "Light Rain"
18
+ elif score <= 85:
19
+ return "Heavy Rain"
20
+ else:
21
+ return "Severe Storm"
22
+
23
  def call_ai_model_for_insights(input_data: Dict, delay_risk: float) -> List[str]:
24
  """
25
+ Generate detailed hardcoded insights based on input data and delay risk.
26
+ Returns 3-5 prioritized, phase/task-specific insights tailored to conditions, with enhanced weather focus.
27
  """
28
  logger.info("Generating detailed hardcoded AI insights")
29
  phase = input_data.get("phase", "")
 
34
  workforce_gap = input_data.get("workforce_gap", 0)
35
  skill_level = input_data.get("workforce_skill_level", "").lower()
36
  shift_hours = input_data.get("workforce_shift_hours", 0)
37
+ weather_score = input_data.get("weather_impact_score", 0)
38
+ weather_condition = input_data.get("weather_condition", get_weather_condition(weather_score))
39
+ city = input_data.get("city", "Unknown")
40
 
41
  # Initialize insights with scores for prioritization
42
  insights = []
 
47
 
48
  # Delay risk-based insights
49
  if delay_risk > 75:
50
+ add_insight(f"Urgent: High delay risk detected for {phase}: {task} in {city}. Take immediate action.", 1.0)
51
  elif delay_risk > 50:
52
+ add_insight(f"Monitor {phase}: {task} closely in {city} to prevent delays.", 0.9)
53
  elif delay_risk > 25:
54
+ add_insight(f"Maintain steady progress for {phase}: {task} in {city}.", 0.7)
55
+ else:
56
+ add_insight(f"Optimize resources for {phase}: {task} in {city} to maintain schedule.", 0.6)
57
+
58
+ # Weather-specific insights (enhanced)
59
+ if weather_score > 85:
60
+ add_insight(f"Critical: Severe storm forecast in {city} for {phase}: {task}. Consider halting outdoor activities.", 1.1)
61
+ elif weather_score > 70:
62
+ add_insight(f"Reschedule outdoor tasks for {phase}: {task} in {city} due to heavy rain forecast.", 1.0)
63
+ elif weather_score > 50:
64
+ add_insight(f"Shift to indoor or weather-resistant tasks for {phase}: {task} in {city} due to light rain.", 0.9)
65
+ elif weather_score > 30:
66
+ add_insight(f"Monitor cloudy conditions in {city} for {phase}: {task} to avoid unexpected delays.", 0.7)
67
  else:
68
+ add_insight(f"Proceed with {phase}: {task} in {city} under favorable weather conditions.", 0.6)
69
 
70
  # Phase/task-specific insights
71
  task_specific = {
72
  "Planning": {
73
+ "Define Scope": f"Ensure stakeholder alignment for Planning: Define Scope in {city}, considering weather impacts.",
74
+ "Resource Allocation": f"Secure budget and resources early for Planning: Resource Allocation in {city}.",
75
+ "Permit Acquisition": f"Expedite permits for Planning: Permit Acquisition in {city} to avoid weather-related delays."
76
  },
77
  "Design": {
78
+ "Architectural Drafting": f"Engage architects early for Design: Architectural Drafting in {city}, accounting for weather.",
79
+ "Engineering Analysis": f"Hire additional engineers for Design: Engineering Analysis in {city} to meet deadlines.",
80
+ "Design Review": f"Schedule thorough reviews for Design: Design Review in {city}, considering forecast."
81
  },
82
  "Construction": {
83
+ "Foundation Work": f"Optimize material delivery for Construction: Foundation Work in {city}, avoiding {weather_condition.lower()}.",
84
+ "Structural Build": f"Ensure equipment availability for Construction: Structural Build in {city} under {weather_condition.lower()}.",
85
+ "Utility Installation": f"Coordinate subcontractors for Construction: Utility Installation in {city}, monitoring weather."
86
  }
87
  }
88
  if phase in task_specific and task in task_specific[phase]:
 
90
 
91
  # Workforce-based insights
92
  if workforce_gap > 30:
93
+ add_insight(f"Urgently hire subcontractors in {city} to address {workforce_gap}% workforce shortage.", 1.0)
94
  elif workforce_gap > 15:
95
+ add_insight(f"Recruit additional workers in {city} to reduce {workforce_gap}% workforce gap.", 0.9)
96
  elif workforce_gap > 5:
97
+ add_insight(f"Consider temporary staff in {city} to address minor workforce gap.", 0.7)
98
 
99
  if skill_level == "low":
100
+ add_insight(f"Provide training in {city} to improve low skill levels for {phase}: {task}.", 0.9)
101
  elif skill_level == "medium" and delay_risk > 50:
102
+ add_insight(f"Upskill workforce in {city} for efficiency in {phase}: {task}.", 0.8)
103
  elif skill_level == "high" and delay_risk < 25:
104
+ add_insight(f"Leverage high skill levels in {city} to maintain {phase}: {task} progress.", 0.6)
105
 
106
  if shift_hours < 6:
107
+ add_insight(f"Extend shift hours beyond {shift_hours} in {city} to meet {phase}: {task} deadlines.", 0.9)
108
  elif shift_hours < 8 and delay_risk > 50:
109
+ add_insight(f"Increase shift hours to 8 in {city} for {phase}: {task}.", 0.8)
110
  elif shift_hours > 10:
111
+ add_insight(f"Balance shifts in {city} to prevent burnout during {phase}: {task}.", 0.7)
 
 
 
 
 
 
 
 
112
 
113
  # Progress and duration-based insights
114
  if expected_duration > 0 and actual_duration > expected_duration:
115
  overrun_pct = ((actual_duration - expected_duration) / expected_duration) * 100
116
  if overrun_pct > 20:
117
+ add_insight(f"Address significant duration overrun ({overrun_pct:.1f}%) for {phase}: {task} in {city}.", 1.0)
118
  elif overrun_pct > 10:
119
+ add_insight(f"Review scheduling to address {overrun_pct:.1f}% overrun in {phase}: {task} in {city}.", 0.8)
120
 
121
  if expected_duration > 0:
122
  expected_progress = min((actual_duration / expected_duration) * 100, 100)
123
  if current_progress < expected_progress * 0.8:
124
+ add_insight(f"Accelerate task progress for {phase}: {task} in {city} to align with schedule.", 0.9)
125
  elif current_progress < 50 and delay_risk > 50:
126
+ add_insight(f"Increase resources to boost {current_progress}% progress in {phase}: {task} in {city}.", 0.8)
127
 
128
  # Edge cases
129
  if workforce_gap >= 90:
130
+ add_insight(f"Critical: Halt non-essential tasks in {city} until workforce gap for {phase}: {task} is resolved.", 1.1)
131
  if current_progress == 0 and delay_risk > 50:
132
+ add_insight(f"Initiate {phase}: {task} in {city} immediately to avoid further delays.", 1.0)
133
  if expected_duration == 0 or actual_duration == 0:
134
+ add_insight(f"Provide accurate duration estimates for {phase}: {task} in {city} for reliable predictions.", 0.7)
135
+ if weather_score > 50 and phase == "Construction":
136
+ add_insight(f"Prepare contingency plans for {phase}: {task} in {city} due to adverse weather forecast.", 0.95)
137
 
138
  # Sort insights by priority and select top 3-5
139
  insights.sort(key=lambda x: x[1], reverse=True)
140
  selected_insights = [insight[0] for insight in insights[:5]]
141
 
142
  logger.info(f"Generated insights: {selected_insights}")
143
+ return selected_insights or [f"No significant delay factors detected for {phase}: {task} in {city}."]
144
 
145
  def predict_delay(input_data: Dict) -> Dict:
146
  """
147
  Predict delay probability based on project task data.
148
+ Uses task duration, progress, workforce info, and weather impact.
149
  Insights are generated using detailed hardcoded rules.
150
  """
151
  logger.info("Starting delay prediction")
 
153
  task = input_data.get("task", "")
154
  expected_duration = input_data.get("task_expected_duration", 0)
155
  actual_duration = input_data.get("task_actual_duration", 0)
156
+
157
+ current_progress = input_data.get("current_progress", 0) # in %
158
+ workforce_gap_pct = input_data.get("workforce_gap", 0) # in %
159
  skill_level = input_data.get("workforce_skill_level", "").lower()
160
  shift_hours = input_data.get("workforce_shift_hours", 0)
161
+ weather_score = input_data.get("weather_impact_score", 0) # 0-100 scale
162
+
163
+ # Auto-set weather condition if missing or inconsistent
164
+ weather_condition = input_data.get("weather_condition", "")
165
+ if not weather_condition:
166
+ weather_condition = get_weather_condition(weather_score)
167
 
168
  # Task options for phase (hardcoded to match app.py)
169
  task_options = {
 
202
  elif shift_hours > 8:
203
  delay_risk -= min((shift_hours - 8) * 2, 10)
204
 
205
+ # 6. Weather impact effect
206
+ if weather_score > 50:
207
+ delay_risk += min(weather_score / 2, 20)
 
 
 
 
 
 
 
208
 
209
  # Ensure delay_risk is between 0 and 100
210
  delay_risk = max(0, min(delay_risk, 100))