AsianPlayer's picture
download
raw
4.29 kB
"""cwm3/weak/run_gpt.py — thin wrapper over cwm2/annotation_package/run_annotation.py for the cwm3 budget (budget.yaml).
Adds the gpt-5 family (the only models visible on the 2026-09-10 key) to the package's model/price tables at import time
(the shipped package itself is not modified), points the ledger at cwm3/weak/budget_ledger.sqlite and enforces the $100 cap.
Usage: python cwm3/weak/run_gpt.py --model gpt-5 --pass observe_prefix --preset standard --detail high --clips <id> --mode sync --cap-usd 1
"""
import os, sys
from pathlib import Path
CWM3 = Path(__file__).resolve().parents[1]
PKG = CWM3.parent / "cwm2" / "annotation_package"
sys.path.insert(0, str(PKG))
os.environ.setdefault("CWM2_ALLOW_PAID_API", "1") # authorised by cwm3/budget.yaml (user, 2026-09-10)
os.environ.setdefault("OPENAI_API_KEY_FILE", os.path.expanduser("~/.openai_api_key"))
import pkg_common as pc # noqa: E402
# OpenAI list prices (USD / 1M tokens) for the gpt-5 family as of the 2025-08 launch; batch = 50 %. Snapshot recorded here;
# the ledger stores the true `usage` so reconciliation catches any drift.
pc.PRICING["gpt-5"] = {"standard": {"input": 1.25, "cached_input": 0.125, "output": 10.0},
"batch": {"input": 0.625, "cached_input": 0.0625, "output": 5.0}}
pc.PRICING["gpt-5-mini"] = {"standard": {"input": 0.25, "cached_input": 0.025, "output": 2.0},
"batch": {"input": 0.125, "cached_input": 0.0125, "output": 1.0}}
pc.MODELS = tuple(pc.MODELS) + ("gpt-5", "gpt-5-mini")
pc.LEDGER_PATH = CWM3 / "weak" / "budget_ledger.sqlite"
HARD_CAP = 100.0
import run_annotation as ra # noqa: E402
if "--ledger" not in sys.argv:
sys.argv += ["--ledger", str(pc.LEDGER_PATH)]
# ---- 2026-09-12 hard rule (roadmap §B3 / owner): TEST (and VAL) clips never leave the machine. Every clip resolved for a paid call must belong to a
# TRAIN-split device (cwm2/private/clip_map_full.json dongle -> s3 anchors split, the split_of rule of score_clean568); anything else aborts before
# any request is built. `--clips all` is resolved through the same check.
CLIP_MAP = CWM3.parent / "cwm2" / "private" / "clip_map_full.json"
S3_ANCHORS = CWM3.parent / "s3_can_baseline" / "results" / "anchors.parquet"
CLIP_MAP_PILOT = CWM3.parent / "cwm2" / "private" / "clip_map.json" # 187-clip pilot manifest; its ids are NOT in clip_map_full.json
def _split_of_dongle(d, known):
"""split_of rule of s12_wm/build_targets_s12.py:40-44 (= build_pilot_manifest.py / score_clean568.py): s3 known map, else md5 bucket."""
import hashlib
if d in known:
return known[d]
h = int(hashlib.md5(d.encode()).hexdigest(), 16) % 100
return "train" if h < 60 else ("val" if h < 70 else "test")
def _split_of_clips(clip_ids):
import json
import pandas as pd
cm = json.load(open(CLIP_MAP))
cmp = json.load(open(CLIP_MAP_PILOT)) if CLIP_MAP_PILOT.is_file() else {} # 2026-09-13: pilot clips resolve through their own private map
a3 = pd.read_parquet(S3_ANCHORS, columns=["dongle", "split"]).drop_duplicates("dongle")
known = dict(zip(a3.dongle, a3.split))
out = {}
for c in clip_ids:
d = cm.get(c, {}).get("dongle") or cmp.get(c, {}).get("dongle")
out[c] = _split_of_dongle(d, known) if d else "unknown" # no dongle -> "unknown" -> refused by assert_train_only
return out
def assert_train_only(clips_arg, limit=None):
ids = pc.resolve_clips(clips_arg, limit, require_frames=False)
sp = _split_of_clips(ids)
bad = {c: s for c, s in sp.items() if s != "train"}
if bad:
ex = ", ".join(f"{c}:{s}" for c, s in list(bad.items())[:5])
raise SystemExit(f"run_gpt.py REFUSED: {len(bad)} of {len(ids)} clips are not on TRAIN-split devices (test / val clips never leave the machine): {ex}"
+ (" ..." if len(bad) > 5 else ""))
return ids
if __name__ == "__main__":
_argv = sys.argv[1:]
_clips = _argv[_argv.index("--clips") + 1] if "--clips" in _argv else "all"
_limit = int(_argv[_argv.index("--limit") + 1]) if "--limit" in _argv else None
assert_train_only(_clips, _limit)
sys.exit(ra.main())

Xet Storage Details

Size:
4.29 kB
·
Xet hash:
1d2907947e8ae2ffcd5de0c1d50fd05ac121206eff8a4efe945ebafae573b900

Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.