samoye16 commited on
Commit
b8c6d5a
·
verified ·
1 Parent(s): 24dd0a1

Create agents.py

Browse files
Files changed (1) hide show
  1. agents.py +135 -0
agents.py ADDED
@@ -0,0 +1,135 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+
3
+ from langgraph.graph import StateGraph, START, MessagesState
4
+ from langgraph.prebuilt import ToolNode, tools_condition
5
+
6
+ from langchain_google_genai import ChatGoogleGenerativeAI
7
+ from langchain_groq import ChatGroq
8
+ from langchain_huggingface import ChatHuggingFace, HuggingFaceEndpoint, HuggingFaceEmbeddings
9
+
10
+ from langchain_community.tools.tavily_search import TavilySearchResults
11
+ from langchain_community.document_loaders import WikipediaLoader, ArxivLoader
12
+ from langchain_community.vectorstores import SupabaseVectorStore
13
+
14
+ from langchain_core.messages import SystemMessage, HumanMessage
15
+ from langchain_core.tools import tool
16
+ from langchain.tools.retriever import create_retriever_tool
17
+
18
+ from supabase.client import create_client, Client
19
+
20
+
21
+ # ---- Basic Arithmetic Utilities ---- #
22
+ @tool
23
+ def multiply(a: int, b: int) -> int:
24
+ """Returns the product of two integers."""
25
+ return a * b
26
+
27
+ @tool
28
+ def add(a: int, b: int) -> int:
29
+ """Returns the sum of two integers."""
30
+ return a + b
31
+
32
+ @tool
33
+ def subtract(a: int, b: int) -> int:
34
+ """Returns the difference between two integers."""
35
+ return a - b
36
+
37
+ @tool
38
+ def divide(a: int, b: int) -> float:
39
+ """Performs division and handles zero division errors."""
40
+ if b == 0:
41
+ raise ValueError("Division by zero is undefined.")
42
+ return a / b
43
+
44
+ @tool
45
+ def modulus(a: int, b: int) -> int:
46
+ """Returns the remainder after division."""
47
+ return a % b
48
+
49
+
50
+ # ---- Search Tools ---- #
51
+ @tool
52
+ def search_wikipedia(query: str) -> str:
53
+ """Returns up to 2 documents related to a query from Wikipedia."""
54
+ docs = WikipediaLoader(query=query, load_max_docs=2).load()
55
+ return {"wiki_results": "\n\n---\n\n".join(
56
+ f'<Document source="{doc.metadata["source"]}" page="{doc.metadata.get("page", "")}"/>\n{doc.page_content}'
57
+ for doc in docs
58
+ )}
59
+
60
+ @tool
61
+ def search_web(query: str) -> str:
62
+ """Fetches up to 3 web results using Tavily."""
63
+ results = TavilySearchResults(max_results=3).invoke(query=query)
64
+ return {"web_results": "\n\n---\n\n".join(
65
+ f'<Document source="{doc.metadata["source"]}" page="{doc.metadata.get("page", "")}"/>\n{doc.page_content}'
66
+ for doc in results
67
+ )}
68
+
69
+ @tool
70
+ def search_arxiv(query: str) -> str:
71
+ """Retrieves up to 3 papers related to the query from ArXiv."""
72
+ results = ArxivLoader(query=query, load_max_docs=3).load()
73
+ return {"arvix_results": "\n\n---\n\n".join(
74
+ f'<Document source="{doc.metadata["source"]}" page="{doc.metadata.get("page", "")}"/>\n{doc.page_content[:1000]}'
75
+ for doc in results
76
+ )}
77
+
78
+
79
+ system_message = SystemMessage(content="""You are a helpful assistant tasked with answering questions using a set of tools. Now, I will ask you a question. Report your thoughts, and finish your answer with the following template:
80
+
81
+ FINAL ANSWER: [YOUR FINAL ANSWER]
82
+
83
+ YOUR FINAL ANSWER should be a number OR as few words as possible OR a comma-separated list of numbers and/or strings.
84
+ - If you are asked for a number, don't use a comma in the number and avoid units like $ or % unless specified otherwise.
85
+ - If you are asked for a string, avoid using articles and abbreviations (e.g. for cities), and write digits in plain text unless specified otherwise.
86
+ - If you are asked for a comma-separated list, apply the above rules depending on whether each item is a number or string.
87
+
88
+ Your answer should start only with "FINAL ANSWER: ", followed by your result.""")
89
+
90
+ toolset = [
91
+ multiply,
92
+ add,
93
+ subtract,
94
+ divide,
95
+ modulus,
96
+ search_wikipedia,
97
+ search_web,
98
+ search_arxiv,
99
+ ]
100
+
101
+
102
+ # ---- Graph Construction ---- #
103
+ def create_agent_flow(provider: str = "groq"):
104
+ """Constructs the LangGraph conversational flow with tool support."""
105
+
106
+ if provider == "google":
107
+ llm = ChatGoogleGenerativeAI(model="gemini-2.0-flash", temperature=0)
108
+ elif provider == "groq":
109
+ llm = ChatGroq(model="qwen-qwq-32b", temperature=0)
110
+ elif provider == "huggingface":
111
+ llm = ChatHuggingFace(llm=HuggingFaceEndpoint(
112
+ url="https://api-inference.huggingface.co/models/Meta-DeepLearning/llama-2-7b-chat-hf",
113
+ temperature=0
114
+ ))
115
+ else:
116
+ raise ValueError("Unsupported provider. Choose from: 'google', 'groq', 'huggingface'.")
117
+
118
+ llm_toolchain = llm.bind_tools(toolset)
119
+
120
+ # Assistant node behavior
121
+ def assistant_node(state: MessagesState):
122
+ response = llm_toolchain.invoke(state["messages"])
123
+ return {"messages": [response]}
124
+
125
+
126
+ # Build the conversational graph
127
+ graph = StateGraph(MessagesState)
128
+ graph.add_node("assistant", assistant_node)
129
+ graph.add_node("tools", ToolNode(toolset))
130
+ graph.add_edge(START, "retriever")
131
+ graph.add_edge("retriever", "assistant")
132
+ graph.add_conditional_edges("assistant", tools_condition)
133
+ graph.add_edge("tools", "assistant")
134
+
135
+ return graph.compile()