chonthichar commited on
Commit
6f0f695
·
1 Parent(s): af5e121

add gradio app + model

Browse files
app.py ADDED
@@ -0,0 +1,125 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # app.py
2
+ import json
3
+ import joblib
4
+ import numpy as np
5
+ import gradio as gr
6
+ from pathlib import Path
7
+
8
+ PIPE_PATH = Path("best_model/pipeline.joblib")
9
+ META_PATH = Path("best_model/model_meta.json")
10
+
11
+ # ---- load once ----
12
+ pipeline = joblib.load(PIPE_PATH)
13
+
14
+ # Try to respect feature order saved in metadata; fallback to a known order
15
+ default_order = [
16
+ "ph",
17
+ "Hardness",
18
+ "Solids",
19
+ "Chloramines",
20
+ "Sulfate",
21
+ "Conductivity",
22
+ "Organic_carbon",
23
+ "Trihalomethanes",
24
+ "Turbidity",
25
+ ]
26
+
27
+ if META_PATH.exists():
28
+ with open(META_PATH, "r") as f:
29
+ meta = json.load(f)
30
+ feature_order = meta.get("feature_order") or meta.get("features_used_in_order") or default_order
31
+ else:
32
+ feature_order = default_order
33
+
34
+ label_map = {0: "Unsafe (not potable)", 1: "Safe (potable)"}
35
+
36
+ def predict_one(
37
+ ph, Hardness, Solids, Chloramines, Sulfate, Conductivity, Organic_carbon, Trihalomethanes, Turbidity
38
+ ):
39
+ values = {
40
+ "ph": ph,
41
+ "Hardness": Hardness,
42
+ "Solids": Solids,
43
+ "Chloramines": Chloramines,
44
+ "Sulfate": Sulfate,
45
+ "Conductivity": Conductivity,
46
+ "Organic_carbon": Organic_carbon,
47
+ "Trihalomethanes": Trihalomethanes,
48
+ "Turbidity": Turbidity,
49
+ }
50
+ X = np.array([[values[k] for k in feature_order]])
51
+ proba = getattr(pipeline, "predict_proba", None)
52
+ if proba:
53
+ p = float(proba(X)[0, 1])
54
+ else:
55
+ # if model has no predict_proba, estimate from decision_function or 0/1
56
+ y_hat = int(pipeline.predict(X)[0])
57
+ p = 0.5 if y_hat == 1 else 0.0
58
+ y = int(pipeline.predict(X)[0])
59
+ return label_map[y], round(p, 4), feature_order
60
+
61
+ # --- A simple "chat" wrapper that lets users type numbers freely ---
62
+ import re
63
+ def chat_predict(message, history):
64
+ # Accept formats like: "ph=7.2 Hardness: 160 ...", or a JSON blob.
65
+ try:
66
+ if message.strip().startswith("{"):
67
+ values = json.loads(message)
68
+ else:
69
+ # extract key=value pairs crudely
70
+ pairs = dict(re.findall(r'(\b[a-zA-Z_]+)\s*[:=]\s*([+-]?\d+(\.\d+)?)', message))
71
+ values = {k: float(v) for k, v in pairs.items()}
72
+ # Fill missing with NaN -> pipeline imputer will handle
73
+ x = []
74
+ for k in feature_order:
75
+ x.append(float(values.get(k, np.nan)))
76
+ X = np.array([x])
77
+ proba = getattr(pipeline, "predict_proba", None)
78
+ if proba:
79
+ p = float(proba(X)[0, 1])
80
+ else:
81
+ y_hat = int(pipeline.predict(X)[0])
82
+ p = 0.5 if y_hat == 1 else 0.0
83
+ y = int(pipeline.predict(X)[0])
84
+ return f"{label_map[y]} (p={p:.4f})"
85
+ except Exception as e:
86
+ return ("Please provide inputs as JSON or 'key=value' pairs for: "
87
+ f"{', '.join(feature_order)}. Example:\n"
88
+ "ph=7.2 Hardness=160 Solids=1800 Chloramines=6.5 Sulfate=220 "
89
+ "Conductivity=350 Organic_carbon=6 Trihalomethanes=25 Turbidity=2.5")
90
+
91
+ # --------- Gradio UI ----------
92
+ with gr.Blocks(title="Water Potability Predictor") as demo:
93
+ gr.Markdown("# 💧 Water Potability Predictor\nEnter water chemistry and get a quick potability prediction.")
94
+ with gr.Tabs():
95
+ with gr.Tab("Form"):
96
+ with gr.Row():
97
+ ph = gr.Number(value=7.0, label="ph")
98
+ Hardness = gr.Number(value=150.0, label="Hardness (mg/L)")
99
+ Solids = gr.Number(value=1000.0, label="Solids (ppm)")
100
+ Chloramines = gr.Number(value=6.0, label="Chloramines (ppm)")
101
+ Sulfate = gr.Number(value=200.0, label="Sulfate (mg/L)")
102
+ Conductivity = gr.Number(value=300.0, label="Conductivity (μS/cm)")
103
+ Organic_carbon = gr.Number(value=6.0, label="Organic carbon (ppm)")
104
+ Trihalomethanes = gr.Number(value=40.0, label="Trihalomethanes (μg/L)")
105
+ Turbidity = gr.Number(value=2.0, label="Turbidity (NTU)")
106
+ btn = gr.Button("Predict")
107
+ out_label = gr.Textbox(label="Label")
108
+ out_prob = gr.Number(label="Probability (class=Safe)")
109
+ out_order = gr.JSON(label="Feature order used")
110
+ btn.click(
111
+ predict_one,
112
+ inputs=[ph, Hardness, Solids, Chloramines, Sulfate, Conductivity, Organic_carbon, Trihalomethanes, Turbidity],
113
+ outputs=[out_label, out_prob, out_order],
114
+ )
115
+ with gr.Tab("Chat"):
116
+ gr.Markdown(
117
+ "Type values as JSON or key=value pairs.\n\n"
118
+ "**Example:** `ph=7.2 Hardness=160 Solids=1800 Chloramines=6.5 "
119
+ "Sulfate=220 Conductivity=350 Organic_carbon=6 Trihalomethanes=25 Turbidity=2.5`"
120
+ )
121
+ chat = gr.ChatInterface(fn=chat_predict, type="messages")
122
+
123
+ # Spaces will look for this
124
+ if __name__ == "__main__":
125
+ demo.launch()
best_model/model_meta.json ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "artifact": "pipeline.joblib",
3
+ "created_at": "2025-10-20 10:29:47",
4
+ "feature_names_in_order": [
5
+ "ph",
6
+ "Hardness",
7
+ "Solids",
8
+ "Chloramines",
9
+ "Sulfate",
10
+ "Conductivity",
11
+ "Organic_carbon",
12
+ "Trihalomethanes",
13
+ "Turbidity"
14
+ ],
15
+ "target": "Potability",
16
+ "winner": "RandomForestClassifier",
17
+ "cv_best_params": {
18
+ "clf": "RandomForestClassifier",
19
+ "clf__max_depth": null,
20
+ "clf__min_samples_split": 5,
21
+ "clf__n_estimators": 200
22
+ },
23
+ "cv_best_score": 0.649618320610687,
24
+ "test_accuracy": 0.6432926829268293,
25
+ "preprocessing": {
26
+ "KNNImputer_on": [
27
+ "ph",
28
+ "Sulfate",
29
+ "Trihalomethanes"
30
+ ],
31
+ "MedianImputer_on": [
32
+ "Hardness",
33
+ "Solids",
34
+ "Chloramines",
35
+ "Conductivity",
36
+ "Organic_carbon",
37
+ "Turbidity"
38
+ ],
39
+ "SMOTE": true
40
+ },
41
+ "scoring": "accuracy"
42
+ }
best_model/pipeline.joblib ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:689cf58d5d0736b3a182aa46f2b840f977c5ebf45b48b1828e05ebf2c1fe2e47
3
+ size 14524206
requirements.txt ADDED
Binary file (570 Bytes). View file