import os import json import joblib import pandas as pd import streamlit as st from huggingface_hub import hf_hub_download st.set_page_config(page_title="Wellness Package Predictor", page_icon="🏝️", layout="centered") st.title("🏝️ Wellness Tourism Package — Purchase Propensity") def get_secret(name: str, default=None): try: return st.secrets[name] except Exception: return os.getenv(name, default) MODEL_REPO = get_secret("MODEL_REPO", "MBG0903/tourism_customer_xgb") HF_TOKEN = get_secret("HF_TOKEN", None) @st.cache_resource(show_spinner=True) def load_artifacts(repo_id: str, token: str | None): # hf_hub_download automatically finds the correct writable cache directory model_path = hf_hub_download(repo_id=repo_id, filename="model.joblib", token=token) meta_path = hf_hub_download(repo_id=repo_id, filename="metadata.json", token=token) model = joblib.load(model_path) with open(meta_path, "r") as f: meta = json.load(f) return model, meta try: model, meta = load_artifacts(MODEL_REPO, HF_TOKEN) except Exception as e: st.error(f"Failed to load model artifacts from {MODEL_REPO}. Details: {e}") st.stop() st.caption("Model metrics (from training)") st.json(meta.get("metrics", {})) # ---- UI ---- st.sidebar.header("Enter Customer Profile") def i_num(label, value, minv=None, maxv=None, step=1): return st.sidebar.number_input(label, value=value, min_value=minv, max_value=maxv, step=step) inputs = {} inputs["CustomerID"] = st.sidebar.text_input("CustomerID", "CUST_000001") inputs["Age"] = i_num("Age", 32, 18, 90) inputs["TypeofContact"] = st.sidebar.selectbox("TypeofContact", ["Company Invited","Self Inquiry"]) inputs["CityTier"] = st.sidebar.selectbox("CityTier", ["Tier 1","Tier 2","Tier 3"]) inputs["Occupation"] = st.sidebar.selectbox("Occupation", ["Salaried","Freelancer","Self Employed","Student","Retired"]) inputs["Gender"] = st.sidebar.selectbox("Gender", ["Male","Female"]) inputs["NumberOfPersonVisiting"] = i_num("NumberOfPersonVisiting", 2, 1, 10) inputs["PreferredPropertyStar"] = i_num("PreferredPropertyStar", 4, 1, 5) inputs["MaritalStatus"] = st.sidebar.selectbox("MaritalStatus", ["Single","Married","Divorced"]) inputs["NumberOfTrips"] = i_num("NumberOfTrips", 3, 0, 50) inputs["Passport"] = st.sidebar.selectbox("Passport", [0,1]) inputs["OwnCar"] = st.sidebar.selectbox("OwnCar", [0,1]) inputs["NumberOfChildrenVisiting"] = i_num("NumberOfChildrenVisiting", 0, 0, 10) inputs["Designation"] = st.sidebar.selectbox("Designation", ["Executive","Manager","Senior Manager","AVP","VP","Director"]) inputs["MonthlyIncome"] = i_num("MonthlyIncome", 70000, 0, 1_000_000, 1000) inputs["PitchSatisfactionScore"] = i_num("PitchSatisfactionScore", 4, 1, 5) inputs["ProductPitched"] = st.sidebar.selectbox("ProductPitched", ["Basic","Deluxe","Super Deluxe","King","Queen"]) inputs["NumberOfFollowups"] = i_num("NumberOfFollowups", 2, 0, 20) inputs["DurationOfPitch"] = i_num("DurationOfPitch", 15, 0, 120) df_in = pd.DataFrame([inputs]) for junk in ["Unnamed: 0", "index"]: if junk in df_in.columns: df_in = df_in.drop(columns=[junk]) feature_order = meta.get("feature_order") if feature_order: missing = [c for c in feature_order if c not in df_in.columns] if missing: st.warning(f"Input missing expected columns: {missing}") df_in = df_in[[c for c in feature_order if c in df_in.columns]] threshold = float(meta.get("threshold", 0.5)) if st.button("Predict"): try: proba = float(model.predict_proba(df_in)[:, 1][0]) pred = int(proba >= threshold) st.metric("Purchase Probability", f"{proba:.3f}") st.write("Prediction:", "Will Purchase (1)" if pred else "Will Not Purchase (0)") with st.expander("Input snapshot"): st.dataframe(df_in) except Exception as e: st.error(f"Prediction failed: {e}")