rnrahate007 commited on
Commit
aa582f9
·
verified ·
1 Parent(s): f268128

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +50 -101
app.py CHANGED
@@ -39,10 +39,10 @@ class GeminiReActAgent:
39
 
40
  # Direct REST API endpoint for Gemini 2.5 Flash
41
  self.url = f"https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent?key={self.api_key}"
42
- print("Vanilla ReAct Gemini Agent initialized.")
43
 
44
  def call_gemini(self, history) -> str:
45
- """Helper to make direct HTTP requests to the Gemini API."""
46
  payload = {
47
  "contents": history,
48
  "generationConfig": {
@@ -51,78 +51,91 @@ class GeminiReActAgent:
51
  "stopSequences": ["Observation:"]
52
  }
53
  }
54
- try:
55
- response = requests.post(self.url, json=payload, timeout=20)
56
- response.raise_for_status()
57
- data = response.json()
58
- return data["candidates"][0]["content"]["parts"][0]["text"].strip()
59
- except Exception as e:
60
- print(f"Gemini API Error: {e}")
61
- if hasattr(e, 'response') and e.response is not None:
62
- print(e.response.text)
63
- return "Error"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
64
 
65
  def __call__(self, question: str) -> str:
66
- print(f"Agent processing question: {question[:50]}...")
67
 
68
  system_instruction = """You are an expert assistant for the GAIA benchmark.
69
  You must provide a short, factual, direct answer. No explanations.
70
- You have access to a Wikipedia search tool to find current facts.
71
 
72
- To use the tool, you MUST output exactly this format:
73
- Thought: <your reasoning>
 
 
 
 
 
74
  Action: Search
75
- Action Input: <search query>
76
 
77
- If you know the answer or have found it from the search, output exactly:
78
- Thought: <final reasoning>
79
  Final Answer: <the short, direct answer>"""
80
 
81
- # Initialize conversation state
82
  history = [
83
  {"role": "user", "parts": [{"text": system_instruction + "\n\nQuestion: " + question}]}
84
  ]
85
 
86
- # The ReAct Loop (Max 5 iterations to prevent infinite loops)
87
  for iteration in range(5):
88
- time.sleep(1) # Pace requests to respect API limits
89
-
90
  reply = self.call_gemini(history)
91
 
92
  if reply == "Error":
93
  return "0"
94
 
95
- # Add model's reply to history
96
  history.append({"role": "model", "parts": [{"text": reply}]})
97
 
98
- # 1. Check if the model arrived at the final answer
99
  if "Final Answer:" in reply:
100
  answer = reply.split("Final Answer:")[-1].strip()
101
  return answer if answer else "0"
102
 
103
- # 2. Check if the model wants to use the Search tool
104
  elif "Action: Search" in reply and "Action Input:" in reply:
105
  query_lines = [line for line in reply.split('\n') if "Action Input:" in line]
106
  if query_lines:
107
  query = query_lines[0].split("Action Input:")[-1].strip()
108
  observation = search_wikipedia(query)
109
-
110
- # Feed the search results back into the model's context
111
  history.append({"role": "user", "parts": [{"text": observation}]})
112
  continue
113
 
114
- # 3. Fallback if the model breaks formatting
115
  else:
116
  history.append({
117
  "role": "user",
118
  "parts": [{"text": "Format error. Please use 'Action: Search' or 'Final Answer:'"}]
119
  })
120
 
121
- # Fallback if loops exhaust
122
  return "0"
123
 
124
  def run_and_submit_all(profile: gr.OAuthProfile | None):
125
- # --- Determine HF Space Runtime URL and Repo URL ---
126
  space_id = os.getenv("SPACE_ID")
127
 
128
  if profile:
@@ -136,7 +149,6 @@ def run_and_submit_all(profile: gr.OAuthProfile | None):
136
  questions_url = f"{api_url}/questions"
137
  submit_url = f"{api_url}/submit"
138
 
139
- # 1. Instantiate Agent
140
  try:
141
  agent = GeminiReActAgent()
142
  except Exception as e:
@@ -144,58 +156,40 @@ def run_and_submit_all(profile: gr.OAuthProfile | None):
144
  return f"Error initializing agent: {e}", None
145
 
146
  agent_code = f"https://huggingface.co/spaces/{space_id}/tree/main"
147
- print(agent_code)
148
 
149
- # 2. Fetch Questions
150
  print(f"Fetching questions from: {questions_url}")
151
  try:
152
  response = requests.get(questions_url, timeout=15)
153
  response.raise_for_status()
154
  questions_data = response.json()
155
  if not questions_data:
156
- print("Fetched questions list is empty.")
157
  return "Fetched questions list is empty or invalid format.", None
158
  print(f"Fetched {len(questions_data)} questions.")
159
- except requests.exceptions.RequestException as e:
160
- print(f"Error fetching questions: {e}")
161
- return f"Error fetching questions: {e}", None
162
- except requests.exceptions.JSONDecodeError as e:
163
- print(f"Error decoding JSON response from questions endpoint: {e}")
164
- print(f"Response text: {response.text[:500]}")
165
- return f"Error decoding server response for questions: {e}", None
166
  except Exception as e:
167
- print(f"An unexpected error occurred fetching questions: {e}")
168
  return f"An unexpected error occurred fetching questions: {e}", None
169
 
170
- # 3. Run your Agent
171
  results_log = []
172
  answers_payload = []
173
  print(f"Running agent on {len(questions_data)} questions...")
 
174
  for item in questions_data:
175
  task_id = item.get("task_id")
176
  question_text = item.get("question")
177
  if not task_id or question_text is None:
178
- print(f"Skipping item with missing task_id or question: {item}")
179
  continue
180
  try:
181
  submitted_answer = agent(question_text)
182
  answers_payload.append({"task_id": task_id, "submitted_answer": submitted_answer})
183
  results_log.append({"Task ID": task_id, "Question": question_text, "Submitted Answer": submitted_answer})
184
  except Exception as e:
185
- print(f"Error running agent on task {task_id}: {e}")
186
  results_log.append({"Task ID": task_id, "Question": question_text, "Submitted Answer": f"AGENT ERROR: {e}"})
187
 
188
  if not answers_payload:
189
- print("Agent did not produce any answers to submit.")
190
  return "Agent did not produce any answers to submit.", pd.DataFrame(results_log)
191
 
192
- # 4. Prepare Submission
193
  submission_data = {"username": username.strip(), "agent_code": agent_code, "answers": answers_payload}
194
- status_update = f"Agent finished. Submitting {len(answers_payload)} answers for user '{username}'..."
195
- print(status_update)
196
 
197
- # 5. Submit
198
- print(f"Submitting {len(answers_payload)} answers to: {submit_url}")
199
  try:
200
  response = requests.post(submit_url, json=submission_data, timeout=60)
201
  response.raise_for_status()
@@ -207,49 +201,21 @@ def run_and_submit_all(profile: gr.OAuthProfile | None):
207
  f"({result_data.get('correct_count', '?')}/{result_data.get('total_attempted', '?')} correct)\n"
208
  f"Message: {result_data.get('message', 'No message received.')}"
209
  )
210
- print("Submission successful.")
211
  results_df = pd.DataFrame(results_log)
212
  return final_status, results_df
213
- except requests.exceptions.HTTPError as e:
214
- error_detail = f"Server responded with status {e.response.status_code}."
215
- try:
216
- error_json = e.response.json()
217
- error_detail += f" Detail: {error_json.get('detail', e.response.text)}"
218
- except requests.exceptions.JSONDecodeError:
219
- error_detail += f" Response: {e.response.text[:500]}"
220
- status_message = f"Submission Failed: {error_detail}"
221
- print(status_message)
222
- results_df = pd.DataFrame(results_log)
223
- return status_message, results_df
224
- except requests.exceptions.Timeout:
225
- status_message = "Submission Failed: The request timed out."
226
- print(status_message)
227
- results_df = pd.DataFrame(results_log)
228
- return status_message, results_df
229
- except requests.exceptions.RequestException as e:
230
- status_message = f"Submission Failed: Network error - {e}"
231
- print(status_message)
232
- results_df = pd.DataFrame(results_log)
233
- return status_message, results_df
234
  except Exception as e:
235
- status_message = f"An unexpected error occurred during submission: {e}"
236
- print(status_message)
237
  results_df = pd.DataFrame(results_log)
238
  return status_message, results_df
239
 
240
  # --- Build Gradio Interface using Blocks ---
241
  with gr.Blocks() as demo:
242
- gr.Markdown("# Gemini Agent Evaluation Runner")
243
  gr.Markdown(
244
  """
245
- **Instructions:**
246
- 1. Please clone this space, then modify the code to define your agent's logic, the tools, the necessary packages, etc ...
247
- 2. Log in to your Hugging Face account using the button below. This uses your HF username for submission.
248
- 3. Click 'Run Evaluation & Submit All Answers' to fetch questions, run your agent, submit answers, and see the score.
249
- ---
250
  **Disclaimers:**
251
- Once clicking on the "submit button, it can take quite some time ( this is the time for the agent to go through all the questions).
252
- This space provides a basic setup and is intentionally sub-optimal to encourage you to develop your own, more robust solution. For instance for the delay process of the submit button, a solution could be to cache the answers and submit in a seperate action or even to answer the questions in async.
253
  """
254
  )
255
  gr.LoginButton()
@@ -263,21 +229,4 @@ with gr.Blocks() as demo:
263
 
264
  if __name__ == "__main__":
265
  print("\n" + "-"*30 + " App Starting " + "-"*30)
266
- space_host_startup = os.getenv("SPACE_HOST")
267
- space_id_startup = os.getenv("SPACE_ID")
268
-
269
- if space_host_startup:
270
- print(f"✅ SPACE_HOST found: {space_host_startup}")
271
- print(f" Runtime URL should be: https://{space_host_startup}.hf.space")
272
- else:
273
- print("ℹ️ SPACE_HOST environment variable not found (running locally?).")
274
-
275
- if space_id_startup:
276
- print(f"✅ SPACE_ID found: {space_id_startup}")
277
- print(f" Repo URL: https://huggingface.co/spaces/{space_id_startup}")
278
- print(f" Repo Tree URL: https://huggingface.co/spaces/{space_id_startup}/tree/main")
279
- else:
280
- print("ℹ️ SPACE_ID environment variable not found (running locally?). Repo URL cannot be determined.")
281
- print("-"*(60 + len(" App Starting ")) + "\n")
282
- print("Launching Gradio Interface for Gemini Agent Evaluation...")
283
  demo.launch(debug=True, share=False)
 
39
 
40
  # Direct REST API endpoint for Gemini 2.5 Flash
41
  self.url = f"https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent?key={self.api_key}"
42
+ print("Vanilla ReAct Gemini Agent initialized with rate-limit handling.")
43
 
44
  def call_gemini(self, history) -> str:
45
+ """Helper to make direct HTTP requests to the Gemini API with strict time pacing."""
46
  payload = {
47
  "contents": history,
48
  "generationConfig": {
 
51
  "stopSequences": ["Observation:"]
52
  }
53
  }
54
+
55
+ max_retries = 3
56
+ for attempt in range(max_retries):
57
+ try:
58
+ # ENFORCED TIME PACING: Wait 15 seconds to stay under the 5 Requests Per Minute limit.
59
+ print(" -> Pacing API: Sleeping for 15 seconds to respect 5 RPM limit...")
60
+ time.sleep(15)
61
+
62
+ response = requests.post(self.url, json=payload, timeout=20)
63
+
64
+ # Check if we hit a 429
65
+ if response.status_code == 429:
66
+ print(f" -> WARNING: Rate limit hit (429). Entering 60-second cooldown... (Attempt {attempt + 1}/{max_retries})")
67
+ time.sleep(60)
68
+ continue
69
+
70
+ response.raise_for_status()
71
+ data = response.json()
72
+ return data["candidates"][0]["content"]["parts"][0]["text"].strip()
73
+
74
+ except requests.exceptions.RequestException as e:
75
+ print(f"Gemini API Network Error: {e}")
76
+ if hasattr(e, 'response') and e.response is not None:
77
+ print(e.response.text)
78
+ time.sleep(10)
79
+ except Exception as e:
80
+ print(f"Unexpected Error parsing Gemini response: {e}")
81
+ return "Error"
82
+
83
+ return "Error"
84
 
85
  def __call__(self, question: str) -> str:
86
+ print(f"\nAgent processing question: {question[:50]}...")
87
 
88
  system_instruction = """You are an expert assistant for the GAIA benchmark.
89
  You must provide a short, factual, direct answer. No explanations.
90
+ You have access to a Wikipedia search tool, but you also have vast internal knowledge.
91
 
92
+ CRITICAL RULES:
93
+ 1. If the question asks you to categorize, sort, or use logic, use your internal knowledge immediately to output the Final Answer. Do not use tools.
94
+ 2. If the question mentions an attached image, video, audio, or Excel/CSV file, do your best to answer based purely on the text provided or by searching the internet. Do NOT say "I cannot analyze this."
95
+ 3. You must output EXACTLY one of the two formats below.
96
+
97
+ FORMAT 1 (To use the search tool):
98
+ Thought: <what you need to search>
99
  Action: Search
100
+ Action Input: <short, specific search query>
101
 
102
+ FORMAT 2 (To give the final answer):
103
+ Thought: <your reasoning>
104
  Final Answer: <the short, direct answer>"""
105
 
 
106
  history = [
107
  {"role": "user", "parts": [{"text": system_instruction + "\n\nQuestion: " + question}]}
108
  ]
109
 
 
110
  for iteration in range(5):
 
 
111
  reply = self.call_gemini(history)
112
 
113
  if reply == "Error":
114
  return "0"
115
 
 
116
  history.append({"role": "model", "parts": [{"text": reply}]})
117
 
 
118
  if "Final Answer:" in reply:
119
  answer = reply.split("Final Answer:")[-1].strip()
120
  return answer if answer else "0"
121
 
 
122
  elif "Action: Search" in reply and "Action Input:" in reply:
123
  query_lines = [line for line in reply.split('\n') if "Action Input:" in line]
124
  if query_lines:
125
  query = query_lines[0].split("Action Input:")[-1].strip()
126
  observation = search_wikipedia(query)
 
 
127
  history.append({"role": "user", "parts": [{"text": observation}]})
128
  continue
129
 
 
130
  else:
131
  history.append({
132
  "role": "user",
133
  "parts": [{"text": "Format error. Please use 'Action: Search' or 'Final Answer:'"}]
134
  })
135
 
 
136
  return "0"
137
 
138
  def run_and_submit_all(profile: gr.OAuthProfile | None):
 
139
  space_id = os.getenv("SPACE_ID")
140
 
141
  if profile:
 
149
  questions_url = f"{api_url}/questions"
150
  submit_url = f"{api_url}/submit"
151
 
 
152
  try:
153
  agent = GeminiReActAgent()
154
  except Exception as e:
 
156
  return f"Error initializing agent: {e}", None
157
 
158
  agent_code = f"https://huggingface.co/spaces/{space_id}/tree/main"
 
159
 
 
160
  print(f"Fetching questions from: {questions_url}")
161
  try:
162
  response = requests.get(questions_url, timeout=15)
163
  response.raise_for_status()
164
  questions_data = response.json()
165
  if not questions_data:
 
166
  return "Fetched questions list is empty or invalid format.", None
167
  print(f"Fetched {len(questions_data)} questions.")
 
 
 
 
 
 
 
168
  except Exception as e:
 
169
  return f"An unexpected error occurred fetching questions: {e}", None
170
 
 
171
  results_log = []
172
  answers_payload = []
173
  print(f"Running agent on {len(questions_data)} questions...")
174
+
175
  for item in questions_data:
176
  task_id = item.get("task_id")
177
  question_text = item.get("question")
178
  if not task_id or question_text is None:
 
179
  continue
180
  try:
181
  submitted_answer = agent(question_text)
182
  answers_payload.append({"task_id": task_id, "submitted_answer": submitted_answer})
183
  results_log.append({"Task ID": task_id, "Question": question_text, "Submitted Answer": submitted_answer})
184
  except Exception as e:
 
185
  results_log.append({"Task ID": task_id, "Question": question_text, "Submitted Answer": f"AGENT ERROR: {e}"})
186
 
187
  if not answers_payload:
 
188
  return "Agent did not produce any answers to submit.", pd.DataFrame(results_log)
189
 
 
190
  submission_data = {"username": username.strip(), "agent_code": agent_code, "answers": answers_payload}
191
+ print(f"Agent finished. Submitting {len(answers_payload)} answers for user '{username}'...")
 
192
 
 
 
193
  try:
194
  response = requests.post(submit_url, json=submission_data, timeout=60)
195
  response.raise_for_status()
 
201
  f"({result_data.get('correct_count', '?')}/{result_data.get('total_attempted', '?')} correct)\n"
202
  f"Message: {result_data.get('message', 'No message received.')}"
203
  )
 
204
  results_df = pd.DataFrame(results_log)
205
  return final_status, results_df
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
206
  except Exception as e:
207
+ status_message = f"Submission Failed: {e}"
 
208
  results_df = pd.DataFrame(results_log)
209
  return status_message, results_df
210
 
211
  # --- Build Gradio Interface using Blocks ---
212
  with gr.Blocks() as demo:
213
+ gr.Markdown("# Gemini Rate-Limited Agent Evaluation")
214
  gr.Markdown(
215
  """
 
 
 
 
 
216
  **Disclaimers:**
217
+ Due to Google's strict Free Tier rate limit (5 requests per minute), the agent forces a 15-second delay before every API call.
218
+ **This process will take roughly 15 to 25 minutes to complete 20 questions.** Please click 'Submit' and do not refresh the page.
219
  """
220
  )
221
  gr.LoginButton()
 
229
 
230
  if __name__ == "__main__":
231
  print("\n" + "-"*30 + " App Starting " + "-"*30)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
232
  demo.launch(debug=True, share=False)