Jeremy Live
commited on
Commit
·
8717362
1
Parent(s):
9f67f77
Revert "upgrade memoria + UX"
Browse filesThis reverts commit f4fa5e0ca87199aac17eb8dc77f24ade018e6cce.
app.py
CHANGED
@@ -435,17 +435,13 @@ def convert_to_messages_format(chat_history):
|
|
435 |
|
436 |
return messages
|
437 |
|
438 |
-
async def stream_agent_response(question: str, chat_history: List[List[str]]) -> Tuple[str, Optional["go.Figure"]
|
439 |
-
"""Procesa la pregunta del usuario y devuelve
|
440 |
-
|
441 |
-
chart_state schema: {"data": List[Dict], "x_col": str, "y_col": str, "title": str, "chart_type": str}
|
442 |
-
"""
|
443 |
global agent # Make sure we can modify the agent's memory
|
444 |
|
445 |
# Initialize response
|
446 |
response_text = ""
|
447 |
chart_fig = None
|
448 |
-
chart_state: Optional[Dict[str, Any]] = None
|
449 |
messages = []
|
450 |
|
451 |
# Add previous chat history in the correct format for the agent
|
@@ -512,6 +508,7 @@ async def stream_agent_response(question: str, chat_history: List[List[str]]) ->
|
|
512 |
sql_query = extract_sql_query(response_text)
|
513 |
if sql_query and looks_like_sql(sql_query):
|
514 |
logger.info(f"Detected SQL query: {sql_query}")
|
|
|
515 |
db_connection, _ = setup_database_connection()
|
516 |
if db_connection:
|
517 |
query_result = execute_sql_query(sql_query, db_connection)
|
@@ -553,26 +550,24 @@ async def stream_agent_response(question: str, chat_history: List[List[str]]) ->
|
|
553 |
|
554 |
# Choose x/y columns (assume first is category, second numeric)
|
555 |
x_col = columns[0]
|
556 |
-
|
557 |
-
|
558 |
-
|
|
|
559 |
try:
|
560 |
-
|
561 |
-
y_col = col
|
562 |
-
break
|
563 |
except Exception:
|
564 |
-
|
565 |
-
|
566 |
-
|
567 |
-
|
568 |
-
|
569 |
-
|
570 |
-
|
571 |
-
|
572 |
-
|
573 |
-
|
574 |
-
|
575 |
-
chart_state = {"data": data, "x_col": x_col, "y_col": y_col, "title": f"{y_col} por {x_col}", "chart_type": desired_type}
|
576 |
except Exception as e:
|
577 |
logger.error(f"Error generating chart: {str(e)}", exc_info=True)
|
578 |
# Don't fail the whole request if chart generation fails
|
@@ -635,7 +630,6 @@ async def stream_agent_response(question: str, chat_history: List[List[str]]) ->
|
|
635 |
)
|
636 |
if chart_fig is not None:
|
637 |
logger.info("Chart generated from second-pass SQL execution.")
|
638 |
-
chart_state = {"data": data, "x_col": x_col, "y_col": y_col, "title": f"{y_col} por {x_col}", "chart_type": desired_type}
|
639 |
else:
|
640 |
logger.info("No DB connection on second pass; skipping.")
|
641 |
except Exception as e:
|
@@ -693,7 +687,6 @@ async def stream_agent_response(question: str, chat_history: List[List[str]]) ->
|
|
693 |
)
|
694 |
if chart_fig is not None:
|
695 |
logger.info(f"Chart generated from text fallback: type={desired_type}, items={len(data)}")
|
696 |
-
chart_state = {"data": data, "x_col": "label", "y_col": "value", "title": "Distribución", "chart_type": desired_type}
|
697 |
|
698 |
# Update the assistant's message with the response
|
699 |
assistant_message["content"] = response_text
|
@@ -720,7 +713,7 @@ async def stream_agent_response(question: str, chat_history: List[List[str]]) ->
|
|
720 |
logger.info("No chart generated for this turn.")
|
721 |
else:
|
722 |
logger.info("Returning a chart figure to UI.")
|
723 |
-
return message_content, chart_fig
|
724 |
|
725 |
except Exception as e:
|
726 |
error_msg = f"## ❌ Error\n\nOcurrió un error al procesar tu solicitud:\n\n```\n{str(e)}\n```"
|
@@ -931,16 +924,13 @@ def create_ui():
|
|
931 |
|
932 |
# Hidden component for streaming output
|
933 |
streaming_output_display = gr.Textbox(visible=False)
|
934 |
-
|
935 |
-
# Session state to persist last chart data for follow-ups
|
936 |
-
chart_state = gr.State(value=None)
|
937 |
|
938 |
-
return demo, chatbot, chart_display, question_input, submit_button, streaming_output_display
|
939 |
|
940 |
def create_application():
|
941 |
"""Create and configure the Gradio application."""
|
942 |
# Create the UI components
|
943 |
-
demo, chatbot, chart_display, question_input, submit_button, streaming_output_display
|
944 |
|
945 |
def user_message(user_input: str, chat_history: List[Dict[str, str]]) -> Tuple[str, List[Dict[str, str]]]:
|
946 |
"""Add user message to chat history (messages format) and clear input."""
|
@@ -957,14 +947,10 @@ def create_application():
|
|
957 |
|
958 |
return "", chat_history
|
959 |
|
960 |
-
async def bot_response(chat_history: List[Dict[str, str]]
|
961 |
-
"""Generate bot response
|
962 |
-
|
963 |
-
Also accepts and returns chart_state (dict) to support follow-up prompts like
|
964 |
-
'muestra los mismos datos en barras'.
|
965 |
-
"""
|
966 |
if not chat_history:
|
967 |
-
return chat_history, None
|
968 |
|
969 |
# Ensure last message is a user turn awaiting assistant reply
|
970 |
last = chat_history[-1]
|
@@ -975,44 +961,6 @@ def create_application():
|
|
975 |
question = last["content"]
|
976 |
logger.info(f"Processing question: {question}")
|
977 |
|
978 |
-
# Detect quick follow-up re-plot using the same data
|
979 |
-
ql = question.lower()
|
980 |
-
wants_reuse = any(kw in ql for kw in [
|
981 |
-
"mismos datos", "estos mismos", "los mismos", "igual data", "misma data", "con los mismos"
|
982 |
-
])
|
983 |
-
# Determine requested chart type if any
|
984 |
-
desired_type = None
|
985 |
-
if any(k in ql for k in ["barras", "bar", "columnas"]):
|
986 |
-
desired_type = "bar"
|
987 |
-
elif any(k in ql for k in ["línea", "linea", "line"]):
|
988 |
-
desired_type = "line"
|
989 |
-
elif any(k in ql for k in ["pastel", "pie", "circular"]):
|
990 |
-
desired_type = "pie"
|
991 |
-
elif "scatter" in ql or "dispersión" in ql or "dispersion" in ql:
|
992 |
-
desired_type = "scatter"
|
993 |
-
elif "histograma" in ql or "histogram" in ql:
|
994 |
-
desired_type = "histogram"
|
995 |
-
|
996 |
-
if wants_reuse and chart_state_value and isinstance(chart_state_value, dict) and chart_state_value.get("data"):
|
997 |
-
# Re-plot with same data using requested type (or keep previous if not specified)
|
998 |
-
new_type = desired_type or chart_state_value.get("chart_type", "bar")
|
999 |
-
fig = generate_chart(
|
1000 |
-
data=chart_state_value.get("data"),
|
1001 |
-
chart_type=new_type,
|
1002 |
-
x=chart_state_value.get("x_col", "label"),
|
1003 |
-
y=chart_state_value.get("y_col", "value"),
|
1004 |
-
title=chart_state_value.get("title", "Distribución")
|
1005 |
-
)
|
1006 |
-
if fig is not None:
|
1007 |
-
friendly = f"He actualizado la visualización a {('gráfico de ' + new_type) if new_type != 'pie' else 'gráfico circular'} usando los mismos datos."
|
1008 |
-
chat_history.append({"role": "assistant", "content": friendly})
|
1009 |
-
# Save new type in state
|
1010 |
-
chart_state_value = {
|
1011 |
-
**chart_state_value,
|
1012 |
-
"chart_type": new_type,
|
1013 |
-
}
|
1014 |
-
return chat_history, fig, chart_state_value
|
1015 |
-
|
1016 |
# Convert prior messages to pair history for stream_agent_response()
|
1017 |
pair_history: List[List[str]] = []
|
1018 |
i = 0
|
@@ -1031,23 +979,20 @@ def create_application():
|
|
1031 |
i += 1
|
1032 |
|
1033 |
# Call the agent for this new user question
|
1034 |
-
assistant_message, chart_fig
|
1035 |
|
1036 |
# Append assistant message back into messages history
|
1037 |
chat_history.append({"role": "assistant", "content": assistant_message})
|
1038 |
|
1039 |
-
# Update chart_state if provided by the agent path
|
1040 |
-
chart_state_value = new_state if new_state is not None else chart_state_value
|
1041 |
-
|
1042 |
logger.info("Response generation complete")
|
1043 |
-
return chat_history, chart_fig
|
1044 |
|
1045 |
except Exception as e:
|
1046 |
error_msg = f"## ❌ Error\n\nError al procesar la solicitud:\n\n```\n{str(e)}\n```"
|
1047 |
logger.error(error_msg, exc_info=True)
|
1048 |
# Ensure we add an assistant error message for the UI
|
1049 |
chat_history.append({"role": "assistant", "content": error_msg})
|
1050 |
-
return chat_history, None
|
1051 |
|
1052 |
# Event handlers
|
1053 |
with demo:
|
@@ -1059,8 +1004,8 @@ def create_application():
|
|
1059 |
queue=True
|
1060 |
).then(
|
1061 |
fn=bot_response,
|
1062 |
-
inputs=[chatbot
|
1063 |
-
outputs=[chatbot, chart_display
|
1064 |
api_name="ask"
|
1065 |
)
|
1066 |
|
@@ -1072,8 +1017,8 @@ def create_application():
|
|
1072 |
queue=True
|
1073 |
).then(
|
1074 |
fn=bot_response,
|
1075 |
-
inputs=[chatbot
|
1076 |
-
outputs=[chatbot, chart_display
|
1077 |
)
|
1078 |
|
1079 |
return demo
|
|
|
435 |
|
436 |
return messages
|
437 |
|
438 |
+
async def stream_agent_response(question: str, chat_history: List[List[str]]) -> Tuple[str, Optional["go.Figure"]]:
|
439 |
+
"""Procesa la pregunta del usuario y devuelve la respuesta del agente con memoria de conversación."""
|
|
|
|
|
|
|
440 |
global agent # Make sure we can modify the agent's memory
|
441 |
|
442 |
# Initialize response
|
443 |
response_text = ""
|
444 |
chart_fig = None
|
|
|
445 |
messages = []
|
446 |
|
447 |
# Add previous chat history in the correct format for the agent
|
|
|
508 |
sql_query = extract_sql_query(response_text)
|
509 |
if sql_query and looks_like_sql(sql_query):
|
510 |
logger.info(f"Detected SQL query: {sql_query}")
|
511 |
+
# Execute the query and update the response
|
512 |
db_connection, _ = setup_database_connection()
|
513 |
if db_connection:
|
514 |
query_result = execute_sql_query(sql_query, db_connection)
|
|
|
550 |
|
551 |
# Choose x/y columns (assume first is category, second numeric)
|
552 |
x_col = columns[0]
|
553 |
+
y_col = columns[1]
|
554 |
+
|
555 |
+
# Coerce numeric values for y
|
556 |
+
for row in data:
|
557 |
try:
|
558 |
+
row[y_col] = float(re.sub(r"[^0-9.\-]", "", str(row[y_col])))
|
|
|
|
|
559 |
except Exception:
|
560 |
+
pass
|
561 |
+
|
562 |
+
chart_fig = generate_chart(
|
563 |
+
data=data,
|
564 |
+
chart_type=desired_type,
|
565 |
+
x=x_col,
|
566 |
+
y=y_col,
|
567 |
+
title=f"{y_col} por {x_col}"
|
568 |
+
)
|
569 |
+
if chart_fig is not None:
|
570 |
+
logger.info(f"Chart generated from SQL table: type={desired_type}, x={x_col}, y={y_col}, rows={len(data)}")
|
|
|
571 |
except Exception as e:
|
572 |
logger.error(f"Error generating chart: {str(e)}", exc_info=True)
|
573 |
# Don't fail the whole request if chart generation fails
|
|
|
630 |
)
|
631 |
if chart_fig is not None:
|
632 |
logger.info("Chart generated from second-pass SQL execution.")
|
|
|
633 |
else:
|
634 |
logger.info("No DB connection on second pass; skipping.")
|
635 |
except Exception as e:
|
|
|
687 |
)
|
688 |
if chart_fig is not None:
|
689 |
logger.info(f"Chart generated from text fallback: type={desired_type}, items={len(data)}")
|
|
|
690 |
|
691 |
# Update the assistant's message with the response
|
692 |
assistant_message["content"] = response_text
|
|
|
713 |
logger.info("No chart generated for this turn.")
|
714 |
else:
|
715 |
logger.info("Returning a chart figure to UI.")
|
716 |
+
return message_content, chart_fig
|
717 |
|
718 |
except Exception as e:
|
719 |
error_msg = f"## ❌ Error\n\nOcurrió un error al procesar tu solicitud:\n\n```\n{str(e)}\n```"
|
|
|
924 |
|
925 |
# Hidden component for streaming output
|
926 |
streaming_output_display = gr.Textbox(visible=False)
|
|
|
|
|
|
|
927 |
|
928 |
+
return demo, chatbot, chart_display, question_input, submit_button, streaming_output_display
|
929 |
|
930 |
def create_application():
|
931 |
"""Create and configure the Gradio application."""
|
932 |
# Create the UI components
|
933 |
+
demo, chatbot, chart_display, question_input, submit_button, streaming_output_display = create_ui()
|
934 |
|
935 |
def user_message(user_input: str, chat_history: List[Dict[str, str]]) -> Tuple[str, List[Dict[str, str]]]:
|
936 |
"""Add user message to chat history (messages format) and clear input."""
|
|
|
947 |
|
948 |
return "", chat_history
|
949 |
|
950 |
+
async def bot_response(chat_history: List[Dict[str, str]]) -> Tuple[List[Dict[str, str]], Optional[go.Figure]]:
|
951 |
+
"""Generate bot response for messages-format chat history and return optional chart figure."""
|
|
|
|
|
|
|
|
|
952 |
if not chat_history:
|
953 |
+
return chat_history, None
|
954 |
|
955 |
# Ensure last message is a user turn awaiting assistant reply
|
956 |
last = chat_history[-1]
|
|
|
961 |
question = last["content"]
|
962 |
logger.info(f"Processing question: {question}")
|
963 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
964 |
# Convert prior messages to pair history for stream_agent_response()
|
965 |
pair_history: List[List[str]] = []
|
966 |
i = 0
|
|
|
979 |
i += 1
|
980 |
|
981 |
# Call the agent for this new user question
|
982 |
+
assistant_message, chart_fig = await stream_agent_response(question, pair_history)
|
983 |
|
984 |
# Append assistant message back into messages history
|
985 |
chat_history.append({"role": "assistant", "content": assistant_message})
|
986 |
|
|
|
|
|
|
|
987 |
logger.info("Response generation complete")
|
988 |
+
return chat_history, chart_fig
|
989 |
|
990 |
except Exception as e:
|
991 |
error_msg = f"## ❌ Error\n\nError al procesar la solicitud:\n\n```\n{str(e)}\n```"
|
992 |
logger.error(error_msg, exc_info=True)
|
993 |
# Ensure we add an assistant error message for the UI
|
994 |
chat_history.append({"role": "assistant", "content": error_msg})
|
995 |
+
return chat_history, None
|
996 |
|
997 |
# Event handlers
|
998 |
with demo:
|
|
|
1004 |
queue=True
|
1005 |
).then(
|
1006 |
fn=bot_response,
|
1007 |
+
inputs=[chatbot],
|
1008 |
+
outputs=[chatbot, chart_display],
|
1009 |
api_name="ask"
|
1010 |
)
|
1011 |
|
|
|
1017 |
queue=True
|
1018 |
).then(
|
1019 |
fn=bot_response,
|
1020 |
+
inputs=[chatbot],
|
1021 |
+
outputs=[chatbot, chart_display]
|
1022 |
)
|
1023 |
|
1024 |
return demo
|