TrBn17
clean repo without secrets
9bc522a
import gradio as gr
import pandas as pd
import numpy as np
import pickle
import os
from typing import Dict, List, Any
import random
# Load sample data function (inline to avoid import issues)
def load_sample_data():
"""Load sample data from CSV file"""
try:
data_path = "data/sample_data.csv"
if os.path.exists(data_path):
df = pd.read_csv(data_path)
return df
else:
# Return mock data if file doesn't exist
return pd.DataFrame({
'Category': ['Electronics', 'Clothing', 'Home & Garden', 'Sports'],
'Region': ['North', 'South', 'East', 'West'],
'Inventory Level': [150.5, 89.2, 205.7, 125.8],
'Units Ordered': [25, 15, 40, 30],
'Demand Forecast': [200.0, 120.5, 300.2, 180.4]
})
except Exception as e:
print(f"Error loading data: {str(e)}")
return pd.DataFrame({
'Category': ['Electronics', 'Clothing', 'Home & Garden', 'Sports'],
'Region': ['North', 'South', 'East', 'West'],
'Inventory Level': [150.5, 89.2, 205.7, 125.8],
'Units Ordered': [25, 15, 40, 30],
'Demand Forecast': [200.0, 120.5, 300.2, 180.4]
})
# Simple prediction pipeline class
class InventoryPredictionPipeline:
def __init__(self):
self.model = None
self.features = None
self.scaler = None
self.label_encoders = {}
self.categorical_cols = []
self.feature_cols = []
self.n_lags = 14
def predict(self, X):
# Simple prediction logic - return random values for demo
return np.random.uniform(100, 1000, len(X))
# Service to auto-generate store_id and product_id
class IDGeneratorService:
@staticmethod
def generate_store_id():
"""Generate random store ID in format S### """
return f"S{random.randint(1, 999):03d}"
@staticmethod
def generate_product_id():
"""Generate random product ID in format P#### """
return f"P{random.randint(1, 9999):04d}"
# Load model
def load_prediction_model():
"""Load the prediction model"""
try:
with open('models_sale_and_material/sale_prediction_pipeline.pkl', 'rb') as f:
return pickle.load(f)
except Exception as e:
print(f"Warning: Could not load model - {e}")
return InventoryPredictionPipeline()
# Initialize model
prediction_model = load_prediction_model()
# Custom CSS for styling with colors from sales forecast theme
custom_css = """
.gradio-container {
background: linear-gradient(135deg, #f0f8ff 0%, #e6f3ff 100%);
font-family: 'Arial', sans-serif;
}
.header-container {
text-align: center;
margin: 20px 0;
padding: 30px;
background: linear-gradient(135deg, rgba(255,107,107,0.1), rgba(78,205,196,0.1), rgba(255,234,167,0.1));
border-radius: 20px;
box-shadow: 0 8px 32px rgba(31, 38, 135, 0.1);
}
.sales-chart-visual {
display: flex;
justify-content: center;
align-items: end;
margin: 20px 0;
height: 120px;
}
.bar {
width: 40px;
margin: 0 5px;
border-radius: 8px 8px 0 0;
display: flex;
flex-direction: column;
justify-content: end;
align-items: center;
position: relative;
}
.bar1 { background: linear-gradient(to top, #4CAF50, #81C784); height: 40px; }
.bar2 { background: linear-gradient(to top, #FFC107, #FFD54F); height: 60px; }
.bar3 { background: linear-gradient(to top, #FF9800, #FFB74D); height: 80px; }
.bar4 { background: linear-gradient(to top, #F44336, #E57373); height: 100px; }
.arrow-up {
color: #4CAF50;
font-size: 2em;
margin-left: 10px;
animation: bounce 2s infinite;
}
@keyframes bounce {
0%, 20%, 50%, 80%, 100% { transform: translateY(0); }
40% { transform: translateY(-10px); }
60% { transform: translateY(-5px); }
}
.header-title {
background: linear-gradient(90deg, #FF6B6B, #4ECDC4, #45B7D1, #96CEB4, #FFEAA7, #DDA0DD);
background-size: 300% 300%;
animation: gradient 8s ease infinite;
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
text-align: center;
font-size: 3em;
font-weight: bold;
margin: 20px 0;
}
@keyframes gradient {
0% { background-position: 0% 50%; }
50% { background-position: 100% 50%; }
100% { background-position: 0% 50%; }
}
.prediction-box {
background: linear-gradient(135deg, #FF6B6B, #4ECDC4);
border-radius: 15px;
padding: 20px;
color: white;
text-align: center;
font-size: 1.5em;
font-weight: bold;
box-shadow: 0 8px 32px rgba(31, 38, 135, 0.37);
}
.feature-box {
background: linear-gradient(135deg, #96CEB4, #FFEAA7);
border-radius: 15px;
padding: 15px;
margin: 10px 0;
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1);
}
.info-card {
background: rgba(255, 255, 255, 0.9);
border-radius: 10px;
padding: 15px;
margin: 10px 0;
border-left: 5px solid #4ECDC4;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
}
.metric-card {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
border-radius: 10px;
padding: 15px;
margin: 5px;
text-align: center;
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2);
}
.button-predict {
background: linear-gradient(135deg, #FF6B6B, #4ECDC4) !important;
color: white !important;
border: none !important;
border-radius: 25px !important;
padding: 12px 30px !important;
font-size: 16px !important;
font-weight: bold !important;
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2) !important;
transition: all 0.3s ease !important;
}
.button-predict:hover {
transform: translateY(-2px) !important;
box-shadow: 0 6px 20px rgba(0, 0, 0, 0.3) !important;
}
.input-field {
border-radius: 10px !important;
border: 2px solid #4ECDC4 !important;
padding: 10px !important;
}
.tab-nav {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%) !important;
border-radius: 10px 10px 0 0 !important;
}
"""
def get_sample_features():
"""Get sample features and statistics"""
try:
df = load_sample_data()
categories = df['Category'].unique().tolist() if 'Category' in df.columns else ['Electronics', 'Clothing', 'Home & Garden', 'Sports']
regions = df['Region'].unique().tolist() if 'Region' in df.columns else ['North', 'South', 'East', 'West']
# Calculate statistics
stats = {}
if 'Inventory Level' in df.columns:
stats['inventory'] = {
'min': float(df['Inventory Level'].min()),
'max': float(df['Inventory Level'].max()),
'mean': float(df['Inventory Level'].mean())
}
return categories, regions, stats, df.head()
except:
return ['Electronics', 'Clothing', 'Home & Garden', 'Sports'], ['North', 'South', 'East', 'West'], {}, pd.DataFrame()
def predict_sales(category, region, inventory_level, units_ordered, demand_forecast):
"""Make sales prediction"""
try:
# Auto-generate IDs
store_id = IDGeneratorService.generate_store_id()
product_id = IDGeneratorService.generate_product_id()
# Create input data
data = pd.DataFrame([{
'Store ID': store_id,
'Product ID': product_id,
'Category': category,
'Region': region,
'Inventory Level': inventory_level,
'Units Ordered': units_ordered,
'Demand Forecast': demand_forecast
}])
# Make prediction
prediction = prediction_model.predict(data)
result_html = f"""
<div class="prediction-box">
<h3>🎯 Sales Prediction Result</h3>
<div style="font-size: 2em; margin: 15px 0;">
${prediction[0]:.2f}
</div>
<p>Generated Store ID: <strong>{store_id}</strong></p>
<p>Generated Product ID: <strong>{product_id}</strong></p>
</div>
"""
return result_html
except Exception as e:
return f"""
<div style="background: #ff4757; color: white; padding: 15px; border-radius: 10px;">
<h3>❌ Prediction Error</h3>
<p>Error: {str(e)}</p>
</div>
"""
def display_sample_data():
"""Display sample data and statistics"""
categories, regions, stats, sample_df = get_sample_features()
# Create sample data display
sample_html = "<div class='feature-box'><h3>πŸ“Š Sample Data</h3>"
if not sample_df.empty:
sample_html += sample_df.to_html(classes='table table-striped', escape=False)
sample_html += "</div>"
# Create statistics display
stats_html = "<div class='info-card'><h3>πŸ“ˆ Dataset Statistics</h3>"
if stats:
for key, value in stats.items():
stats_html += f"""
<div class='metric-card'>
<h4>{key.replace('_', ' ').title()}</h4>
<p>Min: {value.get('min', 'N/A')}</p>
<p>Max: {value.get('max', 'N/A')}</p>
<p>Mean: {value.get('mean', 'N/A'):.2f}</p>
</div>
"""
stats_html += "</div>"
return sample_html, stats_html, categories, regions
# Create Gradio interface
def create_interface():
with gr.Blocks(css=custom_css, title="Sales Forecast Prediction") as demo:
# Header with CSS-based chart visualization
gr.HTML("""
<div class="header-container">
<div class="sales-chart-visual">
<div class="bar bar1"></div>
<div class="bar bar2"></div>
<div class="bar bar3"></div>
<div class="bar bar4"></div>
<div class="arrow-up">πŸ“ˆ</div>
</div>
<div class="header-title">
πŸ“ˆ SALES FORECAST PREDICTION πŸ“Š
</div>
<p style="font-size: 1.2em; color: #666; margin: 10px 0;">
Advanced AI-powered sales prediction system for retail inventory management
</p>
</div>
""")
# Get initial data
categories, regions, _, _ = get_sample_features()
with gr.Tabs():
# Prediction Tab
with gr.TabItem("🎯 Sales Prediction", elem_classes="tab-nav"):
gr.HTML("""
<div class='info-card'>
<h3>πŸš€ Make Your Sales Prediction</h3>
<p>Enter your inventory and demand data below to get an AI-powered sales forecast.
Store ID and Product ID will be automatically generated for you!</p>
</div>
""")
with gr.Row():
with gr.Column(scale=1):
category_input = gr.Dropdown(
choices=categories,
label="πŸ“¦ Product Category",
value=categories[0] if categories else "Electronics",
elem_classes="input-field"
)
region_input = gr.Dropdown(
choices=regions,
label="🌍 Sales Region",
value=regions[0] if regions else "North",
elem_classes="input-field"
)
inventory_input = gr.Number(
label="πŸ“Š Current Inventory Level",
value=150.0,
minimum=0,
elem_classes="input-field"
)
with gr.Column(scale=1):
units_input = gr.Number(
label="πŸ“ˆ Units Ordered",
value=25,
minimum=0,
elem_classes="input-field"
)
demand_input = gr.Number(
label="🎯 Demand Forecast",
value=200.0,
minimum=0,
elem_classes="input-field"
)
predict_btn = gr.Button(
"πŸš€ Predict Sales",
variant="primary",
elem_classes="button-predict"
)
# Prediction result
prediction_output = gr.HTML()
predict_btn.click(
fn=predict_sales,
inputs=[category_input, region_input, inventory_input, units_input, demand_input],
outputs=prediction_output
)
# Features Tab
with gr.TabItem("πŸ“Š Dataset Explorer", elem_classes="tab-nav"):
gr.HTML("""
<div class='info-card'>
<h3>πŸ” Explore Dataset Features</h3>
<p>Discover the available categories, regions, and sample data used for training our prediction model.</p>
</div>
""")
# Sample data display
sample_data_output = gr.HTML()
stats_output = gr.HTML()
def refresh_data():
sample_html, stats_html, _, _ = display_sample_data()
return sample_html, stats_html
refresh_btn = gr.Button("πŸ”„ Refresh Data", elem_classes="button-predict")
refresh_btn.click(
fn=refresh_data,
outputs=[sample_data_output, stats_output]
)
# Load initial data
demo.load(
fn=refresh_data,
outputs=[sample_data_output, stats_output]
)
# About Tab
with gr.TabItem("ℹ️ About", elem_classes="tab-nav"):
gr.HTML("""
<div class='info-card'>
<h3>🎯 About Sales Forecast Prediction</h3>
<p>This application uses advanced machine learning algorithms to predict sales based on inventory levels,
demand forecasts, and historical data patterns.</p>
<h4>πŸ”§ Features:</h4>
<ul>
<li>πŸ€– AI-powered sales forecasting</li>
<li>πŸ“Š Real-time predictions</li>
<li>πŸͺ Auto-generated Store & Product IDs</li>
<li>πŸ“ˆ Multiple product categories and regions</li>
<li>πŸ“‹ Dataset exploration tools</li>
<li>🎨 Beautiful gradient interface</li>
</ul>
<h4>🎨 Model Information:</h4>
<p>The prediction model is trained on retail inventory data and uses features such as:</p>
<ul>
<li>Product category and region</li>
<li>Current inventory levels</li>
<li>Units ordered</li>
<li>Demand forecasting data</li>
</ul>
<div style="text-align: center; margin: 20px 0;">
<p style="color: #666; font-style: italic;">
Powered by AI πŸš€ | Built with Gradio ⚑ | Deployed on Hugging Face πŸ€—
</p>
</div>
</div>
""")
# Footer
gr.HTML("""
<div style="text-align: center; margin-top: 30px; padding: 20px; background: rgba(255,255,255,0.1); border-radius: 10px;">
<p style="color: #666;">
πŸ’‘ <strong>Tip:</strong> Try different combinations of categories and regions to see how they affect sales predictions!
</p>
</div>
""")
return demo
# Launch the app
if __name__ == "__main__":
demo = create_interface()
demo.launch(
server_name="0.0.0.0",
server_port=7860,
share=True,
show_error=True
)