grshot commited on
Commit
7528f0e
·
1 Parent(s): a58a2c6

adjust tools and llm

Browse files
Files changed (3) hide show
  1. agent.py +83 -28
  2. app.py +2 -1
  3. requirements.txt +5 -1
agent.py CHANGED
@@ -2,16 +2,30 @@ import os
2
  from typing import Dict, List, Sequence, TypedDict, cast
3
 
4
  from dotenv import load_dotenv
5
- from langchain_community.document_loaders import WikipediaLoader
6
  from langchain_core.messages import AIMessage, HumanMessage, SystemMessage
7
  from langchain_core.tools import tool
8
- from langchain_groq import ChatGroq
 
9
  from langchain_tavily import TavilySearch
10
  from langgraph.graph import END, START, MessagesState, StateGraph
11
  from langgraph.prebuilt import ToolNode, tools_condition
 
12
 
13
 
14
- @tool
 
 
 
 
 
 
 
 
 
 
 
 
15
  def search_web(query: str) -> Dict[str, str]:
16
  """Search the web using Tavily and return relevant results."""
17
  try:
@@ -34,7 +48,7 @@ def search_web(query: str) -> Dict[str, str]:
34
  return {"error": f"Error searching web: {str(e)}"}
35
 
36
 
37
- @tool
38
  def search_wikipedia(query: str) -> Dict[str, str]:
39
  """Search Wikipedia using LangChain's loader and return the first document summary."""
40
  try:
@@ -50,6 +64,21 @@ def search_wikipedia(query: str) -> Dict[str, str]:
50
  return {"error": f"Error searching Wikipedia: {str(e)}"}
51
 
52
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
53
  # System prompt
54
  system_prompt = SystemMessage(
55
  content="""You are a helpful and precise assistant. When answering questions:
@@ -75,6 +104,12 @@ Available tools:
75
  Returns: {"web_results": "results"} or {"error": "error message"}
76
  Best for: Recent events, current information, diverse sources
77
  Error handling: If no results found, try more specific search terms
 
 
 
 
 
 
78
 
79
  Tool usage strategy:
80
  1. For historical/factual queries:
@@ -87,12 +122,17 @@ Tool usage strategy:
87
  - If no results, try more specific terms
88
  - Cross-reference with Wikipedia if needed
89
 
90
- 3. For complex queries:
91
- - Use both tools to gather comprehensive info
 
 
 
 
 
92
  - Compare and verify information
93
  - Note any discrepancies in your answer
94
 
95
- 4. When both tools fail:
96
  - Try different phrasings
97
  - Break complex queries into simpler parts
98
  - Be transparent about limitations in your answer
@@ -105,28 +145,40 @@ Your final answer must:
105
  5. Admit uncertainty when information is unclear"""
106
  )
107
 
 
 
 
108
 
109
- def build_agent_graph(provider: str = "groq"):
110
  """Build the graph"""
111
- # Initialize tools
112
- tools = [search_wikipedia, search_web]
113
 
114
- # Initialize LLM with error handling
115
  try:
116
- from pydantic import SecretStr
117
-
118
- groq_api_key = os.getenv("GROQ_API_KEY")
119
- if not groq_api_key:
120
- raise EnvironmentError("GROQ_API_KEY environment variable is not set")
121
-
122
- llm = ChatGroq(
123
- model="qwen-qwq-32b",
124
- temperature=0,
125
- api_key=SecretStr(groq_api_key),
126
- )
 
 
 
 
 
 
 
 
 
 
127
  except Exception as e:
128
  raise Exception(f"Failed to initialize LLM: {str(e)}")
129
- llm_with_tools = llm.bind_tools(tools)
 
130
 
131
  # Create nodes
132
  def assistant(state: MessagesState) -> Dict[str, List[AIMessage]]:
@@ -169,28 +221,31 @@ def test_agent():
169
  print("=" * 50)
170
 
171
  # Check environment variables
172
- if not os.getenv("GROQ_API_KEY"):
173
- print("\nError: GROQ_API_KEY not set")
 
 
 
174
  return
175
  if not os.getenv("TAVILY_API_KEY"):
176
  print("\nWarning: TAVILY_API_KEY not set - web search will be unavailable")
177
 
178
  print("\nInitializing agent...")
179
  try:
180
- graph = build_agent_graph()
181
  print("Agent initialized successfully")
182
  except Exception as e:
183
  print(f"Failed to initialize agent: {str(e)}")
184
  return
185
 
186
  # Test a single question
187
- question = "What is the first name of the only Malko Competition recipient from the 20th Century (after 1977) whose nationality on record is a country that no longer exists?"
188
  print("\nTesting question:", question)
189
  print("-" * 50)
190
 
191
  try:
192
  # Create messages state
193
- messages = [system_prompt, HumanMessage(content=question)]
194
 
195
  # Run agent
196
  print("\nWaiting for response...")
 
2
  from typing import Dict, List, Sequence, TypedDict, cast
3
 
4
  from dotenv import load_dotenv
5
+ from langchain_community.document_loaders import ArxivLoader, WikipediaLoader
6
  from langchain_core.messages import AIMessage, HumanMessage, SystemMessage
7
  from langchain_core.tools import tool
8
+ from langchain_google_genai import ChatGoogleGenerativeAI
9
+ from langchain_huggingface import ChatHuggingFace, HuggingFaceEndpoint
10
  from langchain_tavily import TavilySearch
11
  from langgraph.graph import END, START, MessagesState, StateGraph
12
  from langgraph.prebuilt import ToolNode, tools_condition
13
+ from pydantic import BaseModel
14
 
15
 
16
+ class WebSearchInput(BaseModel):
17
+ query: str
18
+
19
+
20
+ class WikipediaSearchInput(BaseModel):
21
+ query: str
22
+
23
+
24
+ class ArxivSearchInput(BaseModel):
25
+ query: str
26
+
27
+
28
+ @tool(args_schema=WebSearchInput)
29
  def search_web(query: str) -> Dict[str, str]:
30
  """Search the web using Tavily and return relevant results."""
31
  try:
 
48
  return {"error": f"Error searching web: {str(e)}"}
49
 
50
 
51
+ @tool(args_schema=WikipediaSearchInput)
52
  def search_wikipedia(query: str) -> Dict[str, str]:
53
  """Search Wikipedia using LangChain's loader and return the first document summary."""
54
  try:
 
64
  return {"error": f"Error searching Wikipedia: {str(e)}"}
65
 
66
 
67
+ @tool(args_schema=ArxivSearchInput)
68
+ def arxiv_search(query: str) -> Dict[str, str]:
69
+ """Search Arxiv for a query and return maximum 3 result.
70
+ Args:
71
+ query: The search query."""
72
+ search_docs = ArxivLoader(query=query, load_max_docs=3).load()
73
+ formatted_search_docs = "\n\n---\n\n".join(
74
+ [
75
+ f'<Document source="{doc.metadata["source"]}" page="{doc.metadata.get("page", "")}"/>\n{doc.page_content[:1000]}\n</Document>'
76
+ for doc in search_docs
77
+ ]
78
+ )
79
+ return {"arxiv_results": formatted_search_docs}
80
+
81
+
82
  # System prompt
83
  system_prompt = SystemMessage(
84
  content="""You are a helpful and precise assistant. When answering questions:
 
104
  Returns: {"web_results": "results"} or {"error": "error message"}
105
  Best for: Recent events, current information, diverse sources
106
  Error handling: If no results found, try more specific search terms
107
+
108
+ - arxiv_search: Search scholarly papers on arXiv
109
+ Input: {"query": "topic or keywords"}
110
+ Returns: {"arxiv_results": "paper summaries with title, authors, abstract"} or {"error": "error message"}
111
+ Best for: Academic research, recent papers in science and technology
112
+ Error handling: If no results, simplify keywords or broaden the topic
113
 
114
  Tool usage strategy:
115
  1. For historical/factual queries:
 
122
  - If no results, try more specific terms
123
  - Cross-reference with Wikipedia if needed
124
 
125
+ 3. For academic/scientific questions:
126
+ - Use arxiv_search to find recent papers
127
+ - Summarize key findings, topics, or citations
128
+ - Cross-check with web or Wikipedia if needed
129
+
130
+ 4. For complex queries:
131
+ - Use all tools to gather comprehensive info
132
  - Compare and verify information
133
  - Note any discrepancies in your answer
134
 
135
+ 5. Whenall tools fail:
136
  - Try different phrasings
137
  - Break complex queries into simpler parts
138
  - Be transparent about limitations in your answer
 
145
  5. Admit uncertainty when information is unclear"""
146
  )
147
 
148
+ # Initialize tools
149
+ tools = [search_wikipedia, search_web, arxiv_search]
150
+
151
 
152
+ def build_agent_graph(provider: str = "gemini"):
153
  """Build the graph"""
 
 
154
 
155
+ # Initialize LLM class
156
  try:
157
+ gemini_api_key = os.getenv("GEMINI_API_KEY")
158
+
159
+ if provider == "gemini":
160
+ chat_model = ChatGoogleGenerativeAI(
161
+ model="gemini-2.5-pro",
162
+ temperature=1.0,
163
+ max_retries=2,
164
+ google_api_key=gemini_api_key,
165
+ )
166
+ elif provider == "huggingface":
167
+ llm = HuggingFaceEndpoint(
168
+ repo_id="TinyLlama/TinyLlama-1.1B-Chat-v1.0",
169
+ task="text-generation",
170
+ max_new_tokens=1024,
171
+ do_sample=False,
172
+ repetition_penalty=1.03,
173
+ temperature=0,
174
+ )
175
+ chat_model = ChatHuggingFace(llm=llm, verbose=True)
176
+ else:
177
+ raise ValueError("Invalid provider.")
178
  except Exception as e:
179
  raise Exception(f"Failed to initialize LLM: {str(e)}")
180
+
181
+ llm_with_tools = chat_model.bind_tools(tools)
182
 
183
  # Create nodes
184
  def assistant(state: MessagesState) -> Dict[str, List[AIMessage]]:
 
221
  print("=" * 50)
222
 
223
  # Check environment variables
224
+ if not os.getenv("HUGGINGFACEHUB_API_TOKEN"):
225
+ print("\nError: HUGGINGFACEHUB_API_TOKEN not set")
226
+ return
227
+ if not os.getenv("GEMINI_API_KEY"):
228
+ print("\nError: GEMINI_API_KEY not set")
229
  return
230
  if not os.getenv("TAVILY_API_KEY"):
231
  print("\nWarning: TAVILY_API_KEY not set - web search will be unavailable")
232
 
233
  print("\nInitializing agent...")
234
  try:
235
+ graph = build_agent_graph(provider="gemini")
236
  print("Agent initialized successfully")
237
  except Exception as e:
238
  print(f"Failed to initialize agent: {str(e)}")
239
  return
240
 
241
  # Test a single question
242
+ question = "What is the surname of the equine veterinarian mentioned in 1.E Exercises from the chemistry materials licensed by Marisa Alviar-Agnew & Henry Agnew under the CK-12 license in LibreText's Introductory Chemistry materials as compiled 08/21/2023?"
243
  print("\nTesting question:", question)
244
  print("-" * 50)
245
 
246
  try:
247
  # Create messages state
248
+ messages = [HumanMessage(content=question)]
249
 
250
  # Run agent
251
  print("\nWaiting for response...")
app.py CHANGED
@@ -42,7 +42,8 @@ class BasicAgent:
42
  try:
43
  if not self.graph:
44
  raise ValueError("Agent graph not initialized")
45
- result = self.graph.invoke(input_state)
 
46
  except Exception as e:
47
  print(f"Graph invocation error: {str(e)}")
48
  return f"Error: Failed to process request - {str(e)}"
 
42
  try:
43
  if not self.graph:
44
  raise ValueError("Agent graph not initialized")
45
+ # result = self.graph.invoke(input_state)
46
+ result = self.graph.invoke({"messages": [human_msg]})
47
  except Exception as e:
48
  print(f"Graph invocation error: {str(e)}")
49
  return f"Error: Failed to process request - {str(e)}"
requirements.txt CHANGED
@@ -10,4 +10,8 @@ requests
10
  pydantic
11
  lxml
12
  youtube-transcript-api==0.6.3
13
- pytube>=15.0.0
 
 
 
 
 
10
  pydantic
11
  lxml
12
  youtube-transcript-api==0.6.3
13
+ pytube>=15.0.0
14
+ langchain_huggingface
15
+ langchain-google-genai
16
+ pymupdf
17
+ arxiv