naman1102 commited on
Commit
d849921
Β·
1 Parent(s): 5b62ef0

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +49 -53
app.py CHANGED
@@ -21,65 +21,61 @@ DEFAULT_API_URL = "https://agents-course-unit4-scoring.hf.space"
21
  # --- Basic Agent Definition ---
22
  # ----- THIS IS WERE YOU CAN BUILD WHAT YOU WANT ------
23
 
24
-
25
  class AgentState(TypedDict):
26
- messages: Annotated[list, add_messages]
27
- # question: str
28
- # answer: str
29
 
 
30
  llm = ChatOpenAI(model_name="gpt-4.1-mini")
31
 
32
- # 4) Wrap the tools in a single ToolNode
33
- # You can list as many @tool functions here as you like.
34
- # search_node = ToolNode([web_search])
35
-
36
- # excel_tool_node = ToolNode([parse_excel])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
37
 
38
- # image_tool_node = ToolNode([ocr_image])
39
  t_node = ToolNode([ocr_image, parse_excel, web_search])
40
 
41
- def tool_node(state: AgentState, agent_output)-> AgentState:
42
- """
43
- Wrap ToolNode so it matches (state, agent_output) β†’ next_state.
44
- `agent_output` is expected to be a dict like {"tool": "...", ...}.
45
- """
46
- print(f"ToolNode received agent_output: {agent_output}")
47
- # Let the ToolNode run with that dict (ToolNode.run(dict) returns a string)
48
- tool_result: str = tool_node.run(agent_output)
49
- # Now you might want the LLM to reason over tool_result, but for simplicity...
50
- # We'll just store tool_result in messages.
51
- return {"messages": [tool_result]}
52
-
53
 
54
- # 5) Build the StateGraph
55
  graph = StateGraph(AgentState)
 
 
56
 
57
- # ────────────────────────
58
- graph.add_node("agent", llm)
59
- graph.add_node("tools", tool_node)
60
- # Edge A: START β†’ "agent"
61
- # Wrap the user_input into state["messages"]
62
- graph.add_edge(
63
- START,
64
- "agent"
65
- )
66
-
67
- # Edge C: "tools" β†’ "agent"
68
- # Whatever string the tool returns becomes the next prompt to the LLM
69
- graph.add_edge(
70
- "tools",
71
- "agent"
72
- )
73
 
74
- # 7) Use add_conditional_edges out of "agent" instead of two separate edges
 
75
 
76
- def route_agent(state: AgentState, agent_out):
77
- """
78
- Return "tools" if the LLM output is a dict with a valid "tool" key,
79
- otherwise return "final".
80
- """
81
- print(f"Route agent received agent_out: {agent_out}")
82
- if isinstance(agent_out, dict) and agent_out.get("tool") in {"ocr_image", "parse_excel", "web_search"}:
83
  return "tools"
84
  return "final"
85
 
@@ -87,20 +83,20 @@ graph.add_conditional_edges(
87
  "agent",
88
  route_agent,
89
  {
90
- "tools": "tools", # if route_agent(...) == "tools", go to node "tools"
91
- "final": END # if route_agent(...) == "final", go to END
92
  }
93
  )
94
 
 
95
  compiled_graph = graph.compile()
 
96
  def respond_to_input(user_input: str) -> str:
97
- print(f"Reached: User input: {user_input}")
98
- initial_state: AgentState = {"messages": []}
99
- print("reached respond_to_input")
100
  return compiled_graph.invoke(initial_state, user_input)
101
 
102
 
103
-
104
  class BasicAgent:
105
  def __init__(self):
106
  print("BasicAgent initialized.")
 
21
  # --- Basic Agent Definition ---
22
  # ----- THIS IS WERE YOU CAN BUILD WHAT YOU WANT ------
23
 
 
24
  class AgentState(TypedDict):
25
+ messages: Annotated[list[str], add_messages]
26
+ tool: str # will store the name of the requested tool (if any)
27
+ agent_out: str # raw output from the LLM
28
 
29
+ # 2) Instantiate the raw LLM and wrap it in a function
30
  llm = ChatOpenAI(model_name="gpt-4.1-mini")
31
 
32
+ def agent_node(state: AgentState, user_input: str) -> AgentState:
33
+ prev_msgs = state.get("messages", [])
34
+ messages = prev_msgs + [f"USER: {user_input}"]
35
+ # Ask the LLM for a response
36
+ llm_response = llm(messages).content # returns a string or maybe JSON string
37
+ # If you expect JSON with {"tool": "...", ...}, parse it:
38
+ tool_requested = None
39
+ try:
40
+ parsed = eval(llm_response) # (use json.loads if the LLM returns valid JSON)
41
+ if isinstance(parsed, dict) and parsed.get("tool"):
42
+ tool_requested = parsed.get("tool")
43
+ except:
44
+ pass
45
+
46
+ return {
47
+ "messages": messages + [f"ASSISTANT: {llm_response}"],
48
+ "agent_out": llm_response,
49
+ "tool": tool_requested or ""
50
+ }
51
 
52
+ # 3) Instantiate a real ToolNode for your three tools
53
  t_node = ToolNode([ocr_image, parse_excel, web_search])
54
 
55
+ def run_tool_node(state: AgentState, agent_output) -> AgentState:
56
+ # `agent_output` is the dict that the LLM returned, e.g. {"tool":"ocr_image", "path": "file.png"}
57
+ tool_result: str = t_node.run(agent_output)
58
+ return {
59
+ "messages": [f"TOOL RESULT: {tool_result}"],
60
+ "tool": "", # once a tool has run, clear this so we don’t loop forever
61
+ "agent_out": tool_result
62
+ }
 
 
 
 
63
 
64
+ # 4) Build the StateGraph with the corrected node names
65
  graph = StateGraph(AgentState)
66
+ graph.add_node("agent", agent_node)
67
+ graph.add_node("tools", run_tool_node)
68
 
69
+ # 5) START β†’ "agent"
70
+ graph.add_edge(START, "agent")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
71
 
72
+ # 6) "tools" β†’ "agent"
73
+ graph.add_edge("tools", "agent")
74
 
75
+ # 7) Conditional edges out of "agent"
76
+ def route_agent(state: AgentState, agent_output):
77
+ # If LLM asked for a tool, we go to "tools"; else we terminate
78
+ if isinstance(agent_output, dict) and agent_output.get("tool") in {"ocr_image", "parse_excel", "web_search"}:
 
 
 
79
  return "tools"
80
  return "final"
81
 
 
83
  "agent",
84
  route_agent,
85
  {
86
+ "tools": "tools",
87
+ "final": END
88
  }
89
  )
90
 
91
+ # 8) Compile the graph and use run(…), not invoke(…)
92
  compiled_graph = graph.compile()
93
+
94
  def respond_to_input(user_input: str) -> str:
95
+ initial_state: AgentState = {"messages": [], "tool": "", "agent_out": ""}
96
+ # Use .run() in v0.3.x; if you see an AttributeError, switch to .invoke()
 
97
  return compiled_graph.invoke(initial_state, user_input)
98
 
99
 
 
100
  class BasicAgent:
101
  def __init__(self):
102
  print("BasicAgent initialized.")