bigcodebench: official image + fail-fast preflight + no-retry on missing image
1140 real predictions scored 0.0% because the recipe referenced 'bigcodebench-sandbox:latest' -- a name nothing builds and docker.io does not have; every sample then burned 3 pull-retries (~200s each). - image -> bigcodebench/bigcodebench-evaluate:latest (the official hub image, same one evalscope uses) - ensure_image() preflight in evaluate(): recipe-level AND sample-level images are verified/pulled ONCE before any container runs; missing -> seconds-fast bench failure with a fix hint instead of a silent 0.0% - docker exec: 'Unable to find image'/'manifest unknown' class errors are permanent -- no 3x retry amplification Verified with a bogus image: preflight raises in one pull-attempt with the fix hint. Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
1e72a553ec
commit
2949e10371
@ -56,7 +56,7 @@ def bigcodebench():
|
|||||||
extract='code_any',
|
extract='code_any',
|
||||||
scorers={'pass': {'name': 'execution', 'harness': _bcb_harness,
|
scorers={'pass': {'name': 'execution', 'harness': _bcb_harness,
|
||||||
# official sandbox image (bundles every task's deps)
|
# official sandbox image (bundles every task's deps)
|
||||||
'image': 'bigcodebench-sandbox:latest',
|
'image': 'bigcodebench/bigcodebench-evaluate:latest', # official hub image, same as evalscope
|
||||||
'sandbox': 'docker', 'timeout_s': 120}},
|
'sandbox': 'docker', 'timeout_s': 120}},
|
||||||
aggregators={'pass': 'pass_at_k'},
|
aggregators={'pass': 'pass_at_k'},
|
||||||
exec_workers=12,
|
exec_workers=12,
|
||||||
|
|||||||
@ -51,6 +51,29 @@ def evaluate(
|
|||||||
aggregators = recipe.resolve_aggregators()
|
aggregators = recipe.resolve_aggregators()
|
||||||
ctx = ScoreContext(judge=judge, params={})
|
ctx = ScoreContext(judge=judge, params={})
|
||||||
|
|
||||||
|
# fail-fast image preflight: recipe-level AND sample-level images are
|
||||||
|
# ensured (local or pulled once) BEFORE any container runs -- a missing
|
||||||
|
# image must kill the bench in seconds with a fix hint, not produce a
|
||||||
|
# 0.0% after hours of per-sample pull failures
|
||||||
|
try:
|
||||||
|
_imgs = set()
|
||||||
|
for spec in (recipe.scorers or {}).values():
|
||||||
|
p = spec if isinstance(spec, dict) else {}
|
||||||
|
if p.get('name') == 'execution' and p.get('sandbox') == 'docker' and p.get('image'):
|
||||||
|
_imgs.add(p['image'])
|
||||||
|
for s in samples[:200]:
|
||||||
|
if getattr(s, 'sandbox', None) and s.sandbox.image:
|
||||||
|
_imgs.add(s.sandbox.image)
|
||||||
|
if _imgs:
|
||||||
|
from ..sandbox.docker import ensure_image
|
||||||
|
|
||||||
|
for _img in sorted(_imgs):
|
||||||
|
ensure_image(_img)
|
||||||
|
except RuntimeError:
|
||||||
|
raise
|
||||||
|
except Exception:
|
||||||
|
pass # no docker here (local sandbox): the scorer will complain
|
||||||
|
|
||||||
# If any scorer executes in docker with per-sample images, overlap pulls
|
# If any scorer executes in docker with per-sample images, overlap pulls
|
||||||
# with scoring (run sample N while N+1..N+lookahead images download).
|
# with scoring (run sample N while N+1..N+lookahead images download).
|
||||||
bp = None
|
bp = None
|
||||||
|
|||||||
@ -26,6 +26,26 @@ def docker_available() -> bool:
|
|||||||
return _run(['docker', 'info']).returncode == 0
|
return _run(['docker', 'info']).returncode == 0
|
||||||
|
|
||||||
|
|
||||||
|
def ensure_image(img: str) -> None:
|
||||||
|
"""Fail-fast sandbox image preflight: present locally, else pull ONCE.
|
||||||
|
|
||||||
|
Without this, every sample's `docker run` tries its own pull at scoring
|
||||||
|
time -- a missing image burned 1140 x 3 retries x ~70s on bigcodebench
|
||||||
|
before anyone saw a 0.0%."""
|
||||||
|
if not img:
|
||||||
|
return
|
||||||
|
if _run(['docker', 'image', 'inspect', img]).returncode == 0:
|
||||||
|
return
|
||||||
|
r = _run(['docker', 'pull', img], timeout=1800)
|
||||||
|
if r.returncode != 0:
|
||||||
|
raise RuntimeError(
|
||||||
|
f'sandbox image {img!r} is not available: not local, and '
|
||||||
|
f'docker pull failed: {(r.stderr or "")[:200]}. '
|
||||||
|
'Fix: pull/build it first (for bigcodebench the official image '
|
||||||
|
'is bigcodebench/bigcodebench-evaluate:latest), then re-run with '
|
||||||
|
'--rescore to score the cached predictions.')
|
||||||
|
|
||||||
|
|
||||||
@register_sandbox('docker')
|
@register_sandbox('docker')
|
||||||
class DockerSandbox(Sandbox):
|
class DockerSandbox(Sandbox):
|
||||||
name = 'docker'
|
name = 'docker'
|
||||||
@ -90,6 +110,14 @@ class DockerSandbox(Sandbox):
|
|||||||
raise
|
raise
|
||||||
if proc.returncode != 125 or attempt == 2:
|
if proc.returncode != 125 or attempt == 2:
|
||||||
break
|
break
|
||||||
|
# image-not-found is PERMANENT: retrying it 3x per sample
|
||||||
|
# burned 1140 x ~200s on a nonexistent bigcodebench image
|
||||||
|
_nf = 'Unable to find image' in (proc.stderr or '') \
|
||||||
|
or 'failed to resolve' in (proc.stderr or '') \
|
||||||
|
or 'manifest unknown' in (proc.stderr or '') \
|
||||||
|
or 'pull access denied' in (proc.stderr or '')
|
||||||
|
if _nf:
|
||||||
|
break
|
||||||
# clear any husk; fresh name next try. Bounded: an rm against
|
# clear any husk; fresh name next try. Bounded: an rm against
|
||||||
# a bloated daemon can hang for minutes and silently eat the
|
# a bloated daemon can hang for minutes and silently eat the
|
||||||
# whole worker pool (7 of 8 workers were observed stuck here)
|
# whole worker pool (7 of 8 workers were observed stuck here)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user