rsobieski commited on
Commit
cfa3fb2
·
verified ·
1 Parent(s): 713c540

Update agent.py

Browse files
Files changed (1) hide show
  1. agent.py +51 -35
agent.py CHANGED
@@ -1,11 +1,10 @@
1
  import os
2
  import pandas as pd
3
  from langchain_core.messages import HumanMessage, AIMessage
4
- from langgraph.graph import StateGraph, MessagesState
5
- from langchain_huggingface import HuggingFaceEndpoint
6
- from tools import TOOLS
7
 
8
- # --- Read local QA data for retriever ---
9
  QA_PATH = "metadata.jsonl"
10
  qa_pairs = pd.read_json(QA_PATH, lines=True)
11
  qa_dict = {
@@ -14,7 +13,6 @@ qa_dict = {
14
  }
15
 
16
  def build_graph():
17
- # Initialize Mistral model with proper configuration
18
  llm = HuggingFaceEndpoint(
19
  endpoint_url="https://api-inference.huggingface.co/models/mistralai/Mistral-7B-Instruct-v0.3",
20
  task="text-generation",
@@ -25,50 +23,43 @@ def build_graph():
25
  huggingfacehub_api_token=os.environ["HF_TOKEN"]
26
  )
27
 
28
- # Retriever node
29
  def retriever_node(state: MessagesState):
30
  query = state["messages"][-1].content.strip()
31
  if query in qa_dict:
32
  print("✅ Exact match found in retriever.")
33
- return {"messages": [AIMessage(content=qa_dict[query])]}
34
- print("🔍 No match. Sending to LLM.")
35
- return {"messages": state["messages"]}
 
36
 
37
- # Assistant node (LLM)
38
  def assistant_node(state: MessagesState):
39
  query = state["messages"][-1].content.strip()
40
 
41
- # Format system prompt
42
  system_prompt = (
43
- "You are a helpful assistant evaluated by the GAIA benchmark. "
44
- "Only return the final answer, with no explanations. "
45
- "- No prefixes like 'Final answer:' "
46
- "- If it's a list, output comma-separated "
47
- "- If unknown, say 'Unknown' "
48
- "- Never justify or explain"
49
  )
50
 
51
- # Format prompt for Mistral model
52
  messages = [
53
  {"role": "system", "content": system_prompt},
54
  {"role": "user", "content": query}
55
  ]
56
 
57
- # Generate response
58
  response = llm.invoke(messages).strip()
59
 
60
- # Clean up response
61
- for tag in ("Final answer:", "Answer:", "assistant:", "assistant:"):
62
  if response.lower().startswith(tag.lower()):
63
  response = response[len(tag):].strip()
64
 
65
- return {"messages": [AIMessage(content=response.strip())]}
66
 
67
- # Tool node
68
  def tool_node(state: MessagesState):
 
69
  try:
70
- tool_signal = state.get("tool_call", "")
71
- _, tool_name, tool_input = tool_signal.split(":", 2)
72
  tool_name = tool_name.strip()
73
  tool_input = tool_input.strip()
74
  tool_fn = TOOLS.get(tool_name)
@@ -83,23 +74,40 @@ def build_graph():
83
 
84
  except Exception as e:
85
  print(f"⚠️ Tool error: {e}")
86
- return {"messages": [AIMessage(content="Unknown")]} # fail-safe
 
 
 
 
 
 
 
 
 
 
 
87
 
88
- # Build LangGraph
89
  builder = StateGraph(MessagesState)
90
  builder.add_node("retriever", retriever_node)
91
  builder.add_node("assistant", assistant_node)
92
  builder.add_node("tool", tool_node)
93
 
94
  builder.set_entry_point("retriever")
95
- builder.add_edge("retriever", "assistant")
96
- builder.add_edge("assistant", "tool")
 
 
 
 
 
 
 
 
 
97
  builder.add_edge("tool", "assistant")
98
- builder.set_finish_point("assistant")
99
 
100
  return builder.compile()
101
 
102
- # Agent class
103
  class BasicAgent:
104
  def __init__(self):
105
  print("✅ BasicAgent initialized with retriever + LLM + tools")
@@ -107,7 +115,15 @@ class BasicAgent:
107
 
108
  def __call__(self, question: str) -> str:
109
  print(f"📥 Question: {question[:100]}")
110
- result = self.graph.invoke({"messages": [HumanMessage(content=question)]})
111
- answer = result["messages"][-1].content.strip()
112
- print(f"📤 Answer: {answer}")
113
- return answer
 
 
 
 
 
 
 
 
 
1
  import os
2
  import pandas as pd
3
  from langchain_core.messages import HumanMessage, AIMessage
4
+ from langgraph.graph import StateGraph, END, MessagesState
5
+ from langchain_huggingface import HuggingFaceEndpoint
6
+ from tools import TOOLS
7
 
 
8
  QA_PATH = "metadata.jsonl"
9
  qa_pairs = pd.read_json(QA_PATH, lines=True)
10
  qa_dict = {
 
13
  }
14
 
15
  def build_graph():
 
16
  llm = HuggingFaceEndpoint(
17
  endpoint_url="https://api-inference.huggingface.co/models/mistralai/Mistral-7B-Instruct-v0.3",
18
  task="text-generation",
 
23
  huggingfacehub_api_token=os.environ["HF_TOKEN"]
24
  )
25
 
 
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
+ answer = qa_dict[query]
31
+ return {"messages": [AIMessage(content=answer)]}
32
+ print("🔍 No match. Passing to LLM.")
33
+ return
34
 
 
35
  def assistant_node(state: MessagesState):
36
  query = state["messages"][-1].content.strip()
37
 
 
38
  system_prompt = (
39
+ "You are a helpful assistant. To answer the user's question, you can use tools. "
40
+ "To use a tool, respond with a single line: 'tool:tool_name:input'. "
41
+ "For example: 'tool:wiki_search:Apple Inc.' "
42
+ "If you have the final answer, provide it directly without any prefixes. "
43
+ "Never justify or explain your final answer."
 
44
  )
45
 
 
46
  messages = [
47
  {"role": "system", "content": system_prompt},
48
  {"role": "user", "content": query}
49
  ]
50
 
 
51
  response = llm.invoke(messages).strip()
52
 
53
+ for tag in ("", "Answer:", "assistant:"):
 
54
  if response.lower().startswith(tag.lower()):
55
  response = response[len(tag):].strip()
56
 
57
+ return {"messages": [AIMessage(content=response)]}
58
 
 
59
  def tool_node(state: MessagesState):
60
+ last_message = state["messages"][-1].content.strip()
61
  try:
62
+ _, tool_name, tool_input = last_message.split(":", 2)
 
63
  tool_name = tool_name.strip()
64
  tool_input = tool_input.strip()
65
  tool_fn = TOOLS.get(tool_name)
 
74
 
75
  except Exception as e:
76
  print(f"⚠️ Tool error: {e}")
77
+ return {"messages": [AIMessage(content="Unknown")]}
78
+
79
+ def route_after_retriever(state: MessagesState):
80
+ if isinstance(state["messages"][-1], AIMessage):
81
+ return END
82
+ return "assistant"
83
+
84
+ def route_after_assistant(state: MessagesState):
85
+ last_message = state["messages"][-1].content.strip().lower()
86
+ if last_message.startswith("tool:"):
87
+ return "tool"
88
+ return END
89
 
 
90
  builder = StateGraph(MessagesState)
91
  builder.add_node("retriever", retriever_node)
92
  builder.add_node("assistant", assistant_node)
93
  builder.add_node("tool", tool_node)
94
 
95
  builder.set_entry_point("retriever")
96
+
97
+ builder.add_conditional_edges(
98
+ "retriever",
99
+ route_after_retriever,
100
+ {"assistant": "assistant", END: END}
101
+ )
102
+ builder.add_conditional_edges(
103
+ "assistant",
104
+ route_after_assistant,
105
+ {"tool": "tool", END: END}
106
+ )
107
  builder.add_edge("tool", "assistant")
 
108
 
109
  return builder.compile()
110
 
 
111
  class BasicAgent:
112
  def __init__(self):
113
  print("✅ BasicAgent initialized with retriever + LLM + tools")
 
115
 
116
  def __call__(self, question: str) -> str:
117
  print(f"📥 Question: {question[:100]}")
118
+ config = {"recursion_limit": 50}
119
+ try:
120
+ result = self.graph.invoke(
121
+ {"messages": [HumanMessage(content=question)]},
122
+ config=config
123
+ )
124
+ answer = result["messages"][-1].content.strip()
125
+ print(f"📤 Answer: {answer}")
126
+ return answer
127
+ except Exception as e:
128
+ print(f"Error during graph invocation: {e}")
129
+ return f"AGENT ERROR: {e}"