PD03 commited on
Commit
399f549
·
verified ·
1 Parent(s): 107143e

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +143 -207
app.py CHANGED
@@ -6,16 +6,12 @@ import plotly.graph_objects as go
6
  from plotly.subplots import make_subplots
7
  import json
8
  import time
9
- import os
10
  from datetime import datetime
11
- import tempfile
12
- import pickle
13
 
14
- # Import your procurement agent code
15
  from agentic_sourcing_ppo_sap_colab import (
16
  suppliers_synthetic, market_signal, rl_recommend_tool,
17
- sap_create_po_mock, check_model_tool, get_model,
18
- CodeAgent, VOL_MAP
19
  )
20
 
21
  # Page config
@@ -47,13 +43,6 @@ st.markdown("""
47
  border-radius: 10px;
48
  margin: 0.5rem 0;
49
  }
50
- .step-container {
51
- background: #f8f9fa;
52
- border-left: 4px solid #007bff;
53
- padding: 1rem;
54
- margin: 1rem 0;
55
- border-radius: 5px;
56
- }
57
  .success-box {
58
  background: #d4edda;
59
  border: 1px solid #c3e6cb;
@@ -61,39 +50,9 @@ st.markdown("""
61
  border-radius: 5px;
62
  margin: 1rem 0;
63
  }
64
- .warning-box {
65
- background: #fff3cd;
66
- border: 1px solid #ffeaa7;
67
- padding: 1rem;
68
- border-radius: 5px;
69
- margin: 1rem 0;
70
- }
71
  </style>
72
  """, unsafe_allow_html=True)
73
 
74
- def create_gauge_chart(value, title, max_value=1.0):
75
- """Create a gauge chart for metrics"""
76
- fig = go.Figure(go.Indicator(
77
- mode = "gauge+number+delta",
78
- value = value,
79
- domain = {'x': [0, 1], 'y': [0, 1]},
80
- title = {'text': title},
81
- delta = {'reference': max_value * 0.8},
82
- gauge = {
83
- 'axis': {'range': [None, max_value]},
84
- 'bar': {'color': "#2E86AB"},
85
- 'steps': [
86
- {'range': [0, max_value * 0.5], 'color': "#FFE5E5"},
87
- {'range': [max_value * 0.5, max_value * 0.8], 'color': "#FFEFCC"},
88
- {'range': [max_value * 0.8, max_value], 'color': "#E5F3E5"}],
89
- 'threshold': {
90
- 'line': {'color': "red", 'width': 4},
91
- 'thickness': 0.75,
92
- 'value': max_value * 0.9}}))
93
-
94
- fig.update_layout(height=300, margin=dict(l=20, r=20, t=40, b=20))
95
- return fig
96
-
97
  def create_allocation_pie_chart(allocations):
98
  """Create pie chart for supplier allocations"""
99
  df = pd.DataFrame(allocations)
@@ -209,14 +168,6 @@ def main():
209
  help="Seed for reproducible supplier generation"
210
  )
211
 
212
- # Model Configuration
213
- st.subheader("AI Model Settings")
214
- use_random_model = st.checkbox(
215
- "Use Random Model (Demo Mode)",
216
- value=True,
217
- help="Use random model when PPO model is not available"
218
- )
219
-
220
  with col2:
221
  st.markdown('<div class="sub-header">📊 Real-time Dashboard</div>', unsafe_allow_html=True)
222
 
@@ -227,163 +178,148 @@ def main():
227
  progress_bar = st.progress(0)
228
  status_text = st.empty()
229
 
230
- # Step 1: Generate suppliers
231
- status_text.text("Step 1/5: Generating supplier data...")
232
- progress_bar.progress(20)
233
-
234
- suppliers_result = suppliers_synthetic(n=num_suppliers, seed=seed)
235
- suppliers_data = suppliers_result["suppliers"]
236
-
237
- # Display suppliers table
238
- st.subheader("Generated Suppliers")
239
- df_suppliers = pd.DataFrame(suppliers_data)
240
- st.dataframe(df_suppliers.round(3), use_container_width=True)
241
-
242
- # Step 2: Market signals
243
- status_text.text("Step 2/5: Analyzing market conditions...")
244
- progress_bar.progress(40)
245
-
246
- market_data = market_signal(volatility, price_mult, demand_mult)
247
-
248
- # Display market metrics
249
- col_m1, col_m2, col_m3 = st.columns(3)
250
- with col_m1:
251
- st.metric("Volatility", volatility.upper(),
252
- delta="High Risk" if volatility == "high" else "Normal")
253
- with col_m2:
254
- st.metric("Demand Change", f"{demand_mult:.1%}",
255
- delta=f"{(demand_mult-1)*100:+.1f}%")
256
- with col_m3:
257
- st.metric("Price Change", f"{price_mult:.1%}",
258
- delta=f"{(price_mult-1)*100:+.1f}%")
259
-
260
- # Step 3: Check model
261
- status_text.text("Step 3/5: Checking AI model availability...")
262
- progress_bar.progress(60)
263
-
264
- # Create a mock model file for demo
265
- model_path = "/tmp/mock_ppo_model.pkl"
266
- if not os.path.exists(model_path):
267
- # Create a simple mock model for demo
268
- class MockPPOModel:
269
- def predict(self, obs, deterministic=True):
270
- # Simple allocation logic for demo
271
- np.random.seed(42)
272
- action = np.random.normal(0, 1, num_suppliers)
273
- return action, None
274
 
275
- with open(model_path, 'wb') as f:
276
- pickle.dump(MockPPOModel(), f)
277
-
278
- # Step 4: Get recommendations
279
- status_text.text("Step 4/5: Getting AI recommendations...")
280
- progress_bar.progress(80)
281
-
282
- recommendation_input = {
283
- "volatility": market_data["volatility"],
284
- "price_multiplier": market_data["price_multiplier"],
285
- "demand_multiplier": market_data["demand_multiplier"],
286
- "baseline_demand": baseline_demand,
287
- "suppliers": suppliers_data,
288
- "auto_align_actions": True
289
- }
290
-
291
- # For demo purposes, create mock recommendations
292
- np.random.seed(42)
293
- weights = np.random.exponential(1, num_suppliers)
294
- weights = weights / weights.sum()
295
-
296
- recommendations = {
297
- "strategy": "multi" if (weights > 0.1).sum() > 2 else "dual",
298
- "allocations": [
299
- {"supplier": suppliers_data[i]["name"], "share": float(weights[i])}
300
- for i in range(num_suppliers)
301
- ],
302
- "demand_units": float(baseline_demand * demand_mult)
303
- }
304
-
305
- # Step 5: Create PO
306
- status_text.text("Step 5/5: Creating purchase order...")
307
- progress_bar.progress(100)
308
-
309
- po_data = {
310
- "lines": [
311
- {
312
- "supplier": alloc["supplier"],
313
- "quantity": round(recommendations["demand_units"] * alloc["share"], 2)
314
- }
315
- for alloc in recommendations["allocations"]
316
- if alloc["share"] > 0.01
317
- ]
318
- }
319
-
320
- po_result = sap_create_po_mock(po_data)
321
-
322
- # Display results
323
- status_text.text(" Procurement process completed!")
324
- time.sleep(0.5)
325
- progress_bar.empty()
326
- status_text.empty()
327
-
328
- # Results section
329
- st.markdown("---")
330
- st.subheader("🎯 Procurement Results")
331
-
332
- # Key metrics
333
- col_r1, col_r2, col_r3, col_r4 = st.columns(4)
334
- with col_r1:
335
- st.metric("Strategy", recommendations["strategy"].title())
336
- with col_r2:
337
- active_suppliers = len([a for a in recommendations["allocations"] if a["share"] > 0.01])
338
- st.metric("Active Suppliers", active_suppliers)
339
- with col_r3:
340
- st.metric("Total Units", f"{recommendations['demand_units']:,.0f}")
341
- with col_r4:
342
- st.metric("PO Number", po_result["PurchaseOrder"])
343
-
344
- # Visualizations
345
- col_v1, col_v2 = st.columns(2)
346
-
347
- with col_v1:
348
- # Allocation pie chart
349
- fig_pie = create_allocation_pie_chart(recommendations["allocations"])
350
- st.plotly_chart(fig_pie, use_container_width=True)
351
-
352
- with col_v2:
353
- # Supplier comparison radar
354
- fig_radar = create_supplier_comparison_chart(suppliers_data)
355
- st.plotly_chart(fig_radar, use_container_width=True)
356
-
357
- # Detailed allocation table
358
- st.subheader("📋 Detailed Allocation")
359
- allocation_df = pd.DataFrame(recommendations["allocations"])
360
- allocation_df["quantity"] = allocation_df["share"] * recommendations["demand_units"]
361
- allocation_df["percentage"] = allocation_df["share"] * 100
362
-
363
- # Merge with supplier data for additional context
364
- supplier_df = pd.DataFrame(suppliers_data)
365
- detailed_df = allocation_df.merge(
366
- supplier_df[["name", "base_cost_per_unit", "current_quality", "financial_risk"]],
367
- left_on="supplier", right_on="name"
368
- )
369
-
370
- st.dataframe(
371
- detailed_df[["supplier", "percentage", "quantity", "base_cost_per_unit", "current_quality", "financial_risk"]]
372
- .round(2),
373
- use_container_width=True
374
- )
375
-
376
- # Purchase Order JSON
377
- with st.expander("📄 View Purchase Order JSON"):
378
- st.json(po_result)
379
-
380
- # Success message
381
- st.markdown(f"""
382
- <div class="success-box">
383
- <strong>✅ Success!</strong> Purchase Order {po_result["PurchaseOrder"]} has been created successfully!
384
- <br><em>Note: This is a demonstration. No actual SAP system was contacted.</em>
385
- </div>
386
- """, unsafe_allow_html=True)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
387
 
388
  # Sidebar with information
389
  with st.sidebar:
 
6
  from plotly.subplots import make_subplots
7
  import json
8
  import time
 
9
  from datetime import datetime
 
 
10
 
11
+ # Import from your fixed procurement agent file
12
  from agentic_sourcing_ppo_sap_colab import (
13
  suppliers_synthetic, market_signal, rl_recommend_tool,
14
+ sap_create_po_mock, check_model_tool
 
15
  )
16
 
17
  # Page config
 
43
  border-radius: 10px;
44
  margin: 0.5rem 0;
45
  }
 
 
 
 
 
 
 
46
  .success-box {
47
  background: #d4edda;
48
  border: 1px solid #c3e6cb;
 
50
  border-radius: 5px;
51
  margin: 1rem 0;
52
  }
 
 
 
 
 
 
 
53
  </style>
54
  """, unsafe_allow_html=True)
55
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
56
  def create_allocation_pie_chart(allocations):
57
  """Create pie chart for supplier allocations"""
58
  df = pd.DataFrame(allocations)
 
168
  help="Seed for reproducible supplier generation"
169
  )
170
 
 
 
 
 
 
 
 
 
171
  with col2:
172
  st.markdown('<div class="sub-header">📊 Real-time Dashboard</div>', unsafe_allow_html=True)
173
 
 
178
  progress_bar = st.progress(0)
179
  status_text = st.empty()
180
 
181
+ try:
182
+ # Step 1: Generate suppliers
183
+ status_text.text("Step 1/5: Generating supplier data...")
184
+ progress_bar.progress(20)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
185
 
186
+ suppliers_result = suppliers_synthetic(n=num_suppliers, seed=seed)
187
+ suppliers_data = suppliers_result["suppliers"]
188
+
189
+ # Display suppliers table
190
+ st.subheader("Generated Suppliers")
191
+ df_suppliers = pd.DataFrame(suppliers_data)
192
+ st.dataframe(df_suppliers.round(3), use_container_width=True)
193
+
194
+ # Step 2: Market signals
195
+ status_text.text("Step 2/5: Analyzing market conditions...")
196
+ progress_bar.progress(40)
197
+
198
+ market_data = market_signal(volatility, price_mult, demand_mult)
199
+
200
+ # Display market metrics
201
+ col_m1, col_m2, col_m3 = st.columns(3)
202
+ with col_m1:
203
+ st.metric("Volatility", volatility.upper(),
204
+ delta="High Risk" if volatility == "high" else "Normal")
205
+ with col_m2:
206
+ st.metric("Demand Change", f"{demand_mult:.1%}",
207
+ delta=f"{(demand_mult-1)*100:+.1f}%")
208
+ with col_m3:
209
+ st.metric("Price Change", f"{price_mult:.1%}",
210
+ delta=f"{(price_mult-1)*100:+.1f}%")
211
+
212
+ # Step 3: Check model
213
+ status_text.text("Step 3/5: Checking AI model availability...")
214
+ progress_bar.progress(60)
215
+
216
+ model_check = check_model_tool("./supplier_selection_ppo_gymnasium.pkl")
217
+
218
+ # Step 4: Get recommendations
219
+ status_text.text("Step 4/5: Getting AI recommendations...")
220
+ progress_bar.progress(80)
221
+
222
+ recommendation_input = {
223
+ "volatility": market_data["volatility"],
224
+ "price_multiplier": market_data["price_multiplier"],
225
+ "demand_multiplier": market_data["demand_multiplier"],
226
+ "baseline_demand": baseline_demand,
227
+ "suppliers": suppliers_data,
228
+ "auto_align_actions": True
229
+ }
230
+
231
+ recommendations = rl_recommend_tool(recommendation_input)
232
+
233
+ if recommendations.get("strategy") == "error":
234
+ st.error(f"AI recommendation failed: {recommendations.get('error', 'Unknown error')}")
235
+ return
236
+
237
+ # Step 5: Create PO
238
+ status_text.text("Step 5/5: Creating purchase order...")
239
+ progress_bar.progress(100)
240
+
241
+ po_data = {
242
+ "lines": [
243
+ {
244
+ "supplier": alloc["supplier"],
245
+ "quantity": round(recommendations["demand_units"] * alloc["share"], 2)
246
+ }
247
+ for alloc in recommendations["allocations"]
248
+ if alloc["share"] > 0.01
249
+ ]
250
+ }
251
+
252
+ po_result = sap_create_po_mock(po_data)
253
+
254
+ # Clear progress indicators
255
+ status_text.text("✅ Procurement process completed!")
256
+ time.sleep(0.5)
257
+ progress_bar.empty()
258
+ status_text.empty()
259
+
260
+ # Display results
261
+ st.markdown("---")
262
+ st.subheader("🎯 Procurement Results")
263
+
264
+ # Key metrics
265
+ col_r1, col_r2, col_r3, col_r4 = st.columns(4)
266
+ with col_r1:
267
+ st.metric("Strategy", recommendations["strategy"].title())
268
+ with col_r2:
269
+ active_suppliers = len([a for a in recommendations["allocations"] if a["share"] > 0.01])
270
+ st.metric("Active Suppliers", active_suppliers)
271
+ with col_r3:
272
+ st.metric("Total Units", f"{recommendations['demand_units']:,.0f}")
273
+ with col_r4:
274
+ st.metric("PO Number", po_result["PurchaseOrder"])
275
+
276
+ # Visualizations
277
+ col_v1, col_v2 = st.columns(2)
278
+
279
+ with col_v1:
280
+ # Allocation pie chart
281
+ fig_pie = create_allocation_pie_chart(recommendations["allocations"])
282
+ st.plotly_chart(fig_pie, use_container_width=True)
283
+
284
+ with col_v2:
285
+ # Supplier comparison radar
286
+ fig_radar = create_supplier_comparison_chart(suppliers_data)
287
+ st.plotly_chart(fig_radar, use_container_width=True)
288
+
289
+ # Detailed allocation table
290
+ st.subheader("📋 Detailed Allocation")
291
+ allocation_df = pd.DataFrame(recommendations["allocations"])
292
+ allocation_df["quantity"] = allocation_df["share"] * recommendations["demand_units"]
293
+ allocation_df["percentage"] = allocation_df["share"] * 100
294
+
295
+ # Merge with supplier data for additional context
296
+ supplier_df = pd.DataFrame(suppliers_data)
297
+ detailed_df = allocation_df.merge(
298
+ supplier_df[["name", "base_cost_per_unit", "current_quality", "financial_risk"]],
299
+ left_on="supplier", right_on="name"
300
+ )
301
+
302
+ st.dataframe(
303
+ detailed_df[["supplier", "percentage", "quantity", "base_cost_per_unit", "current_quality", "financial_risk"]]
304
+ .round(2),
305
+ use_container_width=True
306
+ )
307
+
308
+ # Purchase Order JSON
309
+ with st.expander("📄 View Purchase Order JSON"):
310
+ st.json(po_result)
311
+
312
+ # Success message
313
+ st.markdown(f"""
314
+ <div class="success-box">
315
+ <strong>✅ Success!</strong> Purchase Order {po_result["PurchaseOrder"]} has been created successfully!
316
+ <br><em>Note: This is a demonstration. No actual SAP system was contacted.</em>
317
+ </div>
318
+ """, unsafe_allow_html=True)
319
+
320
+ except Exception as e:
321
+ st.error(f"Error during execution: {str(e)}")
322
+ st.exception(e)
323
 
324
  # Sidebar with information
325
  with st.sidebar: