File size: 3,743 Bytes
e965a88
 
 
 
 
a2f86bb
 
 
764652d
a2f86bb
 
764652d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1deebba
a2f86bb
764652d
 
 
 
 
 
 
1deebba
 
764652d
 
a2f86bb
1deebba
764652d
 
 
 
1deebba
 
764652d
 
 
a2f86bb
764652d
 
1deebba
764652d
 
1deebba
764652d
824d77f
4526c26
764652d
 
 
 
 
 
 
 
 
 
 
 
 
da49b72
764652d
da49b72
764652d
 
 
 
 
 
 
 
 
da49b72
1deebba
764652d
 
 
 
 
 
 
 
824d77f
 
764652d
 
 
 
 
 
1deebba
5eaa699
764652d
 
 
 
 
 
 
 
 
 
 
 
 
5eaa699
 
764652d
 
5eaa699
764652d
 
a2f86bb
764652d
824d77f
a2f86bb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
# AI Assistance Declaration:
# Parts of this script were assisted by ChatGPT GPT.
# AI assistance was limited to code suggestions, debugging tips, or documentation wording.
# All algorithmic design, implementation decisions, and final code structure were created and verified by the project team.

import gradio as gr
import requests

# Cloud Run API URL
API_BASE = "https://ecommerce-ml-346297770564.us-east1.run.app"

# Numeric features
numeric_features = {
    "shipping_fee": 6,
    "tax": 6,
    "avg_order_value": 6,
    "day_of_week": 6
}

# Binary features (0/1) but UI uses "Yes"/"No"
binary_features = {
    "status_cancelled": 1,
    "status_completed": 1,
    "status_processing": 1,
    "status_returned": 0,
    "status_shipped": 1,
    "is_holiday": 1
}

# Create widgets
numeric_inputs = [
    gr.Number(label=f"📊 {f.replace('_',' ').title()}", value=v)
    for f, v in numeric_features.items()
]

binary_inputs = [
    gr.Radio(
        label=f"🔘 {f.replace('_',' ').title()}",
        choices=["Yes (1)", "No (0)"],
        value="Yes (1)" if v == 1 else "No (0)"
    )
    for f, v in binary_features.items()
]

feature_names = list(numeric_features.keys()) + list(binary_features.keys())
all_inputs = numeric_inputs + binary_inputs


def parse_value(v):
    if isinstance(v, str):
        return 1 if "Yes" in v else 0
    return v


def predict_fn(*values):
    parsed_vals = [parse_value(v) for v in values]
    features = {f: v for f, v in zip(feature_names, parsed_vals)}

    payload = {"features": features}
    response = requests.post(f"{API_BASE}/predict", json=payload)

    if response.status_code != 200:
        return f"❌ API Error: {response.text}"

    preds = response.json()["predictions"]

    # prediction UI
    html = """
    <div style='
        background: #f9fafb;
        border-left: 6px solid #4f46e5;
        padding: 15px 20px;
        border-radius: 10px;
        font-size: 16px;
    '>
        <h3 style='margin-top: 0; color: #4f46e5;'>📦 Prediction Results</h3>
    """
    for k, v in preds.items():
        html += f"""
        <p><b>{k}:</b> {v:.4f}</p>
        """
    html += "</div>"

    return html


def reset_inputs():
    merged = list(numeric_features.values()) + list(binary_features.values())
    return [
        v if isinstance(v, (int, float)) else ("Yes (1)" if v == 1 else "No (0)")
        for v in merged
    ]


# UI with Blocks
with gr.Blocks() as demo:

    gr.HTML("""
        <style>
            .gradio-container {
                max-width: 900px !important;
                margin: auto !important;
            }
        </style>
    """)

    gr.Markdown("## 🚀 **E-commerce Sales Forecast Demo**")
    gr.Markdown(
        "Enter feature values below. Boolean features use **Yes/No** but backend receives **1/0**.\n"
        "Click **Predict** to get results from the model deployed on **Google Cloud Run**."
    )

    with gr.Row():
        with gr.Column():
            gr.Markdown("### 📊 Numeric Features")
            for widget in numeric_inputs:
                widget.render()

            gr.Markdown("---")
            gr.Markdown("### 🔘 Binary Features (Yes / No)")
            for widget in binary_inputs:
                widget.render()

        with gr.Column():
            result_box = gr.HTML(label="📦 Predictions")

    with gr.Row():
        predict_btn = gr.Button("🔮 Predict", variant="primary")
        reset_btn = gr.Button("♻️ Reset")

    predict_btn.click(fn=predict_fn, inputs=all_inputs, outputs=result_box)
    reset_btn.click(fn=lambda: reset_inputs(), inputs=None, outputs=all_inputs)

    gr.Markdown("This interface communicates with a FastAPI backend deployed on **Cloud Run**.")

demo.launch()