Spaces:
Runtime error
Runtime error
Update app.py
Browse files
app.py
CHANGED
|
@@ -1,144 +1,40 @@
|
|
| 1 |
-
from fastapi import FastAPI
|
| 2 |
from pydantic import BaseModel
|
| 3 |
-
|
| 4 |
-
|
| 5 |
-
|
| 6 |
-
|
| 7 |
-
|
| 8 |
-
|
| 9 |
-
|
| 10 |
-
|
| 11 |
-
|
| 12 |
-
|
| 13 |
-
|
| 14 |
-
#
|
| 15 |
-
|
| 16 |
-
|
| 17 |
-
|
| 18 |
-
|
| 19 |
-
|
| 20 |
-
|
| 21 |
-
|
| 22 |
-
|
| 23 |
-
#
|
| 24 |
-
|
| 25 |
-
|
| 26 |
-
|
| 27 |
-
|
| 28 |
-
|
| 29 |
-
|
| 30 |
-
|
| 31 |
-
|
| 32 |
-
|
| 33 |
-
|
| 34 |
-
|
| 35 |
-
|
| 36 |
-
|
| 37 |
-
|
| 38 |
-
|
| 39 |
-
|
| 40 |
-
|
| 41 |
-
|
| 42 |
-
@app.post("/score", response_model=VendorScore)
|
| 43 |
-
async def calculate_vendor_score(input_data: VendorInput):
|
| 44 |
-
try:
|
| 45 |
-
logger.info(f"Processing score for vendor {input_data.vendor_id} for {input_data.month}")
|
| 46 |
-
|
| 47 |
-
# Validate month format (YYYY-MM)
|
| 48 |
-
try:
|
| 49 |
-
datetime.strptime(input_data.month, "%Y-%m")
|
| 50 |
-
except ValueError:
|
| 51 |
-
raise HTTPException(status_code=400, detail="Invalid month format. Use YYYY-MM.")
|
| 52 |
-
|
| 53 |
-
# Initialize scores
|
| 54 |
-
quality_score = 100.0
|
| 55 |
-
timeliness_score = 100.0
|
| 56 |
-
safety_score = 100.0
|
| 57 |
-
communication_score = 0.0
|
| 58 |
-
log_count = len(input_data.logs)
|
| 59 |
-
|
| 60 |
-
if log_count == 0:
|
| 61 |
-
raise HTTPException(status_code=400, detail="No logs provided for scoring.")
|
| 62 |
-
|
| 63 |
-
# Process logs to calculate scores
|
| 64 |
-
total_delay_percentage = 0.0
|
| 65 |
-
total_quality_incidents = 0
|
| 66 |
-
total_safety_incidents = 0
|
| 67 |
-
total_feedback_score = 0.0
|
| 68 |
-
feedback_count = 0
|
| 69 |
-
|
| 70 |
-
for log in input_data.logs:
|
| 71 |
-
# Timeliness: Deduct based on delay percentage
|
| 72 |
-
total_delay_percentage += log.delay_percentage or 0.0
|
| 73 |
-
|
| 74 |
-
# Quality: Deduct based on incident count and severity
|
| 75 |
-
total_quality_incidents += log.quality_incident_count or 0
|
| 76 |
-
if log.quality_severity:
|
| 77 |
-
severity_deduction = {"Low": 5, "Medium": 10, "High": 20}.get(log.quality_severity, 0)
|
| 78 |
-
quality_score -= severity_deduction * (log.quality_incident_count or 0)
|
| 79 |
-
|
| 80 |
-
# Safety: Deduct based on safety incident count
|
| 81 |
-
total_safety_incidents += log.safety_incident_count or 0
|
| 82 |
-
|
| 83 |
-
# Communication: Average feedback scores
|
| 84 |
-
if log.feedback_score is not None and log.feedback_score > 0:
|
| 85 |
-
total_feedback_score += log.feedback_score
|
| 86 |
-
feedback_count += 1
|
| 87 |
-
|
| 88 |
-
# Calculate scores
|
| 89 |
-
# Timeliness: Reduce score based on average delay percentage
|
| 90 |
-
avg_delay_percentage = total_delay_percentage / log_count if log_count > 0 else 0.0
|
| 91 |
-
timeliness_score -= avg_delay_percentage * 0.5 # 1% delay reduces score by 0.5
|
| 92 |
-
|
| 93 |
-
# Quality: Further deduct based on total incidents
|
| 94 |
-
quality_score -= total_quality_incidents * 5 # Each incident reduces score by 5
|
| 95 |
-
quality_score = max(0, min(100, quality_score)) # Clamp between 0 and 100
|
| 96 |
-
|
| 97 |
-
# Safety: Deduct 10 points per safety incident
|
| 98 |
-
safety_score -= total_safety_incidents * 10
|
| 99 |
-
safety_score = max(0, min(100, safety_score)) # Clamp between 0 and 100
|
| 100 |
-
|
| 101 |
-
# Communication: Average feedback score
|
| 102 |
-
communication_score = total_feedback_score / feedback_count if feedback_count > 0 else 50.0
|
| 103 |
-
communication_score = max(0, min(100, communication_score))
|
| 104 |
-
|
| 105 |
-
# Calculate final score (weighted average)
|
| 106 |
-
final_score = (
|
| 107 |
-
(quality_score * 0.3) +
|
| 108 |
-
(timeliness_score * 0.3) +
|
| 109 |
-
(safety_score * 0.2) +
|
| 110 |
-
(communication_score * 0.2)
|
| 111 |
-
)
|
| 112 |
-
final_score = round(final_score, 2)
|
| 113 |
-
|
| 114 |
-
# Trend detection: Compare with previous final score
|
| 115 |
-
trend_deviation = 0.0
|
| 116 |
-
if input_data.previous_final_score is not None:
|
| 117 |
-
trend_deviation = round(final_score - input_data.previous_final_score, 2)
|
| 118 |
-
|
| 119 |
-
# Alert flag: Trigger if final score is below 60
|
| 120 |
-
alert_flag = final_score < 60
|
| 121 |
-
|
| 122 |
-
# Prepare response
|
| 123 |
-
response = VendorScore(
|
| 124 |
-
vendor_id=input_data.vendor_id,
|
| 125 |
-
month=input_data.month,
|
| 126 |
-
quality_score=round(quality_score, 2),
|
| 127 |
-
timeliness_score=round(timeliness_score, 2),
|
| 128 |
-
safety_score=round(safety_score, 2),
|
| 129 |
-
communication_score=round(communication_score, 2),
|
| 130 |
-
final_score=final_score,
|
| 131 |
-
trend_deviation=trend_deviation,
|
| 132 |
-
alert_flag=alert_flag
|
| 133 |
-
)
|
| 134 |
-
|
| 135 |
-
logger.info(f"Score calculated successfully for vendor {input_data.vendor_id}")
|
| 136 |
-
return response
|
| 137 |
-
|
| 138 |
-
except Exception as e:
|
| 139 |
-
logger.error(f"Error processing score: {str(e)}")
|
| 140 |
-
raise HTTPException(status_code=500, detail=f"Internal server error: {str(e)}")
|
| 141 |
-
|
| 142 |
-
@app.get("/health")
|
| 143 |
-
async def health_check():
|
| 144 |
-
return {"status": "healthy"}
|
|
|
|
| 1 |
+
from fastapi import FastAPI
|
| 2 |
from pydantic import BaseModel
|
| 3 |
+
import uvicorn
|
| 4 |
+
|
| 5 |
+
app = FastAPI()
|
| 6 |
+
|
| 7 |
+
# Define the request body structure
|
| 8 |
+
class VendorLog(BaseModel):
|
| 9 |
+
work_logs: int
|
| 10 |
+
delay_logs: int
|
| 11 |
+
quality_logs: int
|
| 12 |
+
incident_logs: int
|
| 13 |
+
|
| 14 |
+
# Scoring logic
|
| 15 |
+
@app.post("/score")
|
| 16 |
+
async def calculate_score(logs: VendorLog):
|
| 17 |
+
# Simple scoring logic (you can customize this)
|
| 18 |
+
quality_score = (logs.quality_logs / (logs.work_logs + 1)) * 100
|
| 19 |
+
timeliness_score = (1 - logs.delay_logs / (logs.work_logs + 1)) * 100
|
| 20 |
+
safety_score = (1 - logs.incident_logs / (logs.work_logs + 1)) * 100
|
| 21 |
+
communication_score = 50 # Placeholder, adjust based on your logic
|
| 22 |
+
|
| 23 |
+
# Final score (average of individual scores)
|
| 24 |
+
final_score = (quality_score + timeliness_score + safety_score + communication_score) / 4
|
| 25 |
+
|
| 26 |
+
# Alert flag logic (example: flag if final score < 50)
|
| 27 |
+
alert_flag = final_score < 50
|
| 28 |
+
|
| 29 |
+
return {
|
| 30 |
+
"final_score": round(final_score, 2),
|
| 31 |
+
"alert_flag": alert_flag,
|
| 32 |
+
"quality_score": round(quality_score, 2),
|
| 33 |
+
"timeliness_score": round(timeliness_score, 2),
|
| 34 |
+
"safety_score": round(safety_score, 2),
|
| 35 |
+
"communication_score": round(communication_score, 2)
|
| 36 |
+
}
|
| 37 |
+
|
| 38 |
+
# Run the server
|
| 39 |
+
if __name__ == "__main__":
|
| 40 |
+
uvicorn.run(app, host="0.0.0.0", port=8000)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|