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: 6,724 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 | import pytest
import torch
from fastfill.v2.batch import TinyTokenizer, collate_samples
from fastfill.v2.model import ModelConfig, build_model, load_model, model_inputs
from fastfill.v2.tests.test_batch import sample
def config():
return ModelConfig(backbone="tiny", decoder_dim=32, decoder_heads=4,
decoder_layers=2, tiny_hidden_size=32, max_objects=16,
tiny_layers=1, dropout=0.0)
@pytest.mark.parametrize("kwargs", [
{"decoder_dim": True}, {"decoder_layers": 1.5}, {"decoder_ffn_multiplier": 0},
{"dropout": float("nan")}, {"lora_dropout": float("inf")}, {"lora_rank": -1},
{"train_backbone": "false", "lora_rank": 0}, {"local_files_only": "false"},
{"size_reference": (True, 1., 1.)}, {"size_reference": (1e38, 1., 1.)},
{"size_reference": (1e-42, 1., 1.)}, {"backbone": ""}, {"lora_target_modules": [None]},
])
def test_model_config_rejects_ambiguous_types_and_nonfinite_geometry(kwargs):
with pytest.raises(ValueError):
ModelConfig(**kwargs)
def test_positive_size_bounds_survive_fp16_autocast():
cfg = ModelConfig(backbone="tiny", decoder_dim=32, decoder_heads=4, decoder_layers=1,
tiny_hidden_size=32, size_log_limit=30.)
model = build_model(cfg)
with torch.no_grad():
model.size_head.weight.zero_()
model.size_head.bias.copy_(torch.tensor([30., -30., 0.]))
batch = collate_samples([sample(1)], TinyTokenizer())
with torch.autocast("cpu", dtype=torch.float16):
sizes = model(**model_inputs(batch))["size"]
assert sizes.dtype == torch.float32
assert torch.isfinite(sizes).all() and (sizes > 0).all()
sizes.log().sum().backward()
assert torch.isfinite(model.size_head.bias.grad).all()
def test_exact_slots_positive_size_and_gradients_to_condition_backbone():
model = build_model(config())
b = collate_samples([sample(2), sample(1)], TinyTokenizer())
out = model(**model_inputs(b))
assert out["position_normalized"].shape == (2, 2, 3)
assert out["yaw_logits"].shape == (2, 2, 12)
assert out["slot_mask"].tolist() == [[True, True], [True, False]]
assert (out["size"][out["slot_mask"]] > 0).all()
assert torch.equal(out["position_normalized"][1, 1], torch.zeros(3))
loss = sum(out[k].square().sum() for k in ("position_normalized", "size", "yaw_logits", "yaw_residuals"))
loss.backward()
assert model.backbone.embedding.weight.grad.abs().sum() > 0
assert model.position_head.weight.grad.abs().sum() > 0
def test_batch_padding_does_not_change_valid_object_predictions():
torch.manual_seed(2)
model = build_model(config()).eval()
one = collate_samples([sample(1)], TinyTokenizer())
padded = collate_samples([sample(1), sample(3)], TinyTokenizer())
with torch.no_grad():
a = model(**model_inputs(one))
b = model(**model_inputs(padded))
for key in ("position_normalized", "size", "yaw_logits", "yaw_residuals"):
assert torch.allclose(a[key][0, 0], b[key][0, 0], atol=2e-6), key
def test_full_condition_after_object_changes_predictions():
model = build_model(config()).eval()
a = sample(1)
b = sample(1)
b["condition"]["constraints"] = [{"type": "faces_direction", "object_id": "chair_0", "direction_xy": [0, -1]}]
with torch.no_grad():
x = model(**model_inputs(collate_samples([a], TinyTokenizer())))
y = model(**model_inputs(collate_samples([b], TinyTokenizer())))
assert not torch.allclose(x["position_normalized"], y["position_normalized"])
def test_fixed_size_and_ground_height_override_head():
s = sample(1)
s["condition"]["objects"][0].update(fixed_size_local_m=[1.1, .7, 1.2], support_parent="floor")
s["target"]["objects"][0]["target_size_local_m"] = [1.1, .7, 1.2]
model = build_model(config())
b = collate_samples([s], TinyTokenizer())
out = model(**model_inputs(b))
assert torch.equal(out["size"][0, 0], torch.tensor([1.1, .7, 1.2]))
assert out["position_normalized"][0, 0, 2] == 0
def test_checkpoint_round_trip(tmp_path):
model = build_model(config()).eval()
b = collate_samples([sample(1)], TinyTokenizer())
model.save_pretrained(tmp_path)
loaded = load_model(tmp_path).eval()
with torch.no_grad():
assert torch.equal(model(**model_inputs(b))["size"], loaded(**model_inputs(b))["size"])
def test_empty_scene_and_mixed_empty_batch_do_not_create_nan():
model = build_model(config())
empty = collate_samples([sample(0)], TinyTokenizer())
out = model(**model_inputs(empty))
assert out["size"].shape == (1, 0, 3)
mixed = collate_samples([sample(0), sample(2)], TinyTokenizer())
out = model(**model_inputs(mixed))
assert torch.isfinite(out["size"]).all()
assert torch.equal(out["size"][0], torch.zeros(2, 3))
def test_bidirectional_object_interaction_changes_first_slot():
torch.manual_seed(7)
model = build_model(config()).eval()
a = sample(2)
b = sample(2)
b["condition"]["objects"][1]["description"] = "large reading chair with an attached lamp"
with torch.no_grad():
x = model(**model_inputs(collate_samples([a], TinyTokenizer())))
y = model(**model_inputs(collate_samples([b], TinyTokenizer())))
assert not torch.allclose(x["size"][0, 0], y["size"][0, 0])
@pytest.mark.parametrize("training", ["lora", "full", "frozen"])
def test_local_random_qwen_api_gradients_and_checkpoint(tmp_path, training):
transformers = pytest.importorskip("transformers")
if training == "lora":
pytest.importorskip("peft")
source = tmp_path / "qwen"
transformers.Qwen2Model(transformers.Qwen2Config(vocab_size=258, hidden_size=32,
intermediate_size=64, num_hidden_layers=1, num_attention_heads=4,
num_key_value_heads=2, max_position_embeddings=4096)).save_pretrained(source)
cfg = ModelConfig(backbone=str(source), decoder_dim=32, decoder_heads=4, decoder_layers=1,
lora_rank=2 if training == "lora" else 0, lora_alpha=4,
train_backbone=training == "full", local_files_only=True)
model = build_model(cfg)
b = collate_samples([sample(1)], TinyTokenizer())
model(**model_inputs(b))["size"].sum().backward()
gradients = [p.grad for p in model.backbone.parameters() if p.grad is not None]
assert bool(gradients) == (training != "frozen")
if gradients:
assert sum(float(grad.abs().sum()) for grad in gradients) > 0
checkpoint = tmp_path / "checkpoint"
model.eval().save_pretrained(checkpoint)
loaded = load_model(checkpoint, local_files_only=True).eval()
with torch.no_grad():
assert torch.equal(model(**model_inputs(b))["size"], loaded(**model_inputs(b))["size"])
|