Skip to content
This repository was archived by the owner on May 20, 2026. It is now read-only.

Commit 5d41eaa

Browse files
huvunvidiaHuy Vu2abhinavg4rootroot
authored
Supporting Wan model (#21)
* first commit * workable code * workable thd * clean up, remove all CP for sbhd, CP now is only for thd * run outside of Mbridge * Update example scripts and add new data module for multimodal datasets - Added comments to clarify file purposes in example_commands.sh, inference_wan.py, pretrain_wan.py, wan_provider.py, wan_step.py, and wan.py. - Introduced EnergonMultiModalDataModule for handling multimodal datasets in nemo_vfm. - Created SequentialMegatronSampler for efficient sequential sampling in large datasets. - Added new files for DIT attention and base data handling. This commit enhances documentation and introduces new functionalities for better data management and processing. * workable code before refactoring * refactor attention submodules + reorder files locations * update refactor * update refactor * reorganize files * reorganize files * refactoring code * add README for perf test * using vae, t5, scheduler from Diffusers * update repo, remove Wan's Github moduels * fix Ruff * fix ruff + copyright * fix Ruff + Lint * fix Ruff + Lint * fix Ruff + Lint * fix Ruff + Lint * fix Ruff + Lint * fix Ruff + Lint * fix Ruff + Lint * fix Ruff + Lint * merged main + address comments * remove example_commands.md, Google waits until mid Nov * refactor inference_configs + mockdatamodule * add dit_embeddings.py * fix lint ruff * add 'average_gradients_across_tp_domain' to torch.nn for when running sequence_parallelism * add english negative prompt * fix ruff lint * Update uv.lock for deps: diffusers==0.35.1, easydict, imageio * update dfm/src/megatron/data/dit * change english negative prompt * seem to workable seq_packing * refactor with Sajad's PR - DiT data to common dir * fix Ruff, lint * fix Ruff, lint * fix Ruff, lint * workable mock datamodule (doesn't need setting path); updated training algo + hyper-parameters aligning with Linnan; tested training with anime dataset finetung * bring wan_task encoders features to common, sharing with dit * lint, ruff * lint, ruff * lint, ruff * fix CP error (input of thd_split_inputs_cp to be cu_seqlens_q_padded instead of cu_seqlens_q) * udpate README_perf_test.md * fix lint, ruff * update uv.lock, merge main * uv.lock * uv.lock * uv.lock * update uv.lock [using ci] --------- Co-authored-by: Huy Vu2 <huvu@login-eos02.eos.clusters.nvidia.com> Co-authored-by: Abhinav Garg <abhinavg@stanford.edu> Co-authored-by: root <root@eos0025.eos.clusters.nvidia.com> Co-authored-by: root <root@eos0558.eos.clusters.nvidia.com> Co-authored-by: Pablo Garay <pagaray@nvidia.com>
1 parent ddb1ef3 commit 5d41eaa

27 files changed

Lines changed: 4890 additions & 638 deletions

dfm/src/megatron/data/common/diffusion_sample.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,11 @@ class DiffusionSample(Sample):
3434
num_frames (Optional[torch.Tensor]): Number of frames in the video.
3535
padding_mask (Optional[torch.Tensor]): Mask indicating padding positions.
3636
seq_len_q (Optional[torch.Tensor]): Sequence length for query embeddings.
37+
seq_len_q_padded (Optional[torch.Tensor]): Sequence length for query embeddings after padding.
3738
seq_len_kv (Optional[torch.Tensor]): Sequence length for key/value embeddings.
3839
pos_ids (Optional[torch.Tensor]): Positional IDs.
3940
latent_shape (Optional[torch.Tensor]): Shape of the latent tensor.
41+
video_metadata (Optional[dict]): Metadata of the video.
4042
"""
4143

4244
video: torch.Tensor # video latents (C T H W)
@@ -48,9 +50,12 @@ class DiffusionSample(Sample):
4850
num_frames: Optional[torch.Tensor] = None
4951
padding_mask: Optional[torch.Tensor] = None
5052
seq_len_q: Optional[torch.Tensor] = None
53+
seq_len_q_padded: Optional[torch.Tensor] = None
5154
seq_len_kv: Optional[torch.Tensor] = None
55+
seq_len_kv_padded: Optional[torch.Tensor] = None
5256
pos_ids: Optional[torch.Tensor] = None
5357
latent_shape: Optional[torch.Tensor] = None
58+
video_metadata: Optional[dict] = None
5459

5560
def to_dict(self) -> dict:
5661
"""Converts the sample to a dictionary."""
@@ -64,9 +69,12 @@ def to_dict(self) -> dict:
6469
num_frames=self.num_frames,
6570
padding_mask=self.padding_mask,
6671
seq_len_q=self.seq_len_q,
72+
seq_len_q_padded=self.seq_len_q_padded,
6773
seq_len_kv=self.seq_len_kv,
74+
seq_len_kv_padded=self.seq_len_kv_padded,
6875
pos_ids=self.pos_ids,
6976
latent_shape=self.latent_shape,
77+
video_metadata=self.video_metadata,
7078
)
7179

7280
def __add__(self, other: Any) -> int:

dfm/src/megatron/data/common/diffusion_task_encoder_with_sp.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15-
1615
import random
1716
from abc import ABC, abstractmethod
1817
from typing import List
@@ -103,9 +102,12 @@ def cat(attr):
103102
context_embeddings=cat("context_embeddings"),
104103
loss_mask=cat("loss_mask"),
105104
seq_len_q=cat("seq_len_q"),
105+
seq_len_q_padded=cat("seq_len_q_padded"),
106106
seq_len_kv=cat("seq_len_kv"),
107+
seq_len_kv_padded=cat("seq_len_kv_padded"),
107108
pos_ids=cat("pos_ids"),
108109
latent_shape=stack("latent_shape"),
110+
video_metadata=[sample.video_metadata for sample in samples],
109111
)
110112

111113
@stateless
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
# Copyright (c) 2024, NVIDIA CORPORATION. All rights reserved.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
# pylint: disable=C0115,C0116,C0301
16+
17+
from dataclasses import dataclass
18+
19+
from megatron.bridge.data.utils import DatasetBuildContext
20+
from torch import int_repr
21+
22+
from dfm.src.megatron.data.common.diffusion_energon_datamodule import DiffusionDataModule, DiffusionDataModuleConfig
23+
from dfm.src.megatron.data.wan.wan_taskencoder import WanTaskEncoder
24+
25+
26+
@dataclass(kw_only=True)
27+
class WanDataModuleConfig(DiffusionDataModuleConfig):
28+
path: str
29+
seq_length: int
30+
packing_buffer_size: int
31+
micro_batch_size: int
32+
global_batch_size: int
33+
num_workers: int_repr
34+
dataloader_type: str = "external"
35+
36+
def __post_init__(self):
37+
self.dataset = DiffusionDataModule(
38+
path=self.path,
39+
seq_length=self.seq_length,
40+
packing_buffer_size=self.packing_buffer_size,
41+
task_encoder=WanTaskEncoder(seq_length=self.seq_length, packing_buffer_size=self.packing_buffer_size),
42+
micro_batch_size=self.micro_batch_size,
43+
global_batch_size=self.global_batch_size,
44+
num_workers=self.num_workers,
45+
)
46+
self.sequence_length = self.dataset.seq_length
47+
48+
def build_datasets(self, context: DatasetBuildContext):
49+
return self.dataset.train_dataloader(), self.dataset.train_dataloader(), self.dataset.train_dataloader()
Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
# Copyright (c) 2024, NVIDIA CORPORATION. All rights reserved.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
# pylint: disable=C0115,C0116,C0301
16+
17+
from dataclasses import dataclass
18+
19+
import torch
20+
from megatron.bridge.data.utils import DatasetBuildContext, DatasetProvider
21+
from torch.utils.data import DataLoader, Dataset
22+
23+
from dfm.src.megatron.model.wan.utils import patchify
24+
25+
26+
class _MockDataset(Dataset):
27+
def __init__(self, length: int):
28+
self.length = max(int(length), 1)
29+
30+
def __len__(self) -> int:
31+
return self.length
32+
33+
def __getitem__(self, idx: int) -> dict:
34+
return {}
35+
36+
37+
def mock_batch(
38+
F_latents: int,
39+
H_latents: int,
40+
W_latents: int,
41+
patch_temporal: int,
42+
patch_spatial: int,
43+
number_packed_samples: int,
44+
context_seq_len: int,
45+
context_embeddings_dim: int,
46+
) -> dict:
47+
# set mock values for one video sample
48+
video_latent = torch.randn(16, F_latents, H_latents, W_latents, dtype=torch.float32)
49+
grid_size = torch.tensor(
50+
[
51+
video_latent.shape[1] // patch_temporal,
52+
video_latent.shape[2] // patch_spatial,
53+
video_latent.shape[3] // patch_spatial,
54+
],
55+
dtype=torch.int32,
56+
)
57+
video_latent = patchify([video_latent], (patch_temporal, patch_spatial, patch_spatial))[0]
58+
video_latent = torch.as_tensor(video_latent, dtype=torch.float32)
59+
seq_len_q = video_latent.shape[0]
60+
seq_len_q_padded = seq_len_q
61+
loss_mask = torch.ones(seq_len_q, dtype=torch.bfloat16)
62+
context_embeddings = torch.randn(context_seq_len, context_embeddings_dim, dtype=torch.float32)
63+
seq_len_kv = context_embeddings.shape[0]
64+
seq_len_kv_padded = seq_len_kv
65+
video_metadata = {}
66+
67+
# set mock values for packed video samples
68+
video_latents_packed = [video_latent for _ in range(number_packed_samples)]
69+
video_latents_packed = torch.cat(video_latents_packed, dim=0)
70+
loss_masks_packed = [loss_mask for _ in range(number_packed_samples)]
71+
loss_masks_packed = torch.cat(loss_masks_packed, dim=0)
72+
seq_len_q_packed = torch.tensor([seq_len_q for _ in range(number_packed_samples)], dtype=torch.int32)
73+
seq_len_q_padded_packed = torch.tensor([seq_len_q_padded for _ in range(number_packed_samples)], dtype=torch.int32)
74+
seq_len_kv_packed = torch.tensor([seq_len_kv for _ in range(number_packed_samples)], dtype=torch.int32)
75+
seq_len_kv_padded_packed = torch.tensor(
76+
[seq_len_kv_padded for _ in range(number_packed_samples)], dtype=torch.int32
77+
)
78+
grid_sizes_packed = torch.stack([grid_size for _ in range(number_packed_samples)], dim=0)
79+
context_embeddings_packed = [context_embeddings for _ in range(number_packed_samples)]
80+
context_embeddings_packed = torch.cat(context_embeddings_packed, dim=0)
81+
82+
### Note: shape of sample's values
83+
# video_latent: [num_patches, latents_channels * pF * pH * pW]
84+
# grid_size: [F_patches, W_patches, H_patches]
85+
# context_embeddings: [context_seq_len, text_embedding_dim]
86+
87+
batch = dict(
88+
video_latents=video_latents_packed.unsqueeze(1),
89+
context_embeddings=context_embeddings_packed.unsqueeze(1),
90+
loss_mask=loss_masks_packed.unsqueeze(1),
91+
seq_len_q=seq_len_q_packed,
92+
seq_len_q_padded=seq_len_q_padded_packed,
93+
seq_len_kv=seq_len_kv_packed,
94+
seq_len_kv_padded=seq_len_kv_padded_packed,
95+
grid_sizes=grid_sizes_packed,
96+
video_metadata=video_metadata,
97+
)
98+
99+
return batch
100+
101+
102+
@dataclass(kw_only=True)
103+
class WanMockDataModuleConfig(DatasetProvider):
104+
path: str = ""
105+
seq_length: int
106+
packing_buffer_size: int
107+
micro_batch_size: int
108+
global_batch_size: int
109+
num_workers: int
110+
dataloader_type: str = "external"
111+
F_latents: int = 24
112+
H_latents: int = 104
113+
W_latents: int = 60
114+
patch_spatial: int = 2
115+
patch_temporal: int = 1
116+
number_packed_samples: int = 3
117+
context_seq_len: int = 512
118+
context_embeddings_dim: int = 4096
119+
120+
def __post_init__(self):
121+
mock_ds = _MockDataset(length=1024)
122+
self._train_dl = DataLoader(
123+
mock_ds,
124+
batch_size=self.micro_batch_size,
125+
num_workers=self.num_workers,
126+
collate_fn=lambda samples: mock_batch(
127+
F_latents=self.F_latents,
128+
H_latents=self.H_latents,
129+
W_latents=self.W_latents,
130+
patch_temporal=self.patch_temporal,
131+
patch_spatial=self.patch_spatial,
132+
number_packed_samples=self.number_packed_samples,
133+
context_seq_len=self.context_seq_len,
134+
context_embeddings_dim=self.context_embeddings_dim,
135+
),
136+
shuffle=False,
137+
drop_last=False,
138+
)
139+
self.sequence_length = self.seq_length
140+
141+
def build_datasets(self, _context: DatasetBuildContext):
142+
if hasattr(self, "dataset"):
143+
return self.dataset.train_dataloader(), self.dataset.train_dataloader(), self.dataset.train_dataloader()
144+
return self._train_dl, self._train_dl, self._train_dl

0 commit comments

Comments
 (0)