FMCG / app.py
linkstatic1's picture
Update app.py
5d3691f verified
import gradio as gr
import pandas as pd
import joblib
import plotly.express as px
import plotly.graph_objects as go
# --- 1. DATA & MODEL LOADING ---
# Load your model and feature list
model = joblib.load("sales_model.joblib")
feature_names = joblib.load("feature_names.joblib")
# Load your CSV for EDA charts
df = pd.read_csv("sales_data.csv")
df['date'] = pd.to_datetime(df['date'])
df['revenue'] = df['units_sold'] * df['price_unit']
df['weekday'] = df['date'].dt.day_name()
# --- 2. HELPERS & INSIGHTS ---
def get_business_insights():
promo_avg = df.groupby('promotion_flag')['units_sold'].mean()
lift = ((promo_avg[1] - promo_avg[0]) / promo_avg[0]) * 100
top_brand = df.groupby('brand')['revenue'].sum().idxmax()
top_region = df.groupby('region')['units_sold'].sum().idxmax()
insights = f"""
### ๐Ÿ’ก Key Business Insights
* **Promotion Impact:** Promotions drive a **{lift:.1f}% increase** in average sales volume.
* **Revenue Leader:** **{top_brand}** is currently the top-performing brand by total revenue.
* **Regional Powerhouse:** **{top_region}** is the highest volume region.
* **Inventory Note:** Average stock availability is currently **{df['stock_available'].mean():.1f} units**.
"""
return insights
# --- 2. PREDICTION LOGIC ---
def predict_sales(u_date, u_brand, u_region, u_price, u_promo, u_stock):
target_date = pd.to_datetime(u_date)
# Initialize input row with zeros matching training features
input_row = pd.DataFrame(0, index=[0], columns=feature_names)
# Fill Time Features
input_row['month'] = target_date.month
input_row['day_of_week'] = target_date.weekday()
input_row['is_weekend'] = 1 if target_date.weekday() >= 5 else 0
# Fill Numerical Features
input_row['price_unit'] = u_price
input_row['promotion_flag'] = 1 if u_promo else 0
input_row['stock_available'] = u_stock
# Fill Categorical Features (One-Hot Encoding match)
brand_col = f"brand_{u_brand}"
region_col = f"region_{u_region}"
if brand_col in input_row.columns: input_row[brand_col] = 1
if region_col in input_row.columns: input_row[region_col] = 1
# Predict
prediction = model.predict(input_row)[0]
prediction = max(0, int(prediction))
revenue = prediction * u_price
# Context Chart
brand_avg = df[df['brand'] == u_brand]['units_sold'].mean()
categories = ['Predicted', f'{u_brand} Avg']
values = [prediction, brand_avg]
fig = px.bar(x=categories, y=values, color=categories,
title=f"Forecast vs. {u_brand} Average",
labels={'x': '', 'y': 'Units'})
fig.update_layout(showlegend=False, height=300)
return f"{prediction} Units", f"${revenue:,.2f}", fig
# --- 3. EDA CHART FUNCTIONS ---
def plot_brand_revenue():
brand_rev = df.groupby('brand')['revenue'].sum().sort_values(ascending=True).reset_index()
fig = px.bar(brand_rev, x='revenue', y='brand', orientation='h',
title="Total Revenue by Brand", color='revenue', color_continuous_scale='Viridis')
return fig
def plot_promo_lift():
promo_data = df.groupby('promotion_flag')['units_sold'].mean().reset_index()
promo_data['promotion_flag'] = promo_data['promotion_flag'].map({0: 'No Promo', 1: 'Promo Active'})
fig = px.bar(promo_data, x='promotion_flag', y='units_sold', color='promotion_flag',
title="Average Volume: Promotion Impact")
return fig
def plot_region_sales():
region_sales = df.groupby('region')['units_sold'].sum().reset_index()
fig = px.pie(region_sales, values='units_sold', names='region', title="Volume by Region", hole=0.4)
return fig
def plot_sales_trend():
trend = df.resample('W', on='date')['units_sold'].sum().reset_index()
fig = px.line(trend, x='date', y='units_sold', title="Weekly Sales Trend", markers=True)
return fig
# --- 4. GRADIO UI LAYOUT ---
with gr.Blocks() as demo:
gr.Markdown("# ๐Ÿฅ› Smart Sales & Revenue Intelligence")
gr.Markdown("Predict future performance and explore historical data patterns.")
with gr.Tabs():
# TAB 1: DATA EXPLORATION
with gr.TabItem("๐Ÿ“Š EDA Dashboard"):
gr.Markdown(get_business_insights())
with gr.Row():
gr.Plot(plot_brand_revenue())
gr.Plot(plot_promo_lift())
with gr.Row():
gr.Plot(plot_sales_trend())
gr.Plot(plot_region_sales())
with gr.Accordion("View Raw Data Snippet", open=False):
gr.DataFrame(df.sample(10))
# TAB 2: PREDICTOR
with gr.TabItem("๐Ÿ”ฎ Sales Forecast"):
with gr.Row():
with gr.Column():
gr.Markdown("### Input Parameters")
u_date = gr.DateTime(label="Select Target Date")
u_brand = gr.Dropdown(sorted(df['brand'].unique().tolist()), label="Brand")
u_region = gr.Dropdown(sorted(df['region'].unique().tolist()), label="Region")
u_price = gr.Number(label="Unit Price ($)", value=2.50)
u_promo = gr.Checkbox(label="Is Promotion Active?")
u_stock = gr.Slider(0, 500, label="Stock Availability", value=150)
predict_btn = gr.Button("Generate Prediction", variant="primary")
with gr.Column():
gr.Markdown("### Model Output")
out_sales = gr.Textbox(label="Predicted Sales Volume")
out_rev = gr.Textbox(label="Estimated Gross Revenue")
out_plot = gr.Plot(label="Forecast Context")
gr.Markdown("---")
gr.Info("Note: Predictions are based on historical XGBoost training patterns.")
predict_btn.click(
predict_sales,
inputs=[u_date, u_brand, u_region, u_price, u_promo, u_stock],
outputs=[out_sales, out_rev, out_plot]
)
# --- 5. LAUNCH ---
if __name__ == "__main__":
demo.launch(theme=gr.themes.Soft())