Amitgupta2982 commited on
Commit
28b74a8
Β·
verified Β·
1 Parent(s): a09aa5e

Upload Streamlit frontend

Browse files
Files changed (4) hide show
  1. README.md +8 -5
  2. app.py +85 -57
  3. requirements.txt +2 -6
  4. runtime.txt +1 -0
README.md CHANGED
@@ -1,10 +1,13 @@
1
  ---
2
- title: SuperKartBackend
3
- emoji: πŸ“ˆ
4
  colorFrom: indigo
5
- colorTo: pink
6
- sdk: docker
 
 
7
  pinned: false
8
  ---
9
 
10
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
1
  ---
2
+ title: SuperKartFrontend
3
+ emoji: πŸ›’
4
  colorFrom: indigo
5
+ colorTo: indigo
6
+ sdk: streamlit
7
+ sdk_version: 1.43.2
8
+ app_file: app.py
9
  pinned: false
10
  ---
11
 
12
+ # SuperKartFrontend
13
+ Streamlit UI for SuperKart Sales Prediction.
app.py CHANGED
@@ -1,14 +1,15 @@
1
  import io
2
- import json
3
- import joblib
4
  import pandas as pd
5
- from fastapi import FastAPI, File, UploadFile, HTTPException
6
- from fastapi.middleware.cors import CORSMiddleware
7
- from pydantic import BaseModel
8
 
9
- MODEL_PATH = "SuperKart_prediction_model_v1_0.joblib"
 
 
 
 
10
 
11
- EXPECTED_COLS = [
12
  "Product_Weight",
13
  "Product_Allocated_Area",
14
  "Product_MRP",
@@ -20,65 +21,92 @@ EXPECTED_COLS = [
20
  "Store_Location_City_Type",
21
  ]
22
 
23
- app = FastAPI(title="SuperKart Backend", version="1.0")
 
 
 
 
24
 
25
- app.add_middleware(
26
- CORSMiddleware,
27
- allow_origins=["*"],
28
- allow_credentials=True,
29
- allow_methods=["*"],
30
- allow_headers=["*"],
31
- )
32
 
33
- model = None
 
 
 
 
34
 
35
- @app.on_event("startup")
36
- def load_model():
37
- global model
38
- model = joblib.load(MODEL_PATH)
39
 
40
- class Payload(BaseModel):
41
- Product_Weight: float
42
- Product_Allocated_Area: float
43
- Product_MRP: float
44
- Store_Age: int
45
- Product_Sugar_Content: str
46
- Product_Type: str
47
- Store_Type: str
48
- Store_Size: int
49
- Store_Location_City_Type: int
50
 
51
- def validate_and_order(df: pd.DataFrame) -> pd.DataFrame:
52
- missing = [c for c in EXPECTED_COLS if c not in df.columns]
53
- if missing:
54
- raise HTTPException(status_code=422, detail=f"Missing columns: {missing}")
55
- return df[EXPECTED_COLS].copy()
 
 
 
 
 
56
 
57
- @app.get("/health")
58
- def health():
59
- return {"status": "ok"}
 
 
 
 
 
 
 
 
60
 
61
- @app.post("/v1/salesprice")
62
- def predict_single(payload: Payload):
63
  try:
64
- df = pd.DataFrame([payload.dict()])
65
- X = validate_and_order(df)
66
- y = model.predict(X)
67
- return {"Predicted Price": float(y[0])}
 
 
 
 
68
  except Exception as e:
69
- raise HTTPException(status_code=500, detail=str(e))
 
 
70
 
71
- @app.post("/v1/salespricebatch")
72
- def predict_batch(file: UploadFile = File(...)):
 
 
 
 
 
 
 
 
 
 
73
  try:
74
- content = file.file.read()
75
- df = pd.read_csv(io.BytesIO(content))
76
- X = validate_and_order(df)
77
- y = model.predict(X)
78
- df["Predicted Price"] = y
79
- return json.loads(df.to_json(orient="records"))
80
- except HTTPException:
81
- raise
 
 
 
 
82
  except Exception as e:
83
- raise HTTPException(status_code=500, detail=str(e))
84
-
 
1
  import io
2
+ import requests
 
3
  import pandas as pd
4
+ import streamlit as st
 
 
5
 
6
+ # ------------------ CONFIG ------------------
7
+ DEFAULT_BACKEND_URL = "https://Amitgupta2982-SuperKartBackend.hf.space" # <β€” change if needed
8
+ SINGLE_EP = "/v1/salesprice"
9
+ BATCH_EP = "/v1/salespricebatch"
10
+ TIMEOUT = 60
11
 
12
+ EXPECTED_KEYS = [
13
  "Product_Weight",
14
  "Product_Allocated_Area",
15
  "Product_MRP",
 
21
  "Store_Location_City_Type",
22
  ]
23
 
24
+ def align_schema(df: pd.DataFrame) -> pd.DataFrame:
25
+ missing = [c for c in EXPECTED_KEYS if c not in df.columns]
26
+ if missing:
27
+ raise ValueError(f"Missing columns: {missing}")
28
+ return df[EXPECTED_KEYS].copy()
29
 
30
+ st.set_page_config(page_title="SuperKart Sales Predictor", page_icon="πŸ›’", layout="centered")
31
+ st.title("πŸ›’ SuperKart β€” Sales Prediction")
 
 
 
 
 
32
 
33
+ with st.expander("Backend settings", expanded=False):
34
+ backend_url = st.text_input("Backend URL (no trailing slash)", value=DEFAULT_BACKEND_URL)
35
+ st.caption(f"Will call: `{SINGLE_EP}` and `{BATCH_EP}` on the backend.")
36
+ if not backend_url:
37
+ st.stop()
38
 
39
+ st.subheader("Single Prediction")
 
 
 
40
 
41
+ c1, c2 = st.columns(2)
42
+ with c1:
43
+ product_weight = st.number_input("Product Weight", min_value=0.0, step=0.1, value=1.9)
44
+ product_allocated_area = st.number_input("Product Allocated Area", min_value=0.0, step=0.1, value=2.5)
45
+ product_mrp = st.number_input("Product MRP", min_value=0.0, step=0.1, value=70.0)
46
+ store_age = st.number_input("Store Age (years)", min_value=0, step=1, value=9)
 
 
 
 
47
 
48
+ with c2:
49
+ product_sugar_content = st.selectbox("Product Sugar Content", ["Low Sugar", "Regular", "No Sugar"], index=1)
50
+ product_type = st.selectbox("Product Type", [
51
+ "Frozen Foods", "Dairy", "Canned", "Baking Goods", "Health and Hygiene",
52
+ "Snack Foods", "Meat", "Household", "Hard Drinks", "Fruits and Vegetables",
53
+ "Breads", "Soft Drinks", "Breakfast", "Others", "Starchy Foods", "Seafood"
54
+ ], index=8)
55
+ store_type = st.selectbox("Store Type", ["Supermarket Type1", "Supermarket Type2", "Supermarket Type3", "Grocery Store"], index=1)
56
+ store_size = st.selectbox("Store Size (1=Small, 2=Medium, 3=Large)", [1, 2, 3], index=0)
57
+ store_location_city_type = st.selectbox("City Tier (1, 2, 3)", [1, 2, 3], index=0)
58
 
59
+ single_df = pd.DataFrame([{
60
+ "Product_Weight": product_weight,
61
+ "Product_Allocated_Area": product_allocated_area,
62
+ "Product_MRP": product_mrp,
63
+ "Store_Age": store_age,
64
+ "Product_Sugar_Content": product_sugar_content,
65
+ "Product_Type": product_type,
66
+ "Store_Type": store_type,
67
+ "Store_Size": store_size,
68
+ "Store_Location_City_Type": store_location_city_type,
69
+ }])
70
 
71
+ if st.button("Predict"):
 
72
  try:
73
+ payload = align_schema(single_df).to_dict(orient="records")[0]
74
+ with st.spinner("Predicting..."):
75
+ r = requests.post(backend_url.rstrip("/") + SINGLE_EP, json=payload, timeout=TIMEOUT)
76
+ if r.ok and r.headers.get("content-type","").startswith("application/json"):
77
+ st.success(f"Predicted Sales Price: {r.json().get('Predicted Price')}")
78
+ else:
79
+ st.error(f"Backend error {r.status_code}")
80
+ st.code(r.text[:1000])
81
  except Exception as e:
82
+ st.error(f"Request failed: {e}")
83
+
84
+ st.markdown("---")
85
 
86
+ st.subheader("Batch Prediction")
87
+ st.write("Upload a CSV with these exact columns:")
88
+ st.code(", ".join(EXPECTED_KEYS))
89
+
90
+ tmpl = pd.DataFrame(columns=EXPECTED_KEYS)
91
+ buf = io.BytesIO()
92
+ tmpl.to_csv(buf, index=False)
93
+ buf.seek(0)
94
+ st.download_button("Download CSV template", data=buf, file_name="superkart_template.csv", mime="text/csv")
95
+
96
+ up = st.file_uploader("Upload CSV", type=["csv"])
97
+ if up is not None and st.button("Predict Batch"):
98
  try:
99
+ files = {"file": (up.name, up.getvalue(), "text/csv")}
100
+ with st.spinner("Uploading & predicting..."):
101
+ r = requests.post(backend_url.rstrip("/") + BATCH_EP, files=files, timeout=TIMEOUT)
102
+ if r.ok and r.headers.get("content-type","").startswith("application/json"):
103
+ out = pd.DataFrame(r.json())
104
+ st.success("Batch predictions ready:")
105
+ st.dataframe(out.head(50), use_container_width=True)
106
+ csv = out.to_csv(index=False).encode("utf-8")
107
+ st.download_button("Download predictions", data=csv, file_name="SuperKart_Predicted_Sales.csv", mime="text/csv")
108
+ else:
109
+ st.error(f"Backend error {r.status_code}")
110
+ st.code(r.text[:1000])
111
  except Exception as e:
112
+ st.error(f"Batch request failed: {e}")
 
requirements.txt CHANGED
@@ -1,7 +1,3 @@
1
- fastapi==0.111.0
2
- uvicorn==0.30.3
3
  pandas==2.2.2
4
- numpy==2.0.2
5
- scikit-learn==1.6.1
6
- xgboost==2.1.4
7
- joblib==1.4.2
 
1
+ streamlit==1.43.2
 
2
  pandas==2.2.2
3
+ requests==2.32.3
 
 
 
runtime.txt ADDED
@@ -0,0 +1 @@
 
 
1
+ python-3.10