"""OptiScene-style LLM modes (llm_structured): protocol-only input, a train demonstration, tagged answers, input-only
harness. llm_baseline.py, which today's paid prompt/harness runs are bound to, stays byte-identical to commit 510f1e0."""
import hashlib
import json
import math
from pathlib import Path
import re
import subprocess
import urllib.request
import pytest
from fastfill.v2 import llm_baseline, llm_structured as S
from fastfill.v2.evaluate import project_minimal, run_evaluation
from fastfill.v2.tests.test_evaluate_fix20261006 import real_rows
DATA = Path(S.__file__).parents[2] / "outputs/fastfill_v2/rebuild-main-20261007b/main"
DEMO_SCENE = "il3d:b580392a-86d4-11f0-a478-60cf84ae2082"
def rows():
return [p for p in map(project_minimal, real_rows()) if p is not None]
def design(row, room_type="...", exact=False):
"""The row's target as the [Design] JSON (mm / 0.1 deg unless exact), objects in request order."""
q = (lambda value, digits: value) if exact else round
targets = {t["id"]: t for t in row["target"]["objects"]}
objects = []
for o in row["condition"]["objects"]:
t = targets[o["id"]]
(depth, width, height), (x, y, z) = t["target_size_local_m"], t["bottom_center_m"]
objects.append({"id": o["id"], "width_m": q(width, 3), "depth_m": q(depth, 3), "height_m": q(height, 3),
"x": q(x, 3), "y": q(y, 3), "z": q(z, 3), "facing_deg": q(math.degrees(t["yaw_rad"]) % 360, 1)})
return '{"room type": ' + json.dumps(room_type) + ', "objects": [\n' + ",\n".join(json.dumps(o) for o in objects) + "\n]}"
def tagged(row, objects=None, exact=False):
body = design(row, exact=exact) if objects is None else json.dumps({"objects": objects})
return ('\n[Reason]\nBraces {"like": "these"} in the reasoning are ignored.\n[/Reason]\n\n\n'
f"\n[Design]\n```json\n{body}\n```\n[/Design]\n")
def overlapping(row):
objects = json.loads(design(row))["objects"]
objects[1].update(x=objects[0]["x"], y=objects[0]["y"], z=objects[0]["z"]) # two objects in one place
return objects
def env(tmp_path, rpm=""):
path = tmp_path / "api.env"
path.write_text(f"OPENAI_BASE_URL=https://relay/v1\nOPENAI_API_KEY=k\nOPENAI_MODEL=m\n{rpm}")
return path
def write(tmp_path, data):
path = tmp_path / "rows.jsonl"
path.write_text("".join(json.dumps(r) + "\n" for r in data))
return path
def test_llm_baseline_is_byte_identical_to_510f1e0():
"""autorun reuses today's prompt/harness runs only while sha256(llm_baseline.py) matches their summary.json; any
edit deletes them and pays for new, differently sampled answers. Back them up before changing this file."""
path = Path(llm_baseline.__file__)
try:
old = subprocess.run(["git", "-C", str(path.parent), "show", "510f1e0:fastfill/v2/llm_baseline.py"],
capture_output=True, check=True).stdout
except (OSError, subprocess.CalledProcessError):
pytest.skip("commit 510f1e0 is not in this checkout")
assert path.read_bytes() == old
def test_structured_input_is_the_protocol_fields_only(tmp_path):
data, seen = rows(), []
S.run(write(tmp_path, data), tmp_path / "s", env(tmp_path), ask=lambda env, model, messages: seen.append(messages) or tagged(data[0]))
assert all(m[0] == {"role": "system", "content": S.STRUCTURED} for m in seen)
for row in data:
user = next(m[1]["content"] for m in seen if m[1]["content"] == S.sections(row["condition"]))
room = row["condition"]["room"]
listed = [{k: o[k] for k in ("id", "category", "description")} for o in row["condition"]["objects"]]
protocol = {"room": {k: room[k] for k in ("room_type", "floor_polygon_xy_m", "floor_z_m", "height_m")}, "objects": listed}
noisy = {**row["condition"], "room": {**room, "fixed_objects": [{"id": "f"}], "openings": [1]}, "constraints": [{"type": "near"}],
"objects": [{**o, "target_size_local_m": [9, 9, 9], "attributes": {}} for o in row["condition"]["objects"]]}
assert user == S.sections(protocol) == S.sections(noisy) # reads nothing else
kind, size, objects = user.split("\n\n") # the three sections and nothing else: no hint keyed on category
assert kind == f"[Task Room Type]\n{room['room_type']}\n[/Task Room Type]"
assert objects == "[Task Objects]\n[\n" + ",\n".join(json.dumps(o, ensure_ascii=False) for o in listed) + "\n]\n[/Task Objects]"
head, extent, polygon, floor, tail = size.split("\n")
assert (head, tail) == ("[Task Room Size]", "[/Task Room Size]")
assert re.fullmatch(r"width \(x\) x length \(y\) x height \(z\): \d+\.\d{3} m x \d+\.\d{3} m x (\d+\.\d{3} m|unknown)", extent)
assert polygon == "floor polygon (x, y): " + json.dumps([[round(x, 3), round(y, 3)] for x, y in room["floor_polygon_xy_m"]])
assert re.fullmatch(r"floor z: (-?\d+\.\d{3} m|unknown)", floor)
for t in row["target"]["objects"]:
assert not any(f"{v:.3f}" in user for v in t["bottom_center_m"][:2] + t["target_size_local_m"])
assert f"{math.degrees(t['yaw_rad']):.1f}" not in user
assert row["provenance"]["split"] == "validation" and row["provenance"]["scene_id"] not in S.STRUCTURED
declared = {"room": {"floor_polygon_xy_m": [[0, 0], [1, 0], [1, 1], [0, 1]], "floor_z_m": None, "height_m": None},
"objects": [{"id": "a", "category": "lamp", "description": "", "support_parent": "b"}]}
assert S.sections(declared) == (
"[Task Room Type]\nunknown\n[/Task Room Type]\n\n[Task Room Size]\n"
"width (x) x length (y) x height (z): 1.000 m x 1.000 m x unknown\nfloor polygon (x, y): [[0, 0], [1, 0], [1, 1], [0, 1]]\n"
'floor z: unknown\n[/Task Room Size]\n\n[Task Objects]\n[\n{"id": "a", "category": "lamp", "description": "", "support_parent": "b"}\n]\n[/Task Objects]')
# the template holds no size table: besides the demonstration, only the guidance numbers and "0 / 90 faces ..."
assert set(re.findall(r"\d+(?:\.\d+)?", S.STRUCTURED.replace(S.DEMONSTRATION, ""))) == {"0", "90", *map(str, range(1, 10))}
@pytest.mark.skipif(not (DATA / "train.jsonl").is_file(), reason="rebuild-main-20261007b not on this machine")
def test_demonstration_is_rebuilt_from_its_train_row():
needle = f'"scene_id":"{DEMO_SCENE}"'.encode()
with (DATA / "train.jsonl").open("rb") as stream:
row = json.loads(next(line for line in stream if needle in line))
assert row["provenance"]["split"] == "train"
for split in ("validation", "test"):
assert DEMO_SCENE.encode() not in (DATA / f"{split}.jsonl").read_bytes()
demo = project_minimal(row)
text = S.sections(demo["condition"], "Example") + "\n\n[Example Reason]\n"
assert S.DEMONSTRATION.startswith(text)
shown = design(demo, "bedroom")
assert S.DEMONSTRATION.endswith(f"\n[/Example Reason]\n\n[Example Design]\n{shown}\n[/Example Design]")
reason = S.DEMONSTRATION[len(text):-len(f"\n[/Example Reason]\n\n[Example Design]\n{shown}\n[/Example Design]")]
assert not re.search(r"\d", reason) # the hand-written reason gives no sizes or positions
layout, found = S.check_answer(f"[Design]{shown}[/Design]", demo["condition"])
assert layout is not None and found == []
def test_same_rooms_as_the_prompt_modes_and_one_scorer(tmp_path):
data = rows()
answers = {S.sections(r["condition"]): tagged(r, exact=True) for r in data}
summary = S.run(write(tmp_path, data), tmp_path / "s", env(tmp_path), ask=lambda env, model, messages: answers[messages[1]["content"]])
assert (summary["failed"], summary["api_calls"], summary["mode"]) == (0, len(data), "structured")
assert summary["prompt_sha256"] == hashlib.sha256(S.STRUCTURED.encode()).hexdigest()
report = run_evaluation(tmp_path / "s/rows.jsonl", tmp_path / "eval", predictions=tmp_path / "s/predictions.jsonl")
reference = report["model"]["reference"]
assert reference["bottom_center_error_m"]["mean"] < 1e-6 and reference["log_size_error"]["mean"] < 1e-6
assert report["collapse"]["predicted"] == report["collapse"]["ground_truth"]
llm_baseline.run(write(tmp_path, data), tmp_path / "p", env(tmp_path), ask=lambda *a: "{}")
rooms = (tmp_path / "p/rows.jsonl").read_bytes()
assert (tmp_path / "s/rows.jsonl").read_bytes() == rooms # the rows the prompt modes answered
again = S.run(tmp_path / "p/rows.jsonl", tmp_path / "again", env(tmp_path), ask=lambda env, model, messages: answers[messages[1]["content"]])
assert (tmp_path / "again/rows.jsonl").read_bytes() == rooms and again["data_sha256"] == hashlib.sha256(rooms).hexdigest()
def test_overlap_is_reported_and_the_repaired_answer_kept(tmp_path):
row, seen = rows()[0], []
bad = overlapping(row)
def ask(env, model, messages):
seen.append(messages)
return tagged(row, bad) if len(seen) == 1 else tagged(row)
summary = S.run(write(tmp_path, [row]), tmp_path / "h", env(tmp_path), mode="structured-harness", ask=ask)
assert summary["api_calls"] == 2 and summary["repairs"] == 2 and summary["failed"] == 0
assert "overlap" in seen[1][-1]["content"] and seen[1][-2] == {"role": "assistant", "content": tagged(row, bad)}
prediction = json.loads((tmp_path / "h/predictions.jsonl").read_text())
assert (prediction["repair_rounds"], prediction["checks_final"], prediction["first_answer_valid"]) == (1, 0, True)
assert prediction["checks_first"] >= 1 and prediction["layout"] == S.check_answer(tagged(row), row["condition"])[0]
once = S.run(write(tmp_path, [row]), tmp_path / "p", env(tmp_path), mode="structured", ask=lambda *a: tagged(row, bad))
assert once["api_calls"] == 1 and once["repairs"] == 0 and once["mean_checks_final"] >= 1
@pytest.mark.parametrize("repair", ["unreadable", "request fails"])
def test_a_bad_repair_keeps_the_last_valid_layout(tmp_path, repair):
row, seen = rows()[0], []
bad = overlapping(row)
def ask(env, model, messages):
seen.append(messages)
if len(seen) == 1:
return tagged(row, bad)
if repair == "request fails":
raise ConnectionError("relay down")
return "Sorry, no design this time."
summary = S.run(write(tmp_path, [row]), tmp_path / "h", env(tmp_path), mode="structured-harness", ask=ask)
prediction = json.loads((tmp_path / "h/predictions.jsonl").read_text())
assert summary["failed"] == 0 and prediction["layout"] == S.check_answer(tagged(row, bad), row["condition"])[0]
assert prediction["attempts"] == 1 and prediction["checks_final"] == prediction["checks_first"] >= 1
assert (summary["api_calls"], prediction["repair_rounds"]) == ((2, 0) if repair == "request fails" else (3, 2))
def test_unparseable_first_answer_is_asked_again_with_the_error(tmp_path):
row, seen = rows()[0], []
def ask(env, model, messages):
seen.append(messages)
return "I would rather describe the room." if len(seen) == 1 else tagged(row)
S.run(write(tmp_path, [row]), tmp_path / "h", env(tmp_path), mode="structured-harness", ask=ask)
prediction = json.loads((tmp_path / "h/predictions.jsonl").read_text())
assert prediction["layout"] is not None and (prediction["attempts"], prediction["repair_rounds"]) == (1, 1)
assert prediction["first_answer_valid"] is False and "could not be read" in seen[1][-1]["content"]
seen.clear()
S.run(write(tmp_path, [row]), tmp_path / "s", env(tmp_path), mode="structured", ask=ask)
prediction = json.loads((tmp_path / "s/predictions.jsonl").read_text())
assert prediction["attempts"] == 2 and len(seen[1]) == 2 # without the harness: asked again from scratch
def test_checks_name_numbers_ids_floor_ceiling_and_supports():
condition = {"room": {"floor_polygon_xy_m": [[0, 0], [4, 0], [4, 4], [0, 4]], "floor_z_m": 0., "height_m": 3.},
"objects": [{"id": "t", "category": "table", "description": "", "support_parent": "floor"},
{"id": "l", "category": "lamp", "description": "", "support_parent": "t"}]}
table = {"id": "t", "width_m": 1., "depth_m": 1., "height_m": 3.5, "x": 2., "y": 2., "z": 0., "facing_deg": 0}
lamp = {"id": "l", "width_m": .2, "depth_m": .2, "height_m": .4, "x": 3.5, "y": 2., "z": 0., "facing_deg": 90}
layout, found = S.check_answer(json.dumps({"objects": [{**table, "width_m": -1, "x": None}]}), condition)
assert layout is None and found == ["answer must hold each requested id exactly once: duplicated [], unknown [], missing ['l']",
"t: width_m must be a positive number, got -1", "t: x must be a finite number, got None"]
layout, found = S.check_answer(json.dumps({"objects": [table, lamp]}), condition)
assert layout is not None and any("above the 3.00 m ceiling" in f for f in found)
assert any(f.startswith("l (lamp) must rest on t (table)") for f in found)
on_top = {**lamp, "x": 2.2, "z": 3.5}
assert not any("must rest" in f for f in S.check_answer(json.dumps({"objects": [table, on_top]}), condition)[1])
for z, problem in ((-.5, "t (table) is 0.50 m below the floor"), (.3, "t (table) must stand on the floor (z = 0.00), not at z = 0.30")):
low = {**table, "height_m": 1., "z": z}
assert problem in S.check_answer(json.dumps({"objects": [low, {**on_top, "z": z + 1.}]}), condition)[1]
crowded = {"room": condition["room"], "objects": [{"id": f"o{k}", "category": "box", "description": ""} for k in range(12)]}
boxes = [{**table, "id": f"o{k}", "height_m": 3.5 if k == 11 else 1.} for k in range(12)]
found = S.check_answer(json.dumps({"objects": boxes}), crowded)[1]
assert len(found) == 1 + 66 and found[0] == "o11 (box) reaches 3.50 m, above the 3.00 m ceiling" # 66 overlaps never hide it
class Relay:
"""urlopen stand-in: keyed by the request's first user text, the first answer is ``first[key]``, a repair ``later[key]``."""
def __init__(self, first, later):
self.first, self.later, self.bodies = first, later, []
def __call__(self, request, timeout):
self.bodies.append(request.data)
messages = json.loads(request.data)["messages"]
self.body = json.dumps({"choices": [{"message": {"content": (self.first if len(messages) == 2 else self.later)[messages[1]["content"]]}}],
"usage": {"prompt_tokens": 100, "completion_tokens": 20, "total_tokens": 120}}).encode()
return self
def __enter__(self): return self
def __exit__(self, *a): return False
def read(self): return self.body
def test_structured_rows_record_token_usage(tmp_path, monkeypatch):
data = rows()
first = {S.sections(r["condition"]): tagged(r, [{"id": "nope"}]) for r in data}
later = {S.sections(r["condition"]): tagged(r) for r in data}
fake = Relay(first, later)
monkeypatch.setattr(urllib.request, "urlopen", fake)
summary = S.run(write(tmp_path, data), tmp_path / "s", env(tmp_path, "FASTFILL_LLM_RPM=600000\n"), mode="structured-harness", workers=1)
body = json.loads(fake.bodies[0])
assert body["messages"][0] == {"role": "system", "content": S.STRUCTURED} and len(body["messages"]) == 2
assert {k: v for k, v in body.items() if k != "messages"} == llm_baseline.request_parameters({}, "m")
assert summary["usage"] == {"calls_reported": 2 * len(data), "prompt_tokens": 200 * len(data),
"completion_tokens": 40 * len(data), "total_tokens": 240 * len(data)}
predictions = [json.loads(line) for line in (tmp_path / "s/predictions.jsonl").read_text().splitlines()]
assert all(p["usage"]["total_tokens"] == 240 and p["first_answer_valid"] is False for p in predictions)