varshakolanu commited on
Commit
c435100
·
verified ·
1 Parent(s): e9dd568

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +83 -217
app.py CHANGED
@@ -2,225 +2,91 @@ import gradio as gr
2
  import pandas as pd
3
  import joblib
4
  import numpy as np
5
- from typing import Dict, Any, List, Tuple
 
6
  from reportlab.lib.pagesizes import letter
7
  from reportlab.pdfgen import canvas
8
- from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer
9
- from reportlab.lib.styles import getSampleStyleSheet
10
- from reportlab.lib.units import inch
11
- import io
12
- from simple_salesforce import Salesforce
13
  import os
14
 
15
- # 1. Load the Model and Artifacts
16
- # Model and artifact paths - adjust as necessary
17
- model_path = 'your_model.pkl' # Make sure this path is correct
18
- scaler_path = 'scaler.pkl' # If you used a scaler
19
-
20
- try:
21
- model = joblib.load(model_path)
22
- scaler = joblib.load(scaler_path) if scaler_path else None
23
- except Exception as e:
24
- print(f"Error loading model or artifacts: {e}")
25
- model = None
26
-
27
- # 2. Preprocessing Function
28
- def preprocess_data(data: Dict[str, Any]) -> pd.DataFrame:
29
- """
30
- Preprocesses input data for the model.
31
-
32
- Args:
33
- data (dict): A dictionary containing the input data.
34
-
35
- Returns:
36
- pandas.DataFrame: A DataFrame ready for model prediction.
37
- """
38
- try:
39
- df = pd.DataFrame([data])
40
-
41
- expected_fields = [
42
- 'Quality_Report__c',
43
- 'Delay_Days__c',
44
- 'Incident_Log__c',
45
- 'Vendor__c',
46
- 'Work_Details__c',
47
- 'Work_Completion_Date__c',
48
- 'Actual_Completion_Date__c'
49
- ]
50
-
51
- missing_fields = [field for field in expected_fields if field not in df.columns]
52
- if missing_fields:
53
- raise ValueError(f"Missing required fields: {', '.join(missing_fields)}")
54
-
55
- if 'Delay_Days__c' in df.columns and scaler:
56
- df['Delay_Days__c'] = df['Delay_Days__c'].fillna(0)
57
- df[['Delay_Days__c']] = scaler.transform(df[['Delay_Days__c']])
58
-
59
- if 'Work_Completion_Date__c' in df.columns:
60
- df['Work_Completion_Date__c'] = pd.to_datetime(df['Work_Completion_Date__c'])
61
- df['Work_Completion_Year'] = df['Work_Completion_Date__c'].dt.year
62
- df['Work_Completion_Month'] = df['Work_Completion_Date__c'].dt.month
63
- df['Work_Completion_Day'] = df['Work_Completion_Date__c'].dt.day
64
- df = df.drop(columns=['Work_Completion_Date__c'])
65
-
66
- if 'Actual_Completion_Date__c' in df.columns:
67
- df['Actual_Completion_Date__c'] = pd.to_datetime(df['Actual_Completion_Date__c'])
68
- df['Actual_Completion_Year'] = df['Actual_Completion_Date__c'].dt.year
69
- df['Actual_Completion_Month'] = df['Actual_Completion_Date__c'].dt.month
70
- df = df.drop(columns=['Actual_Completion_Date__c'])
71
-
72
- df = df[expected_fields]
73
- return df
74
- except ValueError as ve:
75
- print(f"Error in preprocess_data: {ve}")
76
- return pd.DataFrame()
77
- except Exception as e:
78
- print(f"Error in preprocess_data: {e}")
79
- return pd.DataFrame()
80
-
81
-
82
- # 3. Prediction Function
83
- def predict_vendor_score() -> Tuple[List[Tuple[str, float]], bytes]:
84
- """
85
- Retrieves data from Salesforce, predicts vendor performance scores, and generates a PDF report.
86
-
87
- Returns:
88
- Tuple[List[Tuple[str, float]], bytes]: A tuple containing the score data and the PDF data.
89
- """
90
- if model is None:
91
- error_message = "Model not loaded. Check server logs."
92
- return [
93
- ("Quality Score (%)", 0.0),
94
- ("Timeliness Score (%)", 0.0),
95
- ("Safety Score (%)", 0.0),
96
- ("Communication Score (%)", 0.0),
97
- ("Final Score (%)", 0.0),
98
- ], generate_pdf(error_message)
99
-
100
- try:
101
- # 1. Connect to Salesforce
102
- sf = Salesforce(
103
- username=os.environ.get('SALESFORCE_USERNAME'), # Use environment variables
104
- password=os.environ.get('SALESFORCE_PASSWORD'),
105
- security_token=os.environ.get('SALESFORCE_SECURITY_TOKEN'),
106
- domain='login' # or 'test' for a sandbox
107
- )
108
-
109
- # 2. SOQL Query (Adapt to your needs)
110
- query = """
111
- SELECT
112
- Quality_Report__c,
113
- Delay_Days__c,
114
- Incident_Log__c,
115
- Vendor__c,
116
- Work_Details__c,
117
- Work_Completion_Date__c,
118
- Actual_Completion_Date__c
119
- FROM
120
- Vendor_Log__c
121
- WHERE
122
- # Add any filtering criteria here (e.g., date range)
123
- CreatedDate >= LAST_MONTH
124
- """
125
- results = sf.query(query)
126
-
127
- # 3. Data Transformation
128
- records = results['records']
129
- df = pd.DataFrame(records)
130
- df = df.rename(columns={
131
- 'Quality_Report__c': 'Quality_Report__c',
132
- 'Delay_Days__c': 'Delay_Days__c',
133
- 'Incident_Log__c': 'Incident_Log__c',
134
- 'Vendor__c': 'Vendor__c',
135
- 'Work_Details__c': 'Work_Details__c',
136
- 'Work_Completion_Date__c': 'Work_Completion_Date__c',
137
- 'Actual_Completion_Date__c': 'Actual_Completion_Date__c'
138
- })
139
- df = df.drop(columns=['attributes'], errors='ignore')
140
-
141
- # 4. Preprocess Data
142
- processed_df = preprocess_data(df.iloc[0].to_dict()) # pass the first row as dict
143
-
144
-
145
- if processed_df.empty:
146
- error_message = "Error in input data. Check logs."
147
- return [
148
- ("Quality Score (%)", 0.0),
149
- ("Timeliness Score (%)", 0.0),
150
- ("Safety Score (%)", 0.0),
151
- ("Communication Score (%)", 0.0),
152
- ("Final Score (%)", 0.0),
153
- ], generate_pdf(error_message)
154
-
155
- # 5. Make Prediction
156
- predictions = model.predict(processed_df)[0]
157
-
158
- # 6. Output
159
- output_data = [
160
- ("Quality Score (%)", predictions[0] * 100),
161
- ("Timeliness Score (%)", predictions[1] * 100),
162
- ("Safety Score (%)", predictions[2] * 100),
163
- ("Communication Score (%)", predictions[3] * 100),
164
- ("Final Score (%)", (predictions[0] + predictions[1] + predictions[2] + predictions[3]) / 4 * 100),
165
- ]
166
- pdf_data = generate_pdf(output_data)
167
- return output_data, pdf_data
168
-
169
- except Exception as e:
170
- error_message = f"Error: {e}"
171
- print(error_message)
172
- return [
173
- ("Quality Score (%)", 0.0),
174
- ("Timeliness Score (%)", 0.0),
175
- ("Safety Score (%)", 0.0),
176
- ("Communication Score (%)", 0.0),
177
- ("Final Score (%)", 0.0),
178
- ], generate_pdf(error_message)
179
-
180
-
181
-
182
- # 4. PDF Generation
183
- def generate_pdf(scores: List[Tuple[str, float]]) -> bytes:
184
- """Generates a PDF report of the subcontractor performance scores.
185
-
186
- Args:
187
- scores (List[Tuple[str, float]]): A list of (score_name, score_value) tuples.
188
- Returns:
189
- bytes: The PDF data as bytes.
190
- """
191
- buffer = io.BytesIO()
192
- doc = SimpleDocTemplate(buffer, pagesize=letter)
193
- styles = getSampleStyleSheet()
194
- Story = []
195
- Story.append(Paragraph("Subcontractor Performance Report", styles['Title']))
196
- Story.append(Spacer(1, 0.2 * inch))
197
- if isinstance(scores, str):
198
- Story.append(Paragraph(scores, styles['Normal']))
199
  else:
200
- for score_name, score_value in scores:
201
- Story.append(Paragraph(f"{score_name}: {score_value:.2f}", styles['Normal']))
202
- Story.append(Spacer(1, 0.1 * inch))
203
- doc.build(Story)
204
- pdf_data = buffer.getvalue()
205
- buffer.close()
206
- return pdf_data
207
-
208
- # 5. Gradio Interface
209
- iface = gr.Interface(
210
- fn=predict_vendor_score,
211
- inputs=[],
212
- outputs=[
213
- gr.HighlightedText(label="Performance Scores"),
214
- gr.File(label="Download PDF Report"),
215
- ],
216
- title="Subcontractor Performance Score Calculator",
217
- description="Click the button to retrieve Vendor Log details from Salesforce, calculate performance scores, and generate a PDF report.",
218
- )
219
-
220
- # 6. Launch the Interface
221
- if __name__ == "__main__":
222
- # Set up environment variables for Salesforce credentials
223
- os.environ['SALESFORCE_USERNAME'] = 'scores@app.com' # Replace with your username
224
- os.environ['SALESFORCE_PASSWORD'] = 'Internal@1' # Replace with your password
225
- os.environ['SALESFORCE_SECURITY_TOKEN'] = 'NbUKcTx45azba5HEdntE9YAh' # Replace with your security token
226
- iface.launch()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2
  import pandas as pd
3
  import joblib
4
  import numpy as np
5
+ from fastapi import FastAPI, HTTPException, Header
6
+ from pydantic import BaseModel
7
  from reportlab.lib.pagesizes import letter
8
  from reportlab.pdfgen import canvas
9
+ import base64
 
 
 
 
10
  import os
11
 
12
+ app = FastAPI()
13
+
14
+ API_KEY = "hf_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" # Replace with your Hugging Face API key
15
+
16
+ class VendorLog(BaseModel):
17
+ vendorLogId: str
18
+ vendorId: str
19
+ workCompletionPercentage: float
20
+ qualityPercentage: float
21
+ incidentSeverity: str
22
+ delayDays: int
23
+
24
+ def calculate_scores(log: VendorLog):
25
+ quality_score = log.qualityPercentage
26
+ timeliness_score = 100.0 if log.delayDays == 0 else 80.0 if log.delayDays <= 3 else 60.0 if log.delayDays <= 7 else 40.0
27
+ safety_score = 100.0 if log.incidentSeverity == 'None' else 80.0 if log.incidentSeverity == 'Minor' else 50.0 if log.incidentSeverity == 'Major' else 20.0
28
+ communication_score = (quality_score + timeliness_score + safety_score) / 3
29
+ return {
30
+ 'qualityScore': quality_score,
31
+ 'timelinessScore': timeliness_score,
32
+ 'safetyScore': safety_score,
33
+ 'communicationScore': communication_score
34
+ }
35
+
36
+ def generate_feedback(score: float, metric: str):
37
+ if score >= 90:
38
+ return 'Excellent: Maintain this standard.'
39
+ elif score >= 70:
40
+ return 'Good: Continue to improve consistency.'
41
+ elif score >= 50:
42
+ return f'Needs Improvement: {metric_feedback(metric)}'
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
43
  else:
44
+ return f'Poor: {metric_feedback(metric, True)}'
45
+
46
+ def metric_feedback(metric: str, poor: bool = False):
47
+ if metric == 'Timeliness':
48
+ return 'Significant delays detected; prioritize timely completion.' if poor else 'Maintain schedules to complete tasks on time.'
49
+ elif metric == 'Safety':
50
+ return 'Critical safety issues; review safety procedures.' if poor else 'Implement stricter safety protocols.'
51
+ elif metric == 'Quality':
52
+ return 'Low quality output; improve quality control.' if poor else 'Enhance work quality standards.'
53
+ else:
54
+ return 'Poor communication; improve team interactions.' if poor else 'Enhance coordination with project teams.'
55
+
56
+ def generate_pdf(vendor_id: str, scores: dict):
57
+ filename = f'report_{vendor_id}.pdf'
58
+ c = canvas.Canvas(filename, pagesize=letter)
59
+ c.setFont('Helvetica', 12)
60
+ c.drawString(100, 750, f'Vendor Performance Report')
61
+ c.drawString(100, 730, f'Vendor ID: {vendor_id}')
62
+ y = 700
63
+ for metric, score in scores.items():
64
+ feedback = generate_feedback(score, metric.replace('Score', ''))
65
+ c.drawString(100, y, f'{metric.replace("Score", " Score")}: {score}% ({feedback})')
66
+ y -= 20
67
+ c.drawString(100, y, f'Final Score: {sum(scores.values()) / 4}%')
68
+ c.save()
69
+
70
+ with open(filename, 'rb') as f:
71
+ pdf_content = f.read()
72
+ os.remove(filename)
73
+ return pdf_content
74
+
75
+ @app.post('/score')
76
+ async def score_vendor(log: VendorLog, authorization: str = Header(...)):
77
+ if authorization != f'Bearer {API_KEY}':
78
+ raise HTTPException(status_code=401, detail='Invalid API key')
79
+
80
+ scores = calculate_scores(log)
81
+ pdf_content = generate_pdf(log.vendorId, scores)
82
+ pdf_base64 = base64.b64encode(pdf_content).decode('utf-8')
83
+
84
+ return {
85
+ 'vendorLogId': log.vendorLogId,
86
+ 'qualityScore': scores['qualityScore'],
87
+ 'timelinessScore': scores['timelinessScore'],
88
+ 'safetyScore': scores['safetyScore'],
89
+ 'communicationScore': scores['communicationScore'],
90
+ 'pdfContent': pdf_base64,
91
+ 'pdfUrl': f'/files/report_{log.vendorId}.pdf'
92
+ }