Andrei Nazarov commited on
Commit
2b1db38
·
1 Parent(s): 3efbcf4
Files changed (1) hide show
  1. app.py +117 -67
app.py CHANGED
@@ -3,15 +3,44 @@ import gradio as gr
3
  import requests
4
  import inspect
5
  import pandas as pd
 
 
 
 
 
6
  from smolagents import CodeAgent, DuckDuckGoSearchTool, load_tool, tool
7
  from smolagents.models import Model, ChatMessage, MessageRole, Tool
8
  from tools import FinalAnswerTool
9
  import google.generativeai as genai
10
- import re
11
 
12
  # (Keep Constants as is)
13
  # --- Constants ---
14
  DEFAULT_API_URL = "https://agents-course-unit4-scoring.hf.space"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15
 
16
  # --- Basic Agent Definition ---
17
 
@@ -23,6 +52,7 @@ class GeminiModel(Model):
23
  self.api_key = api_key
24
  genai.configure(api_key=api_key)
25
  self.model = genai.GenerativeModel('models/gemini-2.0-flash-lite')
 
26
 
27
  # System prompt for smolagents format
28
  self.system_prompt = """You are a highly focused AI assistant tasked with answering specific questions accurately using available tools. Your primary goal is to find and provide precise answers to questions using the tools provided.
@@ -103,79 +133,99 @@ Remember:
103
  tools_to_call_from: list[Tool] | None = None,
104
  **kwargs,
105
  ) -> ChatMessage:
106
- try:
107
- # Handle different prompt types
108
- if isinstance(messages, list) and len(messages) > 0:
109
- # Extract content from the last message (most recent)
110
- last_message = messages[-1]
111
-
112
- if isinstance(last_message, dict) and 'content' in last_message:
113
- content = last_message['content']
114
- elif isinstance(last_message, ChatMessage) and last_message.content:
115
- content = last_message.content
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
116
  else:
117
- # Fallback: combine all message content
118
- content = ""
119
- for msg in messages:
120
- if isinstance(msg, dict) and 'content' in msg:
121
- content += str(msg['content']) + "\n"
122
- elif isinstance(msg, ChatMessage) and msg.content:
123
- content += str(msg.content) + "\n"
124
- else:
125
- content += str(msg) + "\n"
126
- else:
127
- content = str(messages)
128
-
129
- # Ensure content is a simple string for Gemini API
130
- if isinstance(content, list):
131
- # Handle list of content parts
132
- text_parts = []
133
- for part in content:
134
- if isinstance(part, dict):
135
- if 'text' in part:
136
- text_parts.append(part['text'])
137
- elif 'content' in part:
138
- text_parts.append(part['content'])
139
  else:
140
  text_parts.append(str(part))
 
 
 
 
 
 
141
  else:
142
- text_parts.append(str(part))
143
- content = "\n".join(text_parts)
144
- elif isinstance(content, dict):
145
- # Handle dict content - extract text if possible
146
- if 'text' in content:
147
- content = content['text']
148
- elif 'content' in content:
149
- content = content['content']
150
- else:
151
- content = str(content)
152
-
153
- # Combine system prompt with user content
154
- full_prompt = f"{self.system_prompt}\n\nTask: {content}"
155
 
156
- # Generate response
157
- response = self.model.generate_content(full_prompt)
158
-
159
- # Extract text from response
160
- if hasattr(response, 'text'):
161
- response_text = response.text
162
- elif isinstance(response, str):
163
- response_text = response
164
- elif hasattr(response, 'content'):
165
- response_text = response.content
166
- else:
167
- response_text = str(response)
168
 
169
- # Return ChatMessage object as expected by smolagents
170
- return ChatMessage(
171
- role=MessageRole.ASSISTANT,
172
- content=response_text,
173
- raw=response
174
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
175
 
176
- except Exception as e:
177
- print(f"Error in generate: {e}")
178
- raise e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
179
 
180
  class MyAgent:
181
  def __init__(self):
 
3
  import requests
4
  import inspect
5
  import pandas as pd
6
+ import re
7
+ import time
8
+ from datetime import datetime, timedelta
9
+ from collections import deque
10
+ import random
11
  from smolagents import CodeAgent, DuckDuckGoSearchTool, load_tool, tool
12
  from smolagents.models import Model, ChatMessage, MessageRole, Tool
13
  from tools import FinalAnswerTool
14
  import google.generativeai as genai
 
15
 
16
  # (Keep Constants as is)
17
  # --- Constants ---
18
  DEFAULT_API_URL = "https://agents-course-unit4-scoring.hf.space"
19
+ MAX_RETRIES = 3
20
+ INITIAL_RETRY_DELAY = 1 # seconds
21
+ MAX_RETRY_DELAY = 32 # seconds
22
+
23
+ class RateLimiter:
24
+ def __init__(self, requests_per_minute):
25
+ self.requests_per_minute = requests_per_minute
26
+ self.window_size = 60 # 60 seconds = 1 minute
27
+ self.requests = deque()
28
+
29
+ def wait_if_needed(self):
30
+ now = datetime.now()
31
+
32
+ # Remove requests older than our window
33
+ while self.requests and (now - self.requests[0]).total_seconds() > self.window_size:
34
+ self.requests.popleft()
35
+
36
+ # If we've hit our limit, wait until the oldest request expires
37
+ if len(self.requests) >= self.requests_per_minute:
38
+ wait_time = self.window_size - (now - self.requests[0]).total_seconds()
39
+ if wait_time > 0:
40
+ time.sleep(wait_time + 0.1) # Add a small buffer
41
+
42
+ # Add the current request
43
+ self.requests.append(now)
44
 
45
  # --- Basic Agent Definition ---
46
 
 
52
  self.api_key = api_key
53
  genai.configure(api_key=api_key)
54
  self.model = genai.GenerativeModel('models/gemini-2.0-flash-lite')
55
+ self.rate_limiter = RateLimiter(requests_per_minute=25) # Setting to 25 to be safe
56
 
57
  # System prompt for smolagents format
58
  self.system_prompt = """You are a highly focused AI assistant tasked with answering specific questions accurately using available tools. Your primary goal is to find and provide precise answers to questions using the tools provided.
 
133
  tools_to_call_from: list[Tool] | None = None,
134
  **kwargs,
135
  ) -> ChatMessage:
136
+ retry_count = 0
137
+ delay = INITIAL_RETRY_DELAY
138
+
139
+ while True:
140
+ try:
141
+ # Wait if we need to due to rate limiting
142
+ self.rate_limiter.wait_if_needed()
143
+
144
+ # Handle different prompt types
145
+ if isinstance(messages, list) and len(messages) > 0:
146
+ last_message = messages[-1]
147
+
148
+ if isinstance(last_message, dict) and 'content' in last_message:
149
+ content = last_message['content']
150
+ elif isinstance(last_message, ChatMessage) and last_message.content:
151
+ content = last_message.content
152
+ else:
153
+ content = ""
154
+ for msg in messages:
155
+ if isinstance(msg, dict) and 'content' in msg:
156
+ content += str(msg['content']) + "\n"
157
+ elif isinstance(msg, ChatMessage) and msg.content:
158
+ content += str(msg.content) + "\n"
159
+ else:
160
+ content += str(msg) + "\n"
161
  else:
162
+ content = str(messages)
163
+
164
+ # Ensure content is a simple string for Gemini API
165
+ if isinstance(content, list):
166
+ text_parts = []
167
+ for part in content:
168
+ if isinstance(part, dict):
169
+ if 'text' in part:
170
+ text_parts.append(part['text'])
171
+ elif 'content' in part:
172
+ text_parts.append(part['content'])
173
+ else:
174
+ text_parts.append(str(part))
 
 
 
 
 
 
 
 
 
175
  else:
176
  text_parts.append(str(part))
177
+ content = "\n".join(text_parts)
178
+ elif isinstance(content, dict):
179
+ if 'text' in content:
180
+ content = content['text']
181
+ elif 'content' in content:
182
+ content = content['content']
183
  else:
184
+ content = str(content)
185
+
186
+ # Combine system prompt with user content
187
+ full_prompt = f"{self.system_prompt}\n\nTask: {content}"
 
 
 
 
 
 
 
 
 
188
 
189
+ # Generate response
190
+ response = self.model.generate_content(full_prompt)
 
 
 
 
 
 
 
 
 
 
191
 
192
+ # Extract text from response
193
+ if hasattr(response, 'text'):
194
+ response_text = response.text
195
+ elif isinstance(response, str):
196
+ response_text = response
197
+ elif hasattr(response, 'content'):
198
+ response_text = response.content
199
+ else:
200
+ response_text = str(response)
201
+
202
+ # Return ChatMessage object as expected by smolagents
203
+ return ChatMessage(
204
+ role=MessageRole.ASSISTANT,
205
+ content=response_text,
206
+ raw=response
207
+ )
208
+
209
+ except Exception as e:
210
+ error_str = str(e)
211
 
212
+ # Check if it's a rate limit error
213
+ if "429" in error_str and retry_count < MAX_RETRIES:
214
+ retry_count += 1
215
+
216
+ # Add some random jitter to prevent all retries happening at exactly the same time
217
+ jitter = random.uniform(0, 0.1) * delay
218
+ sleep_time = delay + jitter
219
+
220
+ print(f"Rate limit hit. Retrying in {sleep_time:.2f} seconds (attempt {retry_count}/{MAX_RETRIES})")
221
+ time.sleep(sleep_time)
222
+
223
+ # Exponential backoff
224
+ delay = min(delay * 2, MAX_RETRY_DELAY)
225
+ continue
226
+
227
+ print(f"Error in generate: {e}")
228
+ raise e
229
 
230
  class MyAgent:
231
  def __init__(self):