| | import gradio as gr |
| | import pandas as pd |
| | import numpy as np |
| | import pickle |
| | import os |
| | from typing import Dict, List, Any |
| | import random |
| |
|
| | |
| | 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 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] |
| | }) |
| |
|
| | |
| | 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): |
| | |
| | return np.random.uniform(100, 1000, len(X)) |
| |
|
| | |
| | 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}" |
| |
|
| | |
| | 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() |
| |
|
| | |
| | prediction_model = load_prediction_model() |
| |
|
| | |
| | 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'] |
| | |
| | |
| | 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: |
| | |
| | store_id = IDGeneratorService.generate_store_id() |
| | product_id = IDGeneratorService.generate_product_id() |
| | |
| | |
| | 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 |
| | }]) |
| | |
| | |
| | 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() |
| | |
| | |
| | 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>" |
| | |
| | |
| | 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 |
| |
|
| | |
| | def create_interface(): |
| | with gr.Blocks(css=custom_css, title="Sales Forecast Prediction") as demo: |
| | |
| | |
| | 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> |
| | """) |
| | |
| | |
| | categories, regions, _, _ = get_sample_features() |
| | |
| | with gr.Tabs(): |
| | |
| | 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_output = gr.HTML() |
| | |
| | predict_btn.click( |
| | fn=predict_sales, |
| | inputs=[category_input, region_input, inventory_input, units_input, demand_input], |
| | outputs=prediction_output |
| | ) |
| | |
| | |
| | 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_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] |
| | ) |
| | |
| | |
| | demo.load( |
| | fn=refresh_data, |
| | outputs=[sample_data_output, stats_output] |
| | ) |
| | |
| | |
| | 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> |
| | """) |
| | |
| | |
| | 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 |
| |
|
| | |
| | if __name__ == "__main__": |
| | demo = create_interface() |
| | demo.launch( |
| | server_name="0.0.0.0", |
| | server_port=7860, |
| | share=True, |
| | show_error=True |
| | ) |
| |
|