Spaces:
Sleeping
Sleeping
Alireza Aminzadeh
Initial commit: SmartChain AI - Enterprise Supply Chain Optimization Platform
5656ebd | """SmartChain AI - Streamlit Application for Hugging Face Space.""" | |
| import streamlit as st | |
| import pandas as pd | |
| import numpy as np | |
| from datetime import datetime, timedelta | |
| import plotly.graph_objects as go | |
| import plotly.express as px | |
| # Page configuration | |
| st.set_page_config( | |
| page_title="SmartChain AI", | |
| page_icon="π", | |
| layout="wide", | |
| initial_sidebar_state="expanded", | |
| ) | |
| # Custom CSS | |
| st.markdown(""" | |
| <style> | |
| @import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;600;700&display=swap'); | |
| .main { | |
| font-family: 'Inter', sans-serif; | |
| } | |
| h1, h2, h3 { | |
| font-family: 'Inter', sans-serif; | |
| font-weight: 700; | |
| } | |
| .stButton > button { | |
| background-color: #2563eb; | |
| color: white; | |
| border-radius: 8px; | |
| padding: 0.5rem 1.5rem; | |
| font-weight: 600; | |
| border: none; | |
| transition: all 0.3s ease; | |
| } | |
| .stButton > button:hover { | |
| background-color: #1d4ed8; | |
| box-shadow: 0 4px 6px rgba(37, 99, 235, 0.3); | |
| } | |
| </style> | |
| """, unsafe_allow_html=True) | |
| # Sidebar | |
| st.sidebar.title("π SmartChain AI") | |
| st.sidebar.markdown("**Enterprise Supply Chain Optimization**") | |
| page = st.sidebar.selectbox( | |
| "Select Module", | |
| ["π Home", "π Demand Forecasting", "π¦ Inventory Optimization", "π Route Optimization"] | |
| ) | |
| # Helper functions for demo data | |
| def generate_forecast_data(days=30): | |
| """Generate demo forecast data.""" | |
| dates = pd.date_range(start=datetime.now(), periods=days, freq='D') | |
| base_demand = 100 | |
| trend = np.linspace(0, 20, days) | |
| seasonality = 30 * np.sin(np.linspace(0, 4*np.pi, days)) | |
| noise = np.random.normal(0, 10, days) | |
| predictions = base_demand + trend + seasonality + noise | |
| lower_bound = predictions - 20 | |
| upper_bound = predictions + 20 | |
| return pd.DataFrame({ | |
| 'date': dates, | |
| 'prediction': predictions, | |
| 'lower_bound': lower_bound, | |
| 'upper_bound': upper_bound | |
| }) | |
| def generate_inventory_data(): | |
| """Generate demo inventory metrics.""" | |
| return { | |
| 'eoq': 450, | |
| 'reorder_point': 120, | |
| 'safety_stock': 45, | |
| 'holding_cost': 2400, | |
| 'ordering_cost': 800, | |
| 'total_cost': 3200, | |
| 'service_level': 0.95 | |
| } | |
| def generate_route_data(): | |
| """Generate demo route optimization data.""" | |
| np.random.seed(42) | |
| num_locations = 8 | |
| depot = {'lat': 40.7128, 'lon': -74.0060, 'name': 'Distribution Center'} | |
| locations = [] | |
| for i in range(num_locations): | |
| locations.append({ | |
| 'id': i+1, | |
| 'name': f'Customer {i+1}', | |
| 'lat': depot['lat'] + np.random.uniform(-0.5, 0.5), | |
| 'lon': depot['lon'] + np.random.uniform(-0.5, 0.5), | |
| 'demand': np.random.randint(10, 100) | |
| }) | |
| return depot, locations | |
| # Home Page | |
| if page == "π Home": | |
| st.title("π SmartChain AI") | |
| st.subheader("Enterprise Supply Chain Optimization Platform") | |
| st.markdown(""" | |
| Welcome to **SmartChain AI**, an AI-powered platform for optimizing end-to-end supply chain operations. | |
| ### π― Key Features | |
| - **π Demand Forecasting**: Predict future demand using advanced ML models (Prophet + XGBoost) | |
| - **π¦ Inventory Optimization**: Optimize stock levels using EOQ, safety stock, and reorder points | |
| - **π Route Optimization**: Solve vehicle routing problems efficiently with Google OR-Tools | |
| - **π― Scenario Analysis**: Perform what-if analysis for strategic planning | |
| ### π οΈ Technology Stack | |
| - **ML/AI**: Prophet, XGBoost, OR-Tools, CVXPY | |
| - **Backend**: FastAPI, PostgreSQL, Redis | |
| - **Frontend**: Streamlit, Plotly | |
| ### π Getting Started | |
| Use the sidebar to explore different modules and see SmartChain AI in action! | |
| --- | |
| """) | |
| # Quick stats | |
| col1, col2, col3, col4 = st.columns(4) | |
| with col1: | |
| st.metric("Products", "1,000", "+10%") | |
| with col2: | |
| st.metric("Warehouses", "5", "0%") | |
| with col3: | |
| st.metric("Daily Orders", "2,500", "+15%") | |
| with col4: | |
| st.metric("Delivery Locations", "500", "+5%") | |
| st.markdown("---") | |
| st.info("βΉοΈ **Demo Mode**: This is a demonstration version with synthetic data. The full version includes backend API integration.") | |
| # Demand Forecasting Page | |
| elif page == "π Demand Forecasting": | |
| st.title("π Demand Forecasting") | |
| st.markdown("Generate AI-powered demand forecasts using Prophet, XGBoost, or Hybrid models.") | |
| # Sidebar controls | |
| st.sidebar.header("Forecast Configuration") | |
| product_id = st.sidebar.number_input("Product ID", min_value=1, max_value=1000, value=1) | |
| horizon_days = st.sidebar.slider("Forecast Horizon (days)", min_value=7, max_value=90, value=30) | |
| model_type = st.sidebar.selectbox("Model Type", ["Hybrid", "Prophet", "XGBoost"]) | |
| col1, col2 = st.columns([2, 1]) | |
| with col1: | |
| st.subheader("Generate Forecast") | |
| if st.button("π Generate Forecast", type="primary", use_container_width=True): | |
| with st.spinner("Generating forecast..."): | |
| # Generate demo data | |
| forecast_df = generate_forecast_data(horizon_days) | |
| st.success(f"β Forecast generated for Product {product_id} using {model_type} model") | |
| # Create forecast chart | |
| fig = go.Figure() | |
| # Confidence interval | |
| fig.add_trace(go.Scatter( | |
| x=forecast_df['date'], | |
| y=forecast_df['upper_bound'], | |
| fill=None, | |
| mode='lines', | |
| line_color='rgba(37, 99, 235, 0.2)', | |
| showlegend=False, | |
| )) | |
| fig.add_trace(go.Scatter( | |
| x=forecast_df['date'], | |
| y=forecast_df['lower_bound'], | |
| fill='tonexty', | |
| mode='lines', | |
| line_color='rgba(37, 99, 235, 0.2)', | |
| fillcolor='rgba(37, 99, 235, 0.1)', | |
| name='95% Confidence Interval', | |
| )) | |
| # Forecast line | |
| fig.add_trace(go.Scatter( | |
| x=forecast_df['date'], | |
| y=forecast_df['prediction'], | |
| mode='lines+markers', | |
| name='Forecast', | |
| line=dict(color='#2563eb', width=3), | |
| marker=dict(size=6), | |
| )) | |
| fig.update_layout( | |
| title=f'Demand Forecast - Product {product_id}', | |
| xaxis_title='Date', | |
| yaxis_title='Demand (units)', | |
| hovermode='x unified', | |
| template='plotly_white', | |
| height=500, | |
| ) | |
| st.plotly_chart(fig, use_container_width=True) | |
| # Forecast table | |
| st.subheader("π Forecast Data") | |
| st.dataframe( | |
| forecast_df.style.format({ | |
| 'prediction': '{:.2f}', | |
| 'lower_bound': '{:.2f}', | |
| 'upper_bound': '{:.2f}' | |
| }), | |
| use_container_width=True, | |
| height=300, | |
| ) | |
| # Download button | |
| csv = forecast_df.to_csv(index=False) | |
| st.download_button( | |
| "β¬οΈ Download Forecast CSV", | |
| data=csv, | |
| file_name=f"forecast_product_{product_id}.csv", | |
| mime="text/csv", | |
| ) | |
| with col2: | |
| st.subheader("βΉοΈ Model Information") | |
| if model_type == "Hybrid": | |
| st.info(""" | |
| **Hybrid Model** | |
| Combines Prophet and XGBoost: | |
| - Prophet: Captures seasonality | |
| - XGBoost: Learns complex patterns | |
| - Best accuracy for most cases | |
| """) | |
| elif model_type == "Prophet": | |
| st.info(""" | |
| **Prophet Model** | |
| Meta's time-series forecaster: | |
| - Automatic seasonality detection | |
| - Handles holidays | |
| - Robust to missing data | |
| """) | |
| else: | |
| st.info(""" | |
| **XGBoost Model** | |
| Gradient boosting approach: | |
| - Feature-rich predictions | |
| - Captures non-linear patterns | |
| - Fast training and inference | |
| """) | |
| st.metric("Forecast Accuracy (MAPE)", "8.5%", "-1.2%") | |
| st.metric("RΒ² Score", "0.92", "+0.05") | |
| # Inventory Optimization Page | |
| elif page == "π¦ Inventory Optimization": | |
| st.title("π¦ Inventory Optimization") | |
| st.markdown("Optimize inventory policies using EOQ, safety stock, and reorder point calculations.") | |
| # Sidebar controls | |
| st.sidebar.header("Optimization Parameters") | |
| product_id = st.sidebar.number_input("Product ID", min_value=1, max_value=1000, value=1) | |
| service_level = st.sidebar.slider("Service Level", min_value=0.80, max_value=0.99, value=0.95, step=0.01) | |
| holding_cost_rate = st.sidebar.number_input("Holding Cost Rate (%)", min_value=1.0, max_value=50.0, value=20.0) | |
| ordering_cost = st.sidebar.number_input("Ordering Cost ($)", min_value=10, max_value=1000, value=100) | |
| if st.button("π― Optimize Inventory Policy", type="primary", use_container_width=True): | |
| with st.spinner("Optimizing inventory policy..."): | |
| inventory_data = generate_inventory_data() | |
| st.success(f"β Inventory policy optimized for Product {product_id}") | |
| # Metrics | |
| col1, col2, col3 = st.columns(3) | |
| with col1: | |
| st.metric("Economic Order Quantity (EOQ)", f"{inventory_data['eoq']} units") | |
| st.metric("Reorder Point", f"{inventory_data['reorder_point']} units") | |
| with col2: | |
| st.metric("Safety Stock", f"{inventory_data['safety_stock']} units") | |
| st.metric("Service Level", f"{inventory_data['service_level']*100:.1f}%") | |
| with col3: | |
| st.metric("Annual Holding Cost", f"${inventory_data['holding_cost']:,.0f}") | |
| st.metric("Annual Ordering Cost", f"${inventory_data['ordering_cost']:,.0f}") | |
| # Cost breakdown chart | |
| st.subheader("π Cost Analysis") | |
| fig = go.Figure(data=[ | |
| go.Bar( | |
| x=['Holding Cost', 'Ordering Cost', 'Total Cost'], | |
| y=[ | |
| inventory_data['holding_cost'], | |
| inventory_data['ordering_cost'], | |
| inventory_data['total_cost'], | |
| ], | |
| marker_color=['#10b981', '#f59e0b', '#2563eb'], | |
| text=[ | |
| f"${inventory_data['holding_cost']:,.0f}", | |
| f"${inventory_data['ordering_cost']:,.0f}", | |
| f"${inventory_data['total_cost']:,.0f}", | |
| ], | |
| textposition='auto', | |
| ) | |
| ]) | |
| fig.update_layout( | |
| title='Annual Inventory Costs', | |
| yaxis_title='Cost ($)', | |
| template='plotly_white', | |
| height=400, | |
| ) | |
| st.plotly_chart(fig, use_container_width=True) | |
| # Recommendations | |
| st.subheader("π‘ Recommendations") | |
| st.markdown(f""" | |
| - **Order Quantity**: Place orders of **{inventory_data['eoq']} units** each time | |
| - **Reorder Trigger**: Reorder when inventory reaches **{inventory_data['reorder_point']} units** | |
| - **Safety Buffer**: Maintain **{inventory_data['safety_stock']} units** as safety stock | |
| - **Cost Savings**: Optimized policy can save up to **15-20%** on total inventory costs | |
| """) | |
| # Route Optimization Page | |
| elif page == "π Route Optimization": | |
| st.title("π Route Optimization") | |
| st.markdown("Optimize delivery routes using Vehicle Routing Problem (VRP) algorithms.") | |
| # Sidebar controls | |
| st.sidebar.header("Route Configuration") | |
| num_vehicles = st.sidebar.slider("Number of Vehicles", min_value=1, max_value=5, value=2) | |
| vehicle_capacity = st.sidebar.number_input("Vehicle Capacity (kg)", min_value=100, max_value=2000, value=500) | |
| if st.button("πΊοΈ Optimize Routes", type="primary", use_container_width=True): | |
| with st.spinner("Optimizing delivery routes..."): | |
| depot, locations = generate_route_data() | |
| st.success(f"β Routes optimized for {num_vehicles} vehicles") | |
| # Metrics | |
| col1, col2, col3, col4 = st.columns(4) | |
| with col1: | |
| st.metric("Total Distance", "127.5 km") | |
| with col2: | |
| st.metric("Total Time", "3h 45m") | |
| with col3: | |
| st.metric("Cost", "$255") | |
| with col4: | |
| st.metric("Efficiency", "92%", "+8%") | |
| # Map | |
| st.subheader("πΊοΈ Route Visualization") | |
| # Create map figure | |
| fig = go.Figure() | |
| colors = px.colors.qualitative.Plotly | |
| # Split locations into routes for visualization | |
| locations_per_vehicle = len(locations) // num_vehicles | |
| for v in range(num_vehicles): | |
| start_idx = v * locations_per_vehicle | |
| end_idx = start_idx + locations_per_vehicle if v < num_vehicles - 1 else len(locations) | |
| route_locs = locations[start_idx:end_idx] | |
| lats = [depot['lat']] + [loc['lat'] for loc in route_locs] + [depot['lat']] | |
| lons = [depot['lon']] + [loc['lon'] for loc in route_locs] + [depot['lon']] | |
| names = [depot['name']] + [loc['name'] for loc in route_locs] + [depot['name']] | |
| fig.add_trace(go.Scattermapbox( | |
| lat=lats, | |
| lon=lons, | |
| mode='lines+markers', | |
| name=f'Vehicle {v+1}', | |
| marker=dict(size=10, color=colors[v]), | |
| line=dict(width=2, color=colors[v]), | |
| text=names, | |
| )) | |
| # Depot marker | |
| fig.add_trace(go.Scattermapbox( | |
| lat=[depot['lat']], | |
| lon=[depot['lon']], | |
| mode='markers', | |
| name='Depot', | |
| marker=dict(size=20, color='red', symbol='star'), | |
| text=[depot['name']], | |
| )) | |
| fig.update_layout( | |
| mapbox=dict( | |
| style='open-street-map', | |
| center=dict(lat=depot['lat'], lon=depot['lon']), | |
| zoom=10, | |
| ), | |
| height=600, | |
| showlegend=True, | |
| ) | |
| st.plotly_chart(fig, use_container_width=True) | |
| # Route details | |
| st.subheader("π Route Details") | |
| for v in range(num_vehicles): | |
| with st.expander(f"π Vehicle {v+1} Route"): | |
| start_idx = v * locations_per_vehicle | |
| end_idx = start_idx + locations_per_vehicle if v < num_vehicles - 1 else len(locations) | |
| route_locs = locations[start_idx:end_idx] | |
| route_df = pd.DataFrame(route_locs) | |
| st.dataframe(route_df, use_container_width=True) | |
| total_demand = sum(loc['demand'] for loc in route_locs) | |
| st.metric("Total Demand", f"{total_demand} kg") | |
| # Footer | |
| st.sidebar.markdown("---") | |
| st.sidebar.markdown(""" | |
| **Version**: 0.1.0 | |
| **Author**: Alireza Aminzadeh | |
| **License**: Apache 2.0 | |
| [GitHub](https://github.com/syeedalireza) | [HuggingFace](https://huggingface.co/syeedalireza) | |
| """) | |
| st.markdown("---") | |
| st.markdown(""" | |
| <div style='text-align: center'> | |
| <p>Built with β€οΈ using FastAPI + Streamlit + OR-Tools</p> | |
| <p><em>SmartChain AI - Enterprise Supply Chain Optimization Platform</em></p> | |
| </div> | |
| """, unsafe_allow_html=True) | |