Spaces:
Sleeping
Sleeping
| import streamlit as st | |
| import pandas as pd | |
| import numpy as np | |
| import plotly.express as px | |
| import plotly.graph_objects as go | |
| from plotly.subplots import make_subplots | |
| import json | |
| import time | |
| from datetime import datetime | |
| # Import from your fixed procurement agent file | |
| from agentic_sourcing_ppo_sap_colab import ( | |
| suppliers_synthetic, market_signal, rl_recommend_tool, | |
| sap_create_po_mock, check_model_tool | |
| ) | |
| # Page config | |
| st.set_page_config( | |
| page_title="π€ AI Procurement Agent Demo", | |
| page_icon="π€", | |
| layout="wide", | |
| initial_sidebar_state="expanded" | |
| ) | |
| # Custom CSS | |
| st.markdown(""" | |
| <style> | |
| .main-header { | |
| font-size: 3rem; | |
| font-weight: bold; | |
| color: #2E86AB; | |
| text-align: center; | |
| margin-bottom: 2rem; | |
| } | |
| .sub-header { | |
| font-size: 1.5rem; | |
| color: #F24236; | |
| margin-bottom: 1rem; | |
| } | |
| .metric-container { | |
| background: linear-gradient(90deg, #667eea 0%, #764ba2 100%); | |
| padding: 1rem; | |
| border-radius: 10px; | |
| margin: 0.5rem 0; | |
| } | |
| .success-box { | |
| background: #d4edda; | |
| border: 1px solid #c3e6cb; | |
| padding: 1rem; | |
| border-radius: 5px; | |
| margin: 1rem 0; | |
| } | |
| </style> | |
| """, unsafe_allow_html=True) | |
| def create_allocation_pie_chart(allocations): | |
| """Create pie chart for supplier allocations""" | |
| df = pd.DataFrame(allocations) | |
| df = df[df['share'] > 0.01] # Filter out very small allocations | |
| fig = px.pie(df, values='share', names='supplier', | |
| title="Supplier Allocation Distribution", | |
| color_discrete_sequence=px.colors.qualitative.Set3) | |
| fig.update_traces(textposition='inside', textinfo='percent+label') | |
| fig.update_layout(height=400) | |
| return fig | |
| def create_supplier_comparison_chart(suppliers_data): | |
| """Create radar chart comparing suppliers""" | |
| df = pd.DataFrame(suppliers_data) | |
| # Select top 5 suppliers by quality score | |
| df['combined_score'] = df['current_quality'] * 0.4 + df['current_delivery'] * 0.3 + (1-df['financial_risk']) * 0.3 | |
| top_suppliers = df.nlargest(5, 'combined_score') | |
| categories = ['Quality', 'Delivery', 'ESG Score', 'Low Risk', 'Cost Efficiency'] | |
| fig = go.Figure() | |
| for _, supplier in top_suppliers.iterrows(): | |
| values = [ | |
| supplier['current_quality'], | |
| supplier['current_delivery'], | |
| supplier['esg'], | |
| 1 - supplier['financial_risk'], # Invert risk for better visualization | |
| 1 - (supplier['base_cost_per_unit'] / 150) # Normalize cost | |
| ] | |
| fig.add_trace(go.Scatterpolar( | |
| r=values, | |
| theta=categories, | |
| fill='toself', | |
| name=supplier['name'], | |
| opacity=0.7 | |
| )) | |
| fig.update_layout( | |
| polar=dict( | |
| radialaxis=dict(visible=True, range=[0, 1]) | |
| ), | |
| showlegend=True, | |
| title="Top 5 Suppliers Comparison", | |
| height=500 | |
| ) | |
| return fig | |
| def main(): | |
| # Header | |
| st.markdown('<div class="main-header">π€ AI Procurement Agent Demo</div>', unsafe_allow_html=True) | |
| st.markdown("### Intelligent Supplier Selection using Reinforcement Learning") | |
| # Create columns for better layout | |
| col1, col2 = st.columns([1, 2]) | |
| with col1: | |
| st.markdown('<div class="sub-header">ποΈ Control Panel</div>', unsafe_allow_html=True) | |
| # Market Parameters | |
| st.subheader("Market Conditions") | |
| volatility = st.selectbox( | |
| "Market Volatility", | |
| ["low", "medium", "high"], | |
| index=1, | |
| help="Current market volatility level" | |
| ) | |
| demand_mult = st.slider( | |
| "Demand Multiplier", | |
| min_value=0.7, | |
| max_value=1.5, | |
| value=1.0, | |
| step=0.05, | |
| help="Demand change from baseline" | |
| ) | |
| price_mult = st.slider( | |
| "Price Multiplier", | |
| min_value=0.8, | |
| max_value=1.3, | |
| value=1.0, | |
| step=0.05, | |
| help="Price change from baseline" | |
| ) | |
| baseline_demand = st.number_input( | |
| "Baseline Demand (units)", | |
| min_value=100, | |
| max_value=10000, | |
| value=1000, | |
| step=100 | |
| ) | |
| # Supplier Configuration | |
| st.subheader("Supplier Configuration") | |
| num_suppliers = st.slider( | |
| "Number of Suppliers", | |
| min_value=3, | |
| max_value=10, | |
| value=6, | |
| help="Number of suppliers to consider" | |
| ) | |
| seed = st.number_input( | |
| "Random Seed", | |
| min_value=1, | |
| max_value=1000, | |
| value=123, | |
| help="Seed for reproducible supplier generation" | |
| ) | |
| with col2: | |
| st.markdown('<div class="sub-header">π Real-time Dashboard</div>', unsafe_allow_html=True) | |
| # Action button | |
| if st.button("π Run Procurement Agent", type="primary", use_container_width=True): | |
| # Progress bar | |
| progress_bar = st.progress(0) | |
| status_text = st.empty() | |
| try: | |
| # Step 1: Generate suppliers | |
| status_text.text("Step 1/5: Generating supplier data...") | |
| progress_bar.progress(20) | |
| suppliers_result = suppliers_synthetic(n=num_suppliers, seed=seed) | |
| suppliers_data = suppliers_result["suppliers"] | |
| # Display suppliers table | |
| st.subheader("Generated Suppliers") | |
| df_suppliers = pd.DataFrame(suppliers_data) | |
| st.dataframe(df_suppliers.round(3), use_container_width=True) | |
| # Step 2: Market signals | |
| status_text.text("Step 2/5: Analyzing market conditions...") | |
| progress_bar.progress(40) | |
| market_data = market_signal(volatility, price_mult, demand_mult) | |
| # Display market metrics | |
| col_m1, col_m2, col_m3 = st.columns(3) | |
| with col_m1: | |
| st.metric("Volatility", volatility.upper(), | |
| delta="High Risk" if volatility == "high" else "Normal") | |
| with col_m2: | |
| st.metric("Demand Change", f"{demand_mult:.1%}", | |
| delta=f"{(demand_mult-1)*100:+.1f}%") | |
| with col_m3: | |
| st.metric("Price Change", f"{price_mult:.1%}", | |
| delta=f"{(price_mult-1)*100:+.1f}%") | |
| # Step 3: Check model | |
| status_text.text("Step 3/5: Checking AI model availability...") | |
| progress_bar.progress(60) | |
| model_check = check_model_tool("./supplier_selection_ppo_gymnasium.pkl") | |
| # Step 4: Get recommendations | |
| status_text.text("Step 4/5: Getting AI recommendations...") | |
| progress_bar.progress(80) | |
| recommendation_input = { | |
| "volatility": market_data["volatility"], | |
| "price_multiplier": market_data["price_multiplier"], | |
| "demand_multiplier": market_data["demand_multiplier"], | |
| "baseline_demand": baseline_demand, | |
| "suppliers": suppliers_data, | |
| "auto_align_actions": True | |
| } | |
| recommendations = rl_recommend_tool(recommendation_input) | |
| if recommendations.get("strategy") == "error": | |
| st.error(f"AI recommendation failed: {recommendations.get('error', 'Unknown error')}") | |
| return | |
| # Step 5: Create PO | |
| status_text.text("Step 5/5: Creating purchase order...") | |
| progress_bar.progress(100) | |
| po_data = { | |
| "lines": [ | |
| { | |
| "supplier": alloc["supplier"], | |
| "quantity": round(recommendations["demand_units"] * alloc["share"], 2) | |
| } | |
| for alloc in recommendations["allocations"] | |
| if alloc["share"] > 0.01 | |
| ] | |
| } | |
| po_result = sap_create_po_mock(po_data) | |
| # Clear progress indicators | |
| status_text.text("β Procurement process completed!") | |
| time.sleep(0.5) | |
| progress_bar.empty() | |
| status_text.empty() | |
| # Display results | |
| st.markdown("---") | |
| st.subheader("π― Procurement Results") | |
| # Key metrics | |
| col_r1, col_r2, col_r3, col_r4 = st.columns(4) | |
| with col_r1: | |
| st.metric("Strategy", recommendations["strategy"].title()) | |
| with col_r2: | |
| active_suppliers = len([a for a in recommendations["allocations"] if a["share"] > 0.01]) | |
| st.metric("Active Suppliers", active_suppliers) | |
| with col_r3: | |
| st.metric("Total Units", f"{recommendations['demand_units']:,.0f}") | |
| with col_r4: | |
| st.metric("PO Number", po_result["PurchaseOrder"]) | |
| # Visualizations | |
| col_v1, col_v2 = st.columns(2) | |
| with col_v1: | |
| # Allocation pie chart | |
| fig_pie = create_allocation_pie_chart(recommendations["allocations"]) | |
| st.plotly_chart(fig_pie, use_container_width=True) | |
| with col_v2: | |
| # Supplier comparison radar | |
| fig_radar = create_supplier_comparison_chart(suppliers_data) | |
| st.plotly_chart(fig_radar, use_container_width=True) | |
| # Detailed allocation table | |
| st.subheader("π Detailed Allocation") | |
| allocation_df = pd.DataFrame(recommendations["allocations"]) | |
| allocation_df["quantity"] = allocation_df["share"] * recommendations["demand_units"] | |
| allocation_df["percentage"] = allocation_df["share"] * 100 | |
| # Merge with supplier data for additional context | |
| supplier_df = pd.DataFrame(suppliers_data) | |
| detailed_df = allocation_df.merge( | |
| supplier_df[["name", "base_cost_per_unit", "current_quality", "financial_risk"]], | |
| left_on="supplier", right_on="name" | |
| ) | |
| st.dataframe( | |
| detailed_df[["supplier", "percentage", "quantity", "base_cost_per_unit", "current_quality", "financial_risk"]] | |
| .round(2), | |
| use_container_width=True | |
| ) | |
| # Purchase Order JSON | |
| with st.expander("π View Purchase Order JSON"): | |
| st.json(po_result) | |
| # Success message | |
| st.markdown(f""" | |
| <div class="success-box"> | |
| <strong>β Success!</strong> Purchase Order {po_result["PurchaseOrder"]} has been created successfully! | |
| <br><em>Note: This is a demonstration. No actual SAP system was contacted.</em> | |
| </div> | |
| """, unsafe_allow_html=True) | |
| except Exception as e: | |
| st.error(f"Error during execution: {str(e)}") | |
| st.exception(e) | |
| # Sidebar with information | |
| with st.sidebar: | |
| st.markdown("### About This Demo") | |
| st.info(""" | |
| This demo showcases an AI-powered procurement agent that: | |
| π― **Analyzes** market conditions and supplier data | |
| π€ **Uses** reinforcement learning (PPO) for optimal allocation | |
| π **Generates** purchase orders automatically | |
| π **Integrates** with SAP systems (mocked for demo) | |
| """) | |
| st.markdown("### Key Features") | |
| st.markdown(""" | |
| - **Real-time Analysis**: Dynamic market condition assessment | |
| - **Multi-criteria Optimization**: Quality, cost, delivery, ESG factors | |
| - **Risk Management**: Financial and supply chain risk evaluation | |
| - **Scalable Architecture**: Handles multiple suppliers efficiently | |
| """) | |
| st.markdown("### Technology Stack") | |
| st.markdown(""" | |
| - **RL Framework**: Stable-Baselines3 PPO | |
| - **Agent Framework**: SmolagentS | |
| - **Backend**: Python, NumPy, Pandas | |
| - **Frontend**: Streamlit, Plotly | |
| """) | |
| if __name__ == "__main__": | |
| main() | |