SpringyBon commited on
Commit
d659d62
·
verified ·
1 Parent(s): d5245c1

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +65 -81
app.py CHANGED
@@ -1,4 +1,5 @@
1
- # app.py
 
2
  import os
3
  import json
4
  import pickle
@@ -6,104 +7,87 @@ import numpy as np
6
  import gradio as gr
7
  from huggingface_hub import hf_hub_download
8
 
9
- # If your model repo is private, add a Space secret called HF_TOKEN.
10
  HF_TOKEN = os.environ.get("HF_TOKEN")
11
 
12
- # You can override this in Space secrets as HF_MODEL_ID if the path changes.
13
- HF_MODEL_ID = os.environ.get("HF_MODEL_ID", "SpringyBon/entrepreneur-readiness-regressor")
14
 
15
- def _download(fname: str) -> str:
16
- return hf_hub_download(
17
- repo_id=HF_MODEL_ID,
18
- filename=fname,
19
- repo_type="model",
20
- token=HF_TOKEN # None is fine for public repos; required for private
21
- )
22
 
23
- # ---- Download artifacts (expects model.pkl at repo root) ----
24
- model_path = _download("model.pkl")
25
- feat_path = _download("feature_names.json")
26
 
27
- # ---- Load artifacts ----
28
  with open(model_path, "rb") as f:
29
  reg = pickle.load(f)
30
 
31
- with open(feat_path, "r") as f:
32
- FEATURES = json.load(f) # list of feature names in the trained order
33
-
34
- # ---- Prediction ----
35
- def predict(
36
- savings_amount,
37
- monthly_income,
38
- monthly_expenses,
39
- monthly_entertainment,
40
- sales_skills_1to10,
41
- age,
42
- dependents,
43
- assets_count,
44
- risk_tolerance_1to10,
45
- confidence_1to10,
46
- business_idea_difficulty_1to10,
47
- income_stability_1to10,
48
- prior_experience_years,
49
- credit_score
50
- ):
51
- sample = {
52
- "savings_amount": savings_amount,
53
- "monthly_income": monthly_income,
54
- "monthly_expenses": monthly_expenses,
55
- "monthly_entertainment": monthly_entertainment,
56
- "sales_skills_1to10": sales_skills_1to10,
57
- "age": age,
58
- "dependents": dependents,
59
- "assets_count": assets_count,
60
- "risk_tolerance_1to10": risk_tolerance_1to10,
61
- "confidence_1to10": confidence_1to10,
62
- "business_idea_difficulty_1to10": business_idea_difficulty_1to10,
63
- "income_stability_1to10": income_stability_1to10,
64
- "prior_experience_years": prior_experience_years,
65
- "credit_score": credit_score,
66
- }
67
  try:
68
- x = [sample[f] for f in FEATURES] # keep the trained column order
69
- except KeyError as e:
70
- return f"Missing feature in UI: {e}"
71
- pred = float(reg.predict(np.array(x, dtype=float).reshape(1, -1))[0])
72
- return round(pred, 2)
 
 
 
 
73
 
74
- # ---- UI ----
75
  with gr.Blocks(title="Entrepreneur Readiness Regressor") as iface:
76
  gr.Markdown("## Entrepreneur Readiness — Prediction Demo")
77
 
 
 
78
  with gr.Row():
79
  with gr.Column():
80
- savings_amount = gr.Number(label="Savings Amount", value=25000)
81
- monthly_income = gr.Number(label="Monthly Income", value=5000)
82
- monthly_expenses = gr.Number(label="Monthly Expenses", value=3000)
83
- monthly_entertainment = gr.Number(label="Monthly Entertainment", value=200)
84
- sales_skills_1to10 = gr.Slider(1, 10, value=7, step=1, label="Sales Skills (1-10)")
85
- age = gr.Number(label="Age", value=32)
86
- dependents = gr.Number(label="Dependents", value=1, precision=0)
87
-
88
  with gr.Column():
89
- assets_count = gr.Number(label="Assets Count", value=2, precision=0)
90
- risk_tolerance_1to10 = gr.Slider(1, 10, value=6, step=1, label="Risk Tolerance (1-10)")
91
- confidence_1to10 = gr.Slider(1, 10, value=8, step=1, label="Confidence (1-10)")
92
- business_idea_difficulty_1to10 = gr.Slider(1, 10, value=5, step=1, label="Idea Difficulty (1-10)")
93
- income_stability_1to10 = gr.Slider(1, 10, value=7, step=1, label="Income Stability (1-10)")
94
- prior_experience_years = gr.Number(label="Prior Experience (years)", value=4)
95
- credit_score = gr.Number(label="Credit Score", value=710, precision=0)
96
-
97
- output = gr.Number(label="Predicted Readiness Score", precision=2)
98
  gr.Button("Predict Readiness").click(
99
  predict,
100
- inputs=[
101
- savings_amount, monthly_income, monthly_expenses, monthly_entertainment,
102
- sales_skills_1to10, age, dependents, assets_count, risk_tolerance_1to10,
103
- confidence_1to10, business_idea_difficulty_1to10, income_stability_1to10, prior_experience_years, credit_score
104
- ],
105
- outputs=output
106
  )
107
 
108
  if __name__ == "__main__":
109
- iface.launch()
 
1
+
2
+ # app.py — pickle-only, dynamic inputs
3
  import os
4
  import json
5
  import pickle
 
7
  import gradio as gr
8
  from huggingface_hub import hf_hub_download
9
 
10
+ # If the model repo is private, set this in Space secrets
11
  HF_TOKEN = os.environ.get("HF_TOKEN")
12
 
13
+ # Override with a secret if you want; defaults shown here:
14
+ HF_MODEL_ID = os.environ.get("HF_MODEL_ID", "SpringyBon/entrepreneur-readiness-synthetic")
15
 
16
+ def _dl(name: str) -> str:
17
+ return hf_hub_download(repo_id=HF_MODEL_ID, filename=name, repo_type="model", token=HF_TOKEN)
 
 
 
 
 
18
 
19
+ # --- load artifacts ---
20
+ model_path = _dl("model.pkl")
21
+ features_path = _dl("feature_names.json")
22
 
 
23
  with open(model_path, "rb") as f:
24
  reg = pickle.load(f)
25
 
26
+ with open(features_path, "r") as f:
27
+ FEATURES = json.load(f) # list of feature names in training order
28
+
29
+ print("[INFO] n_features_in_:", getattr(reg, "n_features_in_", None))
30
+ print("[INFO] FEATURES:", FEATURES)
31
+
32
+ def _validate_and_vectorize(values):
33
+ """values come in the same order as the UI components we generate from FEATURES."""
34
+ if len(values) != len(FEATURES):
35
+ return None, f"Feature count mismatch: model expects {len(FEATURES)} but got {len(values)} from UI."
36
+
37
+ try:
38
+ x = [float(v) for v in values]
39
+ except Exception as e:
40
+ return None, f"Input formatting error: {type(e).__name__}: {e}"
41
+
42
+ n_expected = getattr(reg, "n_features_in_", None)
43
+ if n_expected is not None and len(x) != int(n_expected):
44
+ return None, (
45
+ f"Model expects {n_expected} features but UI provided {len(x)}. "
46
+ "Double-check feature_names.json vs the trained model."
47
+ )
48
+ return np.array(x, dtype=float).reshape(1, -1), None
49
+
50
+ # --- prediction: accepts a variable number of inputs ---
51
+ def predict(*values):
52
+ X, err = _validate_and_vectorize(values)
53
+ if err:
54
+ return None, err
 
 
 
 
 
 
 
55
  try:
56
+ y = float(reg.predict(X)[0])
57
+ return round(y, 2), "OK"
58
+ except Exception as e:
59
+ import traceback
60
+ return None, f"Model error: {type(e).__name__}: {e}\n{traceback.format_exc()}"
61
+
62
+ # --- UI: build inputs dynamically from FEATURES ---
63
+ def pretty(label: str) -> str:
64
+ return label.replace("_", " ").title()
65
 
 
66
  with gr.Blocks(title="Entrepreneur Readiness Regressor") as iface:
67
  gr.Markdown("## Entrepreneur Readiness — Prediction Demo")
68
 
69
+ # Build inputs in the SAME ORDER as FEATURES
70
+ inputs = []
71
  with gr.Row():
72
  with gr.Column():
73
+ half = (len(FEATURES) + 1) // 2
74
+ left = FEATURES[:half]
75
+ right = FEATURES[half:]
76
+ for name in left:
77
+ # You can customize types here; Number for simplicity
78
+ inputs.append(gr.Number(label=pretty(name), value=0))
 
 
79
  with gr.Column():
80
+ for name in right:
81
+ inputs.append(gr.Number(label=pretty(name), value=0))
82
+
83
+ score_out = gr.Number(label="Predicted Readiness Score", precision=2)
84
+ msg_out = gr.Textbox(label="Message", interactive=False)
85
+
 
 
 
86
  gr.Button("Predict Readiness").click(
87
  predict,
88
+ inputs=inputs, # pass list of components (order matches FEATURES)
89
+ outputs=[score_out, msg_out], # number + message
 
 
 
 
90
  )
91
 
92
  if __name__ == "__main__":
93
+ iface.launch()