rairo commited on
Commit
e09e6c9
·
verified ·
1 Parent(s): a0a5656

Update main.py

Browse files
Files changed (1) hide show
  1. main.py +52 -16
main.py CHANGED
@@ -1,4 +1,4 @@
1
- # app.py — REVISED: Separated KPI snapshot from memory summary
2
 
3
  from langchain_google_genai import ChatGoogleGenerativeAI
4
  import pandas as pd
@@ -278,7 +278,7 @@ def sanitize_answer(ans) -> str:
278
  return s.strip()
279
 
280
  # -----------------------------------------------------------------------------
281
- # Analyst KPI layer (preserved)
282
  # -----------------------------------------------------------------------------
283
  class IrisReportEngine:
284
  def __init__(self, transactions_data: list, llm_instance):
@@ -326,6 +326,7 @@ class IrisReportEngine:
326
  def _get_primary_currency(self) -> str:
327
  try:
328
  if not self.df.empty and "Currency" in self.df.columns and not self.df["Currency"].mode().empty:
 
329
  return str(self.df["Currency"].mode())
330
  except Exception:
331
  pass
@@ -350,8 +351,9 @@ class IrisReportEngine:
350
  if prev == 0:
351
  return "+100%" if cur > 0 else "0.0%"
352
  return f"{((cur - prev) / prev) * 100:+.1f}%"
353
- tx_now = int(current_df.get("Invoice_Number", pd.Series()).nunique()) if "Invoice_Number" in current_df.columns else int(len(current_df))
354
- tx_prev = int(previous_df.get("Invoice_Number", pd.Series()).nunique()) if "Invoice_Number" in previous_df.columns else int(len(previous_df))
 
355
  return {
356
  "Total Revenue": f"{self.currency} {current_revenue:,.2f} ({pct_change(current_revenue, previous_revenue)})",
357
  "Gross Profit": f"{self.currency} {current_profit:,.2f} ({pct_change(current_profit, previous_profit)})",
@@ -376,20 +378,22 @@ class IrisReportEngine:
376
  product_intel = {}
377
  if len(products_by_profit) > 1:
378
  product_intel = {
379
- "Best in Class (Most Profitable)": products_by_profit.idxmax(),
380
- "Workhorse (Most Units Sold)": products_by_units.idxmax() if len(products_by_units) else "N/A",
381
  "Underperformer (Least Profitable > 0)": (
382
- products_by_profit[products_by_profit > 0].idxmin()
383
  if not products_by_profit[products_by_profit > 0].empty else "N/A"
384
  ),
385
  }
386
  elif not products_by_profit.empty:
387
- product_intel = {"Only Product Sold": products_by_profit.index}
 
388
  staff_intel = {}
389
  if len(tellers_by_profit) > 1:
390
- staff_intel = {"Top Performing Teller (by Profit)": tellers_by_profit.idxmax()}
391
  elif not tellers_by_profit.empty:
392
- staff_intel = {"Only Teller": tellers_by_profit.index}
 
393
  return {
394
  "Summary Period": summary_period,
395
  "Performance Snapshot (vs. Prior Period)": headline,
@@ -492,22 +496,54 @@ def bot():
492
  @cross_origin()
493
  def busines_report():
494
  logger.info("=== Starting /report endpoint ===")
495
- # ... (code is preserved)
496
- return jsonify("Report placeholder")
 
 
 
 
 
 
 
 
 
 
 
 
497
 
498
  @app.route("/marketing", methods=["POST"])
499
  @cross_origin()
500
  def marketing():
501
  logger.info("=== Starting /marketing endpoint ===")
502
- # ... (code is preserved)
503
- return jsonify("Marketing placeholder")
 
 
 
 
 
 
 
 
 
 
504
 
505
  @app.route("/notify", methods=["POST"])
506
  @cross_origin()
507
  def notifications():
508
  logger.info("=== Starting /notify endpoint ===")
509
- # ... (code is preserved)
510
- return jsonify("Notification placeholder")
 
 
 
 
 
 
 
 
 
 
511
 
512
  # -----------------------------------------------------------------------------
513
  # REVISED: ElevenLabs Voice Briefing Endpoints
 
1
+ # app.py — FIXED: Corrected JSON serialization error in IrisReportEngine
2
 
3
  from langchain_google_genai import ChatGoogleGenerativeAI
4
  import pandas as pd
 
278
  return s.strip()
279
 
280
  # -----------------------------------------------------------------------------
281
+ # Analyst KPI layer (MODIFIED WITH FIXES)
282
  # -----------------------------------------------------------------------------
283
  class IrisReportEngine:
284
  def __init__(self, transactions_data: list, llm_instance):
 
326
  def _get_primary_currency(self) -> str:
327
  try:
328
  if not self.df.empty and "Currency" in self.df.columns and not self.df["Currency"].mode().empty:
329
+ # FIX 1: Extract the first item from the mode() Series to prevent serialization issues.
330
  return str(self.df["Currency"].mode())
331
  except Exception:
332
  pass
 
351
  if prev == 0:
352
  return "+100%" if cur > 0 else "0.0%"
353
  return f"{((cur - prev) / prev) * 100:+.1f}%"
354
+ # FIX: Added dtype to pd.Series() to silence the FutureWarning from your traceback.
355
+ tx_now = int(current_df.get("Invoice_Number", pd.Series(dtype='object')).nunique()) if "Invoice_Number" in current_df.columns else int(len(current_df))
356
+ tx_prev = int(previous_df.get("Invoice_Number", pd.Series(dtype='object')).nunique()) if "Invoice_Number" in previous_df.columns else int(len(previous_df))
357
  return {
358
  "Total Revenue": f"{self.currency} {current_revenue:,.2f} ({pct_change(current_revenue, previous_revenue)})",
359
  "Gross Profit": f"{self.currency} {current_profit:,.2f} ({pct_change(current_profit, previous_profit)})",
 
378
  product_intel = {}
379
  if len(products_by_profit) > 1:
380
  product_intel = {
381
+ "Best in Class (Most Profitable)": str(products_by_profit.idxmax()),
382
+ "Workhorse (Most Units Sold)": str(products_by_units.idxmax()) if len(products_by_units) > 0 else "N/A",
383
  "Underperformer (Least Profitable > 0)": (
384
+ str(products_by_profit[products_by_profit > 0].idxmin())
385
  if not products_by_profit[products_by_profit > 0].empty else "N/A"
386
  ),
387
  }
388
  elif not products_by_profit.empty:
389
+ # FIX 2: Convert the single item from the index to a string to prevent it being a non-serializable Index object.
390
+ product_intel = {"Only Product Sold": str(products_by_profit.index)}
391
  staff_intel = {}
392
  if len(tellers_by_profit) > 1:
393
+ staff_intel = {"Top Performing Teller (by Profit)": str(tellers_by_profit.idxmax())}
394
  elif not tellers_by_profit.empty:
395
+ # FIX 3: Convert the single item from the index to a string.
396
+ staff_intel = {"Only Teller": str(tellers_by_profit.index)}
397
  return {
398
  "Summary Period": summary_period,
399
  "Performance Snapshot (vs. Prior Period)": headline,
 
496
  @cross_origin()
497
  def busines_report():
498
  logger.info("=== Starting /report endpoint ===")
499
+ try:
500
+ request_json = request.get_json()
501
+ json_data = request_json.get("json_data") if request_json else None
502
+ prompt = (
503
+ "You are Quantilytix business analyst. Analyze the following data and generate a "
504
+ "comprehensive and insightful business report, including appropriate key perfomance "
505
+ "indicators and recommendations Use markdown formatting and tables where necessary. "
506
+ "only return the report and nothing else.\ndata:\n" + str(json_data)
507
+ )
508
+ response = model.generate_content(prompt)
509
+ return jsonify(str(response.text))
510
+ except Exception as e:
511
+ logger.exception("Error in /report endpoint")
512
+ return jsonify({"error": "Failed to generate report.", "details": str(e)}), 500
513
 
514
  @app.route("/marketing", methods=["POST"])
515
  @cross_origin()
516
  def marketing():
517
  logger.info("=== Starting /marketing endpoint ===")
518
+ try:
519
+ request_json = request.get_json()
520
+ json_data = request_json.get("json_data") if request_json else None
521
+ prompt = (
522
+ "You are an Quantilytix Marketing Specialist. Analyze the following data and generate "
523
+ "a comprehensive marketing strategy, Only return the marketing strategy. be very creative:\n" + str(json_data)
524
+ )
525
+ response = model.generate_content(prompt)
526
+ return jsonify(str(response.text))
527
+ except Exception as e:
528
+ logger.exception("Error in /marketing endpoint")
529
+ return jsonify({"error": "Failed to generate marketing strategy.", "details": str(e)}), 500
530
 
531
  @app.route("/notify", methods=["POST"])
532
  @cross_origin()
533
  def notifications():
534
  logger.info("=== Starting /notify endpoint ===")
535
+ try:
536
+ request_json = request.get_json()
537
+ json_data = request_json.get("json_data") if request_json else None
538
+ prompt = (
539
+ "You are Quantilytix business analyst. Write a very brief analysis and marketing tips "
540
+ "using this business data. your output should be suitable for a notification dashboard so no quips.\n" + str(json_data)
541
+ )
542
+ response = model.generate_content(prompt)
543
+ return jsonify(str(response.text))
544
+ except Exception as e:
545
+ logger.exception("Error in /notify endpoint")
546
+ return jsonify({"error": "Failed to generate notification content.", "details": str(e)}), 500
547
 
548
  # -----------------------------------------------------------------------------
549
  # REVISED: ElevenLabs Voice Briefing Endpoints