Tarun Claude Sonnet 4.6 commited on
Commit
caeca79
·
1 Parent(s): 63dab28

Fix inference.py unhandled exception crash

Browse files

get_action() was propagating API errors (network, auth, timeout) which
crashed run_episode → main → non-zero exit. Fix:

- get_action() now catches ALL exceptions, logs them to stdout, and
returns fallback action + error string (error appears in [STEP] log)
- run_episode() logs step_error in [STEP] output
- main() wraps each task in try/except so one failing task doesn't
kill the remaining two — emits [END] with minimum score instead

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

Files changed (1) hide show
  1. inference.py +15 -17
inference.py CHANGED
@@ -217,22 +217,15 @@ async def call_api_model(state: dict, client: AsyncOpenAI, user_prompt: str) ->
217
  else:
218
  raise ValueError(f"No JSON object detected in response. Raw response: {text}")
219
 
220
- async def get_action(state: dict, client: AsyncOpenAI, user_prompt: str) -> SupportAction:
221
- # API errors (network, auth, rate-limit) must NOT be silently swallowed — they
222
- # indicate a misconfigured proxy and must surface so the episode fails visibly.
223
- # Only fall back on JSON parse/decode issues where the API was reached but returned
224
- # malformed output.
225
  try:
226
  data = await call_api_model(state, client, user_prompt)
227
- except (ValueError, json.JSONDecodeError) as parse_exc:
228
- # API was called but response was unparseable — use fallback heuristic
229
- print(f"\n[DEBUG] ⚠️ JSON parse failed: {type(parse_exc).__name__}: {parse_exc}\n", flush=True)
230
- fb_dict = fallback_policy(state)
231
- return SupportAction(**fb_dict)
232
- # All other exceptions (openai.APIConnectionError, openai.AuthenticationError,
233
- # httpx errors, etc.) propagate — they will be caught in main() and abort the run
234
- # with a visible error, preventing silent fallback-only episodes.
235
- return SupportAction(**data)
236
 
237
  async def run_episode(task_name: str, client: AsyncOpenAI) -> None:
238
  """Run one full episode for the given task and emit START/STEP/END logs."""
@@ -260,7 +253,7 @@ async def run_episode(task_name: str, client: AsyncOpenAI) -> None:
260
  "message": obs.message,
261
  "sentiment": obs.sentiment,
262
  }
263
- action = await get_action(state_dict, client, user_prompt)
264
  action_str = json.dumps(action.model_dump())
265
 
266
  result = await env.step(action)
@@ -271,7 +264,7 @@ async def run_episode(task_name: str, client: AsyncOpenAI) -> None:
271
  rewards.append(reward)
272
  steps_taken = step
273
 
274
- log_step(step=step, action=action_str, reward=reward, done=done, error=None)
275
  history.append(f"Step {step}: {action_str} -> reward {reward:+.2f}")
276
 
277
  if done:
@@ -301,7 +294,12 @@ async def main() -> None:
301
  # Always run all three tasks so the validator can enumerate tasks and
302
  # verify each grader produces scores in [0.002, 0.998].
303
  for task in ["easy", "medium", "hard"]:
304
- await run_episode(task, client)
 
 
 
 
 
305
 
306
 
307
  if __name__ == "__main__":
 
217
  else:
218
  raise ValueError(f"No JSON object detected in response. Raw response: {text}")
219
 
220
+ async def get_action(state: dict, client: AsyncOpenAI, user_prompt: str) -> tuple[SupportAction, Optional[str]]:
221
+ """Returns (action, error_message). error_message is None on success."""
 
 
 
222
  try:
223
  data = await call_api_model(state, client, user_prompt)
224
+ return SupportAction(**data), None
225
+ except Exception as exc:
226
+ err = f"{type(exc).__name__}: {exc}"
227
+ print(f"[DEBUG] ⚠️ API/parse error: {err}", flush=True)
228
+ return SupportAction(**fallback_policy(state)), err
 
 
 
 
229
 
230
  async def run_episode(task_name: str, client: AsyncOpenAI) -> None:
231
  """Run one full episode for the given task and emit START/STEP/END logs."""
 
253
  "message": obs.message,
254
  "sentiment": obs.sentiment,
255
  }
256
+ action, step_error = await get_action(state_dict, client, user_prompt)
257
  action_str = json.dumps(action.model_dump())
258
 
259
  result = await env.step(action)
 
264
  rewards.append(reward)
265
  steps_taken = step
266
 
267
+ log_step(step=step, action=action_str, reward=reward, done=done, error=step_error)
268
  history.append(f"Step {step}: {action_str} -> reward {reward:+.2f}")
269
 
270
  if done:
 
294
  # Always run all three tasks so the validator can enumerate tasks and
295
  # verify each grader produces scores in [0.002, 0.998].
296
  for task in ["easy", "medium", "hard"]:
297
+ try:
298
+ await run_episode(task, client)
299
+ except Exception as exc:
300
+ print(f"[DEBUG] ⚠️ Episode failed for task={task}: {type(exc).__name__}: {exc}", flush=True)
301
+ log_end(success=False, steps=0, score=0.002, rewards=[0.002])
302
+ continue
303
 
304
 
305
  if __name__ == "__main__":