Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
@@ -29,34 +29,54 @@ agent = create_react_agent(model=llm, tools=tool_node)
|
|
29 |
|
30 |
def plan_node(state: AgentState) -> AgentState:
|
31 |
"""
|
32 |
-
Decide which tool (if any) to call.
|
33 |
-
|
34 |
-
-
|
35 |
-
|
36 |
-
|
37 |
-
|
|
|
|
|
|
|
|
|
|
|
38 |
"""
|
|
|
39 |
user_input = state.get("user_input", "")
|
40 |
-
prior
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
56 |
try:
|
57 |
parsed = eval(llm_out, {}, {})
|
58 |
if isinstance(parsed, dict):
|
59 |
-
|
|
|
60 |
allowed = {
|
61 |
"web_search_query",
|
62 |
"ocr_path",
|
@@ -71,9 +91,9 @@ def plan_node(state: AgentState) -> AgentState:
|
|
71 |
except Exception:
|
72 |
pass
|
73 |
|
74 |
-
# Fallback if parsing failed
|
75 |
return {
|
76 |
-
"messages":
|
77 |
"final_answer": "Sorry, I could not parse your intent."
|
78 |
}
|
79 |
|
|
|
29 |
|
30 |
def plan_node(state: AgentState) -> AgentState:
|
31 |
"""
|
32 |
+
Decide which tool (if any) to call. The state is expected to contain:
|
33 |
+
- state["messages"]: a list of BaseMessage (SystemMessage, HumanMessage, etc.)
|
34 |
+
- state["user_input"]: the raw user question (string)
|
35 |
+
|
36 |
+
We append a new HumanMessage(user_input) to messages, then ask the LLM
|
37 |
+
(via ChatOpenAI) to return exactly one key: web_search_query, ocr_path,
|
38 |
+
excel_path (with excel_sheet_name), or final_answer. The LLM must reply
|
39 |
+
with a bare Python‐dict literal.
|
40 |
+
|
41 |
+
We then return a new partial AgentState that always includes an updated
|
42 |
+
"messages" list plus exactly one of those tool‐request keys (or final_answer).
|
43 |
"""
|
44 |
+
# 1) Pull user_input out of state
|
45 |
user_input = state.get("user_input", "")
|
46 |
+
# 2) Grab prior chat history, which should already be a list of BaseMessage
|
47 |
+
prior_msgs = state.get("messages", [])
|
48 |
+
# 3) Append the new user message as a HumanMessage
|
49 |
+
new_history = prior_msgs + [HumanMessage(content=user_input)]
|
50 |
+
|
51 |
+
# 4) Build a prompt that explains how to choose exactly one key
|
52 |
+
# We leave new_history as a list of BaseMessage; LLM expects that format.
|
53 |
+
explanation = SystemMessage(
|
54 |
+
content=(
|
55 |
+
"You can set exactly one of the following keys (in a Python dict) and nothing else:\n"
|
56 |
+
" • web_search_query: <search terms> \n"
|
57 |
+
" • ocr_path: <path to an image file> \n"
|
58 |
+
" • excel_path: <path to a .xlsx file> \n"
|
59 |
+
" • excel_sheet_name: <sheet name> \n"
|
60 |
+
"Or, if no tool is needed, set final_answer: <your answer>.\n"
|
61 |
+
"Example: {'web_search_query':'Mercedes Sosa discography'}\n"
|
62 |
+
"Respond with only that Python dict literal—no extra text or explanation."
|
63 |
+
)
|
64 |
+
)
|
65 |
+
|
66 |
+
# 5) Combine the user conversation with our explanation
|
67 |
+
prompt_messages = new_history + [explanation]
|
68 |
+
|
69 |
+
# 6) Call the LLM. Because prompt_messages is a list of BaseMessage,
|
70 |
+
# ChatOpenAI will return an AIMessage.
|
71 |
+
llm_response = llm(prompt_messages)
|
72 |
+
llm_out = llm_response.content.strip()
|
73 |
+
|
74 |
+
# 7) Try to eval the LLM response as a Python dict
|
75 |
try:
|
76 |
parsed = eval(llm_out, {}, {})
|
77 |
if isinstance(parsed, dict):
|
78 |
+
# Build a new state: keep our updated messages, plus exactly one key
|
79 |
+
new_state: AgentState = {"messages": new_history}
|
80 |
allowed = {
|
81 |
"web_search_query",
|
82 |
"ocr_path",
|
|
|
91 |
except Exception:
|
92 |
pass
|
93 |
|
94 |
+
# 8) Fallback if parsing failed: keep messages, set a generic final_answer
|
95 |
return {
|
96 |
+
"messages": new_history,
|
97 |
"final_answer": "Sorry, I could not parse your intent."
|
98 |
}
|
99 |
|