sora 2c3672f2cb concurrency + reliability overhaul for agentic workloads
- AdaptiveGate rewritten (Netflix Gradient2): window-vs-window per-stream
  speed gradient, count-driven windows with admission stamps, no thresholds
  or mode state machine; failures x0.7 + 30s drain pause
- session-level admission for multi-turn agents (_SessionGate): in-progress
  sessions hold slots until done, newcomers queue at the door; capacity
  follows the model gate's discovered limit (CONCUR-style continuity)
- image service: memory-first register (zero docker calls for known
  images), TTL-cached docker images listing, optimistic ready when the
  daemon is unreachable (docker save contention no longer kills runs);
  es tar loading removed in favor of ModelScope shipping (ms_images.py
  per-image tar upload/pull with round-trip verification)
- runner: circuit breaker (12 consecutive failures abort the bench),
  first-failure error printed immediately
- swe_agentic: image wait / docker run / rm off the event loop; exec
  timeout becomes an observation the agent can react to; container gets
  curlrc + git low-speed aborts (stalled github downloads fail fast)
- eval run excludes its own endpoints from http_proxy (a sick personal
  proxy read as 'endpoint dead' and killed whole runs)
- progress bar shows failed count; swe agentic exec_workers 2 -> 4

Co-Authored-By: Claude <noreply@anthropic.com>
2026-09-21 06:41:20 +00:00

215 lines
7.9 KiB
Python

"""ModelScope-hosted sandbox images: per-image tar upload + download.
registry.modelscope.cn does not accept personal docker pushes, so images
ship as ONE docker-save tar per image inside a ModelScope MODEL repo
(file hosting with a stable CN CDN -- measured ~12MB/s anonymous; the
per-task granularity means running 3 instances downloads exactly 3 tars).
This is the only working network source for the swebench/* namespace --
public CN mirrors (daocloud/1ms/...) 403 it.
NB: it must be a MODEL repo, not a dataset repo: upload_file defaults to
repo_type='model' and silently CREATES one when given a dataset repo_id
(the first upload landed in a phantom model repo while the dataset repo
stayed empty -- confusing 404s on pull).
Upload (resumable; skips tars already on the remote):
EVALHARNESS_MS_TOKEN=ms-... python -m evalharness.sandbox.ms_images \\
upload --repo SoraAmami/swebench-images [--limit N]
Download side is wired into ImageService._pull_one (first source, before
the docker-hub mirror chain) whenever EVALHARNESS_MS_IMAGE_REPO is set
(defaults on for this deployment; empty string disables).
"""
import os
import subprocess
import sys
import tempfile
import time
from typing import List, Optional, Set
# a private-repo token for downloads (public repos work without it)
_MS_TOKEN = os.environ.get('EVALHARNESS_MS_TOKEN', '').strip()
_MS_ENDPOINT = os.environ.get('EVALHARNESS_MS_ENDPOINT', 'https://modelscope.cn')
# big enough for a ~4GB uncompressed save; / has less headroom than /data1
_TMP_ROOT = os.environ.get('EVALHARNESS_MS_TMP', '/data1/sora/temp/ms_images')
_STATE = os.path.join(_TMP_ROOT, 'uploaded.txt') # resume manifest
# image prefixes this deployment ships (swe per-instance + code benches)
_DEFAULT_PREFIXES = ('swebench/',)
def _docker(args, timeout=1800):
return subprocess.run(['docker'] + args, capture_output=True, text=True,
timeout=timeout)
def file_for(image: str) -> str:
"""Image ref -> dataset filename: last path segment minus tag.
swebench/sweb.eval.x86_64.django_1776_django-13964:latest
-> sweb.eval.x86_64.django_1776_django-13964.tar.gz
"""
base = image.rsplit('/', 1)[-1]
base = base.split(':')[0]
return f'{base}.tar.gz'
def image_from_file(fname: str) -> Optional[str]:
"""Inverse of file_for for the swe namespace (namespace is not
recoverable in general; callers here only ship swebench/*)."""
if not fname.endswith('.tar.gz'):
return None
return f"swebench/{fname[:-len('.tar.gz')]}:latest"
def _local_images() -> Set[str]:
r = _docker(['images', '--format', '{{.Repository}}:{{.Tag}}'], timeout=60)
return set(r.stdout.split()) if r.returncode == 0 else set()
def _remote_files(repo: str) -> Set[str]:
"""Files currently in the MODEL repo (resume manifest source of truth)."""
from modelscope.hub.api import HubApi
api = HubApi()
if _MS_TOKEN:
api.login(_MS_TOKEN)
files: Set[str] = set()
for e in api.get_model_files(repo, recursive=True):
p = (e.get('Path') or e.get('Name') or '').lstrip('/')
if p.endswith('.tar.gz'):
files.add(p)
return files
def _upload_one(api, repo: str, image: str, tmp_dir: str) -> bool:
tar = os.path.join(tmp_dir, file_for(image))
os.makedirs(tmp_dir, exist_ok=True)
# gzip -1: ~2x faster than default for ~10% more bytes -- upload wall
# time is dominated by docker save IO, not the extra size
r = subprocess.run(f'docker save {image} | gzip -1 > {tar}',
shell=True, timeout=3600)
if r.returncode != 0 or not os.path.exists(tar):
print(f' save failed: {image}', flush=True)
return False
try:
api.upload_file(repo_id=repo, path_or_fileobj=tar,
path_in_repo=file_for(image),
repo_type='model', token=_MS_TOKEN or None)
with open(_STATE, 'a') as f:
f.write(file_for(image) + '\n')
gb = os.path.getsize(tar) / 1e9
print(f' uploaded {file_for(image)} ({gb:.2f} GB)', flush=True)
return True
except Exception as e:
print(f' upload failed {image}: {type(e).__name__}: {str(e)[:120]}',
flush=True)
return False
finally:
try:
os.unlink(tar)
except OSError:
pass
def upload(repo: str, limit: int = 0, prefixes=None) -> None:
"""Ship every local matching image to the MODEL repo. Resumable:
already-remote tars are skipped (state file + remote listing)."""
from modelscope.hub.api import HubApi
os.makedirs(_TMP_ROOT, exist_ok=True)
api = HubApi()
if _MS_TOKEN:
api.login(_MS_TOKEN)
try:
api.get_model(repo)
except Exception:
print(f'creating model repo {repo} ...', flush=True)
api.create_model(model_id=repo)
done = set()
try:
done = {l.strip() for l in open(_STATE) if l.strip()}
except OSError:
pass
print(f'remote listing {repo} ...', flush=True)
try:
done |= _remote_files(repo)
except Exception as e:
print(f' remote listing failed ({e}); relying on local state',
flush=True)
prefixes = prefixes or _DEFAULT_PREFIXES
imgs = sorted(i for i in _local_images() if i.startswith(prefixes))
if limit:
imgs = imgs[:limit]
todo = [i for i in imgs if file_for(i) not in done]
print(f'{len(imgs)} local images, {len(todo)} to upload '
f'({len(imgs) - len(todo)} already remote)', flush=True)
ok = 0
for n, img in enumerate(todo, 1):
print(f'[{n}/{len(todo)}] {img}', flush=True)
for attempt in range(3):
if _upload_one(api, repo, img, _TMP_ROOT):
ok += 1
break
time.sleep(10 * (attempt + 1)) # hub hiccups: backoff + retry
print(f'done: {ok}/{len(todo)} uploaded', flush=True)
def ms_pull(image: str, repo: str) -> bool:
"""Fetch one image tar from the dataset repo and docker-load it.
Returns True iff the image is local afterwards."""
import urllib.request
fname = file_for(image)
url = (f'{_MS_ENDPOINT}/api/v1/models/{repo}/repo'
f'?Revision=master&FilePath={fname}')
hdrs = {'User-Agent': 'evalharness'}
if _MS_TOKEN:
hdrs['Authorization'] = f'Bearer {_MS_TOKEN}'
os.makedirs(_TMP_ROOT, exist_ok=True)
fd, tar = tempfile.mkstemp(suffix='.tar.gz', dir=_TMP_ROOT)
os.close(fd)
try:
req = urllib.request.Request(url, headers=hdrs)
t0 = time.time()
with urllib.request.urlopen(req, timeout=600) as r, open(tar, 'wb') as f:
while True:
chunk = r.read(1 << 20)
if not chunk:
break
f.write(chunk)
r = _docker(['load', '-qi', tar], timeout=1800)
if r.returncode == 0 and image in _local_images():
gb = os.path.getsize(tar) / 1e9
print(f'· ms-images: loaded {image.split("/")[-1][:50]} '
f'({gb:.2f} GB in {time.time() - t0:.0f}s)', flush=True)
return True
print(f'· ms-images: load failed for {image}: '
f'{(r.stderr or "")[:120]}', flush=True)
return False
except Exception as e:
# 404 = this image was never uploaded; anything else = transient
code = getattr(e, 'code', None)
if code != 404:
print(f'· ms-images: fetch {fname}: {type(e).__name__}: '
f'{str(e)[:100]}', flush=True)
return False
finally:
try:
os.unlink(tar)
except OSError:
pass
if __name__ == '__main__':
import argparse
p = argparse.ArgumentParser()
p.add_argument('cmd', choices=['upload'])
p.add_argument('--repo', default='SoraAmami/swebench-images')
p.add_argument('--limit', type=int, default=0)
a = p.parse_args()
if a.cmd == 'upload':
upload(a.repo, limit=a.limit)