import gradio as gr import joblib import numpy as np import matplotlib.pyplot as plt # Load the model - Make sure 'dynamic_pricing_model.pkl' is in the same directory # or provide the full path to your model file. try: model = joblib.load("dynamic_pricing_model.pkl") except FileNotFoundError: print("Error: 'dynamic_pricing_model.pkl' not found. Please ensure the model file is in the correct directory.") print("For demonstration purposes, a dummy model will be used.") # Create a dummy model for demonstration if the actual model is not found class DummyModel: def predict(self, X): # Simple dummy prediction logic demand, stock, expiry, perishable = X[0] base_price = 100.0 price = base_price + (demand * 0.5) - (stock * 0.2) if perishable and expiry > 0: price -= (10 - min(expiry, 10)) * 2 # Price drops as expiry nears return [max(10, price)] # Ensure price is not too low model = DummyModel() # Prediction and chart generation def predict_price_and_plot(forecasted_demand, stock, expiry_days, is_perishable): # Ensure inputs are numerical and handle potential edge cases for model prediction forecasted_demand = max(0, float(forecasted_demand)) stock = max(0, float(stock)) expiry_days = max(0, float(expiry_days)) is_perishable_int = int(bool(is_perishable)) # Convert to 0 or 1 X = np.array([[forecasted_demand, stock, expiry_days, is_perishable_int]]) price = model.predict(X)[0] # Create a modern, beautiful chart plt.style.use('dark_background') fig, ax = plt.subplots(figsize=(10, 6)) # Modern gradient colors colors = ['#667eea', '#764ba2'] # Create bars with modern styling bars = ax.bar(['Forecasted Demand', 'Current Stock'], [forecasted_demand, stock], color=colors, width=0.6, alpha=0.8, edgecolor='white', linewidth=2) # Modern title and labels ax.set_title("📊 Demand vs Stock Analysis", fontsize=20, fontweight='bold', color='white', pad=20) ax.set_ylabel("Quantity", fontsize=14, color='white') # Style the axes ax.tick_params(axis='both', colors='white', labelsize=12) ax.set_facecolor('#1a1a2e') fig.patch.set_facecolor('#1a1a2e') # Remove top and right spines ax.spines['top'].set_visible(False) ax.spines['right'].set_visible(False) ax.spines['left'].set_color('white') ax.spines['bottom'].set_color('white') # Add subtle grid ax.grid(axis='y', alpha=0.3, linestyle='--', color='gray') # Add value labels on bars for bar in bars: height = bar.get_height() ax.text(bar.get_x() + bar.get_width()/2., height + height*0.01, f'{int(height)}', ha='center', va='bottom', fontsize=14, fontweight='bold', color='white') plt.tight_layout() return f"₹{round(price, 2)}", fig # Custom CSS for modern, responsive design css = """ /* Import modern fonts */ @import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap'); /* Root variables for consistent theming */ :root { --primary-color: #667eea; --secondary-color: #764ba2; --accent-color: #f093fb; --background-dark: #0f0f23; --background-card: #1a1a2e; --text-primary: #ffffff; --text-secondary: #a0a0a0; --border-color: #333366; --success-color: #4ade80; --warning-color: #f59e0b; } /* Global styles */ * { box-sizing: border-box; } body { font-family: 'Inter', sans-serif !important; background: linear-gradient(135deg, var(--background-dark) 0%, #16213e 100%) !important; color: var(--text-primary) !important; margin: 0; padding: 0; } /* Main container */ .gradio-container { max-width: 1400px !important; margin: 0 auto !important; padding: 20px !important; background: transparent !important; } /* Header styling */ .header-section { background: linear-gradient(135deg, var(--primary-color) 0%, var(--secondary-color) 100%); border-radius: 20px; padding: 40px 20px; text-align: center; margin-bottom: 30px; box-shadow: 0 20px 40px rgba(0, 0, 0, 0.3); position: relative; overflow: hidden; } .header-section::before { content: ''; position: absolute; top: 0; left: 0; right: 0; bottom: 0; background: linear-gradient(45deg, rgba(255,255,255,0.1) 0%, transparent 100%); pointer-events: none; } .header-title { font-size: clamp(2rem, 5vw, 3.5rem) !important; font-weight: 700 !important; margin-bottom: 15px !important; text-shadow: 2px 2px 10px rgba(0,0,0,0.3); color: white !important; } .header-subtitle { font-size: clamp(1rem, 2.5vw, 1.3rem) !important; opacity: 0.9; max-width: 600px; margin: 0 auto; line-height: 1.6; color: rgba(255,255,255,0.95) !important; } /* Card styling */ .input-card, .output-card { background: var(--background-card) !important; border-radius: 20px !important; padding: 30px !important; box-shadow: 0 15px 35px rgba(0, 0, 0, 0.2) !important; border: 1px solid var(--border-color) !important; backdrop-filter: blur(10px); margin-bottom: 20px; } /* Section headers */ .section-header { font-size: 1.5rem !important; font-weight: 600 !important; color: var(--primary-color) !important; margin-bottom: 25px !important; text-align: center; position: relative; } .section-header::after { content: ''; position: absolute; bottom: -8px; left: 50%; transform: translateX(-50%); width: 50px; height: 3px; background: linear-gradient(90deg, var(--primary-color), var(--secondary-color)); border-radius: 2px; } /* Input styling */ .gr-textbox, .gr-number { margin-bottom: 20px !important; } .gr-textbox label, .gr-number label, .gr-checkbox label { font-weight: 500 !important; color: var(--text-primary) !important; font-size: 1rem !important; margin-bottom: 8px !important; } .gr-textbox input, .gr-number input { background: rgba(255,255,255,0.05) !important; border: 2px solid var(--border-color) !important; border-radius: 12px !important; padding: 12px 16px !important; color: var(--text-primary) !important; font-size: 1rem !important; transition: all 0.3s ease !important; } .gr-textbox input:focus, .gr-number input:focus { border-color: var(--primary-color) !important; box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1) !important; outline: none !important; } /* Checkbox styling */ .gr-checkbox { margin: 20px 0 !important; } .gr-checkbox input[type="checkbox"] { width: 20px !important; height: 20px !important; margin-right: 12px !important; accent-color: var(--primary-color) !important; } /* Button styling */ .gr-button { background: linear-gradient(135deg, var(--primary-color) 0%, var(--secondary-color) 100%) !important; border: none !important; border-radius: 12px !important; padding: 16px 32px !important; font-size: 1.1rem !important; font-weight: 600 !important; color: white !important; cursor: pointer !important; transition: all 0.3s ease !important; box-shadow: 0 8px 25px rgba(102, 126, 234, 0.3) !important; width: 100% !important; margin-top: 10px !important; } .gr-button:hover { transform: translateY(-2px) !important; box-shadow: 0 12px 35px rgba(102, 126, 234, 0.4) !important; } .gr-button:active { transform: translateY(0) !important; } /* Price output styling */ .price-output { background: linear-gradient(135deg, var(--success-color) 0%, #22c55e 100%) !important; border-radius: 16px !important; padding: 20px !important; text-align: center !important; margin-bottom: 20px !important; box-shadow: 0 10px 30px rgba(74, 222, 128, 0.2) !important; } .price-output textarea { background: transparent !important; border: none !important; font-size: 2.5rem !important; font-weight: 700 !important; color: white !important; text-align: center !important; resize: none !important; outline: none !important; } /* Chart container */ .gr-plot { border-radius: 16px !important; overflow: hidden !important; box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2) !important; } /* Responsive design */ @media (max-width: 1024px) { .gradio-container { padding: 15px !important; } .input-card, .output-card { padding: 25px !important; } } @media (max-width: 768px) { .gradio-container { padding: 10px !important; } .header-section { padding: 30px 15px !important; margin-bottom: 20px !important; } .input-card, .output-card { padding: 20px !important; margin-bottom: 15px !important; } .gr-row { flex-direction: column !important; } .gr-column { width: 100% !important; margin-bottom: 20px !important; } } @media (max-width: 480px) { .header-section { padding: 25px 10px !important; } .input-card, .output-card { padding: 15px !important; } .gr-button { padding: 14px 24px !important; font-size: 1rem !important; } .price-output textarea { font-size: 2rem !important; } } /* Loading states */ .gr-button:disabled { opacity: 0.6 !important; cursor: not-allowed !important; } /* Animations */ @keyframes fadeIn { from { opacity: 0; transform: translateY(20px); } to { opacity: 1; transform: translateY(0); } } .input-card, .output-card { animation: fadeIn 0.6s ease forwards; } /* Custom scrollbar */ ::-webkit-scrollbar { width: 8px; } ::-webkit-scrollbar-track { background: var(--background-dark); } ::-webkit-scrollbar-thumb { background: var(--primary-color); border-radius: 4px; } ::-webkit-scrollbar-thumb:hover { background: var(--secondary-color); } """ # Create the Gradio interface with gr.Blocks( title="Dynamic Pricing Engine", css=css, theme=gr.themes.Base( primary_hue="blue", secondary_hue="purple", neutral_hue="slate" ) ) as demo: # Header gr.HTML("""

💰 Dynamic Pricing Engine

Harness the power of AI to optimize your product pricing in real-time. Get intelligent price predictions based on demand forecasts, inventory levels, and product characteristics.

""") # Main content with gr.Row(): with gr.Column(scale=1, elem_classes="input-section"): with gr.Group(elem_classes="input-card"): gr.HTML('

📊 Product Information

') forecasted_demand = gr.Number( label="📈 Forecasted Demand (Units)", value=50, minimum=0, info="Expected demand for the product" ) stock = gr.Number( label="📦 Current Stock Level (Units)", value=100, minimum=0, info="Available inventory quantity" ) expiry_days = gr.Number( label="⏰ Days Until Expiry", value=10, minimum=0, info="Set to 0 for non-perishable products" ) is_perishable = gr.Checkbox( label="🍎 Perishable Product", value=True, info="Check if product has expiration date" ) submit_btn = gr.Button( "🚀 Calculate Optimal Price", variant="primary", size="lg" ) with gr.Column(scale=1, elem_classes="output-section"): with gr.Group(elem_classes="output-card"): gr.HTML('

💡 Pricing Insights

') price_output = gr.Textbox( label="💰 Recommended Price (₹)", placeholder="Click 'Calculate Optimal Price' to see prediction...", interactive=False, elem_classes="price-output" ) chart_output = gr.Plot( label="📊 Market Analysis", show_label=True ) # Event handlers submit_btn.click( fn=predict_price_and_plot, inputs=[forecasted_demand, stock, expiry_days, is_perishable], outputs=[price_output, chart_output] ) # Auto-calculate on input change (optional) for input_component in [forecasted_demand, stock, expiry_days, is_perishable]: input_component.change( fn=predict_price_and_plot, inputs=[forecasted_demand, stock, expiry_days, is_perishable], outputs=[price_output, chart_output] ) if __name__ == "__main__": demo.launch(share=True)