AdityaRatan commited on
Commit
d14a34d
Β·
verified Β·
1 Parent(s): 0cb8324

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +149 -276
app.py CHANGED
@@ -13,29 +13,31 @@ import os
13
  from datetime import datetime
14
  from dotenv import load_dotenv
15
 
 
16
  # Load environment variables
17
  load_dotenv()
18
 
19
  # Configure Gemini API
20
  GEMINI_API_KEY = os.getenv("gemini_api")
 
 
 
21
  genai.configure(api_key=GEMINI_API_KEY)
22
  generation_config = {
23
- "temperature": 1,
24
- "top_p": 0.95,
25
- "top_k": 64,
26
- "max_output_tokens": 8192,
27
- "response_mime_type": "text/plain",
28
  }
29
 
30
  model = genai.GenerativeModel(
31
- model_name="gemini-2.0-pro-exp-02-05",
32
- generation_config=generation_config,
33
  )
34
 
35
- chat_model = genai.GenerativeModel('"gemini-2.0-pro-exp-02-05"')
36
 
37
-
38
- # Enhanced CSS for better header styling
39
  CUSTOM_CSS = '''
40
  .gradio-container {
41
  max-width: 1200px !important;
@@ -141,7 +143,6 @@ CUSTOM_CSS = '''
141
  color: #ffffff !important;
142
  }
143
 
144
- /* Form elements */
145
  input, select, textarea {
146
  background: #363636 !important;
147
  color: #ffffff !important;
@@ -153,7 +154,6 @@ input:focus, select:focus, textarea:focus {
153
  box-shadow: 0 0 0 2px rgba(52, 152, 219, 0.2) !important;
154
  }
155
 
156
- /* Buttons */
157
  .action-button {
158
  background: #3498DB !important;
159
  color: white !important;
@@ -170,7 +170,6 @@ input:focus, select:focus, textarea:focus {
170
  box-shadow: 0 4px 8px rgba(0,0,0,0.2) !important;
171
  }
172
 
173
- /* Footer */
174
  .footer {
175
  text-align: center !important;
176
  padding: 20px !important;
@@ -178,129 +177,7 @@ input:focus, select:focus, textarea:focus {
178
  border-top: 1px solid #404040 !important;
179
  color: #888888 !important;
180
  }
181
- '''
182
-
183
- def create_interface():
184
- """Create Gradio interface with enhanced UI"""
185
- state = SupplyChainState()
186
-
187
- with gr.Blocks(css=CUSTOM_CSS, title="SupplyChainAI Navigator by Aditya Ratan") as demo:
188
- # Enhanced Header
189
- with gr.Row(elem_classes="main-header"):
190
- with gr.Column():
191
- gr.Markdown("# 🚒 SupplyChainAI Navigator", elem_classes="app-title")
192
- gr.Markdown("### Intelligent Supply Chain Analysis & Optimization", elem_classes="app-subtitle")
193
- gr.Markdown("An AI-powered platform for comprehensive supply chain analytics", elem_classes="app-description")
194
- gr.Markdown("Created by Aditya Ratan", elem_classes="creator-info")
195
-
196
- .creator-info {
197
- color: #3498DB !important;
198
- font-size: 1.2em !important;
199
- text-align: right !important;
200
- margin-top: 10px !important;
201
- font-style: italic !important;
202
- }
203
-
204
- .footer {
205
- text-align: center !important;
206
- padding: 20px !important;
207
- margin-top: 40px !important;
208
- border-top: 1px solid #404040 !important;
209
- color: #888888 !important;
210
- }
211
-
212
- [... rest of the CSS remains the same ...]"""
213
-
214
- def create_interface():
215
- """Create Gradio interface with enhanced UI"""
216
- state = SupplyChainState()
217
-
218
- with gr.Blocks(css=CUSTOM_CSS, title="SupplyChainAI Navigator") as demo:
219
- # Header
220
- with gr.Row(elem_classes="main-header"):
221
- gr.Markdown("""
222
- # 🚒 SupplyChainAI Navigator
223
- ### Intelligent Supply Chain Analysis & Optimization
224
- An AI-powered platform for comprehensive supply chain analytics
225
- """)
226
- gr.Markdown("### Created by Aditya Ratan", elem_classes="creator-info")
227
-
228
- # Rest of the interface components remain the same...
229
-
230
- # Add footer
231
- with gr.Row(elem_classes="footer"):
232
- gr.Markdown("Designed and Developed by Aditya Ratan | Β© 2025")
233
-
234
- .tab-content {
235
- background: #2d2d2d !important;
236
- padding: 20px !important;
237
- border-radius: 10px !important;
238
- box-shadow: 0 2px 4px rgba(0,0,0,0.2) !important;
239
- color: #ffffff !important;
240
- }
241
-
242
- .action-button {
243
- background: #3498DB !important;
244
- color: white !important;
245
- border: none !important;
246
- padding: 10px 20px !important;
247
- border-radius: 5px !important;
248
- cursor: pointer !important;
249
- transition: all 0.3s ease !important;
250
- }
251
-
252
- .action-button:hover {
253
- background: #2980B9 !important;
254
- transform: translateY(-2px) !important;
255
- box-shadow: 0 4px 8px rgba(0,0,0,0.2) !important;
256
- }
257
-
258
- .status-box {
259
- background: #363636 !important;
260
- border-left: 4px solid #3498DB !important;
261
- padding: 15px !important;
262
- margin: 10px 0 !important;
263
- border-radius: 0 5px 5px 0 !important;
264
- color: #ffffff !important;
265
- }
266
-
267
- .chart-container {
268
- background: #2d2d2d !important;
269
- padding: 20px !important;
270
- border-radius: 10px !important;
271
- box-shadow: 0 2px 4px rgba(0,0,0,0.2) !important;
272
- color: #ffffff !important;
273
- }
274
-
275
- .chat-container {
276
- height: 400px !important;
277
- overflow-y: auto !important;
278
- border: 1px solid #404040 !important;
279
- border-radius: 10px !important;
280
- padding: 15px !important;
281
- background: #2d2d2d !important;
282
- color: #ffffff !important;
283
- }
284
-
285
- .file-upload {
286
- border: 2px dashed #404040 !important;
287
- border-radius: 10px !important;
288
- padding: 20px !important;
289
- text-align: center !important;
290
- background: #2d2d2d !important;
291
- color: #ffffff !important;
292
- }
293
-
294
- .result-box {
295
- background: #363636 !important;
296
- border: 1px solid #404040 !important;
297
- border-radius: 10px !important;
298
- padding: 20px !important;
299
- margin-top: 15px !important;
300
- color: #ffffff !important;
301
- }
302
 
303
- /* Additional dark mode styles */
304
  .tabs {
305
  background: #2d2d2d !important;
306
  border-radius: 10px !important;
@@ -312,21 +189,6 @@ def create_interface():
312
  color: white !important;
313
  }
314
 
315
- input, select, textarea {
316
- background: #363636 !important;
317
- color: #ffffff !important;
318
- border: 1px solid #404040 !important;
319
- }
320
-
321
- input:focus, select:focus, textarea:focus {
322
- border-color: #3498DB !important;
323
- box-shadow: 0 0 0 2px rgba(52, 152, 219, 0.2) !important;
324
- }
325
-
326
- .label-text {
327
- color: #ffffff !important;
328
- }
329
-
330
  .gr-box {
331
  background: #2d2d2d !important;
332
  border: 1px solid #404040 !important;
@@ -354,7 +216,7 @@ input:focus, select:focus, textarea:focus {
354
  background: #404040 !important;
355
  color: white !important;
356
  }
357
- """
358
 
359
  class SupplyChainState:
360
  def __init__(self):
@@ -369,36 +231,10 @@ class SupplyChainState:
369
  self.model_path = "optimized_xgboost_model.pkl"
370
  try:
371
  self.freight_model = joblib.load(self.model_path)
372
- except:
373
- print(f"Warning: Could not load freight prediction model from {self.model_path}")
374
  self.freight_model = None
375
 
376
- def predict_freight_cost(state, weight, line_item_value, cost_per_kg,
377
- shipment_mode, air_charter_weight, ocean_weight, truck_weight,
378
- air_charter_value, ocean_value, truck_value):
379
- """Predict freight cost using the loaded model"""
380
- if state.freight_model is None:
381
- return "Error: Freight prediction model not loaded"
382
-
383
- features = {
384
- 'weight (kilograms)': weight,
385
- 'line item value': line_item_value,
386
- 'cost per kilogram': cost_per_kg,
387
- 'shipment mode_Air Charter_weight': air_charter_weight if shipment_mode == "Air" else 0,
388
- 'shipment mode_Ocean_weight': ocean_weight if shipment_mode == "Ocean" else 0,
389
- 'shipment mode_Truck_weight': truck_weight if shipment_mode == "Truck" else 0,
390
- 'shipment mode_Air Charter_line_item_value': air_charter_value if shipment_mode == "Air" else 0,
391
- 'shipment mode_Ocean_line_item_value': ocean_value if shipment_mode == "Ocean" else 0,
392
- 'shipment mode_Truck_line_item_value': truck_value if shipment_mode == "Truck" else 0
393
- }
394
- input_data = pd.DataFrame([features])
395
-
396
- try:
397
- prediction = state.freight_model.predict(input_data)
398
- return round(float(prediction[0]), 2)
399
- except Exception as e:
400
- return f"Error making prediction: {str(e)}"
401
-
402
  def process_uploaded_data(state, sales_file, supplier_file, text_data):
403
  """Process uploaded files and store in state"""
404
  try:
@@ -433,14 +269,17 @@ def perform_demand_forecasting(state):
433
  response = model.generate_content(prompt)
434
  analysis_text = response.text
435
 
436
- # Create an enhanced visualization
437
  fig = px.line(state.sales_df, title='Historical Sales Data and Forecast')
438
  fig.update_layout(
439
- template='plotly_white',
440
  title_x=0.5,
441
  title_font_size=20,
442
  showlegend=True,
443
- hovermode='x'
 
 
 
444
  )
445
 
446
  return analysis_text, fig, "βœ… Analysis completed successfully"
@@ -470,14 +309,17 @@ def perform_risk_assessment(state):
470
  response = model.generate_content(prompt)
471
  analysis_text = response.text
472
 
473
- # Create an enhanced risk visualization
474
  fig = px.scatter(state.supplier_df, title='Supplier Risk Assessment')
475
  fig.update_layout(
476
- template='plotly_white',
477
  title_x=0.5,
478
  title_font_size=20,
479
  showlegend=True,
480
- hovermode='closest'
 
 
 
481
  )
482
 
483
  return analysis_text, fig, "βœ… Risk assessment completed"
@@ -526,6 +368,32 @@ def chat_with_navigator(state, message):
526
  except Exception as e:
527
  return [(msg_type, msg) for msg_type, msg in state.chat_history] + [("assistant", f"Error: {str(e)}")]
528
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
529
  def generate_pdf_report(state, analysis_options):
530
  """Generate PDF report with analysis results"""
531
  try:
@@ -545,39 +413,42 @@ def generate_pdf_report(state, analysis_options):
545
  textColor=colors.HexColor('#2C3E50')
546
  )
547
 
548
- # Add company logo if available
549
- # story.append(Image("logo.png", width=100, height=50))
550
-
551
  story.append(Paragraph("SupplyChainAI Navigator Report", title_style))
552
  story.append(Spacer(1, 12))
553
 
 
 
 
 
 
554
  # Add executive summary
555
  story.append(Paragraph("Executive Summary", styles['Heading2']))
556
- summary_text = "This report provides a comprehensive analysis of supply chain data..."
557
  story.append(Paragraph(summary_text, styles['Normal']))
558
  story.append(Spacer(1, 20))
559
 
560
- # Analysis results
561
- for analysis_type, results in state.analysis_results.items():
562
- if analysis_type in analysis_options:
563
- story.append(Paragraph(analysis_type, styles['Heading2']))
564
- story.append(Spacer(1, 12))
565
- story.append(Paragraph(results['text'], styles['Normal']))
566
- story.append(Spacer(1, 12))
567
-
568
- if results.get('figure'):
569
- img_path = os.path.join(temp_dir, f"{analysis_type.lower()}_plot.png")
570
- results['figure'].write_image(img_path)
571
- story.append(Image(img_path))
572
-
573
- story.append(Spacer(1, 20))
574
-
575
- # Recent freight predictions
 
576
  if state.freight_predictions:
577
  story.append(Paragraph("Recent Freight Cost Predictions", styles['Heading2']))
578
  story.append(Spacer(1, 12))
579
 
580
- # Create a table for predictions
581
  pred_data = [["Prediction #", "Cost (USD)"]]
582
  for i, pred in enumerate(state.freight_predictions[-5:], 1):
583
  pred_data.append([f"Prediction {i}", f"${pred:,.2f}"])
@@ -599,14 +470,6 @@ def generate_pdf_report(state, analysis_options):
599
  story.append(table)
600
  story.append(Spacer(1, 20))
601
 
602
- # Chat history
603
- if state.chat_history:
604
- story.append(Paragraph("Recent Chat Interactions", styles['Heading2']))
605
- story.append(Spacer(1, 12))
606
- for msg_type, msg in state.chat_history[-10:]:
607
- story.append(Paragraph(f"{msg_type.title()}: {msg}", styles['Normal']))
608
- story.append(Spacer(1, 6))
609
-
610
  # Build PDF
611
  doc.build(story)
612
  return pdf_path
@@ -614,6 +477,48 @@ def generate_pdf_report(state, analysis_options):
614
  print(f"Error generating PDF: {str(e)}")
615
  return None
616
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
617
  def create_interface():
618
  """Create Gradio interface with enhanced UI"""
619
  state = SupplyChainState()
@@ -621,22 +526,16 @@ def create_interface():
621
  with gr.Blocks(css=CUSTOM_CSS, title="SupplyChainAI Navigator") as demo:
622
  # Header
623
  with gr.Row(elem_classes="main-header"):
624
- gr.Markdown("""
625
- # 🚒 SupplyChainAI Navigator
626
- ### Intelligent Supply Chain Analysis & Optimization
627
- An AI-powered platform for comprehensive supply chain analytics
628
- """)
629
 
630
  # Main Content Tabs
631
  with gr.Tabs() as tabs:
632
  # Data Upload Tab
633
  with gr.Tab("πŸ“Š Data Upload", elem_classes="tab-content"):
634
- with gr.Row():
635
- gr.Markdown("""
636
- ### Upload Your Supply Chain Data
637
- Start by uploading your data files and providing additional context.
638
- """)
639
-
640
  with gr.Row():
641
  with gr.Column(scale=1):
642
  sales_data_upload = gr.File(
@@ -668,18 +567,12 @@ def create_interface():
668
  elem_classes="action-button"
669
  )
670
 
671
- # Analysis Selection Tab
672
  with gr.Tab("πŸ” Analysis", elem_classes="tab-content"):
673
- with gr.Row():
674
- gr.Markdown("### Select Analysis Types")
675
-
676
  analysis_options = gr.CheckboxGroup(
677
  choices=[
678
  "πŸ“ˆ Demand Forecasting",
679
- "⚠️ Risk Assessment",
680
- "πŸ“¦ Inventory Optimization",
681
- "🀝 Supplier Performance",
682
- "🌿 Sustainability Analysis"
683
  ],
684
  label="Choose analyses to perform"
685
  )
@@ -689,9 +582,7 @@ def create_interface():
689
  variant="primary",
690
  elem_classes="action-button"
691
  )
692
-
693
- # Results Tab
694
- with gr.Tab("πŸ“Š Results", elem_classes="tab-content"):
695
  with gr.Row():
696
  with gr.Column(scale=2):
697
  analysis_output = gr.Textbox(
@@ -711,12 +602,6 @@ def create_interface():
711
 
712
  # Freight Cost Prediction Tab
713
  with gr.Tab("πŸ’° Cost Prediction", elem_classes="tab-content"):
714
- with gr.Row():
715
- gr.Markdown("""
716
- ### 🚒 Freight Cost Prediction
717
- Estimate shipping costs based on your parameters
718
- """)
719
-
720
  with gr.Row():
721
  shipment_mode = gr.Dropdown(
722
  choices=["✈️ Air", "🚒 Ocean", "πŸš› Truck"],
@@ -750,53 +635,41 @@ def create_interface():
750
  value=50
751
  )
752
 
753
- # Mode-specific values
754
  with gr.Row(visible=False) as air_inputs:
755
  air_charter_weight = gr.Slider(
756
  label="Air Charter Weight",
757
  minimum=0,
758
- maximum=10000,
759
- step=1,
760
- value=0
761
  )
762
  air_charter_value = gr.Slider(
763
  label="Air Charter Value",
764
  minimum=0,
765
- maximum=1000000,
766
- step=1,
767
- value=0
768
  )
769
 
770
  with gr.Row(visible=False) as ocean_inputs:
771
  ocean_weight = gr.Slider(
772
  label="Ocean Weight",
773
  minimum=0,
774
- maximum=10000,
775
- step=1,
776
- value=0
777
  )
778
  ocean_value = gr.Slider(
779
  label="Ocean Value",
780
  minimum=0,
781
- maximum=1000000,
782
- step=1,
783
- value=0
784
  )
785
 
786
  with gr.Row(visible=False) as truck_inputs:
787
  truck_weight = gr.Slider(
788
  label="Truck Weight",
789
  minimum=0,
790
- maximum=10000,
791
- step=1,
792
- value=0
793
  )
794
  truck_value = gr.Slider(
795
  label="Truck Value",
796
  minimum=0,
797
- maximum=1000000,
798
- step=1,
799
- value=0
800
  )
801
 
802
  with gr.Row():
@@ -832,20 +705,18 @@ def create_interface():
832
 
833
  # Report Tab
834
  with gr.Tab("πŸ“‘ Report", elem_classes="tab-content"):
835
- gr.Markdown("""
836
- ### Generate Comprehensive Report
837
- Create a detailed PDF report including all analyses and insights.
838
- """)
839
-
840
- with gr.Row():
841
- report_button = gr.Button(
842
- "πŸ“„ Generate Report",
843
- variant="primary",
844
- elem_classes="action-button"
845
- )
846
- report_download = gr.File(
847
- label="Download Report"
848
- )
849
 
850
  # Event Handlers
851
  def update_mode_inputs(mode):
@@ -863,7 +734,7 @@ def create_interface():
863
  )
864
 
865
  analyze_button.click(
866
- fn=lambda choices, sales, supplier, text: run_analyses(state, choices, sales, supplier, text),
867
  inputs=[analysis_options, sales_data_upload, supplier_data_upload, text_input_area],
868
  outputs=[analysis_output, plot_output, raw_output]
869
  )
@@ -907,3 +778,5 @@ if __name__ == "__main__":
907
  share=True,
908
  debug=True
909
  )
 
 
 
13
  from datetime import datetime
14
  from dotenv import load_dotenv
15
 
16
+
17
  # Load environment variables
18
  load_dotenv()
19
 
20
  # Configure Gemini API
21
  GEMINI_API_KEY = os.getenv("gemini_api")
22
+ if not GEMINI_API_KEY:
23
+ raise ValueError("GEMINI_API_KEY environment variable not found")
24
+
25
  genai.configure(api_key=GEMINI_API_KEY)
26
  generation_config = {
27
+ "temperature": 1,
28
+ "top_p": 0.95,
29
+ "top_k": 64,
30
+ "max_output_tokens": 8192,
 
31
  }
32
 
33
  model = genai.GenerativeModel(
34
+ model_name="gemini-pro",
35
+ generation_config=generation_config,
36
  )
37
 
38
+ chat_model = genai.GenerativeModel("gemini-pro")
39
 
40
+ # Enhanced CSS for better styling
 
41
  CUSTOM_CSS = '''
42
  .gradio-container {
43
  max-width: 1200px !important;
 
143
  color: #ffffff !important;
144
  }
145
 
 
146
  input, select, textarea {
147
  background: #363636 !important;
148
  color: #ffffff !important;
 
154
  box-shadow: 0 0 0 2px rgba(52, 152, 219, 0.2) !important;
155
  }
156
 
 
157
  .action-button {
158
  background: #3498DB !important;
159
  color: white !important;
 
170
  box-shadow: 0 4px 8px rgba(0,0,0,0.2) !important;
171
  }
172
 
 
173
  .footer {
174
  text-align: center !important;
175
  padding: 20px !important;
 
177
  border-top: 1px solid #404040 !important;
178
  color: #888888 !important;
179
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
180
 
 
181
  .tabs {
182
  background: #2d2d2d !important;
183
  border-radius: 10px !important;
 
189
  color: white !important;
190
  }
191
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
192
  .gr-box {
193
  background: #2d2d2d !important;
194
  border: 1px solid #404040 !important;
 
216
  background: #404040 !important;
217
  color: white !important;
218
  }
219
+ '''
220
 
221
  class SupplyChainState:
222
  def __init__(self):
 
231
  self.model_path = "optimized_xgboost_model.pkl"
232
  try:
233
  self.freight_model = joblib.load(self.model_path)
234
+ except Exception as e:
235
+ print(f"Warning: Could not load freight prediction model from {self.model_path}: {e}")
236
  self.freight_model = None
237
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
238
  def process_uploaded_data(state, sales_file, supplier_file, text_data):
239
  """Process uploaded files and store in state"""
240
  try:
 
269
  response = model.generate_content(prompt)
270
  analysis_text = response.text
271
 
272
+ # Create visualization
273
  fig = px.line(state.sales_df, title='Historical Sales Data and Forecast')
274
  fig.update_layout(
275
+ template='plotly_dark',
276
  title_x=0.5,
277
  title_font_size=20,
278
  showlegend=True,
279
+ hovermode='x',
280
+ paper_bgcolor='#2d2d2d',
281
+ plot_bgcolor='#363636',
282
+ font=dict(color='white')
283
  )
284
 
285
  return analysis_text, fig, "βœ… Analysis completed successfully"
 
309
  response = model.generate_content(prompt)
310
  analysis_text = response.text
311
 
312
+ # Create risk visualization
313
  fig = px.scatter(state.supplier_df, title='Supplier Risk Assessment')
314
  fig.update_layout(
315
+ template='plotly_dark',
316
  title_x=0.5,
317
  title_font_size=20,
318
  showlegend=True,
319
+ hovermode='closest',
320
+ paper_bgcolor='#2d2d2d',
321
+ plot_bgcolor='#363636',
322
+ font=dict(color='white')
323
  )
324
 
325
  return analysis_text, fig, "βœ… Risk assessment completed"
 
368
  except Exception as e:
369
  return [(msg_type, msg) for msg_type, msg in state.chat_history] + [("assistant", f"Error: {str(e)}")]
370
 
371
+ def predict_freight_cost(state, weight, line_item_value, cost_per_kg,
372
+ shipment_mode, air_charter_weight, ocean_weight, truck_weight,
373
+ air_charter_value, ocean_value, truck_value):
374
+ """Predict freight cost using the loaded model"""
375
+ if state.freight_model is None:
376
+ return "Error: Freight prediction model not loaded"
377
+
378
+ try:
379
+ features = {
380
+ 'weight (kilograms)': weight,
381
+ 'line item value': line_item_value,
382
+ 'cost per kilogram': cost_per_kg,
383
+ 'shipment mode_Air Charter_weight': air_charter_weight if "Air" in shipment_mode else 0,
384
+ 'shipment mode_Ocean_weight': ocean_weight if "Ocean" in shipment_mode else 0,
385
+ 'shipment mode_Truck_weight': truck_weight if "Truck" in shipment_mode else 0,
386
+ 'shipment mode_Air Charter_line_item_value': air_charter_value if "Air" in shipment_mode else 0,
387
+ 'shipment mode_Ocean_line_item_value': ocean_value if "Ocean" in shipment_mode else 0,
388
+ 'shipment mode_Truck_line_item_value': truck_value if "Truck" in shipment_mode else 0
389
+ }
390
+ input_data = pd.DataFrame([features])
391
+
392
+ prediction = state.freight_model.predict(input_data)
393
+ return round(float(prediction[0]), 2)
394
+ except Exception as e:
395
+ return f"Error making prediction: {str(e)}"
396
+
397
  def generate_pdf_report(state, analysis_options):
398
  """Generate PDF report with analysis results"""
399
  try:
 
413
  textColor=colors.HexColor('#2C3E50')
414
  )
415
 
416
+ # Add title
 
 
417
  story.append(Paragraph("SupplyChainAI Navigator Report", title_style))
418
  story.append(Spacer(1, 12))
419
 
420
+ # Add timestamp
421
+ timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
422
+ story.append(Paragraph(f"Generated on: {timestamp}", styles['Normal']))
423
+ story.append(Spacer(1, 20))
424
+
425
  # Add executive summary
426
  story.append(Paragraph("Executive Summary", styles['Heading2']))
427
+ summary_text = "This report provides a comprehensive analysis of supply chain data, including demand forecasting, risk assessment, and optimization recommendations."
428
  story.append(Paragraph(summary_text, styles['Normal']))
429
  story.append(Spacer(1, 20))
430
 
431
+ # Add analysis results
432
+ if state.analysis_results:
433
+ for analysis_type, results in state.analysis_results.items():
434
+ if analysis_type in analysis_options:
435
+ story.append(Paragraph(analysis_type, styles['Heading2']))
436
+ story.append(Spacer(1, 12))
437
+ story.append(Paragraph(results['text'], styles['Normal']))
438
+ story.append(Spacer(1, 12))
439
+
440
+ if 'figure' in results:
441
+ img_path = os.path.join(temp_dir, f"{analysis_type.lower()}_plot.png")
442
+ results['figure'].write_image(img_path)
443
+ story.append(Image(img_path, width=400, height=300))
444
+
445
+ story.append(Spacer(1, 20))
446
+
447
+ # Add freight predictions if available
448
  if state.freight_predictions:
449
  story.append(Paragraph("Recent Freight Cost Predictions", styles['Heading2']))
450
  story.append(Spacer(1, 12))
451
 
 
452
  pred_data = [["Prediction #", "Cost (USD)"]]
453
  for i, pred in enumerate(state.freight_predictions[-5:], 1):
454
  pred_data.append([f"Prediction {i}", f"${pred:,.2f}"])
 
470
  story.append(table)
471
  story.append(Spacer(1, 20))
472
 
 
 
 
 
 
 
 
 
473
  # Build PDF
474
  doc.build(story)
475
  return pdf_path
 
477
  print(f"Error generating PDF: {str(e)}")
478
  return None
479
 
480
+ def run_analyses(state, choices, sales_file, supplier_file, text_data):
481
+ """Run selected analyses"""
482
+ results = []
483
+ figures = []
484
+ status_messages = []
485
+
486
+ # Process data first
487
+ process_status = process_uploaded_data(state, sales_file, supplier_file, text_data)
488
+ if "Error" in process_status:
489
+ return process_status, None, process_status
490
+
491
+ for choice in choices:
492
+ if "Demand Forecasting" in choice:
493
+ text, fig, status = perform_demand_forecasting(state)
494
+ results.append(text)
495
+ figures.append(fig)
496
+ status_messages.append(status)
497
+ if text and fig:
498
+ state.analysis_results['Demand Forecasting'] = {'text': text, 'figure': fig}
499
+
500
+ elif "Risk Assessment" in choice:
501
+ text, fig, status = perform_risk_assessment(state)
502
+ results.append(text)
503
+ figures.append(fig)
504
+ status_messages.append(status)
505
+ if text and fig:
506
+ state.analysis_results['Risk Assessment'] = {'text': text, 'figure': fig}
507
+
508
+ combined_results = "\n\n".join(results)
509
+ combined_status = "\n".join(status_messages)
510
+
511
+ final_figure = figures[-1] if figures else None
512
+
513
+ return combined_results, final_figure, combined_status
514
+
515
+ def predict_and_store_freight(state, *args):
516
+ """Predict freight cost and store the result"""
517
+ result = predict_freight_cost(state, *args)
518
+ if isinstance(result, (int, float)):
519
+ state.freight_predictions.append(result)
520
+ return result
521
+
522
  def create_interface():
523
  """Create Gradio interface with enhanced UI"""
524
  state = SupplyChainState()
 
526
  with gr.Blocks(css=CUSTOM_CSS, title="SupplyChainAI Navigator") as demo:
527
  # Header
528
  with gr.Row(elem_classes="main-header"):
529
+ with gr.Column():
530
+ gr.Markdown("# 🚒 SupplyChainAI Navigator", elem_classes="app-title")
531
+ gr.Markdown("### Intelligent Supply Chain Analysis & Optimization", elem_classes="app-subtitle")
532
+ gr.Markdown("An AI-powered platform for comprehensive supply chain analytics", elem_classes="app-description")
533
+ gr.Markdown("Created by Aditya Ratan", elem_classes="creator-info")
534
 
535
  # Main Content Tabs
536
  with gr.Tabs() as tabs:
537
  # Data Upload Tab
538
  with gr.Tab("πŸ“Š Data Upload", elem_classes="tab-content"):
 
 
 
 
 
 
539
  with gr.Row():
540
  with gr.Column(scale=1):
541
  sales_data_upload = gr.File(
 
567
  elem_classes="action-button"
568
  )
569
 
570
+ # Analysis Tab
571
  with gr.Tab("πŸ” Analysis", elem_classes="tab-content"):
 
 
 
572
  analysis_options = gr.CheckboxGroup(
573
  choices=[
574
  "πŸ“ˆ Demand Forecasting",
575
+ "⚠️ Risk Assessment"
 
 
 
576
  ],
577
  label="Choose analyses to perform"
578
  )
 
582
  variant="primary",
583
  elem_classes="action-button"
584
  )
585
+
 
 
586
  with gr.Row():
587
  with gr.Column(scale=2):
588
  analysis_output = gr.Textbox(
 
602
 
603
  # Freight Cost Prediction Tab
604
  with gr.Tab("πŸ’° Cost Prediction", elem_classes="tab-content"):
 
 
 
 
 
 
605
  with gr.Row():
606
  shipment_mode = gr.Dropdown(
607
  choices=["✈️ Air", "🚒 Ocean", "πŸš› Truck"],
 
635
  value=50
636
  )
637
 
638
+ # Mode-specific inputs
639
  with gr.Row(visible=False) as air_inputs:
640
  air_charter_weight = gr.Slider(
641
  label="Air Charter Weight",
642
  minimum=0,
643
+ maximum=10000
 
 
644
  )
645
  air_charter_value = gr.Slider(
646
  label="Air Charter Value",
647
  minimum=0,
648
+ maximum=1000000
 
 
649
  )
650
 
651
  with gr.Row(visible=False) as ocean_inputs:
652
  ocean_weight = gr.Slider(
653
  label="Ocean Weight",
654
  minimum=0,
655
+ maximum=10000
 
 
656
  )
657
  ocean_value = gr.Slider(
658
  label="Ocean Value",
659
  minimum=0,
660
+ maximum=1000000
 
 
661
  )
662
 
663
  with gr.Row(visible=False) as truck_inputs:
664
  truck_weight = gr.Slider(
665
  label="Truck Weight",
666
  minimum=0,
667
+ maximum=10000
 
 
668
  )
669
  truck_value = gr.Slider(
670
  label="Truck Value",
671
  minimum=0,
672
+ maximum=1000000
 
 
673
  )
674
 
675
  with gr.Row():
 
705
 
706
  # Report Tab
707
  with gr.Tab("πŸ“‘ Report", elem_classes="tab-content"):
708
+ report_button = gr.Button(
709
+ "πŸ“„ Generate Report",
710
+ variant="primary",
711
+ elem_classes="action-button"
712
+ )
713
+ report_download = gr.File(
714
+ label="Download Report"
715
+ )
716
+
717
+ # Footer
718
+ with gr.Row(elem_classes="footer"):
719
+ gr.Markdown("Β© 2025 SupplyChainAI Navigator")
 
 
720
 
721
  # Event Handlers
722
  def update_mode_inputs(mode):
 
734
  )
735
 
736
  analyze_button.click(
737
+ fn=lambda *args: run_analyses(state, *args),
738
  inputs=[analysis_options, sales_data_upload, supplier_data_upload, text_input_area],
739
  outputs=[analysis_output, plot_output, raw_output]
740
  )
 
778
  share=True,
779
  debug=True
780
  )
781
+
782
+ # Enhanced title