Lasdw commited on
Commit
ab403f1
·
1 Parent(s): 0ff9cac

added global rate limiting

Browse files
Files changed (3) hide show
  1. agent.py +2 -2
  2. app.py +11 -0
  3. rate_limiter.py +16 -25
agent.py CHANGED
@@ -137,7 +137,7 @@ NEVER fake or simulate tool output yourself. If you are unable to make progreess
137
  Thought: I now know the final answer
138
  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. For one word answers, start with the word with a capital letter.
139
  Make sure to follow any formatting instructions given by the user.
140
- Now begin! Reminder to ALWAYS use the exact characters `Final Answer:` when you provide a definitive answer."""
141
 
142
  # Generate the chat interface, including the tools
143
  llm = ChatOpenAI(
@@ -1391,7 +1391,7 @@ class TurboNerd:
1391
 
1392
  # Example usage:
1393
  if __name__ == "__main__":
1394
- agent = TurboNerd(max_iterations=35)
1395
  response = agent("""The attached Excel file contains the sales of menu items for a local fast-food chain. What were the total sales that the chain made from food (not including drinks)? Express your answer in USD with two decimal places. TEMPP\excel.xlsx """)
1396
  print("\nFinal Response:")
1397
  print(response)
 
137
  Thought: I now know the final answer
138
  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. For one word answers, start with the word with a capital letter.
139
  Make sure to follow any formatting instructions given by the user.
140
+ Now begin! Reminder to ALWAYS use the exact characters `Final Answer:` when you provide a definitive answer. DO NOT USE TAVILY SEARCH FOR CLARIFICATION"""
141
 
142
  # Generate the chat interface, including the tools
143
  llm = ChatOpenAI(
 
1391
 
1392
  # Example usage:
1393
  if __name__ == "__main__":
1394
+ agent = TurboNerd(max_iterations=25)
1395
  response = agent("""The attached Excel file contains the sales of menu items for a local fast-food chain. What were the total sales that the chain made from food (not including drinks)? Express your answer in USD with two decimal places. TEMPP\excel.xlsx """)
1396
  print("\nFinal Response:")
1397
  print(response)
app.py CHANGED
@@ -157,6 +157,17 @@ def chat_with_agent(question: str, file_uploads, history: list) -> tuple:
157
  session_histories[session_id].append({"role": "assistant", "content": formatted_response})
158
 
159
  return history, "", f"Remaining queries this hour: {remaining_queries}/{query_limiter.max_queries}"
 
 
 
 
 
 
 
 
 
 
 
160
  except Exception as e:
161
  error_message = f"Error: {str(e)}"
162
  history.append({"role": "assistant", "content": error_message})
 
157
  session_histories[session_id].append({"role": "assistant", "content": formatted_response})
158
 
159
  return history, "", f"Remaining queries this hour: {remaining_queries}/{query_limiter.max_queries}"
160
+ except RecursionError as e:
161
+ error_message = (
162
+ "I apologize, but I've reached my thinking limit while trying to answer your question. "
163
+ "This usually happens when the question requires too many steps to solve and therefore too much money"
164
+ "Could you please try breaking down your question into smaller, more specific parts? "
165
+ "For example, instead of asking about multiple things at once, try asking about one aspect at a time."
166
+ )
167
+ history.append({"role": "assistant", "content": error_message})
168
+ if session_id in session_histories:
169
+ session_histories[session_id].append({"role": "assistant", "content": error_message})
170
+ return history, "", "Remaining queries this hour: 5/5"
171
  except Exception as e:
172
  error_message = f"Error: {str(e)}"
173
  history.append({"role": "assistant", "content": error_message})
rate_limiter.py CHANGED
@@ -5,22 +5,19 @@ import threading
5
  class QueryRateLimiter:
6
  def __init__(self, max_queries_per_hour: int = 10):
7
  """
8
- Initialize rate limiter for queries per hour.
9
 
10
  Args:
11
- max_queries_per_hour: Maximum number of queries allowed per hour
12
  """
13
  self.max_queries = max_queries_per_hour
14
- self.queries = defaultdict(list) # ip_address -> list of timestamps
15
  self.lock = threading.Lock()
16
 
17
- def is_allowed(self, ip_address: str) -> bool:
18
  """
19
- Check if an IP address is allowed to make another query.
20
 
21
- Args:
22
- ip_address: IP address of the client
23
-
24
  Returns:
25
  bool: True if query is allowed, False if rate limited
26
  """
@@ -29,22 +26,19 @@ class QueryRateLimiter:
29
 
30
  with self.lock:
31
  # Remove queries older than 1 hour
32
- self.queries[ip_address] = [t for t in self.queries[ip_address] if t > hour_ago]
33
 
34
  # Check if under rate limit
35
- if len(self.queries[ip_address]) < self.max_queries:
36
- self.queries[ip_address].append(current_time)
37
  return True
38
 
39
  return False
40
 
41
- def get_remaining_queries(self, ip_address: str) -> int:
42
  """
43
- Get number of remaining queries for an IP address in the current hour.
44
 
45
- Args:
46
- ip_address: IP address of the client
47
-
48
  Returns:
49
  int: Number of remaining queries
50
  """
@@ -53,27 +47,24 @@ class QueryRateLimiter:
53
 
54
  with self.lock:
55
  # Remove queries older than 1 hour
56
- self.queries[ip_address] = [t for t in self.queries[ip_address] if t > hour_ago]
57
 
58
- return self.max_queries - len(self.queries[ip_address])
59
 
60
- def get_time_until_reset(self, ip_address: str) -> float:
61
  """
62
- Get time in seconds until the rate limit resets for an IP address.
63
 
64
- Args:
65
- ip_address: IP address of the client
66
-
67
  Returns:
68
  float: Seconds until rate limit reset
69
  """
70
  current_time = time.time()
71
 
72
  with self.lock:
73
- if not self.queries[ip_address]:
74
  return 0.0
75
 
76
- oldest_query = min(self.queries[ip_address])
77
  reset_time = oldest_query + 3600 # 1 hour in seconds
78
 
79
  return max(0.0, reset_time - current_time)
 
5
  class QueryRateLimiter:
6
  def __init__(self, max_queries_per_hour: int = 10):
7
  """
8
+ Initialize rate limiter for global queries per hour.
9
 
10
  Args:
11
+ max_queries_per_hour: Maximum number of queries allowed per hour globally
12
  """
13
  self.max_queries = max_queries_per_hour
14
+ self.queries = [] # List of timestamps for all queries
15
  self.lock = threading.Lock()
16
 
17
+ def is_allowed(self, _: str = None) -> bool:
18
  """
19
+ Check if another query is allowed within the hourly limit.
20
 
 
 
 
21
  Returns:
22
  bool: True if query is allowed, False if rate limited
23
  """
 
26
 
27
  with self.lock:
28
  # Remove queries older than 1 hour
29
+ self.queries = [t for t in self.queries if t > hour_ago]
30
 
31
  # Check if under rate limit
32
+ if len(self.queries) < self.max_queries:
33
+ self.queries.append(current_time)
34
  return True
35
 
36
  return False
37
 
38
+ def get_remaining_queries(self, _: str = None) -> int:
39
  """
40
+ Get number of remaining queries in the current hour.
41
 
 
 
 
42
  Returns:
43
  int: Number of remaining queries
44
  """
 
47
 
48
  with self.lock:
49
  # Remove queries older than 1 hour
50
+ self.queries = [t for t in self.queries if t > hour_ago]
51
 
52
+ return self.max_queries - len(self.queries)
53
 
54
+ def get_time_until_reset(self, _: str = None) -> float:
55
  """
56
+ Get time in seconds until the rate limit resets.
57
 
 
 
 
58
  Returns:
59
  float: Seconds until rate limit reset
60
  """
61
  current_time = time.time()
62
 
63
  with self.lock:
64
+ if not self.queries:
65
  return 0.0
66
 
67
+ oldest_query = min(self.queries)
68
  reset_time = oldest_query + 3600 # 1 hour in seconds
69
 
70
  return max(0.0, reset_time - current_time)