Jeremy Live commited on
Commit
e7eb58c
·
1 Parent(s): 9f4148c
Files changed (1) hide show
  1. app.py +32 -39
app.py CHANGED
@@ -482,30 +482,6 @@ def is_db_intent(question: str) -> bool:
482
  except Exception:
483
  return False
484
 
485
- def extract_label_value_pairs(text: str) -> List[Dict[str, Union[str, float]]]:
486
- """Extract pairs like 'LABEL: NUMBER' from free text."""
487
- pairs: List[Dict[str, Union[str, float]]] = []
488
- if not text:
489
- return pairs
490
- try:
491
- raw_lines = text.split('\n')
492
- for line in raw_lines:
493
- s = line.strip()
494
- if not s:
495
- continue
496
- s = s.lstrip('•*\t -')
497
- m = re.match(r"^(.+?):\s*([0-9][0-9.,]*)$", s)
498
- if m:
499
- label = re.sub(r"[*_`]+", "", m.group(1)).strip()
500
- try:
501
- value = float(m.group(2).replace(',', ''))
502
- pairs.append({"label": label, "value": value})
503
- except Exception:
504
- continue
505
- return pairs
506
- except Exception:
507
- return pairs
508
-
509
  def generate_plot(data, x_col, y_col, title, x_label, y_label):
510
  """Generate a plot from data and return the file path."""
511
  plt.figure(figsize=(10, 6))
@@ -770,21 +746,44 @@ async def stream_agent_response(question: str, chat_history: List[List[str]], se
770
  logger.error(f"Second-pass SQL synthesis failed: {e}")
771
 
772
  # Fallback: if user asked for a chart and we didn't get SQL or chart yet,
773
- # use the MOST RECENT bot text (this turn or previous) and parse label:value pairs.
774
  if chart_fig is None:
775
  wants_chart, desired_type = detect_chart_preferences(question)
776
  if wants_chart:
 
777
  candidate_text = ""
778
- # Prefer THIS TURN's response_text if it's non-empty
779
- if isinstance(response_text, str) and response_text.strip():
780
- candidate_text = response_text
781
- # Otherwise look back at the latest assistant turn in history
782
- if not candidate_text and chat_history:
783
  for pair in reversed(chat_history):
784
  if len(pair) >= 2 and isinstance(pair[1], str) and pair[1].strip():
785
  candidate_text = pair[1]
786
  break
787
- data = extract_label_value_pairs(candidate_text)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
788
  logger.info(f"Fallback parse from text: extracted {len(data)} items for potential chart")
789
  if len(data) >= 2:
790
  chart_fig = generate_chart(
@@ -794,14 +793,8 @@ async def stream_agent_response(question: str, chat_history: List[List[str]], se
794
  y="value",
795
  title="Distribución"
796
  )
797
- if chart_fig is not None and not response_text.strip():
798
- # Provide a helpful text if the agent didn't produce one
799
- response_text = (
800
- f"Gráfico {('de barras' if desired_type=='bar' else desired_type)} "
801
- f"con {len(data)} categorías basado en los datos previos."
802
- )
803
- if chart_fig is not None:
804
- logger.info(f"Chart generated from text fallback: type={desired_type}, items={len(data)}")
805
 
806
  # Update the assistant's message with the response
807
  assistant_message["content"] = response_text
 
482
  except Exception:
483
  return False
484
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
485
  def generate_plot(data, x_col, y_col, title, x_label, y_label):
486
  """Generate a plot from data and return the file path."""
487
  plt.figure(figsize=(10, 6))
 
746
  logger.error(f"Second-pass SQL synthesis failed: {e}")
747
 
748
  # Fallback: if user asked for a chart and we didn't get SQL or chart yet,
749
+ # parse the most recent assistant text for lines like "LABEL: NUMBER" (bulleted or plain).
750
  if chart_fig is None:
751
  wants_chart, desired_type = detect_chart_preferences(question)
752
  if wants_chart:
753
+ # Find the most recent assistant message with usable numeric pairs
754
  candidate_text = ""
755
+ if chat_history:
 
 
 
 
756
  for pair in reversed(chat_history):
757
  if len(pair) >= 2 and isinstance(pair[1], str) and pair[1].strip():
758
  candidate_text = pair[1]
759
  break
760
+ # Also consider current response_text as a data source
761
+ if not candidate_text and isinstance(response_text, str) and response_text.strip():
762
+ candidate_text = response_text
763
+ if candidate_text:
764
+ raw_lines = candidate_text.split('\n')
765
+ # Normalize lines: strip bullets and markdown symbols
766
+ norm_lines = []
767
+ for l in raw_lines:
768
+ s = l.strip()
769
+ if not s:
770
+ continue
771
+ s = s.lstrip("•*-\t ")
772
+ # Remove surrounding markdown emphasis from labels later
773
+ norm_lines.append(s)
774
+ data = []
775
+ for l in norm_lines:
776
+ # Accept patterns like "**LABEL**: 123" or "LABEL: 1,234"
777
+ m = re.match(r"^(.+?):\s*([0-9][0-9.,]*)$", l)
778
+ if m:
779
+ label = m.group(1).strip()
780
+ # Strip common markdown emphasis
781
+ label = re.sub(r"[*_`]+", "", label).strip()
782
+ try:
783
+ val = float(m.group(2).replace(',', ''))
784
+ except Exception:
785
+ continue
786
+ data.append({"label": label, "value": val})
787
  logger.info(f"Fallback parse from text: extracted {len(data)} items for potential chart")
788
  if len(data) >= 2:
789
  chart_fig = generate_chart(
 
793
  y="value",
794
  title="Distribución"
795
  )
796
+ if chart_fig is not None:
797
+ logger.info(f"Chart generated from text fallback: type={desired_type}, items={len(data)}")
 
 
 
 
 
 
798
 
799
  # Update the assistant's message with the response
800
  assistant_message["content"] = response_text