Download gen/spatial.py from doofz/THX-01: direct link, hf CLI and curl.
- Browser
- Download file 6.52 kB
-
https://huggingface.co/doofz/THX-01/resolve/main/gen/spatial.py
- Command line
-
hf download hf://doofz/THX-01/gen/spatial.py
-
curl -L -o spatial.py https://huggingface.co/doofz/THX-01/resolve/main/gen/spatial.py
6.52 kB
| """Procedurally generated spatial-control decisions (no game data). | |
| A controller (camera, turret, drone, UI cursor, robot arm, car) has a centre/aim point; a target | |
| is left of it, right of it, on it, or not visible; distractors may sit elsewhere. The model must | |
| pick the control whose *description* matches, and answer yes/no probes such as "is the target | |
| centred?". Surface forms, units, action names and languages vary so nothing ties it to one domain. | |
| """ | |
| import json, random | |
| OUT = "./data/synth/spatial.jsonl" | |
| DOMAINS = [ | |
| dict(name="security camera", aim="the centre of the camera view", target=["intruder", "person", "car", "drone"], | |
| left="pan left", right="pan right", on="record a close-up", idle="keep scanning (pan left)", | |
| keys=("PAN_LEFT", "PAN_RIGHT", "CAPTURE")), | |
| dict(name="UI automation agent", aim="the mouse cursor", target=["'Submit' button", "search box", "close icon", "menu item"], | |
| left="move the cursor left", right="move the cursor right", on="click", idle="scroll to search (move left)", | |
| keys=("CURSOR_LEFT", "CURSOR_RIGHT", "CLICK")), | |
| dict(name="delivery drone", aim="the drone's heading", target=["landing pad", "customer", "beacon"], | |
| left="yaw left", right="yaw right", on="descend and drop the parcel", idle="rotate left to search", | |
| keys=("YAW_LEFT", "YAW_RIGHT", "DROP")), | |
| dict(name="robot arm", aim="the gripper", target=["red cube", "bolt", "bottle", "package"], | |
| left="rotate the base left", right="rotate the base right", on="close the gripper", idle="rotate left to search", | |
| keys=("ROTATE_LEFT", "ROTATE_RIGHT", "GRAB")), | |
| dict(name="self-driving car", aim="the car's lane centre", target=["lane centre line", "parking spot", "exit ramp"], | |
| left="steer left", right="steer right", on="keep straight and accelerate", idle="steer left to find the lane", | |
| keys=("STEER_LEFT", "STEER_RIGHT", "GO_STRAIGHT")), | |
| dict(name="telescope", aim="the eyepiece reticle", target=["comet", "Jupiter", "satellite"], | |
| left="slew left", right="slew right", on="start the exposure", idle="slew left to search", | |
| keys=("SLEW_LEFT", "SLEW_RIGHT", "EXPOSE")), | |
| dict(name="sports camera robot", aim="the frame centre", target=["ball", "player 10", "goalkeeper"], | |
| left="pan left", right="pan right", on="zoom in", idle="pan left to search", | |
| keys=("PAN_LEFT", "PAN_RIGHT", "ZOOM_IN")), | |
| dict(name="paintball turret", aim="the sight", target=["red flag", "moving target", "balloon"], | |
| left="traverse left", right="traverse right", on="fire", idle="traverse left to search", | |
| keys=("TRAVERSE_LEFT", "TRAVERSE_RIGHT", "FIRE")), | |
| ] | |
| UNITS = [("deg", lambda r: f"{r.randint(3, 120)} degrees"), ("px", lambda r: f"{r.randint(8, 400)} px"), | |
| ("cm", lambda r: f"{r.randint(2, 90)} cm"), ("clock", lambda r: None)] | |
| AZ = {"left": "solda", "right": "sağda", "on": "tam mərkəzdə", "none": "görünmür"} | |
| RU = {"left": "слева", "right": "справа", "on": "точно в центре", "none": "не видно"} | |
| def make(rng, dom, lang): | |
| kind = rng.choice(["left", "right", "on", "none", "left", "right"]) | |
| tgt = rng.choice(dom["target"]) | |
| unit, f = rng.choice(UNITS) | |
| off = f(rng) if f else None | |
| if lang == "en": | |
| pos = {"left": f"the {tgt} is to the LEFT of {dom['aim']}" + (f" by {off}" if off else ""), | |
| "right": f"the {tgt} is to the RIGHT of {dom['aim']}" + (f" by {off}" if off else ""), | |
| "on": f"the {tgt} is exactly on {dom['aim']}", "none": f"no {tgt} is visible"}[kind] | |
| elif lang == "az": | |
| pos = f"{tgt}: {AZ[kind]}" + (f" ({off})" if off and kind in ("left", "right") else "") | |
| else: | |
| pos = f"{tgt}: {RU[kind]}" + (f" ({off})" if off and kind in ("left", "right") else "") | |
| lines = [f"{dom['name']} status", pos] | |
| if rng.random() < 0.6: # a distractor on some other side, marked as not the target | |
| side = rng.choice(["left", "right"]) | |
| lines.append(f"other object (not the target): {side} side, {rng.randint(5, 90)} units away") | |
| if rng.random() < 0.6: | |
| hist = [rng.choice(dom["keys"]) for _ in range(rng.randint(1, 4))] | |
| lines.append("last actions: " + " ".join(hist)) | |
| if rng.random() < 0.5: | |
| lines.append(f"battery {rng.randint(5, 100)}% | step {rng.randint(1, 900)}") | |
| body = lines[1:]; rng.shuffle(body) | |
| state = "\n".join([lines[0]] + body) | |
| L, R, O = dom["keys"] | |
| crit = {L: f"{dom['left']}: the {'target' if rng.random() < .5 else tgt} is to the LEFT" + (", or it is not visible" if rng.random() < .7 else ""), | |
| R: f"{dom['right']}: the {'target' if rng.random() < .5 else tgt} is to the RIGHT", | |
| O: f"{dom['on']}: the target is exactly on {dom['aim']}"} | |
| if ", or it is not visible" not in crit[L]: | |
| crit[L] = crit[L] # 'none' then has no matching option; skip such items below | |
| gold_a = {"left": L, "right": R, "on": O, "none": L}[kind] | |
| if kind == "none" and ", or it is not visible" not in crit[L]: | |
| return [] | |
| items = list(crit.items()); rng.shuffle(items) | |
| ins = rng.choice(["Which control fits the current situation?", "Pick the action whose description matches the state.", | |
| f"What should the {dom['name']} do next?", "Which action is correct now?"]) | |
| out = [(state, {"action": {"type": "choice", "instructions": ins, "criteria": dict(items)}}, {"action": gold_a})] | |
| probes = [(f"Is the target exactly on {dom['aim']}?", kind == "on"), | |
| (f"Is {dom['aim']} empty (the target is not on it)?", kind != "on"), | |
| ("Is the target to the left?", kind == "left"), ("Is the target to the right?", kind == "right"), | |
| ("Is the target visible?", kind != "none")] | |
| pq, pg = rng.choice(probes) | |
| out.append((state, {"probe": {"type": "noul", "instructions": pq}}, {"probe": pg})) | |
| return out | |
| def main(n=9000, seed=0): | |
| rng = random.Random(seed) | |
| with open(OUT, "w") as fh: | |
| k = 0 | |
| while k < n: | |
| dom = rng.choice(DOMAINS) | |
| lang = rng.choices(["en", "az", "ru"], [70, 20, 10])[0] | |
| for s, q, g in make(rng, dom, lang): | |
| fh.write(json.dumps({"state": s, "questions": q, "gold": g, | |
| "meta": {"gen": "spatial", "group": f"s{k // 40}", "lang": lang}}, ensure_ascii=False) + "\n") | |
| k += 1 | |
| print("wrote", k) | |
| if __name__ == "__main__": | |
| main() | |