Skip to content

Commit ab0eb5b

Browse files
committed
[new-model] Harden Helios history validation
1 parent 20814fa commit ab0eb5b

2 files changed

Lines changed: 69 additions & 12 deletions

File tree

fastvideo/models/dits/helios.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -577,6 +577,16 @@ def materialize_non_persistent_buffers(self, device: torch.device, dtype: torch.
577577
del dtype
578578
self.rope.materialize_buffers(device)
579579

580+
@staticmethod
581+
def _validate_history_pair(
582+
history: torch.Tensor | None,
583+
history_indices: torch.Tensor | None,
584+
history_name: str,
585+
history_indices_name: str,
586+
) -> None:
587+
if (history is None) != (history_indices is None):
588+
raise ValueError(f"{history_name} and {history_indices_name} must be provided together")
589+
580590
def _patch_history(
581591
self,
582592
hidden_states: torch.Tensor,
@@ -629,6 +639,24 @@ def forward(
629639
**kwargs,
630640
) -> torch.Tensor:
631641
del kwargs
642+
self._validate_history_pair(
643+
latents_history_short,
644+
indices_latents_history_short,
645+
"latents_history_short",
646+
"indices_latents_history_short",
647+
)
648+
self._validate_history_pair(
649+
latents_history_mid,
650+
indices_latents_history_mid,
651+
"latents_history_mid",
652+
"indices_latents_history_mid",
653+
)
654+
self._validate_history_pair(
655+
latents_history_long,
656+
indices_latents_history_long,
657+
"latents_history_long",
658+
"indices_latents_history_long",
659+
)
632660
if isinstance(encoder_hidden_states, list):
633661
encoder_hidden_states = encoder_hidden_states[0]
634662
batch_size = hidden_states.shape[0]

tests/local_tests/transformers/test_helios_transformer_parity.py

Lines changed: 41 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,7 @@ def _assert_real_bf16_parity(
230230
assert_close(actual, expected, atol=5e-2, rtol=5e-2)
231231

232232

233-
def test_helios_distilled_config_matches_pinned_checkpoint():
233+
def test_helios_distilled_config_defaults_match_distilled_variant():
234234
HeliosArchConfig, _, _ = _native_types()
235235
config = HeliosArchConfig()
236236
assert config.patch_size == (1, 2, 2)
@@ -247,18 +247,47 @@ def test_helios_distilled_config_matches_pinned_checkpoint():
247247
assert config.has_multi_term_memory_patch is True
248248
assert config.guidance_cross_attn is True
249249

250+
251+
def test_helios_distilled_config_matches_local_pinned_checkpoint():
252+
HeliosArchConfig, _, _ = _native_types()
253+
config = HeliosArchConfig()
250254
config_path = TRANSFORMER_DIR / "config.json"
251-
if config_path.is_file():
252-
checkpoint_config = json.loads(config_path.read_text(encoding="utf-8"))
253-
assert checkpoint_config.pop("_class_name") == "HeliosTransformer3DModel"
254-
checkpoint_config.pop("_diffusers_version", None)
255-
arch_fields = {field.name for field in fields(HeliosArchConfig)}
256-
assert set(checkpoint_config) <= arch_fields
257-
for name, expected in checkpoint_config.items():
258-
actual = getattr(config, name)
259-
if isinstance(actual, tuple):
260-
expected = tuple(expected)
261-
assert actual == expected, f"unexpected Helios config {name}={actual!r}"
255+
if not config_path.is_file():
256+
pytest.skip(
257+
"Pinned Helios transformer config is absent; set HELIOS_TRANSFORMER_DIR "
258+
f"to BestWishYsh/Helios-Distilled@{HF_REVISION}/transformer")
259+
checkpoint_config = json.loads(config_path.read_text(encoding="utf-8"))
260+
assert checkpoint_config.pop("_class_name") == "HeliosTransformer3DModel"
261+
checkpoint_config.pop("_diffusers_version", None)
262+
arch_fields = {field.name for field in fields(HeliosArchConfig)}
263+
assert set(checkpoint_config) <= arch_fields
264+
for name, expected in checkpoint_config.items():
265+
actual = getattr(config, name)
266+
if isinstance(actual, tuple):
267+
expected = tuple(expected)
268+
assert actual == expected, f"unexpected Helios config {name}={actual!r}"
269+
270+
271+
@pytest.mark.parametrize(
272+
("history_name", "indices_name"),
273+
[
274+
("latents_history_short", "indices_latents_history_short"),
275+
("latents_history_mid", "indices_latents_history_mid"),
276+
("latents_history_long", "indices_latents_history_long"),
277+
],
278+
)
279+
@pytest.mark.parametrize("missing_input", ["history", "indices"])
280+
def test_helios_history_tensor_and_indices_must_be_paired(
281+
history_name: str,
282+
indices_name: str,
283+
missing_input: str,
284+
):
285+
_, _, FastVideoHeliosTransformer = _native_types()
286+
history = torch.empty(1) if missing_input == "indices" else None
287+
indices = torch.empty(1, dtype=torch.long) if missing_input == "history" else None
288+
289+
with pytest.raises(ValueError, match=rf"{history_name}.*{indices_name}"):
290+
FastVideoHeliosTransformer._validate_history_pair(history, indices, history_name, indices_name)
262291

263292

264293
@pytest.mark.parametrize(

0 commit comments

Comments
 (0)