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

Commit 0ca76a8

Browse files
author
Huy Vu2
committed
merge main
2 parents 377ff5b + 3fc4706 commit 0ca76a8

497 files changed

Lines changed: 2151 additions & 136492 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/actions/test-template/action.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ runs:
140140
- name: Checkout repository
141141
uses: actions/checkout@v2
142142
with:
143-
path: VFM
143+
path: DFM
144144

145145
- name: Start container
146146
shell: bash
@@ -164,7 +164,7 @@ runs:
164164
--env HYDRA_FULL_ERROR=1 \
165165
--env HF_HOME=/home/TestData/HF_HOME \
166166
--env RUN_ID=${{ github.run_id }} \
167-
--volume $(pwd)/VFM:/workspace \
167+
--volume $(pwd)/DFM:/workspace \
168168
--volume $MNT_PATH/TestData:/home/TestData \
169169
nemoci.azurecr.io/${{ inputs.image }}:${{ github.run_id }} \
170170
bash -c "sleep $(( ${{ inputs.timeout }} * 60 + 60))"

dfm/__init__.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# Copyright (c) 2025, 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+
from dfm.package_info import (
15+
__contact_emails__,
16+
__contact_names__,
17+
__description__,
18+
__download_url__,
19+
__homepage__,
20+
__keywords__,
21+
__license__,
22+
__package_name__,
23+
__repository_url__,
24+
__shortversion__,
25+
__version__,
26+
)
Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,12 @@
2424
__shortversion__ = ".".join(map(str, VERSION[:3]))
2525
__version__ = ".".join(map(str, VERSION[:3])) + "".join(VERSION[3:])
2626

27-
__package_name__ = "nemo_vfm"
27+
__package_name__ = "dfm"
2828
__contact_names__ = "NVIDIA"
2929
__contact_emails__ = "nemo-toolkit@nvidia.com"
30-
__homepage__ = "https://github.com/NVIDIA-NeMo/NeMo-VFM"
31-
__repository_url__ = "https://github.com/NVIDIA-NeMo/NeMo-VFM"
32-
__download_url__ = "https://github.com/NVIDIA-NeMo/NeMo-VFM/releases"
33-
__description__ = "NeMo VFM"
30+
__homepage__ = "https://github.com/NVIDIA-NeMo/NeMo-DFM"
31+
__repository_url__ = "https://github.com/NVIDIA-NeMo/NeMo-DFM"
32+
__download_url__ = "https://github.com/NVIDIA-NeMo/NeMo-DFM/releases"
33+
__description__ = "NeMo DFM"
3434
__license__ = "Apache2"
3535
__keywords__ = "deep learning, machine learning, gpu, NLP, pytorch, torch"
File renamed without changes.
File renamed without changes.
File renamed without changes.

nemo_vfm/physicalai/Cosmos/cosmos1/models/tokenizer/inference/video_lib.py renamed to dfm/src/common/tokenizers/cosmos/cosmos1/causal_video_tokenizer.py

Lines changed: 67 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -17,49 +17,95 @@
1717

1818
"""A library for Causal Video Tokenizer inference."""
1919

20-
from typing import Any
20+
from pathlib import Path
2121

2222
import numpy as np
2323
import torch
24-
from cosmos1.models.tokenizer.inference.utils import (
25-
load_decoder_model,
26-
load_encoder_model,
27-
load_model,
24+
from huggingface_hub import get_token as get_hf_token
25+
from huggingface_hub import hf_hub_download
26+
from tqdm import tqdm
27+
28+
from dfm.src.common.tokenizers.cosmos.cosmos1.video_tokenizer_utils import (
29+
load_jit_model,
2830
numpy2tensor,
2931
pad_video_batch,
3032
tensor2numpy,
3133
unpad_video_batch,
3234
)
33-
from tqdm import tqdm
3435

3536

3637
class CausalVideoTokenizer(torch.nn.Module):
3738
def __init__(
3839
self,
39-
checkpoint: str = None,
40-
checkpoint_enc: str = None,
41-
checkpoint_dec: str = None,
42-
tokenizer_config: dict[str, Any] = None,
40+
checkpoint_dir: str = None,
41+
load_full_model: bool = True,
42+
load_dec_model: bool = True,
43+
load_enc_model: bool = True,
4344
device: str = "cuda",
4445
dtype: str = "bfloat16",
4546
) -> None:
4647
super().__init__()
48+
49+
checkpoint = Path(checkpoint_dir)
50+
self._full_model_path = str(checkpoint / "autoencoder.jit")
51+
self._enc_model_path = str(checkpoint / "encoder.jit")
52+
self._dec_model_path = str(checkpoint / "decoder.jit")
53+
self._dtype = dtype
4754
self._device = device
48-
self._dtype = getattr(torch, dtype)
49-
self._full_model = (
50-
load_model(checkpoint, tokenizer_config, device).to(self._dtype) if checkpoint is not None else None
55+
56+
self._full_model = load_jit_model(self._full_model_path, self._device) if load_full_model else None
57+
self._enc_model = load_jit_model(self._enc_model_path, self._device) if load_enc_model else None
58+
self._dec_model = load_jit_model(self._dec_model_path, self._device) if load_dec_model else None
59+
60+
@classmethod
61+
def from_pretrained(
62+
cls,
63+
tokenizer_type="Cosmos-Tokenizer-DV4x8x8",
64+
load_encoder=True,
65+
load_decoder=True,
66+
load_full_model=False,
67+
use_pytorch=False,
68+
dtype="bfloat16",
69+
):
70+
cls._hf_model_name = f"nvidia/{tokenizer_type}"
71+
72+
# Requires setting HF_TOKEN env variable
73+
hf_token = get_hf_token()
74+
75+
full_model_path = hf_hub_download(
76+
repo_id=cls._hf_model_name,
77+
filename="autoencoder.jit",
78+
token=hf_token,
5179
)
52-
self._enc_model = (
53-
load_encoder_model(checkpoint_enc, tokenizer_config, device).to(self._dtype)
54-
if checkpoint_enc is not None
55-
else None
80+
81+
_ = hf_hub_download(
82+
repo_id=cls._hf_model_name,
83+
filename="encoder.jit",
84+
token=hf_token,
5685
)
57-
self._dec_model = (
58-
load_decoder_model(checkpoint_dec, tokenizer_config, device).to(self._dtype)
59-
if checkpoint_dec is not None
60-
else None
86+
87+
_ = hf_hub_download(
88+
repo_id=cls._hf_model_name,
89+
filename="decoder.jit",
90+
token=hf_token,
6191
)
6292

93+
# No need to load in encoder and decoder with full model loaded
94+
if load_full_model:
95+
load_encoder = False
96+
load_decoder = False
97+
98+
# Assumes HF downloads all files to same local dir
99+
ckpt_dir = str(Path(full_model_path).parent)
100+
args = {
101+
"checkpoint_dir": ckpt_dir,
102+
"dtype": dtype,
103+
"load_enc_model": load_encoder,
104+
"load_dec_model": load_decoder,
105+
"load_full_model": load_full_model,
106+
}
107+
return cls(**args)
108+
63109
@torch.no_grad()
64110
def autoencode(self, input_tensor: torch.Tensor) -> torch.Tensor:
65111
"""Reconstrcuts a batch of video tensors after embedding into a latent.
Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
# SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2+
# SPDX-License-Identifier: Apache-2.0
3+
#
4+
# Licensed under the Apache License, Version 2.0 (the "License");
5+
# you may not use this file except in compliance with the License.
6+
# You may obtain a copy of the License at
7+
#
8+
# http://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS,
12+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
# See the License for the specific language governing permissions and
14+
# limitations under the License.
15+
16+
"""Utility functions for the inference libraries."""
17+
18+
import numpy as np
19+
import torch
20+
21+
22+
_DTYPE, _DEVICE = torch.bfloat16, "cuda"
23+
_UINT8_MAX_F = float(torch.iinfo(torch.uint8).max)
24+
_SPATIAL_ALIGN = 16
25+
_TEMPORAL_ALIGN = 8
26+
27+
28+
def load_jit_model(jit_filepath: str = None, device: str = "cuda") -> torch.jit.ScriptModule:
29+
"""Loads a torch.jit.ScriptModule from a filepath.
30+
31+
Args:
32+
jit_filepath: The filepath to the JIT-compiled model.
33+
device: The device to load the model onto, default=cuda.
34+
Returns:
35+
The JIT compiled model loaded to device and on eval mode.
36+
"""
37+
model = torch.jit.load(jit_filepath, map_location=device)
38+
return model.eval().to(device)
39+
40+
41+
def numpy2tensor(
42+
input_image: np.ndarray,
43+
dtype: torch.dtype = _DTYPE,
44+
device: str = _DEVICE,
45+
range_min: int = -1,
46+
) -> torch.Tensor:
47+
"""Converts image(dtype=np.uint8) to `dtype` in range [0..255].
48+
49+
Args:
50+
input_image: A batch of images in range [0..255], BxHxWx3 layout.
51+
Returns:
52+
A torch.Tensor of layout Bx3xHxW in range [-1..1], dtype.
53+
"""
54+
ndim = input_image.ndim
55+
indices = list(range(1, ndim))[-1:] + list(range(1, ndim))[:-1]
56+
image = input_image.transpose((0,) + tuple(indices)) / _UINT8_MAX_F
57+
if range_min == -1:
58+
image = 2.0 * image - 1.0
59+
return torch.from_numpy(image).to(dtype).to(device)
60+
61+
62+
def tensor2numpy(input_tensor: torch.Tensor, range_min: int = -1) -> np.ndarray:
63+
"""Converts tensor in [-1,1] to image(dtype=np.uint8) in range [0..255].
64+
65+
Args:
66+
input_tensor: Input image tensor of Bx3xHxW layout, range [-1..1].
67+
Returns:
68+
A numpy image of layout BxHxWx3, range [0..255], uint8 dtype.
69+
"""
70+
if range_min == -1:
71+
input_tensor = (input_tensor.float() + 1.0) / 2.0
72+
ndim = input_tensor.ndim
73+
output_image = input_tensor.clamp(0, 1).cpu().numpy()
74+
output_image = output_image.transpose((0,) + tuple(range(2, ndim)) + (1,))
75+
return (output_image * _UINT8_MAX_F + 0.5).astype(np.uint8)
76+
77+
78+
def pad_video_batch(
79+
batch: np.ndarray,
80+
temporal_align: int = _TEMPORAL_ALIGN,
81+
spatial_align: int = _SPATIAL_ALIGN,
82+
) -> tuple[np.ndarray, list[int]]:
83+
"""Pads a batch of videos to be divisible by `temporal_align` or `spatial_align`.
84+
85+
Zero pad spatially. Reflection pad temporally to handle causality better.
86+
Args:
87+
batch: The batch of videos to pad., layout BxFxHxWx3, in any range.
88+
align: The alignment to pad to.
89+
Returns:
90+
The padded batch and the crop region.
91+
"""
92+
num_frames, height, width = batch.shape[-4:-1]
93+
align = spatial_align
94+
height_to_pad = (align - height % align) if height % align != 0 else 0
95+
width_to_pad = (align - width % align) if width % align != 0 else 0
96+
97+
align = temporal_align
98+
frames_to_pad = (align - (num_frames - 1) % align) if (num_frames - 1) % align != 0 else 0
99+
100+
crop_region = [
101+
frames_to_pad >> 1,
102+
height_to_pad >> 1,
103+
width_to_pad >> 1,
104+
num_frames + (frames_to_pad >> 1),
105+
height + (height_to_pad >> 1),
106+
width + (width_to_pad >> 1),
107+
]
108+
batch = np.pad(
109+
batch,
110+
(
111+
(0, 0),
112+
(0, 0),
113+
(height_to_pad >> 1, height_to_pad - (height_to_pad >> 1)),
114+
(width_to_pad >> 1, width_to_pad - (width_to_pad >> 1)),
115+
(0, 0),
116+
),
117+
mode="constant",
118+
)
119+
batch = np.pad(
120+
batch,
121+
(
122+
(0, 0),
123+
(frames_to_pad >> 1, frames_to_pad - (frames_to_pad >> 1)),
124+
(0, 0),
125+
(0, 0),
126+
(0, 0),
127+
),
128+
mode="edge",
129+
)
130+
return batch, crop_region
131+
132+
133+
def unpad_video_batch(batch: np.ndarray, crop_region: list[int]) -> np.ndarray:
134+
"""Unpads video with `crop_region`.
135+
136+
Args:
137+
batch: A batch of numpy videos, layout BxFxHxWxC.
138+
crop_region: [f1,y1,x1,f2,y2,x2] first, top, left, last, bot, right crop indices.
139+
140+
Returns:
141+
np.ndarray: Cropped numpy video, layout BxFxHxWxC.
142+
"""
143+
assert len(crop_region) == 6, "crop_region should be len of 6."
144+
f1, y1, x1, f2, y2, x2 = crop_region
145+
return batch[..., f1:f2, y1:y2, x1:x2, :]
File renamed without changes.

0 commit comments

Comments
 (0)