Instructions to use XXXpilar/Fastfill-test with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- PEFT
How to use XXXpilar/Fastfill-test with PEFT:
Task type is invalid.
- Notebooks
- Google Colab
- Kaggle
File size: 8,515 Bytes
e6f80f3 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 | """Reference room extents retain coordinates without claiming a measured room."""
from copy import deepcopy
import json
from pathlib import Path
import subprocess
import sys
import pytest
import torch
from fastfill.v2.direct_layout import bbox_diagnostics, layout_to_roomgenbench, layout_to_scene, request_to_condition
from fastfill.v2.schema import validate_condition, validate_layout
def request(dimensions=(5., 4.)):
return {"room_type": "unknown", "room_size_m": list(dimensions), "furniture_list": ["chair"]}
def prediction(condition, position=(-1., 2., -.5)):
return {"schema_version": "fastfill.v2", "objects": [
{"id": condition["objects"][0]["id"], "target_size_local_m": [1., 1., 1.],
"bottom_center_m": list(position), "yaw_rad": 0.}]}
@pytest.mark.parametrize("dimensions", [(5., 4.), (5., 4., 3.)])
def test_reference_extent_preserves_request_without_fabricating_boundary_or_floor(dimensions):
source = request(dimensions)
saved = deepcopy(source)
condition = request_to_condition(source, room_size_semantics="reference_extent")
validate_condition(condition)
assert source == saved
assert set(source) == {"room_type", "room_size_m", "furniture_list"}
assert condition["room"] == {
"frame": "right_handed_z_up", "room_type": "unknown",
"floor_polygon_xy_m": [[0., 0.], [5., 0.], [5., 4.], [0., 4.]],
"floor_z_m": 0., "floor_known": False, "boundary_known": False,
"boundary_quality": "source_reference_extent",
"height_m": dimensions[2] if len(dimensions) == 3 else None}
assert condition["constraints"] == []
assert condition["objects"] == [{"id": "obj_0000", "category": "chair", "description": "chair"}]
scene = layout_to_scene(condition, prediction(condition))
assert scene["room"] == condition["room"]
scene["room"]["floor_polygon_xy_m"][0][0] = 100.
assert condition["room"]["floor_polygon_xy_m"][0][0] == 0.
def test_default_and_explicit_rectangular_profiles_remain_exact_and_independent():
source = request((5., 4., 3.))
saved = deepcopy(source)
default = request_to_condition(source)
explicit = request_to_condition(source, room_size_semantics="rectangular")
reference = request_to_condition(source, room_size_semantics="reference_extent")
assert source == saved and default == explicit
assert default["room"]["floor_known"] is True
assert default["room"]["boundary_known"] is True
assert default["room"]["boundary_quality"] == "explicit_rectangular_request"
assert {key: value for key, value in reference["room"].items()
if key not in {"floor_known", "boundary_known", "boundary_quality"}} == {
key: value for key, value in default["room"].items()
if key not in {"floor_known", "boundary_known", "boundary_quality"}}
@pytest.mark.parametrize("semantics", [None, True, "extent", "", "REFERENCE_EXTENT"])
def test_unknown_room_size_semantics_is_rejected(semantics):
with pytest.raises(ValueError, match="room_size_semantics"):
request_to_condition(request(), room_size_semantics=semantics)
@pytest.mark.parametrize("semantics,expected", [("rectangular", "fail"), ("reference_extent", "unknown")])
def test_boundary_floor_and_ceiling_diagnostics_obey_profile(semantics, expected):
condition = request_to_condition(request((5., 4., 3.)), room_size_semantics=semantics)
# One outside object below nominal z=0; a second case above nominal ceiling.
for position in [(-1., 2., -.5), (-1., 2., 4.)]:
scene = layout_to_scene(condition, prediction(condition, position))
report = bbox_diagnostics(scene)
checks = {check["code"]: check["status"] for check in report["checks"]}
assert checks["boundary"] == expected
assert checks["floor_lower_bound"] == (expected if position[2] < 0 else (
"pass" if semantics == "rectangular" else "unknown"))
assert checks["ceiling"] == (expected if position[2] > 3 else (
"pass" if semantics == "rectangular" else "unknown"))
assert report["asset_retrieval"] == "not_attempted"
assert report["support"] == "unknown" and report["commit"] == "not_attempted"
if semantics == "reference_extent":
assert report["room_size_semantics"] == "reference_extent"
def test_reference_extent_prediction_cli_exports_raw_geometry_with_unknown_physical_checks(tmp_path):
from fastfill.v2.batch import TinyTokenizer
from fastfill.v2.model import ModelConfig, build_model
checkpoint = tmp_path / "model"
model = build_model(ModelConfig(backbone="tiny", lora_rank=0, decoder_dim=16,
decoder_heads=2, decoder_layers=1, tiny_hidden_size=16))
with torch.no_grad():
for head in (model.position_head, model.size_head, model.yaw_logits_head, model.yaw_residual_head):
head.weight.zero_()
head.bias.zero_()
model.position_head.bias.copy_(torch.tensor([-.2, .5, -.5]))
model.save_pretrained(checkpoint)
TinyTokenizer().save_pretrained(tmp_path / "tokenizer")
source = request()
request_path = tmp_path / "request.json"
request_path.write_text(json.dumps(source))
output, handoff = tmp_path / "prediction.json", tmp_path / "handoff"
command = [sys.executable, "-m", "fastfill.v2.predict", "--checkpoint", str(checkpoint),
"--request", str(request_path), "--room-size-semantics", "reference_extent",
"--output", str(output), "--export-dir", str(handoff), "--device", "cpu"]
proc = subprocess.run(command, cwd=Path(__file__).resolve().parents[3],
capture_output=True, text=True, timeout=30)
assert proc.returncode == 0, proc.stderr
condition = request_to_condition(source, room_size_semantics="reference_extent")
actual = json.loads(output.read_text())
validate_layout(actual, condition)
assert actual["objects"][0]["bottom_center_m"][0] < 0.
assert actual["objects"][0]["bottom_center_m"][2] < 0.
scene = json.loads((handoff / "scene.json").read_text())
assert scene == layout_to_scene(condition, actual)
assert scene["room"]["height_m"] is None
assert not scene["room"]["boundary_known"] and not scene["room"]["floor_known"]
diagnostics = json.loads((handoff / "diagnostics.json").read_text())
assert {check["status"] for check in diagnostics["checks"]} == {"unknown"}
assert diagnostics["room_size_semantics"] == "reference_extent"
assert diagnostics["asset_retrieval"] == "not_attempted"
assert diagnostics["commit"] == "not_attempted"
assert json.loads(request_path.read_text()) == source
assert (handoff / "layout.glb").exists() and (handoff / "preview.svg").exists()
def test_roomgenbench_handoff_keeps_reference_range_distinct_from_physical_room():
condition = request_to_condition(request((5., 4., 3.)), room_size_semantics="reference_extent")
actual = prediction(condition)
saved_condition, saved_prediction = deepcopy(condition), deepcopy(actual)
downstream = layout_to_roomgenbench(condition, actual)
assert downstream["room_size_semantics"] == "reference_extent"
assert downstream["room"]["boundary_known"] is False
assert downstream["room"]["floor_known"] is False
assert downstream["room"]["boundary_quality"] == "source_reference_extent"
assert "reference" in downstream["room_interpretation"]
assert downstream["room"]["dimensions"] == {"width": 5., "length": 4., "height": 3.}
assert downstream["objects"][0]["position"] == {"x": -1., "y": 2., "z": -.5}
assert condition == saved_condition and actual == saved_prediction
strict = request_to_condition(request((5., 4., 3.)))
assert "room_size_semantics" not in layout_to_roomgenbench(strict, prediction(strict))
def test_prediction_rejects_reference_flag_with_full_condition_before_model_loading(tmp_path, monkeypatch):
from fastfill.v2 import predict
def forbidden_load(*args, **kwargs):
raise AssertionError("inapplicable semantics flags must be rejected before model load")
monkeypatch.setattr(predict, "load_model", forbidden_load)
with pytest.raises(ValueError, match="only to --request"):
predict.main(["--checkpoint", str(tmp_path / "missing-model"),
"--condition", str(tmp_path / "missing-condition.json"),
"--room-size-semantics", "reference_extent", "--output", str(tmp_path / "prediction.json")])
|