Spaces:
Sleeping
Sleeping
short
Browse files
app.py
CHANGED
@@ -95,15 +95,16 @@ def plan_node(state: AgentState) -> AgentState:
|
|
95 |
# ─── 3) Revised finalize_node ───
|
96 |
def finalize_node(state: AgentState) -> AgentState:
|
97 |
if state.get("final_answer") is not None:
|
98 |
-
print(">>> finalize_node: returning existing final_answer:", state["final_answer"])
|
99 |
return {"final_answer": state["final_answer"]}
|
100 |
|
|
|
101 |
question = ""
|
102 |
for msg in reversed(state.get("messages", [])):
|
103 |
if isinstance(msg, HumanMessage):
|
104 |
question = msg.content
|
105 |
break
|
106 |
|
|
|
107 |
combined = f"USER_QUESTION: {question}\n"
|
108 |
if sr := state.get("web_search_result"):
|
109 |
combined += f"WEB_SEARCH_RESULT: {sr}\n"
|
@@ -111,20 +112,35 @@ def finalize_node(state: AgentState) -> AgentState:
|
|
111 |
combined += f"OCR_RESULT: {orc}\n"
|
112 |
if exr := state.get("excel_result"):
|
113 |
combined += f"EXCEL_RESULT: {exr}\n"
|
114 |
-
|
115 |
-
if
|
116 |
-
combined += f"AUDIO_TRANSCRIPT: {
|
117 |
|
|
|
118 |
combined += (
|
119 |
-
"Based on the above,
|
120 |
-
"
|
|
|
|
|
|
|
|
|
|
|
121 |
)
|
122 |
|
123 |
-
#
|
124 |
-
print("\n>>> finalize_node prompt
|
125 |
|
126 |
llm_response = llm([SystemMessage(content=combined)])
|
127 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
128 |
|
129 |
# ─── 4) Wrap tools in a ToolNode ───
|
130 |
def tool_node(state: AgentState) -> AgentState:
|
|
|
95 |
# ─── 3) Revised finalize_node ───
|
96 |
def finalize_node(state: AgentState) -> AgentState:
|
97 |
if state.get("final_answer") is not None:
|
|
|
98 |
return {"final_answer": state["final_answer"]}
|
99 |
|
100 |
+
# Re‐extract the last user question
|
101 |
question = ""
|
102 |
for msg in reversed(state.get("messages", [])):
|
103 |
if isinstance(msg, HumanMessage):
|
104 |
question = msg.content
|
105 |
break
|
106 |
|
107 |
+
# Build one monolithic context
|
108 |
combined = f"USER_QUESTION: {question}\n"
|
109 |
if sr := state.get("web_search_result"):
|
110 |
combined += f"WEB_SEARCH_RESULT: {sr}\n"
|
|
|
112 |
combined += f"OCR_RESULT: {orc}\n"
|
113 |
if exr := state.get("excel_result"):
|
114 |
combined += f"EXCEL_RESULT: {exr}\n"
|
115 |
+
# Note: your code already stores the audio transcription under "transcript"
|
116 |
+
if tr := state.get("transcript"):
|
117 |
+
combined += f"AUDIO_TRANSCRIPT: {tr}\n"
|
118 |
|
119 |
+
# Here we demand a JSON response with a single key "final_answer"
|
120 |
combined += (
|
121 |
+
"Based on the above, respond with exactly one JSON object, and nothing else. "
|
122 |
+
"The JSON object must have exactly one key: \"final_answer\". "
|
123 |
+
"For example:\n"
|
124 |
+
"{\"final_answer\":\"42\"}\n"
|
125 |
+
"Do NOT include any explanation, markdown, or any extra whitespace outside the JSON object. "
|
126 |
+
"If the answer is multiple words, put them in a comma-separated string, e.g. \"red,green,blue\". "
|
127 |
+
"If the answer is a number, it must be digits only—e.g. \"725.00\".\n"
|
128 |
)
|
129 |
|
130 |
+
# Debug print
|
131 |
+
print("\n>>> finalize_node JSON‐strict prompt:\n" + combined + "\n<<< end prompt >>>\n")
|
132 |
|
133 |
llm_response = llm([SystemMessage(content=combined)])
|
134 |
+
raw = llm_response.content.strip()
|
135 |
+
print(">>> finalize_node got raw response:", raw)
|
136 |
+
|
137 |
+
try:
|
138 |
+
parsed = json.loads(raw)
|
139 |
+
return {"final_answer": parsed["final_answer"]}
|
140 |
+
except Exception as e:
|
141 |
+
# If the LLM did not return valid JSON, store the error so you can see it
|
142 |
+
print(">>> finalize_node JSON parse error:", e, "raw was:", raw)
|
143 |
+
return {"final_answer": f"ERROR: invalid JSON from finalize_node: {raw}"}
|
144 |
|
145 |
# ─── 4) Wrap tools in a ToolNode ───
|
146 |
def tool_node(state: AgentState) -> AgentState:
|
tools.py
CHANGED
@@ -6,6 +6,7 @@ from pathlib import Path
|
|
6 |
from PIL import Image
|
7 |
import pytesseract
|
8 |
from state import AgentState
|
|
|
9 |
def web_search_tool(state: AgentState) -> AgentState:
|
10 |
"""
|
11 |
Expects: state["web_search_query"] is a non‐empty string.
|
|
|
6 |
from PIL import Image
|
7 |
import pytesseract
|
8 |
from state import AgentState
|
9 |
+
from langchain.schema import HumanMessage
|
10 |
def web_search_tool(state: AgentState) -> AgentState:
|
11 |
"""
|
12 |
Expects: state["web_search_query"] is a non‐empty string.
|