felixmortas commited on
Commit
8233fc5
·
1 Parent(s): 5af6e07

Handle API rate limit reached

Browse files
Files changed (4) hide show
  1. app.py +56 -3
  2. custom_tools.py +55 -4
  3. react_agent.py +43 -13
  4. requirements.txt +1 -0
app.py CHANGED
@@ -4,6 +4,7 @@ import requests
4
  import inspect
5
  import pandas as pd
6
  from react_agent import ReActAgent
 
7
 
8
  # (Keep Constants as is)
9
  # --- Constants ---
@@ -70,12 +71,64 @@ def run_and_submit_all( profile: gr.OAuthProfile | None):
70
  print(f"Skipping item with missing task_id or question: {item}")
71
  continue
72
  try:
73
- submitted_answer = agent(item)
74
  answers_payload.append({"task_id": task_id, "submitted_answer": submitted_answer})
75
  results_log.append({"Task ID": task_id, "Question": question_text, "Submitted Answer": submitted_answer})
 
76
  except Exception as e:
77
- print(f"Error running agent on task {task_id}: {e}")
78
- results_log.append({"Task ID": task_id, "Question": question_text, "Submitted Answer": f"AGENT ERROR: {e}"})
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
79
 
80
  if not answers_payload:
81
  print("Agent did not produce any answers to submit.")
 
4
  import inspect
5
  import pandas as pd
6
  from react_agent import ReActAgent
7
+ import time
8
 
9
  # (Keep Constants as is)
10
  # --- Constants ---
 
71
  print(f"Skipping item with missing task_id or question: {item}")
72
  continue
73
  try:
74
+ submitted_answer = agent(str(item))
75
  answers_payload.append({"task_id": task_id, "submitted_answer": submitted_answer})
76
  results_log.append({"Task ID": task_id, "Question": question_text, "Submitted Answer": submitted_answer})
77
+ print(results_log[-1])
78
  except Exception as e:
79
+ print(f"Error running agent on task {task_id}: {e}")
80
+ # results_log.append({"Task ID": task_id, "Question": question_text, "Submitted Answer": f"AGENT ERROR: {e}"})
81
+
82
+ try:
83
+ # Build new client with other provider and retry
84
+ agent = ReActAgent(provider="Google", model="gemini-2.5-pro")
85
+ submitted_answer = agent(str(item))
86
+ answers_payload.append({"task_id": task_id, "submitted_answer": submitted_answer})
87
+ results_log.append({"Task ID": task_id, "Question": question_text, "Submitted Answer": submitted_answer})
88
+ print(results_log[-1])
89
+
90
+ except Exception as e:
91
+ print(f"Error running agent on task {task_id}: {e}")
92
+
93
+ try:
94
+ agent = ReActAgent(provider="Mistral", model="mistral-large-latest")
95
+ submitted_answer = agent(str(item))
96
+ answers_payload.append({"task_id": task_id, "submitted_answer": submitted_answer})
97
+ results_log.append({"Task ID": task_id, "Question": question_text, "Submitted Answer": submitted_answer})
98
+ print(results_log[-1])
99
+
100
+ except Exception as e:
101
+ print(f"Error running agent on task {task_id}: {e}")
102
+
103
+ try:
104
+ agent = ReActAgent(provider="Groq", model="llama-3.3-70b-versatile")
105
+ submitted_answer = agent(str(item))
106
+ answers_payload.append({"task_id": task_id, "submitted_answer": submitted_answer})
107
+ results_log.append({"Task ID": task_id, "Question": question_text, "Submitted Answer": submitted_answer})
108
+ print(results_log[-1])
109
+
110
+ except Exception as e:
111
+ print(f"Error running agent on task {task_id}: {e}")
112
+ try:
113
+ agent = ReActAgent(provider="Groq", model="deepseek-r1-distill-llama-70b")
114
+ submitted_answer = agent(str(item))
115
+ answers_payload.append({"task_id": task_id, "submitted_answer": submitted_answer})
116
+ results_log.append({"Task ID": task_id, "Question": question_text, "Submitted Answer": submitted_answer})
117
+ print(results_log[-1])
118
+ except Exception as e:
119
+ print(f"Error running agent on task {task_id}: {e}")
120
+ try:
121
+ agent = ReActAgent(provider="Groq", model="qwen-qwq-32b")
122
+ submitted_answer = agent(str(item))
123
+ answers_payload.append({"task_id": task_id, "submitted_answer": submitted_answer})
124
+ results_log.append({"Task ID": task_id, "Question": question_text, "Submitted Answer": submitted_answer})
125
+ print(results_log[-1])
126
+ except Exception as e:
127
+ print(f"Error running agent on task {task_id}: {e}")
128
+ results_log.append({"Task ID": task_id, "Question": question_text, "Error": e})
129
+
130
+ # Wait for a while to ensure the agent is not overwhelmed
131
+ time.sleep(10)
132
 
133
  if not answers_payload:
134
  print("Agent did not produce any answers to submit.")
custom_tools.py CHANGED
@@ -7,10 +7,10 @@ from bs4 import BeautifulSoup
7
  import pandas as pd
8
  from dotenv import load_dotenv
9
  from mistralai import Mistral
 
10
 
11
  from requests.exceptions import RequestException, Timeout, TooManyRedirects
12
- import errno
13
- from typing import Optional, List, Union
14
  from youtube_transcript_api._errors import (
15
  TranscriptsDisabled,
16
  NoTranscriptFound,
@@ -20,7 +20,57 @@ from youtube_transcript_api._errors import (
20
  from urllib.parse import urlparse, parse_qs
21
 
22
  from langchain_core.tools import tool
23
- from langchain_community.tools import DuckDuckGoSearchResults
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
24
 
25
 
26
  @tool
@@ -322,7 +372,8 @@ def transcript_audio(task_id: str, file_name: str) -> str:
322
 
323
  custom_tools = [
324
  wiki_search,
325
- DuckDuckGoSearchResults(),
 
326
  # add_numbers,
327
  sum_excel_cols,
328
  youtube_transcript,
 
7
  import pandas as pd
8
  from dotenv import load_dotenv
9
  from mistralai import Mistral
10
+ from groq import Groq
11
 
12
  from requests.exceptions import RequestException, Timeout, TooManyRedirects
13
+ from typing import List, Union
 
14
  from youtube_transcript_api._errors import (
15
  TranscriptsDisabled,
16
  NoTranscriptFound,
 
20
  from urllib.parse import urlparse, parse_qs
21
 
22
  from langchain_core.tools import tool
23
+ from langchain_community.tools import BraveSearch
24
+
25
+ @tool
26
+ def web_search(query: str) -> str:
27
+ """
28
+ Search the web using Brave Search and return the top 3 results.
29
+ Before starting any search, you must first think about the TRUE necessary steps that are required to answer the question.
30
+ If you need to search for information, the query should be just a few keywords that can be used to find the desired web page.
31
+ If the question specifies a date, do not put the date into the query
32
+ Args:
33
+ query (str): The search query.
34
+ Returns:
35
+ str: A string containing the top 3 search results.
36
+ """
37
+ api_key = os.getenv("BRAVE")
38
+ tool = BraveSearch.from_api_key(api_key=api_key, search_kwargs={"count":3, "spellcheck": False})
39
+ results = tool.invoke(query)
40
+ return results
41
+
42
+ @tool
43
+ def url_search(url: str) -> str:
44
+ """
45
+ Access a specific URL provided by the web_search tool call.
46
+
47
+ Args:
48
+ url (str): The URL to access.
49
+
50
+ Returns:
51
+ str: The HTML content of the accessed URL or an error message.
52
+ """
53
+ try:
54
+ response = requests.get(url, timeout=10)
55
+ response.raise_for_status()
56
+ soup = BeautifulSoup(response.text, 'html.parser')
57
+
58
+ for tag in soup(['script']):
59
+ tag.decompose()
60
+
61
+ # Extract and return the body of the page
62
+ body_content = soup.find('body')
63
+ if body_content:
64
+ return body_content.get_text(separator='\n', strip=True)
65
+ else:
66
+ return "No body content found in the accessed URL."
67
+
68
+ except Timeout:
69
+ return "Request timed out while trying to access the URL."
70
+ except TooManyRedirects:
71
+ return "Too many redirects while trying to access the URL."
72
+ except RequestException as e:
73
+ return f"Failed to access the URL. Error: {e}"
74
 
75
 
76
  @tool
 
372
 
373
  custom_tools = [
374
  wiki_search,
375
+ web_search,
376
+ url_search,
377
  # add_numbers,
378
  sum_excel_cols,
379
  youtube_transcript,
react_agent.py CHANGED
@@ -2,37 +2,67 @@ import os
2
  from dotenv import load_dotenv
3
  from langchain_core.messages import HumanMessage
4
  from langchain_google_genai import ChatGoogleGenerativeAI
 
 
5
  from langgraph.prebuilt import create_react_agent
6
  from custom_tools import custom_tools
7
 
8
  class ReActAgent:
9
- def __init__(self):
10
  load_dotenv()
11
- os.environ["GOOGLE_API_KEY"] = os.getenv("GOOGLE")
12
- # Initialize your LLM
13
- llm = ChatGoogleGenerativeAI(
14
- model="gemini-2.5-flash",
15
- temperature=0,
16
- max_retries=5
17
- )
18
- sys_prompt = "You are a general AI assistant. I will ask you a question. Report your thoughts, and finish your answer with the following template: FINAL ANSWER: [YOUR FINAL ANSWER]. 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.\n\n\n\
19
- You will be provided with tools to help you answer questions. If you are asked to look for an information or make a calculation, absolutely use the tools provided to you. You should AVOID calculating by yourself and ABSOLUTELY use appropriate tools. If needed, use one tool first, then use the output of that tool as an input to another thinking then to the use of another tool."
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
20
  # Build the ReAct agent
21
  self.agent = create_react_agent(
22
  model=llm,
23
  tools=custom_tools,
24
  prompt=sys_prompt
25
  )
26
- print("ReActAgent initialized.")
27
 
28
  def __call__(self, question: str) -> str:
29
  # Wrap question in HumanMessage to match React expectations
30
  input_msg = HumanMessage(content=question)
31
  # Invoke the agent; returns a stream or single response
32
  out = self.agent.invoke({"messages": [input_msg]})
 
 
33
  # The last message contains the agent's reply
34
  reply = out["messages"][-1].content
35
  # Optionally, strip out “Final Answer:” headers
36
- if "Final Answer:" in reply:
37
- reply = reply.split("Final Answer:")[-1].strip()
38
  return reply
 
2
  from dotenv import load_dotenv
3
  from langchain_core.messages import HumanMessage
4
  from langchain_google_genai import ChatGoogleGenerativeAI
5
+ from langchain_mistralai import ChatMistralAI
6
+ from langchain_groq import ChatGroq
7
  from langgraph.prebuilt import create_react_agent
8
  from custom_tools import custom_tools
9
 
10
  class ReActAgent:
11
+ def __init__(self, provider: str="Google", model: str="gemini-2.5-flash"):
12
  load_dotenv()
13
+
14
+ if provider=="Google":
15
+ os.environ["GOOGLE_API_KEY"] = os.getenv("GOOGLE")
16
+ # Initialize your LLM
17
+ llm = ChatGoogleGenerativeAI(
18
+ model=model,
19
+ temperature=0,
20
+ max_retries=5
21
+ )
22
+
23
+ if provider=="Mistral":
24
+ os.environ["MISTRAL_API_KEY"] = os.getenv("MISTRAL")
25
+ # Initialize your LLM
26
+ llm = ChatMistralAI(
27
+ model=model,
28
+ temperature=0,
29
+ max_retries=5
30
+ )
31
+
32
+ if provider=="Groq":
33
+ os.environ["GROQ_API_KEY"] = os.getenv("GROQ")
34
+ # Initialize your LLM
35
+ llm = ChatGroq(
36
+ model=model,
37
+ temperature=0,
38
+ max_retries=5
39
+ )
40
+
41
+ sys_prompt = "You are a general AI assistant. I will ask you a question. Report your thoughts, and finish your answer with the following template: FINAL ANSWER: [YOUR FINAL ANSWER]. 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) capitalize the first letter, and write the digits in plain text unless specified otherwise. If you are asked for a comma separated list, apply the above rules depending, unless the first letter capitalization, whether the element to be put in the list is a number or a string.\n\n\n \
42
+ \n \
43
+ You will be provided with tools to help you answer questions.\n \
44
+ If you are asked to make a calculation, absolutely use the tools provided to you. You should AVOID calculating by yourself and ABSOLUTELY use appropriate tools.\n \
45
+ If you need to search for information, use the web_search tool rather than wiki_search, unless the question specifies searching on wikipedia. After using the web_search tool, look for the first URL provided with the url_search tool and ask yourself if the answer is in the tool response. If it is, answer the question. If not, search on other links.\n \
46
+ \n \
47
+ If needed, use one tool first, then use the output of that tool as an input to another thinking then to the use of another tool."
48
  # Build the ReAct agent
49
  self.agent = create_react_agent(
50
  model=llm,
51
  tools=custom_tools,
52
  prompt=sys_prompt
53
  )
54
+ print(f"ReActAgent initialized with {provider} - {model}.")
55
 
56
  def __call__(self, question: str) -> str:
57
  # Wrap question in HumanMessage to match React expectations
58
  input_msg = HumanMessage(content=question)
59
  # Invoke the agent; returns a stream or single response
60
  out = self.agent.invoke({"messages": [input_msg]})
61
+ for o in out["messages"]:
62
+ print(o)
63
  # The last message contains the agent's reply
64
  reply = out["messages"][-1].content
65
  # Optionally, strip out “Final Answer:” headers
66
+ if "FINAL ANSWER: " in reply:
67
+ reply = reply.split("FINAL ANSWER: ")[-1].strip()
68
  return reply
requirements.txt CHANGED
@@ -4,6 +4,7 @@ gradio
4
  langchain==0.3.26
5
  langchain_community==0.3.26
6
  langchain-google-genai==2.1.6
 
7
  langchain-mistralai==0.2.10
8
  langgraph==0.4.10
9
  mistralai==1.7.0
 
4
  langchain==0.3.26
5
  langchain_community==0.3.26
6
  langchain-google-genai==2.1.6
7
+ langchain-groq==0.3.5
8
  langchain-mistralai==0.2.10
9
  langgraph==0.4.10
10
  mistralai==1.7.0