maodd commited on
Commit
155f4b7
·
verified ·
1 Parent(s): 222b65b

Switch back to Claude via LiteLLM, add step rate limiter

Browse files

Free HF Inference Providers OAuth access was 403ing; switch back to LiteLLMModel/ANTHROPIC_API_KEY, add a step_callback rate limiter to avoid provider throttling across a full eval run.

Files changed (1) hide show
  1. app.py +35 -16
app.py CHANGED
@@ -1,5 +1,6 @@
1
  import os
2
  import tempfile
 
3
  import gradio as gr
4
  import requests
5
  import inspect
@@ -7,8 +8,9 @@ import pandas as pd
7
  import spaces
8
 
9
  from smolagents import (
 
10
  CodeAgent,
11
- InferenceClientModel,
12
  WebSearchTool,
13
  VisitWebpageTool,
14
  WikipediaSearchTool,
@@ -22,7 +24,7 @@ DEFAULT_API_URL = "https://agents-course-unit4-scoring.hf.space"
22
  @spaces.GPU
23
  def _zerogpu_startup_check():
24
  # This Space runs on ZeroGPU hardware but the agent below only makes
25
- # network calls (HF Inference API, web search) and never touches CUDA.
26
  # ZeroGPU requires at least one @spaces.GPU function to be declared,
27
  # so this no-op satisfies that check without spending any GPU quota
28
  # (it is never actually invoked).
@@ -37,20 +39,36 @@ If you are asked for a string, don't use articles or abbreviations (e.g. for cit
37
  If you are asked for a comma separated list, apply the above rules to each element depending on whether it's a number or a string.
38
  """
39
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
40
  # --- Basic Agent Definition ---
41
  # ----- THIS IS WERE YOU CAN BUILD WHAT YOU WANT ------
42
  class BasicAgent:
43
- def __init__(self, hf_token: str | None = None):
44
- # Uses the logged-in user's own HF Inference Providers quota (via the
45
- # "Sign in with Hugging Face" OAuth token, scope: inference-api).
46
- # Falls back to the HF_TOKEN env var (e.g. for local testing) if no
47
- # OAuth token is available.
48
- model_kwargs = {"token": hf_token or os.getenv("HF_TOKEN"), "temperature": 0}
49
- model_id = os.getenv("AGENT_MODEL_ID")
50
- if model_id:
51
- model_kwargs["model_id"] = model_id
52
-
53
- self.model = InferenceClientModel(**model_kwargs)
54
  self.agent = CodeAgent(
55
  model=self.model,
56
  tools=[WebSearchTool(), VisitWebpageTool(), WikipediaSearchTool()],
@@ -60,6 +78,7 @@ class BasicAgent:
60
  "collections", "statistics", "datetime", "io", "openpyxl", "PIL",
61
  ],
62
  max_steps=12,
 
63
  )
64
  print("BasicAgent initialized.")
65
 
@@ -80,7 +99,7 @@ class BasicAgent:
80
  print(f"Agent returning answer: {answer}")
81
  return answer
82
 
83
- def run_and_submit_all( profile: gr.OAuthProfile | None, oauth_token: gr.OAuthToken | None):
84
  """
85
  Fetches all questions, runs the BasicAgent on them, submits all answers,
86
  and displays the results.
@@ -101,7 +120,7 @@ def run_and_submit_all( profile: gr.OAuthProfile | None, oauth_token: gr.OAuthTo
101
 
102
  # 1. Instantiate Agent ( modify this part to create your agent)
103
  try:
104
- agent = BasicAgent(hf_token=oauth_token.token if oauth_token else None)
105
  except Exception as e:
106
  print(f"Error instantiating agent: {e}")
107
  return f"Error initializing agent: {e}", None
@@ -232,7 +251,7 @@ with gr.Blocks() as demo:
232
  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).
233
  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.
234
 
235
- **Setup:** This agent calls Hugging Face's Inference Providers via `smolagents`, using your own account's quota through the login below (no separate API key needed). No hardware/model access beyond your normal HF account is required.
236
  """
237
  )
238
 
 
1
  import os
2
  import tempfile
3
+ import time
4
  import gradio as gr
5
  import requests
6
  import inspect
 
8
  import spaces
9
 
10
  from smolagents import (
11
+ ActionStep,
12
  CodeAgent,
13
+ LiteLLMModel,
14
  WebSearchTool,
15
  VisitWebpageTool,
16
  WikipediaSearchTool,
 
24
  @spaces.GPU
25
  def _zerogpu_startup_check():
26
  # This Space runs on ZeroGPU hardware but the agent below only makes
27
+ # network calls (Claude API, web search) and never touches CUDA.
28
  # ZeroGPU requires at least one @spaces.GPU function to be declared,
29
  # so this no-op satisfies that check without spending any GPU quota
30
  # (it is never actually invoked).
 
39
  If you are asked for a comma separated list, apply the above rules to each element depending on whether it's a number or a string.
40
  """
41
 
42
+ class RateLimiter:
43
+ """
44
+ Counts agent LLM calls (one per step) and sleeps for a fixed duration
45
+ once a threshold is reached, then resets the counter. Used as a
46
+ step_callback to stay under the model provider's rate limits across a
47
+ full run of ~20 GAIA questions, each potentially taking several steps.
48
+ """
49
+ def __init__(self, calls_per_wait: int = 15, seconds_to_wait: int = 30):
50
+ self.calls_per_wait = calls_per_wait
51
+ self.seconds_to_wait = seconds_to_wait
52
+ self._call_count = 0
53
+
54
+ def __call__(self, memory_step: ActionStep, agent: CodeAgent) -> None:
55
+ self._call_count += 1
56
+ if self._call_count >= self.calls_per_wait:
57
+ print(f"Rate limiter: {self.calls_per_wait} calls reached, sleeping {self.seconds_to_wait}s")
58
+ time.sleep(self.seconds_to_wait)
59
+ self._call_count = 0
60
+
61
+
62
  # --- Basic Agent Definition ---
63
  # ----- THIS IS WERE YOU CAN BUILD WHAT YOU WANT ------
64
  class BasicAgent:
65
+ def __init__(self):
66
+ model_id = os.getenv("AGENT_MODEL_ID", "anthropic/claude-sonnet-5")
67
+ api_key = os.getenv("ANTHROPIC_API_KEY")
68
+ if not api_key:
69
+ print("Warning: ANTHROPIC_API_KEY is not set - the agent will fail to call the model.")
70
+
71
+ self.model = LiteLLMModel(model_id=model_id, api_key=api_key, temperature=0)
 
 
 
 
72
  self.agent = CodeAgent(
73
  model=self.model,
74
  tools=[WebSearchTool(), VisitWebpageTool(), WikipediaSearchTool()],
 
78
  "collections", "statistics", "datetime", "io", "openpyxl", "PIL",
79
  ],
80
  max_steps=12,
81
+ step_callbacks=[RateLimiter()],
82
  )
83
  print("BasicAgent initialized.")
84
 
 
99
  print(f"Agent returning answer: {answer}")
100
  return answer
101
 
102
+ def run_and_submit_all( profile: gr.OAuthProfile | None):
103
  """
104
  Fetches all questions, runs the BasicAgent on them, submits all answers,
105
  and displays the results.
 
120
 
121
  # 1. Instantiate Agent ( modify this part to create your agent)
122
  try:
123
+ agent = BasicAgent()
124
  except Exception as e:
125
  print(f"Error instantiating agent: {e}")
126
  return f"Error initializing agent: {e}", None
 
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
+ **Setup:** This agent calls Anthropic's Claude via `smolagents`. Set the `ANTHROPIC_API_KEY` secret in this Space's settings before running.
255
  """
256
  )
257