PD03 commited on
Commit
5ec7e4c
·
verified ·
1 Parent(s): 0e1a34f

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +43 -14
app.py CHANGED
@@ -113,7 +113,7 @@ def optimize_supply_tool(forecast_json: str) -> str:
113
  c[i_sell(p)] -= price[p]
114
  c[i_einv(p)] += 0.0
115
  bounds[i_prod(p)] = (0, None)
116
- bounds[i_sell(p)] = (0, demand[p])
117
  bounds[i_einv(p)] = (0, None)
118
  for r in RMs:
119
  c[i_pur(r)] += rm_cost[r]
@@ -221,26 +221,35 @@ SYSTEM_PLAN = (
221
  "Return: {'forecast': <json>, 'plan': <json>, 'md61': <json>}"
222
  )
223
 
224
- def run_agentic(horizon, plant, use_demo, file_obj):
225
  agent = make_agent()
226
  if file_obj is not None:
227
  path = file_obj.name
228
  prompt = (f"{SYSTEM_PLAN}\n"
229
- f"Use forecast_tool(horizon_months={int(horizon)}, use_demo=False, history_csv_path='{path}'). "
230
  f"Then run the other two steps as specified. Return only the final JSON.")
231
  else:
232
  prompt = (f"{SYSTEM_PLAN}\n"
233
- f"Use forecast_tool(horizon_months={int(horizon)}, use_demo={bool(use_demo)}). "
234
  f"Then run the other two steps as specified. Return only the final JSON.")
235
  return agent.run(prompt)
236
 
237
 
238
- # ==== UI Helpers (pretty outputs) ============================================
 
 
 
 
 
 
 
 
239
  def parse_forecast(json_str):
240
  df = pd.DataFrame(json.loads(json_str))
241
- return df[["product_id","period_start","forecast_qty"]].rename(columns={
242
  "product_id":"Product","period_start":"Period Start","forecast_qty":"Forecast Qty"
243
  })
 
244
 
245
  def parse_plan(json_str):
246
  d = json.loads(json_str)
@@ -250,11 +259,11 @@ def parse_plan(json_str):
250
  prod = pd.DataFrame(d["products"])
251
  raw = pd.DataFrame(d["raw_materials"])
252
  res = pd.DataFrame(d["resources"])
253
- return d["status"], kpis, prod, raw, res
254
 
255
  def parse_md61(json_str):
256
  d = json.loads(json_str)
257
- prev = pd.DataFrame(d.get("preview", []))
258
  path = d.get("csv_path", "")
259
  return d.get("status",""), prev, path
260
 
@@ -345,14 +354,31 @@ with gr.Blocks(title="Forecast → Optimize → SAP MD61") as demo:
345
  a_md61_prev = gr.Dataframe(label="MD61 Preview", interactive=False)
346
  a_md61_file = gr.File(label="Download MD61 CSV", interactive=False)
347
 
 
348
  def do_agent(h, p, demo_flag, f):
 
 
 
 
 
349
  try:
350
- res = run_agentic(h, p, demo_flag, f)
351
- out = json.loads(res)
352
- f_df = parse_forecast(out["forecast"])
353
- _, kpis, prod, raw, res_tbl = parse_plan(out["plan"])
354
- _, prev, csv_path = parse_md61(out["md61"])
355
- return (json.dumps(out, indent=2), f_df, kpis, prod, raw, res_tbl, prev, csv_path)
 
 
 
 
 
 
 
 
 
 
 
356
  except Exception as e:
357
  return (f"Agent error: {e}", pd.DataFrame(), pd.DataFrame(), pd.DataFrame(), pd.DataFrame(),
358
  pd.DataFrame(), pd.DataFrame(), None)
@@ -361,4 +387,7 @@ with gr.Blocks(title="Forecast → Optimize → SAP MD61") as demo:
361
  outputs=[out_json, a_forecast_tbl, a_plan_kpis, a_plan_prod, a_plan_raw, a_plan_res, a_md61_prev, a_md61_file])
362
 
363
  if __name__ == "__main__":
 
 
 
364
  demo.launch()
 
113
  c[i_sell(p)] -= price[p]
114
  c[i_einv(p)] += 0.0
115
  bounds[i_prod(p)] = (0, None)
116
+ bounds[i_sell(p)] = (0, demand[p]) # demand as an upper bound (no backorders)
117
  bounds[i_einv(p)] = (0, None)
118
  for r in RMs:
119
  c[i_pur(r)] += rm_cost[r]
 
221
  "Return: {'forecast': <json>, 'plan': <json>, 'md61': <json>}"
222
  )
223
 
224
+ def run_agentic(h, plant, demo_flag, file_obj):
225
  agent = make_agent()
226
  if file_obj is not None:
227
  path = file_obj.name
228
  prompt = (f"{SYSTEM_PLAN}\n"
229
+ f"Use forecast_tool(horizon_months={int(h)}, use_demo=False, history_csv_path='{path}'). "
230
  f"Then run the other two steps as specified. Return only the final JSON.")
231
  else:
232
  prompt = (f"{SYSTEM_PLAN}\n"
233
+ f"Use forecast_tool(horizon_months={int(h)}, use_demo={bool(demo_flag)}). "
234
  f"Then run the other two steps as specified. Return only the final JSON.")
235
  return agent.run(prompt)
236
 
237
 
238
+ # ==== UI Helpers (rounding + pretty) =========================================
239
+ def _round_df(df: pd.DataFrame, places: int = 2) -> pd.DataFrame:
240
+ if df is None or df.empty:
241
+ return df
242
+ out = df.copy()
243
+ num_cols = out.select_dtypes(include=["number"]).columns
244
+ out[num_cols] = out[num_cols].astype(float).round(places)
245
+ return out
246
+
247
  def parse_forecast(json_str):
248
  df = pd.DataFrame(json.loads(json_str))
249
+ df = df[["product_id","period_start","forecast_qty"]].rename(columns={
250
  "product_id":"Product","period_start":"Period Start","forecast_qty":"Forecast Qty"
251
  })
252
+ return _round_df(df)
253
 
254
  def parse_plan(json_str):
255
  d = json.loads(json_str)
 
259
  prod = pd.DataFrame(d["products"])
260
  raw = pd.DataFrame(d["raw_materials"])
261
  res = pd.DataFrame(d["resources"])
262
+ return d["status"], _round_df(kpis), _round_df(prod), _round_df(raw), _round_df(res)
263
 
264
  def parse_md61(json_str):
265
  d = json.loads(json_str)
266
+ prev = _round_df(pd.DataFrame(d.get("preview", [])))
267
  path = d.get("csv_path", "")
268
  return d.get("status",""), prev, path
269
 
 
354
  a_md61_prev = gr.Dataframe(label="MD61 Preview", interactive=False)
355
  a_md61_file = gr.File(label="Download MD61 CSV", interactive=False)
356
 
357
+ # Robust agent handler: accepts dict OR str and rounds outputs
358
  def do_agent(h, p, demo_flag, f):
359
+ def to_obj(x):
360
+ return x if isinstance(x, (dict, list)) else json.loads(x)
361
+ def to_str(x):
362
+ return x if isinstance(x, str) else json.dumps(x)
363
+
364
  try:
365
+ res = run_agentic(h, p, demo_flag, f) # may be dict or str
366
+ out = to_obj(res)
367
+
368
+ forecast_json = to_str(out["forecast"])
369
+ plan_json = to_str(out["plan"])
370
+ md61_json = to_str(out["md61"])
371
+
372
+ f_df = parse_forecast(forecast_json)
373
+ _, kpis, prod, raw, res_tbl = parse_plan(plan_json)
374
+ _, prev, csv_path = parse_md61(md61_json)
375
+
376
+ pretty = {
377
+ "forecast": json.loads(forecast_json),
378
+ "plan": json.loads(plan_json),
379
+ "md61": json.loads(md61_json),
380
+ }
381
+ return (json.dumps(pretty, indent=2), f_df, kpis, prod, raw, res_tbl, prev, csv_path)
382
  except Exception as e:
383
  return (f"Agent error: {e}", pd.DataFrame(), pd.DataFrame(), pd.DataFrame(), pd.DataFrame(),
384
  pd.DataFrame(), pd.DataFrame(), None)
 
387
  outputs=[out_json, a_forecast_tbl, a_plan_kpis, a_plan_prod, a_plan_raw, a_plan_res, a_md61_prev, a_md61_file])
388
 
389
  if __name__ == "__main__":
390
+ # Needs OPENAI_API_KEY in env for agent tab; manual tab works without it.
391
+ if not os.environ.get("OPENAI_API_KEY"):
392
+ print("⚠️ Set OPENAI_API_KEY (Space secret) to use Agentic tab.")
393
  demo.launch()