Spaces:
Sleeping
Sleeping
| # 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() | |