Eval robustness: fresh HarborEnv client per rollout (openenv reconnect bug); failed checkpoint evals retried next poll
Browse files- eval_adapter.py +18 -12
- eval_watch.py +7 -1
eval_adapter.py
CHANGED
|
@@ -22,7 +22,6 @@ Config via env:
|
|
| 22 |
|
| 23 |
import json
|
| 24 |
import os
|
| 25 |
-
import threading
|
| 26 |
from concurrent.futures import ThreadPoolExecutor, as_completed
|
| 27 |
|
| 28 |
from harbor_env import HarborEnv # re-export of openenv.harbor.client.HarborEnv
|
|
@@ -37,13 +36,14 @@ N_TASKS = int(os.environ.get("N_TASKS", "50"))
|
|
| 37 |
CONCURRENCY = int(os.environ.get("CONCURRENCY", "8"))
|
| 38 |
OUT = os.environ.get("OUT", "/app/eval_results.json")
|
| 39 |
|
| 40 |
-
_local = threading.local()
|
| 41 |
-
|
| 42 |
-
|
| 43 |
def run_one(task_index, model):
|
| 44 |
-
"""One graded rollout. Returns (correct, failed, error_or_none).
|
| 45 |
-
|
| 46 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 47 |
kwargs = dict(
|
| 48 |
split=TEST_SPLIT,
|
| 49 |
task_index=task_index,
|
|
@@ -58,13 +58,19 @@ def run_one(task_index, model):
|
|
| 58 |
agent_timeout_sec=600,
|
| 59 |
)
|
| 60 |
try:
|
| 61 |
-
|
| 62 |
-
|
| 63 |
-
|
| 64 |
-
|
| 65 |
-
|
|
|
|
| 66 |
except Exception as exc:
|
| 67 |
return task_index, model, None, True, f"{type(exc).__name__}: {exc}"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 68 |
if not result.ok or result.reward is None:
|
| 69 |
return task_index, model, None, True, getattr(result, "error", None) or "not ok"
|
| 70 |
return task_index, model, float(result.reward) == 1.0, False, None
|
|
|
|
| 22 |
|
| 23 |
import json
|
| 24 |
import os
|
|
|
|
| 25 |
from concurrent.futures import ThreadPoolExecutor, as_completed
|
| 26 |
|
| 27 |
from harbor_env import HarborEnv # re-export of openenv.harbor.client.HarborEnv
|
|
|
|
| 36 |
CONCURRENCY = int(os.environ.get("CONCURRENCY", "8"))
|
| 37 |
OUT = os.environ.get("OUT", "/app/eval_results.json")
|
| 38 |
|
|
|
|
|
|
|
|
|
|
| 39 |
def run_one(task_index, model):
|
| 40 |
+
"""One graded rollout. Returns (correct, failed, error_or_none).
|
| 41 |
+
|
| 42 |
+
A FRESH client per rollout: HarborSessionFactory documents that shared
|
| 43 |
+
clients break under concurrency, and a reused websocket hits an openenv
|
| 44 |
+
reconnect bug (mcp_client close() returning None) that kills the run.
|
| 45 |
+
"""
|
| 46 |
+
env = HarborEnv(base_url=ENV_URL)
|
| 47 |
kwargs = dict(
|
| 48 |
split=TEST_SPLIT,
|
| 49 |
task_index=task_index,
|
|
|
|
| 58 |
agent_timeout_sec=600,
|
| 59 |
)
|
| 60 |
try:
|
| 61 |
+
try:
|
| 62 |
+
result = env.run_rollout(**kwargs)
|
| 63 |
+
except TypeError:
|
| 64 |
+
# older server without eval_sampling: retry without it
|
| 65 |
+
kwargs.pop("eval_sampling")
|
| 66 |
+
result = env.run_rollout(**kwargs)
|
| 67 |
except Exception as exc:
|
| 68 |
return task_index, model, None, True, f"{type(exc).__name__}: {exc}"
|
| 69 |
+
finally:
|
| 70 |
+
try:
|
| 71 |
+
env.close()
|
| 72 |
+
except Exception:
|
| 73 |
+
pass
|
| 74 |
if not result.ok or result.reward is None:
|
| 75 |
return task_index, model, None, True, getattr(result, "error", None) or "not ok"
|
| 76 |
return task_index, model, float(result.reward) == 1.0, False, None
|
eval_watch.py
CHANGED
|
@@ -93,7 +93,13 @@ def main():
|
|
| 93 |
loaded.append(ckpt)
|
| 94 |
if len(loaded) > 4: # stay under --max-loras
|
| 95 |
lora_rpc("unload_lora_adapter", loaded.pop(0))
|
| 96 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 97 |
upload(f"/tmp/{ckpt}_cells.json", f"eval/{ckpt}_results.json")
|
| 98 |
p1, n = pass_at_1(f"/tmp/{ckpt}_cells.json")
|
| 99 |
pb, nb = pass_at_1("/tmp/base_cells.json")
|
|
|
|
| 93 |
loaded.append(ckpt)
|
| 94 |
if len(loaded) > 4: # stay under --max-loras
|
| 95 |
lora_rpc("unload_lora_adapter", loaded.pop(0))
|
| 96 |
+
try:
|
| 97 |
+
run_eval(ckpt, f"/tmp/{ckpt}_cells.json")
|
| 98 |
+
except subprocess.CalledProcessError as exc:
|
| 99 |
+
# Transient eval failure (client reconnect flake, sandbox hiccup):
|
| 100 |
+
# skip it — the next poll recomputes pending and retries it.
|
| 101 |
+
print(f"[watch] {ckpt} eval failed ({exc}); will retry next poll", flush=True)
|
| 102 |
+
continue
|
| 103 |
upload(f"/tmp/{ckpt}_cells.json", f"eval/{ckpt}_results.json")
|
| 104 |
p1, n = pass_at_1(f"/tmp/{ckpt}_cells.json")
|
| 105 |
pb, nb = pass_at_1("/tmp/base_cells.json")
|