THX-01 / gen /spatial.py
doofz's picture
System1 v1.0
fa7df86 verified
Raw History Blame Contribute Delete
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()