Jeremy Live commited on
Commit
d42de93
·
1 Parent(s): f504669

upgrade v2 graph

Browse files
Files changed (1) hide show
  1. app.py +64 -5
app.py CHANGED
@@ -578,19 +578,78 @@ async def stream_agent_response(question: str, chat_history: List[List[str]]) ->
578
  response_text += "\n\n⚠️ No se pudo conectar a la base de datos para ejecutar la consulta."
579
  elif sql_query and not looks_like_sql(sql_query):
580
  logger.info("Detected code block but it does not look like SQL; skipping execution.")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
581
 
582
  # Fallback: if user asked for a chart (e.g., pie) and we didn't get SQL or chart yet,
583
  # parse the most recent assistant text for lines like "LABEL: NUMBER" (bulleted or plain).
584
  if chart_fig is None:
585
  q_lower = question.lower()
586
  wants_chart = any(k in q_lower for k in ["gráfico", "grafico", "chart", "graph", "pastel", "pie"])
587
- if wants_chart and chat_history:
588
  # Find the most recent assistant message with usable numeric pairs
589
  candidate_text = ""
590
- for pair in reversed(chat_history):
591
- if len(pair) >= 2 and isinstance(pair[1], str) and pair[1].strip():
592
- candidate_text = pair[1]
593
- break
 
594
  # Also consider current response_text as a data source
595
  if not candidate_text and isinstance(response_text, str) and response_text.strip():
596
  candidate_text = response_text
 
578
  response_text += "\n\n⚠️ No se pudo conectar a la base de datos para ejecutar la consulta."
579
  elif sql_query and not looks_like_sql(sql_query):
580
  logger.info("Detected code block but it does not look like SQL; skipping execution.")
581
+
582
+ # If we still have no chart but the user clearly wants one,
583
+ # try a second pass to get ONLY a SQL query from the agent and execute it.
584
+ if chart_fig is None:
585
+ q_lower = question.lower()
586
+ wants_chart = any(k in q_lower for k in ["gráfico", "grafico", "chart", "graph", "pastel", "pie"])
587
+ if wants_chart:
588
+ try:
589
+ logger.info("Second pass: asking agent for ONLY SQL query in fenced block.")
590
+ sql_only_prompt = (
591
+ "Devuelve SOLO la consulta SQL en un bloque ```sql``` para responder a: "
592
+ f"{question}. No incluyas explicación ni texto adicional."
593
+ )
594
+ sql_only_resp = await agent.ainvoke({"input": sql_only_prompt})
595
+ sql_only_text = str(sql_only_resp)
596
+ sql_query2 = extract_sql_query(sql_only_text)
597
+ if sql_query2 and looks_like_sql(sql_query2):
598
+ logger.info(f"Second pass SQL detected: {sql_query2}")
599
+ db_connection, _ = setup_database_connection()
600
+ if db_connection:
601
+ query_result = execute_sql_query(sql_query2, db_connection)
602
+ # Try to parse table-like text into DataFrame if possible
603
+ data = None
604
+ if isinstance(query_result, str):
605
+ try:
606
+ import pandas as pd
607
+ df = pd.read_csv(io.StringIO(query_result), sep="|")
608
+ data = df
609
+ except Exception:
610
+ pass
611
+ # As a fallback, don't rely on text table; just skip charting here
612
+ if data is not None and hasattr(data, "empty") and not data.empty:
613
+ # Heuristics: choose first column as x and second as y if numeric
614
+ x_col = data.columns[0]
615
+ # pick first numeric column different to x
616
+ y_col = None
617
+ for col in data.columns[1:]:
618
+ try:
619
+ pd.to_numeric(data[col])
620
+ y_col = col
621
+ break
622
+ except Exception:
623
+ continue
624
+ if y_col:
625
+ desired_type = 'pie' if any(k in q_lower for k in ["gráfico circular", "grafico circular", "pie", "pastel"]) else 'bar'
626
+ chart_fig = generate_chart(
627
+ data=data,
628
+ chart_type=desired_type,
629
+ x=x_col,
630
+ y=y_col,
631
+ title=f"{y_col} por {x_col}"
632
+ )
633
+ if chart_fig is not None:
634
+ logger.info("Chart generated from second-pass SQL execution.")
635
+ else:
636
+ logger.info("No DB connection on second pass; skipping.")
637
+ except Exception as e:
638
+ logger.error(f"Second-pass SQL synthesis failed: {e}")
639
 
640
  # Fallback: if user asked for a chart (e.g., pie) and we didn't get SQL or chart yet,
641
  # parse the most recent assistant text for lines like "LABEL: NUMBER" (bulleted or plain).
642
  if chart_fig is None:
643
  q_lower = question.lower()
644
  wants_chart = any(k in q_lower for k in ["gráfico", "grafico", "chart", "graph", "pastel", "pie"])
645
+ if wants_chart:
646
  # Find the most recent assistant message with usable numeric pairs
647
  candidate_text = ""
648
+ if chat_history:
649
+ for pair in reversed(chat_history):
650
+ if len(pair) >= 2 and isinstance(pair[1], str) and pair[1].strip():
651
+ candidate_text = pair[1]
652
+ break
653
  # Also consider current response_text as a data source
654
  if not candidate_text and isinstance(response_text, str) and response_text.strip():
655
  candidate_text = response_text