| """Brain-2 heldout eval set: agent-authored automation requests for the 10 |
| reserved homes (data/homes/heldout/), validated against the live inventory with |
| taskgen's exact rules. These homes never appear in warmup or GRPO data. |
| |
| Output: data/processed/grpo/heldout.parquet (same columns the probe/eval reads). |
| |
| Run: uv run --group sandbox --group train python train/heldout_prep.py |
| """ |
|
|
| import json |
| import pathlib |
| import sys |
|
|
| _REPO = pathlib.Path(__file__).resolve().parent.parent |
| sys.path.insert(0, str(_REPO)) |
|
|
| HOMES = _REPO / "data" / "homes" / "heldout" |
| REQS = _REPO / "data" / "processed" / "route_requests" / "heldout" |
| OUT = _REPO / "data" / "processed" / "grpo" |
|
|
|
|
| def main() -> None: |
| from datasets import Dataset |
|
|
| from sandbox.harness import SandboxHome |
|
|
| rows, dropped = [], 0 |
| for path in sorted(HOMES.glob("*.yaml")): |
| home_id = path.stem |
| reqs = json.loads((REQS / f"{home_id}.json").read_text()) |
| inventory = path.read_text() |
| home = SandboxHome(inventory) |
| ents = home.inventory.get("entities", []) |
| ids = {e["id"] for e in ents} |
| name_of = {e["id"]: e.get("name", e["id"]) for e in ents} |
| seen = set() |
| for req in reqs: |
| utt, trig, act = req["utterance"].strip(), req["trigger"], req["actuator"] |
| problem = ( |
| "empty" if not utt |
| else "dup" if utt.lower() in seen |
| else "bad actuator" if act not in ids |
| else "bad trigger" if trig not in ids and trig not in ("time", "sun") |
| else "actuator name missing" if name_of[act].lower() not in utt.lower() |
| else None |
| ) |
| if problem: |
| dropped += 1 |
| print(f"[heldout] drop ({home_id}, {problem}): {utt[:60]!r}") |
| continue |
| seen.add(utt.lower()) |
| rows.append( |
| { |
| "utterance": utt, |
| "devices_block": home.devices_block(), |
| "trigger": trig, |
| "actuator": act, |
| "inventory": inventory, |
| "home": home_id, |
| "category": "route_automation", |
| } |
| ) |
| home.close() |
|
|
| OUT.mkdir(parents=True, exist_ok=True) |
| Dataset.from_list(rows).to_parquet(str(OUT / "heldout.parquet")) |
| homes = len({r["home"] for r in rows}) |
| print(f"[heldout] {len(rows)} prompts across {homes} homes ({dropped} dropped) -> {OUT / 'heldout.parquet'}") |
|
|
|
|
| if __name__ == "__main__": |
| main() |
|
|