[feat] cosmos3: native MoT sequence-packing (video) + framework parity

This commit is contained in:
SolitaryThinker
2026-07-21 15:45:37 -07:00
parent 9117b3bbac
commit 564233fabb
2 changed files with 644 additions and 0 deletions
@@ -0,0 +1,332 @@
# SPDX-License-Identifier: Apache-2.0
"""FastVideo-native Cosmos3 sequence packing (video subset).
Numerical-parity port of the official ``cosmos_framework`` data packer
(``cosmos_framework.data.vfm.sequence_packing.pack_input_sequence``) restricted
to the VIDEO generation path that the FastVideo Cosmos3 DiT consumes (T2V / I2V
/ T2I). It builds, per sample, two splits:
* a ``causal`` text split (prompt token ids, plus the trailing ``eos`` and
``start_of_generation`` markers the framework appends when a generation
modality follows), and
* a ``full`` vision split (VAE latent patch tokens).
The 3D-MRoPE position ids ``[3, seq]`` are produced exactly like the framework:
text tokens broadcast a single monotone id across the (t, h, w) axes, the
temporal offset is bumped by ``temporal_modality_margin`` at the text->vision
boundary, and vision tokens lay out a (T, H, W) grid with spatial ids reset per
segment. Condition frames (I2V cond frame 0, T2I single conditioned frame, ...)
are kept in the packed sequence and rope grid but excluded from the MSE-loss /
timestep bookkeeping, mirroring the framework.
The output ``Cosmos3PackedSequence`` maps 1:1 onto the
``Cosmos3VFMTransformer.forward`` kwargs via :meth:`to_dit_kwargs`. This module
is pure torch/python; it imports no diffusers/transformers model classes.
Reference of record: ``cosmos_framework`` (NVIDIA), the parity oracle used by
``tests/local_tests/cosmos3/test_cosmos3_packing_parity.py``.
"""
from __future__ import annotations
import math
from dataclasses import dataclass, field
from typing import Any
import torch
from fastvideo.models.dits.cosmos3 import (
compute_mrope_position_ids_text,
compute_mrope_position_ids_vision,
)
__all__ = [
"Cosmos3VisionItem",
"Cosmos3SampleInputs",
"Cosmos3PackedSequence",
"pack_cosmos3_video_sequence",
]
# ---------------------------------------------------------------------------
# Inputs
# ---------------------------------------------------------------------------
@dataclass
class Cosmos3VisionItem:
"""One vision latent for a sample.
Args:
latent: VAE latent ``[C, T, H, W]`` (a leading batch axis of size 1 is
accepted and squeezed).
condition_frame_indexes: Latent-frame indices that are *conditioned*
(clean) rather than noisy. ``[]`` for T2V, ``[0]`` for I2V, and the
single conditioned frame for T2I.
fps: Frames-per-second for this clip; only used when
``enable_fps_modulation`` is set.
"""
latent: torch.Tensor
condition_frame_indexes: list[int] = field(default_factory=list)
fps: float | None = None
@dataclass
class Cosmos3SampleInputs:
"""Per-sample packing inputs (one text prompt + its vision item)."""
text_ids: list[int]
vision: Cosmos3VisionItem
timestep: float
# ---------------------------------------------------------------------------
# Output
# ---------------------------------------------------------------------------
@dataclass
class Cosmos3PackedSequence:
"""Packed-sequence inputs consumed by ``Cosmos3VFMTransformer.forward``.
Field names mirror the framework ``PackedSequence`` (+ its ``vision``
``ModalityData``) so the parity test can compare field-by-field.
"""
# Sequence structure.
sample_lens: list[int]
split_lens: list[int]
attn_modes: list[str]
sequence_length: int
is_image_batch: bool
# Text modality.
text_ids: torch.Tensor
text_indexes: torch.Tensor
position_ids: torch.Tensor # [3, sequence_length]
# Vision modality.
vision_tokens: list[torch.Tensor]
vision_token_shapes: list[tuple[int, int, int]]
vision_sequence_indexes: torch.Tensor
vision_timesteps: torch.Tensor
vision_mse_loss_indexes: torch.Tensor
vision_noisy_frame_indexes: list[torch.Tensor]
vision_condition_mask: list[torch.Tensor]
fps_vision: torch.Tensor | None = None
def to_dit_kwargs(self) -> dict[str, Any]:
"""Return the kwargs dict for ``Cosmos3VFMTransformer.forward``."""
return dict(
text_ids=self.text_ids,
text_indexes=self.text_indexes,
position_ids=self.position_ids,
sequence_length=int(self.sequence_length),
split_lens=list(self.split_lens),
attn_modes=list(self.attn_modes),
vision_tokens=list(self.vision_tokens),
vision_token_shapes=list(self.vision_token_shapes),
vision_sequence_indexes=self.vision_sequence_indexes,
vision_timesteps=self.vision_timesteps,
vision_mse_loss_indexes=self.vision_mse_loss_indexes,
vision_noisy_frame_indexes=list(self.vision_noisy_frame_indexes),
fps_vision=self.fps_vision,
)
# ---------------------------------------------------------------------------
# Packing
# ---------------------------------------------------------------------------
def pack_cosmos3_video_sequence(
samples: list[Cosmos3SampleInputs],
special_tokens: dict[str, int],
*,
latent_patch_size: int = 2,
include_end_of_generation_token: bool = False,
temporal_modality_margin: int = 15_000,
reset_spatial_ids: bool = True,
enable_fps_modulation: bool = False,
base_fps: float = 24.0,
temporal_compression_factor: int = 4,
initial_mrope_temporal_offset: int | float = 0,
) -> Cosmos3PackedSequence:
"""Pack prompts + vision latents into the Cosmos3 DiT packed-sequence inputs.
Video subset of ``cosmos_framework`` ``pack_input_sequence`` under
``unified_3d_mrope``: each sample is ``[causal text, full vision]``.
Args:
samples: Per-sample text prompt token ids + vision item + timestep.
special_tokens: Must contain ``eos_token_id`` and
``start_of_generation`` (and ``end_of_generation`` if
``include_end_of_generation_token``). ``bos_token_id`` is honored if
present (prepended) to match the framework.
latent_patch_size: Latent patch size used by the DiT.
include_end_of_generation_token: Append the framework's end-of-generation
marker after the vision split.
temporal_modality_margin: Temporal-offset bump applied at the
text->vision boundary (``unified_3d_mrope_temporal_modality_margin``).
reset_spatial_ids: Reset vision spatial ids to 0 per segment.
enable_fps_modulation: Use float, fps-scaled temporal positions.
base_fps: Base FPS used when ``enable_fps_modulation``.
temporal_compression_factor: VAE temporal compression factor.
initial_mrope_temporal_offset: Per-sample starting temporal offset.
Returns:
A :class:`Cosmos3PackedSequence`.
"""
assert "eos_token_id" in special_tokens, "special_tokens must contain eos_token_id"
assert "start_of_generation" in special_tokens, "special_tokens must contain start_of_generation"
if latent_patch_size < 1:
raise ValueError(f"latent_patch_size must be >= 1, got {latent_patch_size}")
# Build-time accumulators (concatenated across samples).
sample_lens: list[int] = []
split_lens: list[int] = []
attn_modes: list[str] = []
text_ids: list[int] = []
text_indexes: list[int] = []
position_id_blocks: list[torch.Tensor] = [] # each [3, n]
vision_tokens: list[torch.Tensor] = []
vision_token_shapes: list[tuple[int, int, int]] = []
vision_sequence_indexes: list[int] = []
vision_timesteps: list[float] = []
vision_mse_loss_indexes: list[int] = []
vision_noisy_frame_indexes: list[torch.Tensor] = []
vision_condition_mask: list[torch.Tensor] = []
fps_values: list[float] = []
curr = 0 # running position in the packed sequence
is_image_batch = True
for sample in samples:
temporal_offset: int | float = initial_mrope_temporal_offset
sample_len = 0
# ---- 1. Text split (causal) ----
if "bos_token_id" in special_tokens:
shifted_text_ids = [special_tokens["bos_token_id"], *sample.text_ids]
else:
shifted_text_ids = list(sample.text_ids)
# The video path always has a following generation modality, so the
# framework appends eos + start_of_generation.
shifted_text_ids = [*shifted_text_ids, special_tokens["eos_token_id"], special_tokens["start_of_generation"]]
text_split_len = len(shifted_text_ids)
text_ids.extend(shifted_text_ids)
text_indexes.extend(range(curr, curr + text_split_len))
text_mrope, temporal_offset = compute_mrope_position_ids_text(
num_tokens=text_split_len,
temporal_offset=int(temporal_offset),
)
position_id_blocks.append(text_mrope)
attn_modes.append("causal")
split_lens.append(text_split_len)
curr += text_split_len
sample_len += text_split_len
# End of text modality: bump temporal offset before vision.
temporal_offset += temporal_modality_margin
# ---- 2. Vision split (full) ----
latent = sample.vision.latent
latent = latent.squeeze(0) if latent.dim() == 5 else latent # [C, T, H, W]
_c, latent_t, latent_h, latent_w = latent.shape
patch_h = math.ceil(latent_h / latent_patch_size)
patch_w = math.ceil(latent_w / latent_patch_size)
num_vision_tokens = latent_t * patch_h * patch_w
vision_tokens.append(sample.vision.latent)
vision_token_shapes.append((latent_t, patch_h, patch_w))
vision_sequence_indexes.extend(range(curr, curr + num_vision_tokens))
condition_set = {idx for idx in sample.vision.condition_frame_indexes if 0 <= idx < latent_t}
cond_mask = torch.zeros((latent_t, 1, 1), device=latent.device, dtype=latent.dtype)
for frame_idx in condition_set:
cond_mask[frame_idx, 0, 0] = 1.0
vision_condition_mask.append(cond_mask)
noisy_frames = torch.tensor(
[idx for idx in range(latent_t) if idx not in condition_set],
device=latent.device,
dtype=torch.long,
)
vision_noisy_frame_indexes.append(noisy_frames)
# MSE-loss indices + per-token timesteps cover only the noisy frames.
frame_token_stride = patch_h * patch_w
for frame_idx in range(latent_t):
if frame_idx in condition_set:
continue
frame_start = curr + frame_idx * frame_token_stride
vision_mse_loss_indexes.extend(range(frame_start, frame_start + frame_token_stride))
vision_timesteps.extend([float(sample.timestep)] * frame_token_stride)
vision_fps = sample.vision.fps if enable_fps_modulation else None
if vision_fps is not None:
fps_values.append(float(vision_fps))
vision_mrope, temporal_offset = compute_mrope_position_ids_vision(
grid_t=latent_t,
grid_h=patch_h,
grid_w=patch_w,
temporal_offset=temporal_offset,
fps=vision_fps,
base_fps=base_fps,
temporal_compression_factor=temporal_compression_factor,
enable_fps_modulation=enable_fps_modulation,
)
position_id_blocks.append(vision_mrope)
curr += num_vision_tokens
sample_len += num_vision_tokens
# ---- 3. Optional end-of-generation marker ----
eov_len = 0
if include_end_of_generation_token:
assert "end_of_generation" in special_tokens, ("special_tokens must contain end_of_generation when "
"include_end_of_generation_token=True")
text_ids.append(special_tokens["end_of_generation"])
text_indexes.append(curr)
eov_dtype = torch.float32 if enable_fps_modulation else torch.long
eov_ids = torch.full((3, 1), temporal_offset, dtype=eov_dtype)
position_id_blocks.append(eov_ids)
temporal_offset += 1
curr += 1
eov_len = 1
sample_len += 1
# The vision split and any trailing eov marker share the "full" split.
attn_modes.append("full")
split_lens.append(num_vision_tokens + eov_len)
sample_lens.append(sample_len)
if latent_t != 1:
is_image_batch = False
sequence_length = sum(sample_lens)
# position_ids: float iff any block is float (fps modulation path).
any_float = any(b.dtype.is_floating_point for b in position_id_blocks)
if any_float:
position_id_blocks = [b.to(torch.float32) for b in position_id_blocks]
position_ids = torch.cat(position_id_blocks, dim=1) # [3, sequence_length]
timesteps_dtype = torch.float32
return Cosmos3PackedSequence(
sample_lens=sample_lens,
split_lens=split_lens,
attn_modes=attn_modes,
sequence_length=sequence_length,
is_image_batch=is_image_batch,
text_ids=torch.tensor(text_ids, dtype=torch.long),
text_indexes=torch.tensor(text_indexes, dtype=torch.long),
position_ids=position_ids,
vision_tokens=vision_tokens,
vision_token_shapes=vision_token_shapes,
vision_sequence_indexes=torch.tensor(vision_sequence_indexes, dtype=torch.long),
vision_timesteps=torch.tensor(vision_timesteps, dtype=timesteps_dtype),
vision_mse_loss_indexes=torch.tensor(vision_mse_loss_indexes, dtype=torch.long),
vision_noisy_frame_indexes=vision_noisy_frame_indexes,
vision_condition_mask=vision_condition_mask,
fps_vision=(torch.tensor(fps_values, dtype=torch.float32) if fps_values else None),
)
@@ -0,0 +1,312 @@
# SPDX-License-Identifier: Apache-2.0
"""Numerical-parity test: FastVideo Cosmos3 sequence packing vs the OFFICIAL framework.
FastVideo's native packer
(``fastvideo.pipelines.basic.cosmos3.sequence_packing.pack_cosmos3_video_sequence``)
builds the packed-sequence inputs the ``Cosmos3VFMTransformer`` consumes. This
test asserts, for the SAME logical inputs (prompt token ids, vision latents,
condition-frame indices, diffusion timestep, fps), that FastVideo's packing
matches the official ``cosmos_framework.data.vfm.sequence_packing.pack_input_sequence``
oracle field-by-field:
* ``position_ids`` (exact, ``[3, seq]``),
* ``text_ids`` / ``text_indexes``,
* ``split_lens`` / ``attn_modes`` / ``sample_lens`` / ``sequence_length``,
* vision ``sequence_indexes`` / ``token_shapes`` / ``timesteps`` /
``mse_loss_indexes`` / ``noisy_frame_indexes`` / ``condition_mask``.
Coverage spans T2V (no condition frames), I2V (condition frame 0), and T2I
(single conditioned frame), across multiple grids, plus a multi-sample batch.
Then BOTH the framework-packed and FastVideo-packed inputs are fed through the
SAME tiny FastVideo DiT (framework weights copied in as in the existing DiT
parity tests). Asserting bit-identical DiT output confirms FastVideo's own
packing drives the DiT to the same result as the framework's packing.
The official framework is the parity ORACLE; it runs on CPU / float32 via the
SDPA monkey-patch from ``test_cosmos3_reference_forward``.
Run:
cd <worktree> && <fv-cosmos3 python> -m pytest \
tests/local_tests/cosmos3/test_cosmos3_packing_parity.py -q
"""
from __future__ import annotations
import pytest
import torch
# The official framework provides the parity oracle.
cosmos_framework = pytest.importorskip(
"cosmos_framework",
reason="cosmos_framework not installed; run in fv-cosmos3 env.",
)
# Reuse the DiT parity helpers (weight copy + framework->DiT kwarg builder) and
# the mRoPE tiny-model builders (real-checkpoint rope constants).
from .test_cosmos3_dit_parity import ( # noqa: E402
_copy_weights,
_fastvideo_inputs_from_packed_seq,
)
from .test_cosmos3_dit_parity_mrope import ( # noqa: E402
_LATENT_CHANNEL,
_LATENT_PATCH_SIZE,
_MROPE_SECTION,
_RESET_SPATIAL_IDS,
_ROPE_THETA,
_TCF,
_TEMPORAL_MODALITY_MARGIN,
_build_tiny_cosmos3_mrope,
_build_tiny_fastvideo_dit_mrope,
)
from .test_cosmos3_reference_forward import _apply_sdpa_patches # noqa: E402
pytestmark = [pytest.mark.local]
# Ensure the CPU/float32 SDPA patches are installed (idempotent).
_apply_sdpa_patches()
# Tiny special-token ids (kept < tiny vocab_size=64). The video path appends
# eos + start_of_generation after the prompt tokens.
_SPECIAL_TOKENS = {
"start_of_generation": 60,
"end_of_generation": 61,
"eos_token_id": 62,
}
# ---------------------------------------------------------------------------
# Builders for the two packers from the SAME logical sample inputs.
# ---------------------------------------------------------------------------
def _make_vision(grid_t: int, latent_h: int, latent_w: int, seed: int) -> torch.Tensor:
"""Deterministic VAE latent ``[1, C, T, H, W]``."""
torch.manual_seed(seed)
return torch.randn(1, _LATENT_CHANNEL, grid_t, latent_h, latent_w)
def _framework_pack(
*,
text_ids_per_sample: list[list[int]],
visions: list[torch.Tensor],
cond_frames_per_sample: list[list[int]],
timesteps: list[float],
is_image_batch: bool,
):
from cosmos_framework.data.vfm.sequence_packing import (
GenerationDataClean,
SequencePlan,
pack_input_sequence,
)
gen_data_clean = GenerationDataClean(
batch_size=len(visions),
is_image_batch=is_image_batch,
x0_tokens_vision=list(visions),
fps_vision=None,
num_vision_items_per_sample=[1] * len(visions),
)
plans = [
SequencePlan(has_text=True, has_vision=True, condition_frame_indexes_vision=list(cf))
for cf in cond_frames_per_sample
]
return pack_input_sequence(
sequence_plans=plans,
input_text_indexes=[list(t) for t in text_ids_per_sample],
gen_data_clean=gen_data_clean,
input_timesteps=torch.tensor(timesteps, dtype=torch.float32),
special_tokens=_SPECIAL_TOKENS,
latent_patch_size=_LATENT_PATCH_SIZE,
include_end_of_generation_token=False,
position_embedding_type="unified_3d_mrope",
unified_3d_mrope_reset_spatial_ids=_RESET_SPATIAL_IDS,
unified_3d_mrope_temporal_modality_margin=_TEMPORAL_MODALITY_MARGIN,
enable_fps_modulation=False,
base_fps=24.0,
temporal_compression_factor=_TCF,
)
def _fastvideo_pack(
*,
text_ids_per_sample: list[list[int]],
visions: list[torch.Tensor],
cond_frames_per_sample: list[list[int]],
timesteps: list[float],
):
from fastvideo.pipelines.basic.cosmos3.sequence_packing import (
Cosmos3SampleInputs,
Cosmos3VisionItem,
pack_cosmos3_video_sequence,
)
samples = [
Cosmos3SampleInputs(
text_ids=list(t),
vision=Cosmos3VisionItem(latent=v, condition_frame_indexes=list(cf)),
timestep=float(ts),
)
for t, v, cf, ts in zip(text_ids_per_sample, visions, cond_frames_per_sample, timesteps)
]
return pack_cosmos3_video_sequence(
samples,
_SPECIAL_TOKENS,
latent_patch_size=_LATENT_PATCH_SIZE,
include_end_of_generation_token=False,
temporal_modality_margin=_TEMPORAL_MODALITY_MARGIN,
reset_spatial_ids=_RESET_SPATIAL_IDS,
enable_fps_modulation=False,
base_fps=24.0,
temporal_compression_factor=_TCF,
)
# ---------------------------------------------------------------------------
# Field-by-field comparison.
# ---------------------------------------------------------------------------
def _assert_packs_match(fw, fv) -> None:
"""Assert the framework PackedSequence and FastVideo pack agree field-by-field."""
# Structure.
assert fv.split_lens == list(fw.split_lens), f"split_lens: fv={fv.split_lens} fw={list(fw.split_lens)}"
assert fv.attn_modes == list(fw.attn_modes), f"attn_modes: fv={fv.attn_modes} fw={list(fw.attn_modes)}"
assert fv.sample_lens == list(fw.sample_lens), f"sample_lens: fv={fv.sample_lens} fw={list(fw.sample_lens)}"
assert int(fv.sequence_length) == int(fw.sequence_length)
# Text.
torch.testing.assert_close(fv.text_ids, fw.text_ids.to(torch.long), rtol=0, atol=0)
torch.testing.assert_close(fv.text_indexes, fw.text_indexes.to(torch.long), rtol=0, atol=0)
# position_ids: exact, [3, seq], same dtype.
assert fv.position_ids.shape == fw.position_ids.shape, (
f"position_ids shape: fv={tuple(fv.position_ids.shape)} fw={tuple(fw.position_ids.shape)}")
assert fv.position_ids.dtype == fw.position_ids.dtype, (
f"position_ids dtype: fv={fv.position_ids.dtype} fw={fw.position_ids.dtype}")
torch.testing.assert_close(fv.position_ids, fw.position_ids, rtol=0, atol=0)
# Vision.
fwv = fw.vision
torch.testing.assert_close(fv.vision_sequence_indexes, fwv.sequence_indexes.to(torch.long), rtol=0, atol=0)
assert fv.vision_token_shapes == [tuple(s) for s in fwv.token_shapes], (
f"token_shapes: fv={fv.vision_token_shapes} fw={[tuple(s) for s in fwv.token_shapes]}")
torch.testing.assert_close(fv.vision_timesteps.to(torch.float32), fwv.timesteps.to(torch.float32))
torch.testing.assert_close(fv.vision_mse_loss_indexes, fwv.mse_loss_indexes.to(torch.long), rtol=0, atol=0)
assert len(fv.vision_noisy_frame_indexes) == len(fwv.noisy_frame_indexes)
for a, b in zip(fv.vision_noisy_frame_indexes, fwv.noisy_frame_indexes):
torch.testing.assert_close(a.to(torch.long), b.to(torch.long), rtol=0, atol=0)
assert len(fv.vision_condition_mask) == len(fwv.condition_mask)
for a, b in zip(fv.vision_condition_mask, fwv.condition_mask):
torch.testing.assert_close(a.flatten().to(torch.float32), b.flatten().to(torch.float32))
# (grid_t, latent_h, latent_w, n_text, cond_frames, id) — single-sample cases.
_CASES = [
pytest.param(1, 8, 8, 4, [], id="t2i_1x4x4"),
pytest.param(1, 4, 4, 5, [0], id="t2i_cond_1x2x2"),
pytest.param(2, 4, 4, 4, [], id="t2v_2x2x2"),
pytest.param(3, 8, 4, 6, [], id="t2v_3x4x2"),
pytest.param(2, 4, 4, 5, [0], id="i2v_2x2x2"),
pytest.param(3, 4, 4, 4, [0], id="i2v_3x2x2"),
]
class TestCosmos3PackingParity:
# -- Field-by-field packing parity -------------------------------------
@pytest.mark.parametrize(("grid_t", "latent_h", "latent_w", "n_text", "cond"), _CASES)
def test_packing_fields_match_framework(self, grid_t, latent_h, latent_w, n_text, cond):
torch.manual_seed(0)
text_ids = torch.randint(0, 60, (n_text,)).tolist()
vision = _make_vision(grid_t, latent_h, latent_w, seed=123)
timestep = 500.0
fw = _framework_pack(
text_ids_per_sample=[text_ids],
visions=[vision],
cond_frames_per_sample=[cond],
timesteps=[timestep],
is_image_batch=(grid_t == 1),
)
fv = _fastvideo_pack(
text_ids_per_sample=[text_ids],
visions=[vision],
cond_frames_per_sample=[cond],
timesteps=[timestep],
)
_assert_packs_match(fw, fv)
def test_packing_fields_match_framework_multi_sample(self):
"""A batch of two samples (T2V + I2V) packs identically to the framework."""
torch.manual_seed(1)
t0 = torch.randint(0, 60, (3,)).tolist()
t1 = torch.randint(0, 60, (5,)).tolist()
v0 = _make_vision(2, 4, 4, seed=11)
v1 = _make_vision(2, 4, 4, seed=22)
kwargs = dict(
text_ids_per_sample=[t0, t1],
visions=[v0, v1],
cond_frames_per_sample=[[], [0]],
timesteps=[500.0, 250.0],
)
fw = _framework_pack(is_image_batch=False, **kwargs)
fv = _fastvideo_pack(**kwargs)
_assert_packs_match(fw, fv)
# -- End-to-end: FastVideo packing drives the DiT identically ----------
@pytest.mark.parametrize(("grid_t", "latent_h", "latent_w", "n_text", "cond"), _CASES)
def test_fastvideo_packing_drives_dit_like_framework(self, grid_t, latent_h, latent_w, n_text, cond):
"""Feed BOTH the framework-packed and FastVideo-packed inputs through the
SAME FastVideo DiT (framework weights copied in); assert identical output.
"""
num_layers = 2
torch.manual_seed(0)
text_ids = torch.randint(0, 60, (n_text,)).tolist()
vision = _make_vision(grid_t, latent_h, latent_w, seed=123)
timestep = 500.0
fw_pack = _framework_pack(
text_ids_per_sample=[text_ids],
visions=[vision],
cond_frames_per_sample=[cond],
timesteps=[timestep],
is_image_batch=(grid_t == 1),
)
fv_pack = _fastvideo_pack(
text_ids_per_sample=[text_ids],
visions=[vision],
cond_frames_per_sample=[cond],
timesteps=[timestep],
)
# Guard: the two packs must agree before we trust the DiT comparison.
_assert_packs_match(fw_pack, fv_pack)
# One DiT instance, framework weights copied in (parity oracle weights).
vfm = _build_tiny_cosmos3_mrope(seed=42, num_layers=num_layers)
dit = _build_tiny_fastvideo_dit_mrope(num_layers=num_layers)
_copy_weights(vfm, dit)
with torch.no_grad():
out_fw = dit(**_fastvideo_inputs_from_packed_seq(fw_pack))
out_fv = dit(**fv_pack.to_dit_kwargs())
# last_hidden_state must be bit-identical.
lhs_fw = out_fw["last_hidden_state"]
lhs_fv = out_fv["last_hidden_state"]
assert lhs_fw.shape == lhs_fv.shape
max_abs_lhs = (lhs_fw - lhs_fv).abs().max().item()
print(f"\n[packing->dit {grid_t}x{latent_h}x{latent_w} cond={cond}] "
f"last_hidden_state max abs diff = {max_abs_lhs:.3e}")
torch.testing.assert_close(lhs_fv, lhs_fw, rtol=0, atol=0)
# preds_vision must be bit-identical when there are noisy frames to
# predict. (A fully-conditioned clip has no noisy patches, so the DiT
# emits no "preds_vision" — both packs agree the mse-loss set is empty,
# already asserted by the field-parity guard above.)
has_preds = fv_pack.vision_mse_loss_indexes.numel() > 0
assert ("preds_vision" in out_fw) == has_preds
assert ("preds_vision" in out_fv) == has_preds
if has_preds:
pv_fw = out_fw["preds_vision"][0]
pv_fv = out_fv["preds_vision"][0]
assert pv_fw.shape == pv_fv.shape
max_abs_pv = (pv_fw - pv_fv).abs().max().item()
print(f"[packing->dit {grid_t}x{latent_h}x{latent_w} cond={cond}] "
f"preds_vision max abs diff = {max_abs_pv:.3e}")
torch.testing.assert_close(pv_fv, pv_fw, rtol=0, atol=0)