rairo commited on
Commit
3262424
·
verified ·
1 Parent(s): aa088fd

Update main.py

Browse files
Files changed (1) hide show
  1. main.py +39 -0
main.py CHANGED
@@ -1345,6 +1345,45 @@ class IrisReportEngine:
1345
  emit_kpi_debug(self.profile_id, "briefing_done", snapshot["meta"])
1346
  return json_safe(snapshot)
1347
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1348
  # ------------------------- helpers (outside class) -------------------------
1349
 
1350
  def rfm_to_list(df: pd.DataFrame) -> List[Dict[str, Any]]:
 
1345
  emit_kpi_debug(self.profile_id, "briefing_done", snapshot["meta"])
1346
  return json_safe(snapshot)
1347
 
1348
+ def synthesize_fallback_response(self, briefing: dict, user_question: str) -> str:
1349
+ """
1350
+ LLM is narration-only. Do NOT invent or recompute numbers here.
1351
+ Use the already-deterministic 'briefing' dict as the single source of truth.
1352
+ Safe for PandasAI exception fallback.
1353
+ """
1354
+ try:
1355
+ tz = TZ
1356
+ prompt = (
1357
+ "You are Iris, a concise business analyst.\n"
1358
+ "IMPORTANT RULES:\n"
1359
+ "• DO NOT invent numbers. ONLY use values present in the Business Data JSON.\n"
1360
+ "• If a metric is missing, say 'N/A' or 'no data for this period'.\n"
1361
+ "• Harare timezone is the reference for dates/times.\n"
1362
+ "• Keep it brief: headings + bullets; no tables unless clearly helpful.\n"
1363
+ "• If the user asked something specific (e.g., 'top 5 products'), answer directly from the JSON.\n"
1364
+ "• Otherwise, provide a short business briefing (performance, products, timing, customers, branches).\n"
1365
+ "• Never expose internal keys; paraphrase labels.\n"
1366
+ f"User Question: {json.dumps(user_question)}\n\n"
1367
+ "Business Data (authoritative; JSON):\n"
1368
+ f"{json.dumps(json_safe(briefing), ensure_ascii=False)}\n"
1369
+ )
1370
+
1371
+ resp = self.llm.invoke(prompt)
1372
+ # ChatGoogleGenerativeAI returns an object with .content
1373
+ text = getattr(resp, "content", None) or str(resp)
1374
+ # Final safety scrub (remove accidental code fences / tracebacks)
1375
+ return sanitize_answer(text)
1376
+
1377
+ except Exception as e:
1378
+ # Absolute last resort: dump a compact JSON view so the UI shows *something*
1379
+ fallback = {
1380
+ "note": "Narrative fallback failed; returning raw snapshot.",
1381
+ "error": str(e)[:200],
1382
+ "snapshot_keys": list(briefing.keys()) if isinstance(briefing, dict) else "N/A"
1383
+ }
1384
+ return "### Business Snapshot\n\n```\n" + json.dumps(json_safe(briefing), indent=2) + "\n```\n\n" + \
1385
+ "```\n" + json.dumps(fallback, indent=2) + "\n```"
1386
+
1387
  # ------------------------- helpers (outside class) -------------------------
1388
 
1389
  def rfm_to_list(df: pd.DataFrame) -> List[Dict[str, Any]]: