rsobieski commited on
Commit
a72ec7c
Β·
verified Β·
1 Parent(s): 95f4932

Update agent.py

Browse files
Files changed (1) hide show
  1. agent.py +50 -34
agent.py CHANGED
@@ -2,9 +2,9 @@ import os
2
  import pandas as pd
3
  from langchain_core.messages import HumanMessage, AIMessage
4
  from langgraph.graph import StateGraph, MessagesState
5
- from langgraph.prebuilt import ToolNode, tools_condition
6
  from langchain_huggingface import HuggingFaceEndpoint
7
- from tools import TOOLS
8
 
9
  # --- Load local QA metadata for retriever ---
10
  QA_PATH = "metadata.jsonl"
@@ -14,74 +14,90 @@ qa_dict = {
14
  for _, row in qa_pairs.iterrows()
15
  }
16
 
17
- from langchain_huggingface import HuggingFaceEndpoint
18
-
19
  def build_graph():
20
  llm = HuggingFaceEndpoint(
21
- # repo_id="Qwen/Qwen2.5-32B-Instruct",
22
  repo_id="mistralai/Mistral-7B-Instruct-v0.3",
23
  task="text-generation",
24
  huggingfacehub_api_token=os.environ["HF_TOKEN"]
25
  )
26
-
27
- llm_with_tools = llm.bind_tools(TOOLS)
28
-
29
 
30
- # Node: retriever
31
  def retriever_node(state: MessagesState):
32
  query = state["messages"][-1].content.strip()
33
  if query in qa_dict:
34
  print("βœ… Exact match found in retriever.")
35
  return {"messages": [AIMessage(content=qa_dict[query])]}
36
- print("πŸ” No match found. Falling back to LLM.")
37
  return {"messages": state["messages"]}
38
 
39
- # Node: assistant
40
  def assistant_node(state: MessagesState):
41
  query = state["messages"][-1].content.strip()
42
 
43
- system_prompt = (
44
- "You are a helpful assistant evaluated by the GAIA benchmark.\n"
45
- "Only return the final answer, with no explanations.\n"
46
- "- No prefixes like 'Final answer:'\n"
47
- "- If it's a list, output comma-separated\n"
48
- "- If unknown, say 'Unknown'\n"
49
- "- Never justify or explain"
50
  )
51
 
52
- # LangChain expects list of messages for tool-call-capable models
53
- messages = [
54
- {"role": "system", "content": system_prompt},
55
- {"role": "user", "content": query},
56
- ]
 
 
 
 
 
 
57
 
58
- response = llm_with_tools.invoke(messages)
59
- return {"messages": [AIMessage(content=response.strip())]}
 
 
 
 
 
 
60
 
61
- # === Build LangGraph ===
 
 
 
 
 
 
 
 
 
 
 
 
62
  builder = StateGraph(MessagesState)
63
  builder.add_node("retriever", retriever_node)
64
  builder.add_node("assistant", assistant_node)
65
- builder.add_node("tools", ToolNode(TOOLS)) # LangGraph's tool executor
66
 
67
- # --- Edges ---
68
  builder.set_entry_point("retriever")
69
  builder.add_edge("retriever", "assistant")
70
- builder.add_conditional_edges("assistant", tools_condition)
71
- builder.add_edge("tools", "assistant")
72
  builder.set_finish_point("assistant")
73
 
74
  return builder.compile()
75
 
76
-
77
- # --- Agent class wrapper for app.py ---
78
  class BasicAgent:
79
  def __init__(self):
80
- print("BasicAgent initialized with retriever + fallback LLM.")
81
  self.graph = build_graph()
82
 
83
  def __call__(self, question: str) -> str:
84
- print(f"πŸ“₯ Received question: {question[:80]}")
85
  result = self.graph.invoke({"messages": [HumanMessage(content=question)]})
86
  answer = result["messages"][-1].content.strip()
87
  print(f"πŸ“€ Answer: {answer}")
 
2
  import pandas as pd
3
  from langchain_core.messages import HumanMessage, AIMessage
4
  from langgraph.graph import StateGraph, MessagesState
5
+ from langgraph.prebuilt import ToolNode
6
  from langchain_huggingface import HuggingFaceEndpoint
7
+ from tools import TOOLS # your dictionary of tool functions
8
 
9
  # --- Load local QA metadata for retriever ---
10
  QA_PATH = "metadata.jsonl"
 
14
  for _, row in qa_pairs.iterrows()
15
  }
16
 
17
+ # === LangGraph builder ===
 
18
  def build_graph():
19
  llm = HuggingFaceEndpoint(
 
20
  repo_id="mistralai/Mistral-7B-Instruct-v0.3",
21
  task="text-generation",
22
  huggingfacehub_api_token=os.environ["HF_TOKEN"]
23
  )
 
 
 
24
 
25
+ # Node 1: Retriever
26
  def retriever_node(state: MessagesState):
27
  query = state["messages"][-1].content.strip()
28
  if query in qa_dict:
29
  print("βœ… Exact match found in retriever.")
30
  return {"messages": [AIMessage(content=qa_dict[query])]}
31
+ print("πŸ” No match. Sending to LLM.")
32
  return {"messages": state["messages"]}
33
 
34
+ # Node 2: Assistant (LLM response parsing)
35
  def assistant_node(state: MessagesState):
36
  query = state["messages"][-1].content.strip()
37
 
38
+ prompt = (
39
+ "You are a helpful assistant for GAIA benchmark.\n"
40
+ "If you can answer directly, output ONLY the answer.\n"
41
+ "If you need to use a tool, reply in this format:\n"
42
+ "use_tool: <tool_name>: <tool_input>\n"
43
+ "Never explain anything."
 
44
  )
45
 
46
+ full_prompt = f"{prompt}\n\nQuestion: {query}\nAnswer:"
47
+ response = llm.invoke(full_prompt).strip()
48
+ print(f"🧠 LLM said: {response}")
49
+
50
+ if response.startswith("use_tool:"):
51
+ return {
52
+ "messages": state["messages"] + [AIMessage(content=response)],
53
+ "tool_call": response # carry tool signal
54
+ }
55
+ else:
56
+ return {"messages": [AIMessage(content=response)]}
57
 
58
+ # Node 3: Tool execution
59
+ def tool_node(state: MessagesState):
60
+ try:
61
+ tool_signal = state.get("tool_call", "")
62
+ _, tool_name, tool_input = tool_signal.split(":", 2)
63
+ tool_name = tool_name.strip()
64
+ tool_input = tool_input.strip()
65
+ tool_fn = TOOLS.get(tool_name)
66
 
67
+ if not tool_fn:
68
+ print(f"❌ Unknown tool: {tool_name}")
69
+ return {"messages": [AIMessage(content="Unknown")]}
70
+
71
+ print(f"πŸ”§ Using tool: {tool_name} with input: {tool_input}")
72
+ tool_result = tool_fn(tool_input)
73
+ return {"messages": [AIMessage(content=str(tool_result))]}
74
+
75
+ except Exception as e:
76
+ print(f"⚠️ Tool error: {e}")
77
+ return {"messages": [AIMessage(content="Unknown")]} # fail-safe
78
+
79
+ # Build LangGraph
80
  builder = StateGraph(MessagesState)
81
  builder.add_node("retriever", retriever_node)
82
  builder.add_node("assistant", assistant_node)
83
+ builder.add_node("tool", tool_node)
84
 
 
85
  builder.set_entry_point("retriever")
86
  builder.add_edge("retriever", "assistant")
87
+ builder.add_edge("assistant", "tool")
88
+ builder.add_edge("tool", "assistant")
89
  builder.set_finish_point("assistant")
90
 
91
  return builder.compile()
92
 
93
+ # === BasicAgent wrapper ===
 
94
  class BasicAgent:
95
  def __init__(self):
96
+ print("BasicAgent initialized with retriever + LLM + manual tool logic.")
97
  self.graph = build_graph()
98
 
99
  def __call__(self, question: str) -> str:
100
+ print(f"πŸ“₯ Question: {question[:100]}")
101
  result = self.graph.invoke({"messages": [HumanMessage(content=question)]})
102
  answer = result["messages"][-1].content.strip()
103
  print(f"πŸ“€ Answer: {answer}")