AjaykumarPilla commited on
Commit
27da82c
·
verified ·
1 Parent(s): c3c49bc

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +175 -59
app.py CHANGED
@@ -5,101 +5,217 @@ from fastapi.responses import JSONResponse
5
  import uvicorn
6
  from sklearn.linear_model import LinearRegression
7
  from sklearn.model_selection import train_test_split
 
 
 
 
 
 
8
 
9
  # Hardcoded mappings
10
  weather_map = {"Cloudy": 0, "Rainy": 1, "Sunny": 2}
11
 
12
  # Load and preprocess training data
13
- df = pd.read_csv("new_delay_data.csv")
14
-
15
- # Encode categorical features
16
- df = pd.get_dummies(df, columns=["Phase"], drop_first=True) # Finishing as baseline
17
- df["Weather"] = df["Weather"].map(weather_map)
18
-
19
- # Handle missing or invalid mappings
20
- df.dropna(subset=["Phase_Framing", "Phase_Foundation", "Weather", "Absentee", "DelayLog", "Delay%"], inplace=True)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
21
 
22
  # Split features and target
23
- X = df[["Phase_Framing", "Phase_Foundation", "Weather", "Absentee", "DelayLog"]]
24
- y = df["Delay%"]
 
 
 
 
25
 
26
  # Train model
27
- model = LinearRegression()
28
- model.fit(X, y)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
29
 
30
  # Main prediction function
31
  def predict_delay(phase, weather, absentee_pct, delay_log):
32
- # Encode phase as dummy variables
33
- framing = 1 if phase == "Framing" else 0
34
- foundation = 1 if phase == "Foundation" else 0
35
- weather_encoded = weather_map.get(weather, 0)
36
- input_data = [[framing, foundation, weather_encoded, absentee_pct, delay_log]]
37
-
38
- # Model makes prediction
39
- prediction = model.predict(input_data)[0]
40
- prediction = round(prediction, 2)
41
-
42
- # Risk tagging based on predicted delay percentage
43
- if prediction >= 75:
44
- risk = "High Risk"
45
- elif prediction >= 50:
46
- risk = "Moderate Risk"
47
- else:
48
- risk = "Low Risk"
49
 
50
- # AI reasoning for insights
51
- insight = f"Phase: {phase}, Weather: {weather}, Absenteeism: {absentee_pct}%, Previous Delay: {delay_log} → Risk: {risk}"
 
 
52
 
53
- return prediction, risk, insight
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
54
 
55
  # FastAPI for Salesforce
56
  api_app = FastAPI()
57
 
58
  @api_app.post("/predict")
59
  async def predict_from_salesforce(request: Request):
 
60
  try:
61
  data = await request.json()
62
  phase = data.get("phase", "Framing")
63
  weather = data.get("weather", "Sunny")
64
- absentee_pct = float(data.get("absentee_pct", 0))
65
- delay_log = float(data.get("delay_log", 0))
66
 
67
- prediction, risk, insight = predict_delay(phase, weather, absentee_pct, delay_log)
 
 
 
68
 
69
  return JSONResponse(content={
70
  "delay_probability": prediction,
71
  "risk_alert": risk,
72
  "ai_insight": insight,
 
 
73
  "status": "success"
74
  })
75
  except Exception as e:
 
76
  return JSONResponse(status_code=500, content={"status": "error", "message": str(e)})
77
 
78
  # Gradio UI for manual testing
79
- with gr.Blocks() as demo:
80
- gr.Markdown("## 🏗️ Delay Predictor")
81
- with gr.Row():
82
- phase_input = gr.Textbox(label="Phase (Framing/Foundation/Finishing)")
83
- weather_input = gr.Textbox(label="Weather (Sunny/Rainy/Cloudy)")
84
- with gr.Row():
85
- absentee_input = gr.Number(label="Absentee %")
86
- delay_input = gr.Number(label="Previous Delay Log")
87
- output = gr.Textbox(label="Prediction Summary")
88
-
89
- def predict_and_format(phase, weather, absentee, delay_log):
90
- prediction, risk, insight = predict_delay(phase, weather, absentee, delay_log)
91
- return f"Predicted Delay: {prediction}%\nRisk Level: {risk}\nInsight: {insight}"
92
-
93
- submit = gr.Button("Predict")
94
- submit.click(
95
- predict_and_format,
96
- inputs=[phase_input, weather_input, absentee_input, delay_input],
97
- outputs=output
98
- )
 
 
 
 
 
 
 
 
 
99
 
100
  # Mount Gradio inside FastAPI
101
- app = gr.mount_gradio_app(api_app, demo, path="/")
102
-
103
- # Run locally (Hugging Face will ignore this)
 
 
 
 
 
 
104
  if __name__ == "__main__":
105
- uvicorn.run(app, host="0.0.0.0", port=7860)
 
 
 
 
 
 
5
  import uvicorn
6
  from sklearn.linear_model import LinearRegression
7
  from sklearn.model_selection import train_test_split
8
+ import base64
9
+ import os
10
+ from datetime import datetime
11
+ from reportlab.lib.pagesizes import letter
12
+ from reportlab.pdfgen import canvas
13
+ from io import BytesIO
14
 
15
  # Hardcoded mappings
16
  weather_map = {"Cloudy": 0, "Rainy": 1, "Sunny": 2}
17
 
18
  # Load and preprocess training data
19
+ print("Loading and preprocessing data...")
20
+ try:
21
+ if not os.path.exists("new_delay_data.csv"):
22
+ print("Warning: new_delay_data.csv not found. Using default dataset.")
23
+ default_data = {
24
+ "Phase": ["Framing", "Foundation", "Finishing"],
25
+ "Weather": ["Sunny", "Rainy", "Cloudy"],
26
+ "Absentee": [10, 20, 5],
27
+ "DelayLog": [5, 10, 2],
28
+ "Delay%": [30, 60, 15]
29
+ }
30
+ df = pd.DataFrame(default_data)
31
+ else:
32
+ df = pd.read_csv("new_delay_data.csv")
33
+
34
+ df = pd.get_dummies(df, columns=["Phase"], drop_first=True) # Finishing as baseline
35
+ df["Weather"] = df["Weather"].map(weather_map)
36
+ df.dropna(subset=["Weather", "Absentee", "DelayLog", "Delay%"], inplace=True)
37
+
38
+ for col in ["Phase_Framing", "Phase_Foundation"]:
39
+ if col not in df.columns:
40
+ df[col] = 0
41
+ print("Data loaded and preprocessed successfully. Columns:", df.columns.tolist())
42
+ except Exception as e:
43
+ print(f"Error loading data: {e}")
44
+ raise
45
 
46
  # Split features and target
47
+ try:
48
+ X = df[["Phase_Framing", "Phase_Foundation", "Weather", "Absentee", "DelayLog"]]
49
+ y = df["Delay%"]
50
+ except Exception as e:
51
+ print(f"Error preparing features: {e}")
52
+ raise
53
 
54
  # Train model
55
+ print("Training model...")
56
+ try:
57
+ model = LinearRegression()
58
+ model.fit(X, y)
59
+ print("Model trained successfully.")
60
+ except Exception as e:
61
+ print(f"Error training model: {e}")
62
+ raise
63
+
64
+ # Function to generate simple PDF and return base64-encoded string
65
+ def generate_pdf_report(phase, weather, absentee_pct, delay_log, prediction, risk, insight):
66
+ print("Generating PDF report...")
67
+ try:
68
+ buffer = BytesIO()
69
+ c = canvas.Canvas(buffer, pagesize=letter)
70
+ c.setFont("Helvetica", 12)
71
+
72
+ c.drawString(100, 750, "Project Delay Prediction Report")
73
+ c.drawString(100, 730, f"Generated on: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
74
+
75
+ y_position = 700
76
+ details = [
77
+ f"Phase: {phase}",
78
+ f"Weather: {weather}",
79
+ f"Absentee Percentage: {absentee_pct}%",
80
+ f"Previous Delay Log: {delay_log}",
81
+ f"Predicted Delay: {prediction}%",
82
+ f"Risk Level: {risk}",
83
+ f"AI Insight: {insight}"
84
+ ]
85
+ for line in details:
86
+ c.drawString(100, y_position, line)
87
+ y_position -= 20
88
+
89
+ c.showPage()
90
+ c.save()
91
+
92
+ pdf_data = buffer.getvalue()
93
+ buffer.close()
94
+ pdf_base64 = base64.b64encode(pdf_data).decode("utf-8")
95
+
96
+ output_dir = "pdf_reports"
97
+ os.makedirs(output_dir, exist_ok=True)
98
+ timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
99
+ output_path = os.path.join(output_dir, f"delay_report_{timestamp}.pdf")
100
+ with open(output_path, "wb") as f:
101
+ f.write(pdf_data)
102
+ print(f"PDF saved locally at: {output_path}")
103
+
104
+ return pdf_base64, output_path
105
+ except Exception as e:
106
+ print(f"PDF generation failed: {e}")
107
+ return None, None
108
 
109
  # Main prediction function
110
  def predict_delay(phase, weather, absentee_pct, delay_log):
111
+ print(f"Predicting delay for Phase: {phase}, Weather: {weather}, Absentee: {absentee_pct}, Delay Log: {delay_log}")
112
+ try:
113
+ valid_phases = ["Framing", "Foundation", "Finishing"]
114
+ valid_weather = ["Sunny", "Rainy", "Cloudy"]
115
+ phase = phase if isinstance(phase, str) and phase in valid_phases else "Framing"
116
+ weather = weather if isinstance(weather, str) and weather in valid_weather else "Sunny"
117
+ absentee_pct = float(absentee_pct) if isinstance(absentee_pct, (int, float, str)) and float(absentee_pct) >= 0 else 0
118
+ delay_log = float(delay_log) if isinstance(delay_log, (int, float, str)) and float(delay_log) >= 0 else 0
 
 
 
 
 
 
 
 
 
119
 
120
+ framing = 1 if phase == "Framing" else 0
121
+ foundation = 1 if phase == "Foundation" else 0
122
+ weather_encoded = weather_map.get(weather, 0)
123
+ input_data = [[framing, foundation, weather_encoded, absentee_pct, delay_log]]
124
 
125
+ prediction = model.predict(input_data)[0]
126
+ prediction = round(prediction, 2)
127
+
128
+ if prediction >= 75:
129
+ risk = "High Risk"
130
+ elif prediction >= 50:
131
+ risk = "Moderate Risk"
132
+ else:
133
+ risk = "Low Risk"
134
+
135
+ insight = f"Phase: {phase}, Weather: {weather}, Absenteeism: {absentee_pct}%, Previous Delay: {delay_log} → Risk: {risk}"
136
+
137
+ pdf_base64, pdf_path = generate_pdf_report(phase, weather, absentee_pct, delay_log, prediction, risk, insight)
138
+
139
+ return prediction, risk, insight, pdf_base64, pdf_path
140
+ except Exception as e:
141
+ print(f"Prediction error: {e}")
142
+ return None, None, f"Error: {e}", None, None
143
 
144
  # FastAPI for Salesforce
145
  api_app = FastAPI()
146
 
147
  @api_app.post("/predict")
148
  async def predict_from_salesforce(request: Request):
149
+ print("Received API request...")
150
  try:
151
  data = await request.json()
152
  phase = data.get("phase", "Framing")
153
  weather = data.get("weather", "Sunny")
154
+ absentee_pct = data.get("absentee_pct", 0)
155
+ delay_log = data.get("delay_log", 0)
156
 
157
+ prediction, risk, insight, pdf_base64, pdf_path = predict_delay(phase, weather, absentee_pct, delay_log)
158
+
159
+ if prediction is None:
160
+ return JSONResponse(status_code=500, content={"status": "error", "message": insight})
161
 
162
  return JSONResponse(content={
163
  "delay_probability": prediction,
164
  "risk_alert": risk,
165
  "ai_insight": insight,
166
+ "pdf_report_base64": pdf_base64 if pdf_base64 else "",
167
+ "pdf_local_path": pdf_path if pdf_path else "PDF generation failed",
168
  "status": "success"
169
  })
170
  except Exception as e:
171
+ print(f"API error: {e}")
172
  return JSONResponse(status_code=500, content={"status": "error", "message": str(e)})
173
 
174
  # Gradio UI for manual testing
175
+ try:
176
+ print("Setting up Gradio UI...")
177
+ with gr.Blocks() as demo:
178
+ gr.Markdown("## 🏗️ Delay Predictor")
179
+ with gr.Row():
180
+ phase_input = gr.Textbox(label="Phase (Framing/Foundation/Finishing)", value="Framing")
181
+ weather_input = gr.Textbox(label="Weather (Sunny/Rainy/Cloudy)", value="Sunny")
182
+ with gr.Row():
183
+ absentee_input = gr.Number(label="Absentee %", value=0)
184
+ delay_input = gr.Number(label="Previous Delay Log", value=0)
185
+ output = gr.Textbox(label="Prediction Summary")
186
+ submit = gr.Button("Predict")
187
+
188
+ def predict_and_format(phase, weather, absentee, delay_log):
189
+ print("Gradio predict button clicked.")
190
+ prediction, risk, insight, pdf_base64, pdf_path = predict_delay(phase, weather, absentee, delay_log)
191
+ if prediction is None:
192
+ return f"Error: {insight}"
193
+ return f"Predicted Delay: {prediction}%\nRisk Level: {risk}\nInsight: {insight}\nPDF Report: {'Saved locally at ' + pdf_path if pdf_path else 'Failed to generate'}\nPDF Base64: {'Generated' if pdf_base64 else 'Not generated'}"
194
+
195
+ submit.click(
196
+ predict_and_format,
197
+ inputs=[phase_input, weather_input, absentee_input, delay_input],
198
+ outputs=output
199
+ )
200
+ print("Gradio UI setup complete.")
201
+ except Exception as e:
202
+ print(f"Error setting up Gradio UI: {e}")
203
+ raise
204
 
205
  # Mount Gradio inside FastAPI
206
+ try:
207
+ print("Mounting Gradio app...")
208
+ app = gr.mount_gradio_app(api_app, demo, path="/")
209
+ print("Gradio app mounted successfully.")
210
+ except Exception as e:
211
+ print(f"Error mounting Gradio app: {e}")
212
+ raise
213
+
214
+ # Run locally
215
  if __name__ == "__main__":
216
+ print("Starting server on http://0.0.0.0:7860...")
217
+ try:
218
+ uvicorn.run(app, host="0.0.0.0", port=7860)
219
+ except Exception as e:
220
+ print(f"Server failed to start: {e}")
221
+ raise