Download scripts/generate.py from yqi19/mp_yam_code: direct link, hf CLI and curl.
- Browser
- Download file 5.75 kB
-
https://huggingface.co/yqi19/mp_yam_code/resolve/main/scripts/generate.py
- Command line
-
hf download hf://yqi19/mp_yam_code/scripts/generate.py
-
curl -L -o generate.py https://huggingface.co/yqi19/mp_yam_code/resolve/main/scripts/generate.py
5.75 kB
| """Scale up: run many randomized episodes per task and keep only the ones that succeeded. | |
| Each episode is a fresh seed, so the scene randomization differs every time; the scripted solver | |
| plays it and the task's own conditions decide whether it counts. Failed episodes are discarded | |
| (or kept under --keep-failures for debugging), which is what makes this a demonstration | |
| generator rather than a batch runner. | |
| python scripts/generate.py --episodes 20 # every task | |
| python scripts/generate.py --tasks grape_box,stack_blocks --episodes 50 | |
| python scripts/generate.py --tasks passing --episodes 100 # only tasks known to work | |
| python scripts/generate.py --episodes 20 --resume # skip episodes already done | |
| Writes: | |
| <out>/<task>/ep<seed>.mp4 video, successes only unless --keep-failures | |
| <out>/<task>/ep<seed>.json per-episode result + the exact randomized placements | |
| <out>/manifest.json running totals and success rate per task | |
| One episode is one simulator launch, so this is slow and long-running by nature; it prints a | |
| line per episode and is safe to interrupt and --resume. | |
| """ | |
| import argparse | |
| import json | |
| import os | |
| import re | |
| import subprocess | |
| import sys | |
| import time | |
| REPO = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) | |
| ap = argparse.ArgumentParser() | |
| ap.add_argument("--tasks", default="all", | |
| help="'all', 'passing', or a comma-separated list of task names") | |
| ap.add_argument("--episodes", type=int, default=10, help="episodes per task") | |
| ap.add_argument("--start-seed", type=int, default=100, | |
| help="seeds run from here upward; keep clear of the 0-9 used for development") | |
| ap.add_argument("--out", default="data") | |
| ap.add_argument("--keep-failures", action="store_true") | |
| ap.add_argument("--resume", action="store_true", help="skip episodes whose json already exists") | |
| ap.add_argument("--timeout", type=int, default=1500) | |
| ap.add_argument("--python", default=sys.executable) | |
| a = ap.parse_args() | |
| def registered(): | |
| out = subprocess.run([a.python, "scripts/yam_task.py", "--list"], cwd=REPO, | |
| capture_output=True, text=True).stdout | |
| return [l.split()[0] for l in out.splitlines()[1:] if l.strip() and not l.startswith(("name", "-")) | |
| and len(l.split()) > 2] | |
| def known_passing(): | |
| """Tasks whose most recent development run succeeded -- the ones worth spending seeds on.""" | |
| good = [] | |
| for t in registered(): | |
| log = os.path.join(REPO, "outputs", "tasks", f"v3_{t}.log") | |
| if os.path.exists(log) and "EPISODE_RESULT: SUCCESS" in open(log, errors="ignore").read(): | |
| good.append(t) | |
| return good | |
| tasks = (registered() if a.tasks == "all" else | |
| known_passing() if a.tasks == "passing" else | |
| [t.strip() for t in a.tasks.split(",") if t.strip()]) | |
| if not tasks: | |
| raise SystemExit("no tasks selected") | |
| out_root = os.path.join(REPO, a.out) | |
| os.makedirs(out_root, exist_ok=True) | |
| manifest_path = os.path.join(out_root, "manifest.json") | |
| manifest = json.load(open(manifest_path)) if os.path.exists(manifest_path) else {} | |
| env = dict(os.environ) | |
| env.setdefault("OMNI_KIT_ACCEPT_EULA", "YES") | |
| env.setdefault("PYTHONUNBUFFERED", "1") | |
| print(f"[gen] {len(tasks)} task(s) x {a.episodes} episodes, seeds " | |
| f"{a.start_seed}..{a.start_seed+a.episodes-1} -> {out_root}", flush=True) | |
| t_start = time.time() | |
| for task in tasks: | |
| tdir = os.path.join(out_root, task) | |
| os.makedirs(tdir, exist_ok=True) | |
| rec = manifest.setdefault(task, {"attempted": 0, "succeeded": 0, "episodes": []}) | |
| for i in range(a.episodes): | |
| seed = a.start_seed+i | |
| meta_p = os.path.join(tdir, f"ep{seed}.json") | |
| if a.resume and os.path.exists(meta_p): | |
| continue | |
| vid = os.path.join(tdir, f"ep{seed}.mp4") | |
| t0 = time.time() | |
| try: | |
| p = subprocess.run( | |
| [a.python, "scripts/yam_task.py", "--task", task, "--seed", str(seed), | |
| "--video", vid, | |
| "--kit_args=--/rtx/verifyDriverVersion/enabled=false"], | |
| cwd=REPO, env=env, capture_output=True, text=True, timeout=a.timeout) | |
| log = p.stdout+p.stderr | |
| except subprocess.TimeoutExpired: | |
| log = "TIMEOUT" | |
| ok = "EPISODE_RESULT: SUCCESS" in log | |
| # the randomized placements the env printed -- this is the episode's actual scene | |
| m = re.search(r"placements=(\{.*?\})\s*$", log, re.M) | |
| meta = {"task": task, "seed": seed, "success": ok, | |
| "seconds": round(time.time()-t0, 1), | |
| "placements": m.group(1) if m else None, | |
| "conditions": re.findall(r"^\[env\] (PASS|FAIL) (.+)$", log, re.M)} | |
| json.dump(meta, open(meta_p, "w"), indent=1) | |
| if not ok and not a.keep_failures and os.path.exists(vid): | |
| os.remove(vid) | |
| rec["attempted"] += 1 | |
| rec["succeeded"] += int(ok) | |
| rec["episodes"].append({"seed": seed, "success": ok}) | |
| json.dump(manifest, open(manifest_path, "w"), indent=1) | |
| print(f"[gen] {task:<18} seed {seed:<4} {'ok ' if ok else 'FAIL'} " | |
| f"{meta['seconds']:>5.1f}s ({rec['succeeded']}/{rec['attempted']})", flush=True) | |
| print(f"\n[gen] done in {(time.time()-t_start)/60:.1f} min") | |
| tot_a = sum(r["attempted"] for r in manifest.values()) | |
| tot_s = sum(r["succeeded"] for r in manifest.values()) | |
| for t, r in sorted(manifest.items()): | |
| if r["attempted"]: | |
| print(f" {t:<20} {r['succeeded']:>4}/{r['attempted']:<4} " | |
| f"{100*r['succeeded']/r['attempted']:5.1f}%") | |
| print(f" {'TOTAL':<20} {tot_s:>4}/{tot_a:<4} " | |
| f"{(100*tot_s/tot_a if tot_a else 0):5.1f}% manifest -> {manifest_path}") | |