DarkRodry commited on
Commit
b24aefb
·
1 Parent(s): 3298bf0

agent graph improvements

Browse files
Files changed (3) hide show
  1. agent.py +36 -15
  2. requirements.txt +1 -0
  3. tools.py +6 -2
agent.py CHANGED
@@ -1,27 +1,48 @@
1
  from langchain_google_genai import ChatGoogleGenerativeAI
2
- from langchain_core.messages import HumanMessage, SystemMessage
3
- from tools import *
 
 
 
 
 
4
 
5
  model = ChatGoogleGenerativeAI(model="gemini-2.5-flash", temperature=0)
 
6
 
7
  system_template = "You are a general AI assistant. I will ask you a question. Your final answer should be a number OR as few words as possible OR a comma separated list of numbers and/or strings. If you are asked for a number, don't use comma to write your number neither use units such as $ or percent sign unless specified otherwise. If you are asked for a string, don't use articles, neither abbreviations (e.g. for cities), and write the digits in plain text unless specified otherwise. If you are asked for a comma separated list, apply the above rules depending of whether the element to be put in the list is a number or a string."
8
- messages = [
9
- SystemMessage(system_template),
10
- HumanMessage("I'm making a grocery list for my mom, but she's a professor of botany and she's a real stickler when it comes to categorizing things. I need to add different foods to different categories on the grocery list, but if I make a mistake, she won't buy anything inserted in the wrong category. Here's the list I have so far:\n\nmilk, eggs, flour, whole bean coffee, Oreos, sweet potatoes, fresh basil, plums, green beans, rice, corn, bell pepper, whole allspice, acorns, broccoli, celery, zucchini, lettuce, peanuts\n\nI need to make headings for the fruits and vegetables. Could you please create a list of just the vegetables from my list? If you could do that, then I can figure out how to categorize the rest of the list into the appropriate categories. But remember that my mom is a real stickler, so make sure that no botanical fruits end up on the vegetable list, or she won't get them when she's at the store. Please alphabetize the list of vegetables, and place each item in a comma separated list."),
11
- ]
12
 
13
- tools = [web_search]
 
14
 
15
- model_with_tools = model.bind_tools(tools)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
16
 
17
  def invoke_agent(query: str) -> str:
18
  """
19
  Invoke the agent with a given question.
20
  """
21
- messages = [
22
- SystemMessage(system_template),
23
- HumanMessage(query),
24
- ]
25
-
26
- response = model.invoke(messages)
27
- return response.text()
 
1
  from langchain_google_genai import ChatGoogleGenerativeAI
2
+ from langchain_core.messages import HumanMessage, SystemMessage, AnyMessage
3
+ from typing import TypedDict, Annotated
4
+ from langgraph.graph.message import add_messages
5
+ from langgraph.prebuilt import ToolNode
6
+ from langgraph.graph import START, StateGraph
7
+ from langgraph.prebuilt import tools_condition
8
+ from tools import tools
9
 
10
  model = ChatGoogleGenerativeAI(model="gemini-2.5-flash", temperature=0)
11
+ model_with_tools = model.bind_tools(tools)
12
 
13
  system_template = "You are a general AI assistant. I will ask you a question. Your final answer should be a number OR as few words as possible OR a comma separated list of numbers and/or strings. If you are asked for a number, don't use comma to write your number neither use units such as $ or percent sign unless specified otherwise. If you are asked for a string, don't use articles, neither abbreviations (e.g. for cities), and write the digits in plain text unless specified otherwise. If you are asked for a comma separated list, apply the above rules depending of whether the element to be put in the list is a number or a string."
 
 
 
 
14
 
15
+ class AgentState(TypedDict):
16
+ messages: Annotated[list[AnyMessage], add_messages]
17
 
18
+ def assistant(state: AgentState):
19
+ return {
20
+ "messages": [model_with_tools.invoke(state["messages"])],
21
+ }
22
+
23
+ ## The graph
24
+ builder = StateGraph(AgentState)
25
+
26
+ # Define nodes: these do the work
27
+ builder.add_node("assistant", assistant)
28
+ builder.add_node("tools", ToolNode(tools))
29
+
30
+ # Define edges: these determine how the control flow moves
31
+ builder.add_edge(START, "assistant")
32
+ builder.add_conditional_edges(
33
+ "assistant",
34
+ # If the latest message requires a tool, route to tools
35
+ # Otherwise, provide a direct response
36
+ tools_condition,
37
+ )
38
+ builder.add_edge("tools", "assistant")
39
+ chat = builder.compile()
40
+
41
+ config = {"configurable": {"thread_id": "1"}}
42
 
43
  def invoke_agent(query: str) -> str:
44
  """
45
  Invoke the agent with a given question.
46
  """
47
+ response = chat.invoke({"messages": [HumanMessage(content=query)]})
48
+ return response['messages'][-1].content
 
 
 
 
 
requirements.txt CHANGED
@@ -1,5 +1,6 @@
1
  gradio
2
  requests
 
3
  langchain
4
  langchain-community
5
  langchain-google-genai
 
1
  gradio
2
  requests
3
+ langgraph
4
  langchain
5
  langchain-community
6
  langchain-google-genai
tools.py CHANGED
@@ -1,3 +1,7 @@
1
- from langchain_community.tools import DuckDuckGoSearchRun
2
 
3
- web_search = DuckDuckGoSearchRun()
 
 
 
 
 
1
+ from langchain_community.tools import DuckDuckGoSearchResults
2
 
3
+ web_search = DuckDuckGoSearchResults()
4
+
5
+ tools = [
6
+ web_search
7
+ ]