PROTHAM commited on
Commit
431d2c4
·
1 Parent(s): 41120b8

Implement strict judge feedback: ambiguous task descriptions, server-side payload clues, increased exploration steps

Browse files
inference.py CHANGED
@@ -11,7 +11,7 @@ MODEL_NAME = os.getenv("MODEL_NAME", "mistralai/Mistral-7B-Instruct-v0.3")
11
  HF_TOKEN = os.getenv("HF_TOKEN")
12
  ENV_URL = os.getenv("ENV_URL", "http://localhost:7860")
13
  BENCHMARK = "api_debug_env"
14
- MAX_STEPS = 5
15
  SUCCESS_SCORE_THRESHOLD = 0.8
16
 
17
  llm = OpenAI(base_url=API_BASE_URL, api_key=HF_TOKEN)
 
11
  HF_TOKEN = os.getenv("HF_TOKEN")
12
  ENV_URL = os.getenv("ENV_URL", "http://localhost:7860")
13
  BENCHMARK = "api_debug_env"
14
+ MAX_STEPS = 10
15
  SUCCESS_SCORE_THRESHOLD = 0.8
16
 
17
  llm = OpenAI(base_url=API_BASE_URL, api_key=HF_TOKEN)
models.py CHANGED
@@ -35,5 +35,5 @@ class APIObservation(Observation):
35
 
36
  class APIState(State):
37
  task_id: str = Field(default="easy")
38
- max_steps: int = Field(default=5)
39
  solved: bool = Field(default=False)
 
35
 
36
  class APIState(State):
37
  task_id: str = Field(default="easy")
38
+ max_steps: int = Field(default=10)
39
  solved: bool = Field(default=False)
server/api_debug_environment.py CHANGED
@@ -35,7 +35,7 @@ class APIDebugEnvironment(Environment):
35
  episode_id=f"ep_{random.randint(10000, 99999)}",
36
  step_count=0,
37
  task_id=task_id,
38
- max_steps=5,
39
  solved=False,
40
  )
41
  return APIObservation(
 
35
  episode_id=f"ep_{random.randint(10000, 99999)}",
36
  step_count=0,
37
  task_id=task_id,
38
+ max_steps=10,
39
  solved=False,
40
  )
41
  return APIObservation(
server/mock_api.py CHANGED
@@ -37,10 +37,10 @@ async def get_token(body: TokenRequest):
37
  @router.get("/users")
38
  async def get_users(authorization: Optional[str] = Header(default=None)):
39
  if not authorization or not authorization.startswith("Bearer "):
40
- raise HTTPException(status_code=401, detail="Authorization header missing or malformed")
41
  token = authorization.split(" ")[1]
42
  if token not in _issued_tokens and token != "demo_token_123":
43
- raise HTTPException(status_code=401, detail="Invalid token")
44
  return {"users": [{"id": 1, "name": "Alice"}, {"id": 2, "name": "Bob"}]}
45
 
46
 
@@ -104,7 +104,11 @@ async def rate_limited(request: Request, x_retry_after: Optional[str] = Header(d
104
  window = [t for t in _request_log.get(client_id, []) if now - t < 5]
105
  if len(window) >= 3 and not x_retry_after:
106
  _request_log[client_id] = window
107
- raise HTTPException(status_code=429, detail="Rate limit exceeded", headers={"Retry-After": "2"})
 
 
 
 
108
  window.append(now)
109
  _request_log[client_id] = window
110
  return {"data": "rate_limited_resource", "requests_in_window": len(window)}
 
37
  @router.get("/users")
38
  async def get_users(authorization: Optional[str] = Header(default=None)):
39
  if not authorization or not authorization.startswith("Bearer "):
40
+ raise HTTPException(status_code=401, detail="Authorization header missing or malformed. Expected format: Bearer <token>. Use 'demo_token_123' for testing.")
41
  token = authorization.split(" ")[1]
42
  if token not in _issued_tokens and token != "demo_token_123":
43
+ raise HTTPException(status_code=401, detail="Invalid token. Try 'demo_token_123'.")
44
  return {"users": [{"id": 1, "name": "Alice"}, {"id": 2, "name": "Bob"}]}
45
 
46
 
 
104
  window = [t for t in _request_log.get(client_id, []) if now - t < 5]
105
  if len(window) >= 3 and not x_retry_after:
106
  _request_log[client_id] = window
107
+ raise HTTPException(
108
+ status_code=429,
109
+ detail={"error": "Rate limit exceeded", "hint": "Please add X-Retry-After header with value 2 to override."},
110
+ headers={"Retry-After": "2"}
111
+ )
112
  window.append(now)
113
  _request_log[client_id] = window
114
  return {"data": "rate_limited_resource", "requests_in_window": len(window)}
tasks/easy.py CHANGED
@@ -1,7 +1,7 @@
1
  EASY_TASKS = [
2
  {
3
  "id": "easy_auth",
4
- "description": "The request is missing an Authorization header. The API requires: Authorization: Bearer demo_token_123. Fix the request to GET /mock_api/users successfully.",
5
  "broken_request": {
6
  "method": "GET",
7
  "url": "/mock_api/users",
@@ -14,7 +14,7 @@ EASY_TASKS = [
14
  },
15
  {
16
  "id": "easy_content_type",
17
- "description": "The request uses Content-Type: text/plain but the API requires application/json. Fix the header and send body with a name field to POST /mock_api/items.",
18
  "broken_request": {
19
  "method": "POST",
20
  "url": "/mock_api/items",
@@ -27,7 +27,7 @@ EASY_TASKS = [
27
  },
28
  {
29
  "id": "easy_query_param",
30
- "description": "The search endpoint requires a query parameter q. The request omits it. Add q=python to the query params for GET /mock_api/search.",
31
  "broken_request": {
32
  "method": "GET",
33
  "url": "/mock_api/search",
 
1
  EASY_TASKS = [
2
  {
3
  "id": "easy_auth",
4
+ "description": "Access the protected resource at GET /mock_api/users to get a 200 OK. The current request is failing.",
5
  "broken_request": {
6
  "method": "GET",
7
  "url": "/mock_api/users",
 
14
  },
15
  {
16
  "id": "easy_content_type",
17
+ "description": "Create an item with name 'test_item' via POST /mock_api/items to get a 200 OK. The current request payload is rejected by the server.",
18
  "broken_request": {
19
  "method": "POST",
20
  "url": "/mock_api/items",
 
27
  },
28
  {
29
  "id": "easy_query_param",
30
+ "description": "Search for 'python' via GET /mock_api/search. The current request is missing required parameters.",
31
  "broken_request": {
32
  "method": "GET",
33
  "url": "/mock_api/search",
tasks/hard.py CHANGED
@@ -1,7 +1,7 @@
1
  HARD_TASKS = [
2
  {
3
  "id": "hard_token_exchange",
4
- "description": "The protected endpoint needs a fresh token. First POST to /mock_api/auth/token with body client_id abc and client_secret xyz to get an access_token. Then use it as Authorization: Bearer <token> to GET /mock_api/protected. The token in the broken request is expired.",
5
  "broken_request": {
6
  "method": "GET",
7
  "url": "/mock_api/protected",
@@ -14,7 +14,7 @@ HARD_TASKS = [
14
  },
15
  {
16
  "id": "hard_rate_limit",
17
- "description": "The rate_limited endpoint returns 429 if you send more than 3 requests without the X-Retry-After header. After receiving a 429 include header X-Retry-After with value 2.",
18
  "broken_request": {
19
  "method": "GET",
20
  "url": "/mock_api/rate_limited",
@@ -27,7 +27,7 @@ HARD_TASKS = [
27
  },
28
  {
29
  "id": "hard_pagination",
30
- "description": "GET /mock_api/logs returns only the first page with a next_cursor field. Follow the cursor chain by passing cursor as a query param until has_more is false.",
31
  "broken_request": {
32
  "method": "GET",
33
  "url": "/mock_api/logs",
 
1
  HARD_TASKS = [
2
  {
3
  "id": "hard_token_exchange",
4
+ "description": "Access the protected resource at GET /mock_api/protected. You might need to authenticate first to get a valid token. Valid credentials are client_id 'abc' and client_secret 'xyz' at /mock_api/auth/token.",
5
  "broken_request": {
6
  "method": "GET",
7
  "url": "/mock_api/protected",
 
14
  },
15
  {
16
  "id": "hard_rate_limit",
17
+ "description": "Retrieve data from /mock_api/rate_limited. The server has strict rate limits. Continuously attempt to fetch until you get a successful 200 OK.",
18
  "broken_request": {
19
  "method": "GET",
20
  "url": "/mock_api/rate_limited",
 
27
  },
28
  {
29
  "id": "hard_pagination",
30
+ "description": "Fetch all logs from GET /mock_api/logs to get a 200 OK without more pages. The endpoint returns a cursor. Follow the cursor chain until has_more is false.",
31
  "broken_request": {
32
  "method": "GET",
33
  "url": "/mock_api/logs",
tasks/medium.py CHANGED
@@ -1,7 +1,7 @@
1
  MEDIUM_TASKS = [
2
  {
3
  "id": "medium_wrong_method",
4
- "description": "Creating an order requires POST not GET. Fix the HTTP method and send body with product_id 5 and qty 2 to /mock_api/orders.",
5
  "broken_request": {
6
  "method": "GET",
7
  "url": "/mock_api/orders",
@@ -14,7 +14,7 @@ MEDIUM_TASKS = [
14
  },
15
  {
16
  "id": "medium_type_mismatch",
17
- "description": "The API expects product_id as an integer but the request sends the string five. Fix the type to the integer 5 in the body.",
18
  "broken_request": {
19
  "method": "POST",
20
  "url": "/mock_api/orders",
@@ -27,7 +27,7 @@ MEDIUM_TASKS = [
27
  },
28
  {
29
  "id": "medium_nested_field",
30
- "description": "The profile endpoint expects address to be a dict like street and city keys, not a plain string. Fix the body structure.",
31
  "broken_request": {
32
  "method": "POST",
33
  "url": "/mock_api/profile",
 
1
  MEDIUM_TASKS = [
2
  {
3
  "id": "medium_wrong_method",
4
+ "description": "Create an order for product_id 5 with qty 2 at /mock_api/orders. The given request is failing.",
5
  "broken_request": {
6
  "method": "GET",
7
  "url": "/mock_api/orders",
 
14
  },
15
  {
16
  "id": "medium_type_mismatch",
17
+ "description": "Submit a new order for product_id 5 and qty 2 at /mock_api/orders. The API is returning a validation error for the current payload.",
18
  "broken_request": {
19
  "method": "POST",
20
  "url": "/mock_api/orders",
 
27
  },
28
  {
29
  "id": "medium_nested_field",
30
+ "description": "Update the profile with name 'Alice' and address containing street '123 Main St' and city 'Metropolis'. The current payload structure is rejected.",
31
  "broken_request": {
32
  "method": "POST",
33
  "url": "/mock_api/profile",