Upload folder using huggingface_hub
Browse files
app.py
CHANGED
|
@@ -1,147 +1,96 @@
|
|
| 1 |
import pandas as pd
|
| 2 |
from flask import Flask, request, jsonify
|
| 3 |
-
from CatBoostWrapper import CatBoostWrapper
|
| 4 |
-
from FeatureEngineering import FeatureEngineering
|
| 5 |
-
# To serialize the model
|
| 6 |
import joblib
|
| 7 |
-
|
| 8 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 9 |
app = Flask("Store Capacity Predictor")
|
| 10 |
|
| 11 |
-
# Load the trained pipeline
|
| 12 |
-
# Load the trained churn prediction model
|
| 13 |
pipeline = joblib.load("catbooster_model_v1_0.joblib")
|
| 14 |
|
| 15 |
-
#
|
|
|
|
|
|
|
| 16 |
@app.get('/')
|
| 17 |
def home():
|
| 18 |
return "Welcome to the Store Capacity Prediction API"
|
| 19 |
|
| 20 |
-
#
|
| 21 |
@app.post('/v1/predict')
|
| 22 |
def predict_capacity():
|
| 23 |
-
"""
|
| 24 |
-
Expects JSON input with store and slot information.
|
| 25 |
-
Example JSON:
|
| 26 |
-
{
|
| 27 |
-
"Store": "BU1",
|
| 28 |
-
"QueueType": "Normal",
|
| 29 |
-
"StaffEmployed": 20,
|
| 30 |
-
"StaffOnline": 15,
|
| 31 |
-
"StaffLeave": 2,
|
| 32 |
-
"StoreArea": 1000,
|
| 33 |
-
"PickingArea": 200,
|
| 34 |
-
"TechAdvancement": 3,
|
| 35 |
-
"SpecialEvent": "",
|
| 36 |
-
"Date": "2025-10-06",
|
| 37 |
-
"Slot": "14:00"
|
| 38 |
-
}
|
| 39 |
-
"""
|
| 40 |
try:
|
| 41 |
-
# Get JSON data from request
|
| 42 |
sales_data = request.get_json()
|
|
|
|
|
|
|
|
|
|
|
|
|
| 43 |
|
| 44 |
-
#
|
| 45 |
-
sample = {
|
| 46 |
-
'Store': sales_data['Store'],
|
| 47 |
-
'QueueType': sales_data['QueueType'],
|
| 48 |
-
'StaffEmployed': sales_data['StaffEmployed'],
|
| 49 |
-
'StaffOnline': sales_data['StaffOnline'],
|
| 50 |
-
'StaffLeave': sales_data['StaffLeave'],
|
| 51 |
-
'StoreArea': sales_data['StoreArea'],
|
| 52 |
-
'PickingArea': sales_data['PickingArea'],
|
| 53 |
-
'TechAdvancement': sales_data['TechAdvancement'],
|
| 54 |
-
'SpecialEvent': sales_data['SpecialEvent'],
|
| 55 |
-
'Date': sales_data['Date'],
|
| 56 |
-
'Slot': sales_data['Slot']
|
| 57 |
-
}
|
| 58 |
-
|
| 59 |
-
# Convert to DataFrame
|
| 60 |
-
input_data = pd.DataFrame([sample])
|
| 61 |
-
input_data["Date"] = pd.to_datetime(input_data["Date"]) # ⚡ convert to datetime
|
| 62 |
-
data_set = input_data.copy() # optional backup
|
| 63 |
-
|
| 64 |
-
# Drop any IDs if your pipeline doesn’t need them
|
| 65 |
-
# input_data.drop(["Store_Id"], axis=1, inplace=True) # example
|
| 66 |
-
|
| 67 |
-
|
| 68 |
-
# Predict using the trained pipeline
|
| 69 |
prediction = pipeline.predict(input_data).tolist()[0]
|
| 70 |
|
| 71 |
-
#
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 72 |
return jsonify({'Predicted_Capacity': prediction})
|
| 73 |
|
| 74 |
except Exception as e:
|
|
|
|
| 75 |
return jsonify({'error': str(e)}), 400
|
| 76 |
|
| 77 |
-
#
|
| 78 |
@app.post('/v1/predict_batch')
|
| 79 |
def predict_capacity_batch():
|
| 80 |
-
"""
|
| 81 |
-
Expects JSON input with a list of store capacity data.
|
| 82 |
-
Example JSON:
|
| 83 |
-
{
|
| 84 |
-
"data": [
|
| 85 |
-
{
|
| 86 |
-
"Store": "BU1",
|
| 87 |
-
"QueueType": "Normal",
|
| 88 |
-
"StaffEmployed": 20,
|
| 89 |
-
"StaffOnline": 15,
|
| 90 |
-
"StaffLeave": 2,
|
| 91 |
-
"StoreArea": 1000,
|
| 92 |
-
"PickingArea": 200,
|
| 93 |
-
"TechAdvancement": 3,
|
| 94 |
-
"SpecialEvent": "",
|
| 95 |
-
"Date": "2025-10-06",
|
| 96 |
-
"Slot": "14:00"
|
| 97 |
-
},
|
| 98 |
-
{
|
| 99 |
-
"Store": "BU2",
|
| 100 |
-
"QueueType": "Express",
|
| 101 |
-
"StaffEmployed": 25,
|
| 102 |
-
"StaffOnline": 20,
|
| 103 |
-
"StaffLeave": 1,
|
| 104 |
-
"StoreArea": 1200,
|
| 105 |
-
"PickingArea": 250,
|
| 106 |
-
"TechAdvancement": 4,
|
| 107 |
-
"SpecialEvent": "BlackFriday",
|
| 108 |
-
"Date": "2025-10-06",
|
| 109 |
-
"Slot": "10:00"
|
| 110 |
-
}
|
| 111 |
-
]
|
| 112 |
-
}
|
| 113 |
-
"""
|
| 114 |
try:
|
| 115 |
-
# Get JSON data from request
|
| 116 |
input_json = request.get_json()
|
| 117 |
data_list = input_json.get("data", [])
|
| 118 |
-
|
| 119 |
-
# Convert list of dicts to DataFrame
|
| 120 |
input_data = pd.DataFrame(data_list)
|
| 121 |
-
input_data["Date"] = pd.to_datetime(input_data["Date"])
|
| 122 |
-
print("Batch prediction input shape:", input_data.shape)
|
| 123 |
-
print("Batch input preview:\n", input_data.head())
|
| 124 |
|
|
|
|
|
|
|
| 125 |
|
| 126 |
-
# Predict using pipeline
|
| 127 |
predictions = pipeline.predict(input_data).tolist()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 128 |
|
| 129 |
-
|
| 130 |
|
| 131 |
-
# Prepare output DataFrame with Date, Store, Predicted_Capacity
|
| 132 |
output_df = pd.DataFrame({
|
| 133 |
"Date": input_data["Date"],
|
| 134 |
"Store": input_data["Store"],
|
| 135 |
-
"Predicted_Capacity":
|
| 136 |
})
|
| 137 |
|
| 138 |
-
# Return as HTML table
|
| 139 |
return output_df.to_html(index=False)
|
| 140 |
|
| 141 |
-
|
| 142 |
except Exception as e:
|
|
|
|
| 143 |
return jsonify({"error": str(e)}), 400
|
| 144 |
|
| 145 |
-
#
|
|
|
|
|
|
|
| 146 |
if __name__ == '__main__':
|
| 147 |
app.run(debug=True)
|
|
|
|
| 1 |
import pandas as pd
|
| 2 |
from flask import Flask, request, jsonify
|
|
|
|
|
|
|
|
|
|
| 3 |
import joblib
|
| 4 |
+
import numpy as np
|
| 5 |
+
import logging
|
| 6 |
+
|
| 7 |
+
# -----------------------
|
| 8 |
+
# Setup logging
|
| 9 |
+
# -----------------------
|
| 10 |
+
logging.basicConfig(level=logging.INFO)
|
| 11 |
+
logger = logging.getLogger(__name__)
|
| 12 |
+
|
| 13 |
+
# -----------------------
|
| 14 |
+
# Initialize Flask app
|
| 15 |
+
# -----------------------
|
| 16 |
app = Flask("Store Capacity Predictor")
|
| 17 |
|
| 18 |
+
# Load the trained pipeline
|
|
|
|
| 19 |
pipeline = joblib.load("catbooster_model_v1_0.joblib")
|
| 20 |
|
| 21 |
+
# -----------------------
|
| 22 |
+
# Routes
|
| 23 |
+
# -----------------------
|
| 24 |
@app.get('/')
|
| 25 |
def home():
|
| 26 |
return "Welcome to the Store Capacity Prediction API"
|
| 27 |
|
| 28 |
+
# ----------------------- SINGLE PREDICTION -----------------------
|
| 29 |
@app.post('/v1/predict')
|
| 30 |
def predict_capacity():
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 31 |
try:
|
|
|
|
| 32 |
sales_data = request.get_json()
|
| 33 |
+
input_data = pd.DataFrame([sales_data])
|
| 34 |
+
input_data["Date"] = pd.to_datetime(input_data["Date"])
|
| 35 |
+
|
| 36 |
+
logger.info("Single prediction input:\n%s", input_data)
|
| 37 |
|
| 38 |
+
# Predict
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 39 |
prediction = pipeline.predict(input_data).tolist()[0]
|
| 40 |
|
| 41 |
+
# Sanitize and convert to integer
|
| 42 |
+
if pd.isna(prediction) or np.isinf(prediction) or not np.isfinite(prediction):
|
| 43 |
+
logger.warning("Single prediction invalid (%s), replacing with 0", prediction)
|
| 44 |
+
prediction = 0
|
| 45 |
+
else:
|
| 46 |
+
prediction = int(np.clip(prediction, 0, 10000)) # Adjust max if needed
|
| 47 |
+
|
| 48 |
+
logger.info("Single prediction output: %s", prediction)
|
| 49 |
+
|
| 50 |
return jsonify({'Predicted_Capacity': prediction})
|
| 51 |
|
| 52 |
except Exception as e:
|
| 53 |
+
logger.error("Error in single prediction: %s", e)
|
| 54 |
return jsonify({'error': str(e)}), 400
|
| 55 |
|
| 56 |
+
# ----------------------- BATCH PREDICTION -----------------------
|
| 57 |
@app.post('/v1/predict_batch')
|
| 58 |
def predict_capacity_batch():
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 59 |
try:
|
|
|
|
| 60 |
input_json = request.get_json()
|
| 61 |
data_list = input_json.get("data", [])
|
|
|
|
|
|
|
| 62 |
input_data = pd.DataFrame(data_list)
|
| 63 |
+
input_data["Date"] = pd.to_datetime(input_data["Date"])
|
|
|
|
|
|
|
| 64 |
|
| 65 |
+
logger.info("Batch input shape: %s", input_data.shape)
|
| 66 |
+
logger.info("Batch input preview:\n%s", input_data.head())
|
| 67 |
|
|
|
|
| 68 |
predictions = pipeline.predict(input_data).tolist()
|
| 69 |
+
clean_predictions = []
|
| 70 |
+
|
| 71 |
+
for idx, p in enumerate(predictions):
|
| 72 |
+
if pd.isna(p) or np.isinf(p) or not np.isfinite(p):
|
| 73 |
+
logger.warning("Row %d prediction invalid (%s), replacing with 0", idx, p)
|
| 74 |
+
clean_predictions.append(0)
|
| 75 |
+
else:
|
| 76 |
+
clean_predictions.append(int(np.clip(p, 0, 10000)))
|
| 77 |
|
| 78 |
+
logger.info("Batch predictions: %s", clean_predictions)
|
| 79 |
|
|
|
|
| 80 |
output_df = pd.DataFrame({
|
| 81 |
"Date": input_data["Date"],
|
| 82 |
"Store": input_data["Store"],
|
| 83 |
+
"Predicted_Capacity": clean_predictions
|
| 84 |
})
|
| 85 |
|
|
|
|
| 86 |
return output_df.to_html(index=False)
|
| 87 |
|
|
|
|
| 88 |
except Exception as e:
|
| 89 |
+
logger.error("Error in batch prediction: %s", e)
|
| 90 |
return jsonify({"error": str(e)}), 400
|
| 91 |
|
| 92 |
+
# -----------------------
|
| 93 |
+
# Run Flask app
|
| 94 |
+
# -----------------------
|
| 95 |
if __name__ == '__main__':
|
| 96 |
app.run(debug=True)
|