Files
wehub-resource-sync c8a779b1bb
Docker Image CI / build-ubuntu2004 (push) Waiting to run
chore: import upstream snapshot with attribution
2026-07-13 13:36:55 +08:00

1014 lines
40 KiB
Python

#
# SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
import os
import torch
from huggingface_hub import hf_hub_download
from safetensors import safe_open
from demo_diffusion.dynamic_import import import_from_diffusers
from demo_diffusion.model import base_model, load, optimizer
from demo_diffusion.utils_sd3.other_impls import load_into
from demo_diffusion.utils_sd3.sd3_impls import BaseModel as BaseModelSD3
# List of models to import from diffusers.models
models_to_import = ["FluxTransformer2DModel", "SD3Transformer2DModel", "WanTransformer3DModel", "CosmosTransformer3DModel"]
for model in models_to_import:
globals()[model] = import_from_diffusers(model, "diffusers.models")
# Import FluxKontextUtil from pipeline module
# Using a deferred import to avoid circular dependencies
def _get_flux_kontext_util():
from demo_diffusion.pipeline.flux_pipeline import FluxKontextUtil
return FluxKontextUtil
class SD3_MMDiTModel(base_model.BaseModel):
def __init__(
self,
version,
pipeline,
device,
hf_token,
verbose,
framework_model_dir,
shift=1.0,
fp16=False,
max_batch_size=16,
text_maxlen=77,
):
super(SD3_MMDiTModel, self).__init__(
version,
pipeline,
device=device,
hf_token=hf_token,
verbose=verbose,
framework_model_dir=framework_model_dir,
fp16=fp16,
max_batch_size=max_batch_size,
text_maxlen=text_maxlen,
)
self.subfolder = "sd3"
self.mmdit_dim = 16
self.shift = shift
self.xB = 2
def get_model(self, torch_inference=""):
sd3_model_dir = load.get_checkpoint_dir(self.framework_model_dir, self.version, self.pipeline, self.subfolder)
sd3_filename = "sd3_medium.safetensors"
sd3_model_path = f"{sd3_model_dir}/{sd3_filename}"
if not os.path.exists(sd3_model_path):
hf_hub_download(repo_id=self.path, filename=sd3_filename, local_dir=sd3_model_dir)
with safe_open(sd3_model_path, framework="pt", device=self.device) as f:
model = BaseModelSD3(
shift=self.shift, file=f, prefix="model.diffusion_model.", device=self.device, dtype=torch.float16
).eval()
load_into(f, model, "model.", self.device, torch.float16)
model = optimizer.optimize_checkpoint(model, torch_inference)
return model
def get_input_names(self):
return ["sample", "sigma", "c_crossattn", "y"]
def get_output_names(self):
return ["latent"]
def get_dynamic_axes(self):
xB = "2B" if self.xB == 2 else "B"
return {
"sample": {0: xB, 2: "H", 3: "W"},
"sigma": {0: xB},
"c_crossattn": {0: xB},
"y": {0: xB},
"latent": {0: xB, 2: "H", 3: "W"},
}
def get_input_profile(self, batch_size, image_height, image_width, static_batch, static_shape):
latent_height, latent_width = self.check_dims(batch_size, image_height, image_width)
min_batch, max_batch, _, _, _, _, min_latent_height, max_latent_height, min_latent_width, max_latent_width = (
self.get_minmax_dims(batch_size, image_height, image_width, static_batch, static_shape)
)
return {
"sample": [
(self.xB * min_batch, self.mmdit_dim, min_latent_height, min_latent_width),
(self.xB * batch_size, self.mmdit_dim, latent_height, latent_width),
(self.xB * max_batch, self.mmdit_dim, max_latent_height, max_latent_width),
],
"sigma": [(self.xB * min_batch,), (self.xB * batch_size,), (self.xB * max_batch,)],
"c_crossattn": [
(self.xB * min_batch, 154, 4096),
(self.xB * batch_size, 154, 4096),
(self.xB * max_batch, 154, 4096),
],
"y": [(self.xB * min_batch, 2048), (self.xB * batch_size, 2048), (self.xB * max_batch, 2048)],
}
def get_shape_dict(self, batch_size, image_height, image_width):
latent_height, latent_width = self.check_dims(batch_size, image_height, image_width)
return {
"sample": (self.xB * batch_size, self.mmdit_dim, latent_height, latent_width),
"sigma": (self.xB * batch_size,),
"c_crossattn": (self.xB * batch_size, 154, 4096),
"y": (self.xB * batch_size, 2048),
"latent": (self.xB * batch_size, self.mmdit_dim, latent_height, latent_width),
}
def get_sample_input(self, batch_size, image_height, image_width, static_shape):
latent_height, latent_width = self.check_dims(batch_size, image_height, image_width)
dtype = torch.float16 if self.fp16 else torch.float32
return (
torch.randn(batch_size, self.mmdit_dim, latent_height, latent_width, dtype=dtype, device=self.device),
torch.randn(batch_size, dtype=dtype, device=self.device),
{
"c_crossattn": torch.randn(batch_size, 154, 4096, dtype=dtype, device=self.device),
"y": torch.randn(batch_size, 2048, dtype=dtype, device=self.device),
},
)
class FluxTransformerModel(base_model.BaseModel):
def __init__(
self,
version,
pipeline,
device,
hf_token,
verbose,
framework_model_dir,
fp16=False,
tf32=False,
int8=False,
fp8=False,
bf16=False,
max_batch_size=16,
text_maxlen=77,
weight_streaming=False,
weight_streaming_budget_percentage=None,
kontext_resolution=None,
):
super(FluxTransformerModel, self).__init__(
version,
pipeline,
device=device,
hf_token=hf_token,
verbose=verbose,
framework_model_dir=framework_model_dir,
fp16=fp16,
tf32=tf32,
int8=int8,
fp8=fp8,
bf16=bf16,
max_batch_size=max_batch_size,
text_maxlen=text_maxlen,
)
self.subfolder = "transformer"
self.transformer_model_dir = load.get_checkpoint_dir(
self.framework_model_dir, self.version, self.pipeline, self.subfolder
)
if not os.path.exists(self.transformer_model_dir):
self.config = FluxTransformer2DModel.load_config(self.path, subfolder=self.subfolder, token=self.hf_token)
else:
print(f"[I] Load FluxTransformer2DModel config from: {self.transformer_model_dir}")
self.config = FluxTransformer2DModel.load_config(self.transformer_model_dir)
self.weight_streaming = weight_streaming
self.weight_streaming_budget_percentage = weight_streaming_budget_percentage
self.out_channels = self.config.get("out_channels") or self.config["in_channels"]
self.kontext_resolution = kontext_resolution
def get_model(self, torch_inference=""):
model_opts = (
{"torch_dtype": torch.float16} if self.fp16 else {"torch_dtype": torch.bfloat16} if self.bf16 else {}
)
if not load.is_model_cached(self.transformer_model_dir, model_opts, self.hf_safetensor):
model = FluxTransformer2DModel.from_pretrained(
self.path,
subfolder=self.subfolder,
use_safetensors=self.hf_safetensor,
token=self.hf_token,
**model_opts,
).to(self.device)
model.save_pretrained(self.transformer_model_dir, **model_opts)
else:
print(f"[I] Load FluxTransformer2DModel model from: {self.transformer_model_dir}")
model = FluxTransformer2DModel.from_pretrained(self.transformer_model_dir, **model_opts).to(self.device)
if torch_inference:
model.to(memory_format=torch.channels_last)
model = optimizer.optimize_checkpoint(model, torch_inference)
return model
def get_input_names(self):
return [
"hidden_states",
"encoder_hidden_states",
"pooled_projections",
"timestep",
"img_ids",
"txt_ids",
"guidance",
]
def get_output_names(self):
return ["latent"]
def get_dynamic_axes(self):
dynamic_axes = {
"hidden_states": {0: "B", 1: "latent_dim"},
"encoder_hidden_states": {0: "B"},
"pooled_projections": {0: "B"},
"timestep": {0: "B"},
"img_ids": {0: "latent_dim"},
"txt_ids": {},
}
if self.config["guidance_embeds"]:
dynamic_axes["guidance"] = {0: "B"}
return dynamic_axes
def get_context_latent_dim(self, static_shape=False):
FluxKontextUtil = _get_flux_kontext_util()
return FluxKontextUtil.get_context_latent_dim(
version=self.version,
kontext_resolution=self.kontext_resolution,
compression_factor=self.compression_factor,
static_shape=static_shape,
)
def get_input_profile(self, batch_size, image_height, image_width, static_batch, static_shape):
latent_height, latent_width = self.check_dims(batch_size, image_height, image_width)
(
min_batch,
max_batch,
min_image_height,
max_image_height,
min_image_width,
max_image_width,
min_latent_height,
max_latent_height,
min_latent_width,
max_latent_width,
) = self.get_minmax_dims(batch_size, image_height, image_width, static_batch, static_shape)
min_context_latent_dim, context_latent_dim, max_context_latent_dim = self.get_context_latent_dim(static_shape)
input_profile = {
"hidden_states": [
(
min_batch,
(min_latent_height // 2) * (min_latent_width // 2) + min_context_latent_dim,
self.config["in_channels"],
),
(
batch_size,
(latent_height // 2) * (latent_width // 2) + context_latent_dim,
self.config["in_channels"],
),
(
max_batch,
(max_latent_height // 2) * (max_latent_width // 2) + max_context_latent_dim,
self.config["in_channels"],
),
],
"encoder_hidden_states": [
(min_batch, self.text_maxlen, self.config["joint_attention_dim"]),
(batch_size, self.text_maxlen, self.config["joint_attention_dim"]),
(max_batch, self.text_maxlen, self.config["joint_attention_dim"]),
],
"pooled_projections": [
(min_batch, self.config["pooled_projection_dim"]),
(batch_size, self.config["pooled_projection_dim"]),
(max_batch, self.config["pooled_projection_dim"]),
],
"timestep": [(min_batch,), (batch_size,), (max_batch,)],
"img_ids": [
((min_latent_height // 2) * (min_latent_width // 2) + min_context_latent_dim, 3),
((latent_height // 2) * (latent_width // 2) + context_latent_dim, 3),
((max_latent_height // 2) * (max_latent_width // 2) + max_context_latent_dim, 3),
],
"txt_ids": [(self.text_maxlen, 3), (self.text_maxlen, 3), (self.text_maxlen, 3)],
}
if self.config["guidance_embeds"]:
input_profile["guidance"] = [(min_batch,), (batch_size,), (max_batch,)]
return input_profile
def get_shape_dict(self, batch_size, image_height, image_width):
latent_height, latent_width = self.check_dims(batch_size, image_height, image_width)
_, context_latent_dim, _ = self.get_context_latent_dim()
shape_dict = {
"hidden_states": (
batch_size,
(latent_height // 2) * (latent_width // 2) + context_latent_dim,
self.config["in_channels"],
),
"encoder_hidden_states": (batch_size, self.text_maxlen, self.config["joint_attention_dim"]),
"pooled_projections": (batch_size, self.config["pooled_projection_dim"]),
"timestep": (batch_size,),
"img_ids": ((latent_height // 2) * (latent_width // 2) + context_latent_dim, 3),
"txt_ids": (self.text_maxlen, 3),
"latent": (batch_size, (latent_height // 2) * (latent_width // 2) + context_latent_dim, self.out_channels),
}
if self.config["guidance_embeds"]:
shape_dict["guidance"] = (batch_size,)
return shape_dict
def get_sample_input(self, batch_size, image_height, image_width, static_shape):
latent_height, latent_width = self.check_dims(batch_size, image_height, image_width)
dtype = torch.float32
assert not (self.fp16 and self.bf16), "fp16 and bf16 cannot be enabled simultaneously"
tensor_dtype = torch.bfloat16 if self.bf16 else (torch.float16 if self.fp16 else torch.float32)
sample_input = (
torch.randn(
batch_size,
(latent_height // 2) * (latent_width // 2),
self.config["in_channels"],
dtype=tensor_dtype,
device=self.device,
),
torch.randn(
batch_size, self.text_maxlen, self.config["joint_attention_dim"], dtype=tensor_dtype, device=self.device
),
torch.randn(batch_size, self.config["pooled_projection_dim"], dtype=tensor_dtype, device=self.device),
torch.tensor([1.0] * batch_size, dtype=tensor_dtype, device=self.device),
torch.randn((latent_height // 2) * (latent_width // 2), 3, dtype=dtype, device=self.device),
torch.randn(self.text_maxlen, 3, dtype=dtype, device=self.device),
{},
)
if self.config["guidance_embeds"]:
sample_input[-1]["guidance"] = torch.tensor([1.0] * batch_size, dtype=dtype, device=self.device)
return sample_input
def optimize(self, onnx_graph):
if self.fp8:
return super().optimize(onnx_graph)
if self.int8:
return super().optimize(onnx_graph, modify_int8_graph=True)
return super().optimize(onnx_graph)
class UpcastLayer(torch.nn.Module):
def __init__(self, base_layer: torch.nn.Module, upcast_to: torch.dtype):
super().__init__()
self.output_dtype = next(base_layer.parameters()).dtype
self.upcast_to = upcast_to
self.context_pre_only = base_layer.context_pre_only
base_layer = base_layer.to(dtype=self.upcast_to)
self.base_layer = base_layer
def forward(self, *inputs, **kwargs):
casted_inputs = tuple(
in_val.to(self.upcast_to) if isinstance(in_val, torch.Tensor) else in_val for in_val in inputs
)
kwarg_casted = {}
for name, val in kwargs.items():
kwarg_casted[name] = val.to(dtype=self.upcast_to) if isinstance(val, torch.Tensor) else val
output = self.base_layer(*casted_inputs, **kwarg_casted)
if isinstance(output, tuple):
output = tuple(out.to(self.output_dtype) if isinstance(out, torch.Tensor) else out for out in output)
else:
output = output.to(dtype=self.output_dtype)
return output
class SD3TransformerModel(base_model.BaseModel):
def __init__(
self,
version,
pipeline,
device,
hf_token,
verbose,
framework_model_dir,
fp16=False,
tf32=False,
bf16=False,
fp8=False,
int8=False,
fp4=False,
max_batch_size=16,
text_maxlen=256,
weight_streaming=False,
weight_streaming_budget_percentage=None,
do_classifier_free_guidance=False,
):
super(SD3TransformerModel, self).__init__(
version,
pipeline,
device=device,
hf_token=hf_token,
verbose=verbose,
framework_model_dir=framework_model_dir,
fp16=fp16,
tf32=tf32,
bf16=bf16,
fp8=fp8,
int8=int8,
fp4=fp4,
max_batch_size=max_batch_size,
text_maxlen=text_maxlen,
)
self.subfolder = "transformer"
self.transformer_model_dir = load.get_checkpoint_dir(
self.framework_model_dir, self.version, self.pipeline, self.subfolder
)
if not os.path.exists(self.transformer_model_dir):
self.config = SD3Transformer2DModel.load_config(self.path, subfolder=self.subfolder, token=self.hf_token)
else:
print(f"[I] Load SD3Transformer2DModel config from: {self.transformer_model_dir}")
self.config = SD3Transformer2DModel.load_config(self.transformer_model_dir)
self.weight_streaming = weight_streaming
self.weight_streaming_budget_percentage = weight_streaming_budget_percentage
self.out_channels = self.config.get("out_channels")
self.xB = 2 if do_classifier_free_guidance else 1 # batch multiplier
self.num_controlnet_layers = 19 # Can be queried from the ControlNet model config
def get_model(self, torch_inference=""):
model_opts = (
{"torch_dtype": torch.float16} if self.fp16 else {"torch_dtype": torch.bfloat16} if self.bf16 else {}
)
if not load.is_model_cached(self.transformer_model_dir, model_opts, self.hf_safetensor):
model = SD3Transformer2DModel.from_pretrained(
self.path,
subfolder=self.subfolder,
use_safetensors=self.hf_safetensor,
token=self.hf_token,
**model_opts,
).to(self.device)
model.save_pretrained(self.transformer_model_dir, **model_opts)
else:
print(f"[I] Load SD3Transformer2DModel model from: {self.transformer_model_dir}")
model = SD3Transformer2DModel.from_pretrained(self.transformer_model_dir, **model_opts).to(self.device)
if self.version == "3.5-large":
model.transformer_blocks[35] = UpcastLayer(model.transformer_blocks[35], torch.float32)
if torch_inference:
model.to(memory_format=torch.channels_last)
model = optimizer.optimize_checkpoint(model, torch_inference)
return model
def get_input_names(self):
input_names = [
"hidden_states",
"encoder_hidden_states",
"pooled_projections",
"timestep",
"block_controlnet_hidden_states"
]
return input_names
def get_output_names(self):
return ["latent"]
def get_dynamic_axes(self):
xB = "2B" if self.xB == 2 else "B"
dynamic_axes = {
"hidden_states": {0: xB, 2: "H", 3: "W"},
"encoder_hidden_states": {0: xB},
"pooled_projections": {0: xB},
"timestep": {0: xB},
"latent": {0: xB, 2: "H", 3: "W"},
"block_controlnet_hidden_states": {1: xB, 2: "latent_dim"}
}
return dynamic_axes
def get_input_profile(
self,
batch_size: int,
image_height: int,
image_width: int,
static_batch: bool,
static_shape: bool,
):
latent_height, latent_width = self.check_dims(batch_size, image_height, image_width)
(
min_batch,
max_batch,
_,
_,
_,
_,
min_latent_height,
max_latent_height,
min_latent_width,
max_latent_width,
) = self.get_minmax_dims(batch_size, image_height, image_width, static_batch, static_shape)
input_profile = {
"hidden_states": [
(self.xB * min_batch, self.config["in_channels"], min_latent_height, min_latent_width),
(self.xB * batch_size, self.config["in_channels"], latent_height, latent_width),
(self.xB * max_batch, self.config["in_channels"], max_latent_height, max_latent_width),
],
"encoder_hidden_states": [
(self.xB * min_batch, self.text_maxlen, self.config["joint_attention_dim"]),
(self.xB * batch_size, self.text_maxlen, self.config["joint_attention_dim"]),
(self.xB * max_batch, self.text_maxlen, self.config["joint_attention_dim"]),
],
"pooled_projections": [
(self.xB * min_batch, self.config["pooled_projection_dim"]),
(self.xB * batch_size, self.config["pooled_projection_dim"]),
(self.xB * max_batch, self.config["pooled_projection_dim"]),
],
"timestep": [(self.xB * min_batch,), (self.xB * batch_size,), (self.xB * max_batch,)],
"block_controlnet_hidden_states": [
(
self.num_controlnet_layers,
self.xB * min_batch,
min_latent_height // self.config["patch_size"] * min_latent_width // self.config["patch_size"],
self.config["num_attention_heads"] * self.config["attention_head_dim"],
),
(
self.num_controlnet_layers,
self.xB * batch_size,
latent_height // self.config["patch_size"] * latent_width // self.config["patch_size"],
self.config["num_attention_heads"] * self.config["attention_head_dim"],
),
(
self.num_controlnet_layers,
self.xB * max_batch,
max_latent_height // self.config["patch_size"] * max_latent_width // self.config["patch_size"],
self.config["num_attention_heads"] * self.config["attention_head_dim"],
),
]
}
return input_profile
def get_shape_dict(self, batch_size, image_height, image_width):
latent_height, latent_width = self.check_dims(batch_size, image_height, image_width)
shape_dict = {
"hidden_states": (self.xB * batch_size, self.config["in_channels"], latent_height, latent_width),
"encoder_hidden_states": (self.xB * batch_size, self.text_maxlen, self.config["joint_attention_dim"]),
"pooled_projections": (self.xB * batch_size, self.config["pooled_projection_dim"]),
"timestep": (self.xB * batch_size,),
"latent": (self.xB * batch_size, self.out_channels, latent_height, latent_width),
"block_controlnet_hidden_states": (
self.num_controlnet_layers,
self.xB * batch_size,
latent_height // self.config["patch_size"] * latent_width // self.config["patch_size"],
self.config["num_attention_heads"] * self.config["attention_head_dim"],
)
}
return shape_dict
def get_sample_input(self, batch_size, image_height, image_width, static_shape):
assert not (self.fp16 and self.bf16), "fp16 and bf16 cannot be enabled simultaneously"
dtype = torch.float16 if self.fp16 else torch.bfloat16 if self.bf16 else torch.float32
latent_height, latent_width = self.check_dims(batch_size, image_height, image_width)
sample_input = (
torch.randn(
self.xB * batch_size,
self.config["in_channels"],
latent_height,
latent_width,
dtype=dtype,
device=self.device,
),
torch.randn(
self.xB * batch_size,
self.text_maxlen,
self.config["joint_attention_dim"],
dtype=dtype,
device=self.device,
),
torch.randn(self.xB * batch_size, self.config["pooled_projection_dim"], dtype=dtype, device=self.device),
torch.randn(self.xB * batch_size, dtype=torch.float32, device=self.device),
{
"block_controlnet_hidden_states": torch.randn(
self.num_controlnet_layers,
self.xB * batch_size,
latent_height // self.config["patch_size"] * latent_width // self.config["patch_size"],
self.config["num_attention_heads"] * self.config["attention_head_dim"],
dtype=dtype,
device=self.device,
),
}
)
return sample_input
class WanTransformerModel(base_model.BaseModel):
def __init__(
self,
version,
pipeline,
device,
hf_token,
verbose,
framework_model_dir,
subfolder="transformer",
fp16=False,
tf32=False,
bf16=True,
fp8=False,
int8=False,
max_batch_size=1,
text_maxlen=512,
num_frames=81,
height=720,
width=1280,
weight_streaming=False,
weight_streaming_budget_percentage=None,
):
super(WanTransformerModel, self).__init__(
version,
pipeline,
device=device,
hf_token=hf_token,
verbose=verbose,
framework_model_dir=framework_model_dir,
fp16=fp16,
tf32=tf32,
bf16=bf16,
fp8=fp8,
int8=int8,
max_batch_size=max_batch_size,
text_maxlen=text_maxlen,
embedding_dim=4096,
compression_factor=8,
)
self.subfolder = subfolder
self.transformer_model_dir = load.get_checkpoint_dir(
self.framework_model_dir, self.version, self.pipeline, self.subfolder
)
if not os.path.exists(self.transformer_model_dir):
self.config = WanTransformer3DModel.load_config(
self.path, subfolder=self.subfolder, token=self.hf_token
)
else:
print(f"[I] Load WanTransformer3DModel config from: {self.transformer_model_dir}")
self.config = WanTransformer3DModel.load_config(self.transformer_model_dir)
self.weight_streaming = weight_streaming
self.weight_streaming_budget_percentage = weight_streaming_budget_percentage
self.do_constant_folding = False
self.latent_channels = self.config.get("in_channels", 16)
self.temporal_compression_factor = 4
self.num_frames = num_frames
self.min_latent_frames = 81 # hardcode to 81 frames for Wan 2.2
self.max_latent_frames = 81
def get_model(self, torch_inference=""):
model_opts = {"torch_dtype": torch.bfloat16} if self.bf16 else {}
if not load.is_model_cached(self.transformer_model_dir, model_opts, self.hf_safetensor):
model = WanTransformer3DModel.from_pretrained(
self.path,
subfolder=self.subfolder,
use_safetensors=self.hf_safetensor,
token=self.hf_token,
**model_opts,
).to(self.device)
model.save_pretrained(self.transformer_model_dir, **model_opts)
else:
print(f"[I] Load WanTransformer3DModel model from: {self.transformer_model_dir}")
model = WanTransformer3DModel.from_pretrained(self.transformer_model_dir, **model_opts).to(self.device)
if torch_inference:
model.to(memory_format=torch.channels_last)
model = optimizer.optimize_checkpoint(model, torch_inference)
return model
def get_input_names(self):
return [
"hidden_states",
"timestep",
"encoder_hidden_states",
]
def get_output_names(self):
return ["denoised_latents"]
def get_dynamic_axes(self):
return {}
def get_input_profile(self, batch_size, image_height, image_width, static_batch, static_shape, num_frames):
latent_height, latent_width, latent_frames = self.check_dims(
batch_size, image_height, image_width, num_frames
)
(
min_batch,
max_batch,
_,
_,
_,
_,
min_latent_height,
max_latent_height,
min_latent_width,
max_latent_width,
min_latent_frames,
max_latent_frames
) = self.get_minmax_dims(batch_size, image_height, image_width, static_batch, static_shape, num_frames)
input_profile = {
"hidden_states": [
(min_batch, self.latent_channels, min_latent_frames, min_latent_height, min_latent_width),
(batch_size, self.latent_channels, latent_frames, latent_height, latent_width),
(max_batch, self.latent_channels, max_latent_frames, max_latent_height, max_latent_width),
],
"timestep": [
(min_batch,),
(batch_size,),
(max_batch,)
],
"encoder_hidden_states": [
(min_batch, self.text_maxlen, self.embedding_dim),
(batch_size, self.text_maxlen, self.embedding_dim),
(max_batch, self.text_maxlen, self.embedding_dim),
],
}
return input_profile
def get_shape_dict(self, batch_size, image_height, image_width, num_frames):
latent_height, latent_width, latent_frames = self.check_dims(
batch_size, image_height, image_width, num_frames
)
return {
"hidden_states": (
batch_size,
self.latent_channels,
latent_frames,
latent_height,
latent_width
),
"timestep": (batch_size,),
"encoder_hidden_states": (
batch_size,
self.text_maxlen,
self.embedding_dim
),
"denoised_latents": (
batch_size,
self.latent_channels,
latent_frames,
latent_height,
latent_width
),
}
def get_sample_input(self, batch_size, image_height, image_width, static_shape, num_frames):
latent_height, latent_width, latent_frames = self.check_dims(
batch_size, image_height, image_width, num_frames
)
assert (self.bf16), "transformer must be BF16"
dtype = torch.bfloat16 if self.bf16 else torch.float32
timesteps = torch.tensor([999], dtype=torch.long, device=self.device) if self.subfolder == "transformer" else torch.tensor([1], dtype=torch.long, device=self.device)
sample_input = (
torch.randn(
batch_size,
self.latent_channels,
latent_frames,
latent_height,
latent_width,
dtype=dtype,
device=self.device,
),
timesteps,
torch.randn(
batch_size,
self.text_maxlen,
self.embedding_dim,
dtype=dtype,
device=self.device,
),
)
return sample_input
class CosmosTransformerModel(base_model.BaseModel):
def __init__(
self,
version,
pipeline,
device,
hf_token,
verbose,
framework_model_dir,
fp16=False,
tf32=False,
int8=False,
fp8=False,
bf16=False,
max_batch_size=16,
text_maxlen=77,
weight_streaming=False,
weight_streaming_budget_percentage=None,
):
super(CosmosTransformerModel, self).__init__(
version,
pipeline,
device=device,
hf_token=hf_token,
verbose=verbose,
framework_model_dir=framework_model_dir,
fp16=fp16,
tf32=tf32,
int8=int8,
fp8=fp8,
bf16=bf16,
max_batch_size=max_batch_size,
text_maxlen=text_maxlen,
)
self.subfolder = "transformer"
self.transformer_model_dir = load.get_checkpoint_dir(
self.framework_model_dir, self.version, self.pipeline, self.subfolder
)
if not os.path.exists(self.transformer_model_dir):
self.config = CosmosTransformer3DModel.load_config(self.path, subfolder=self.subfolder, token=self.hf_token)
else:
print(f"[I] Load CosmosTransformer3DModel config from: {self.transformer_model_dir}")
self.config = CosmosTransformer3DModel.load_config(self.transformer_model_dir)
self.weight_streaming = weight_streaming
self.weight_streaming_budget_percentage = weight_streaming_budget_percentage
def get_model(self, torch_inference=""):
model_opts = (
{"torch_dtype": torch.float16} if self.fp16 else {"torch_dtype": torch.bfloat16} if self.bf16 else {}
)
if not load.is_model_cached(self.transformer_model_dir, model_opts, self.hf_safetensor):
model = CosmosTransformer3DModel.from_pretrained(
self.path,
subfolder=self.subfolder,
use_safetensors=self.hf_safetensor,
token=self.hf_token,
**model_opts,
).to(self.device)
model.save_pretrained(self.transformer_model_dir, **model_opts)
else:
print(f"[I] Load CosmosTransformer3DModel model from: {self.transformer_model_dir}")
model = CosmosTransformer3DModel.from_pretrained(self.transformer_model_dir, **model_opts).to(self.device)
if torch_inference:
model.to(memory_format=torch.channels_last)
if self.fp16:
model.transformer_blocks[6].attn1.norm_q.float().to(self.device)
model = optimizer.optimize_checkpoint(model, torch_inference)
return model.to(self.device)
def get_input_names(self):
input_names = [
"hidden_states",
"timestep",
"encoder_hidden_states",
"padding_mask",
]
if self.pipeline_type.is_video2world():
input_names.append("fps")
input_names.append("condition_mask")
return input_names
def get_output_names(self):
return ["latent"]
def get_dynamic_axes(self):
dynamic_axes = {
"hidden_states": {0: "B", 2: "latent_frames", 3: "latent_H", 4: "latent_W"},
"timestep": {0: "B"},
"encoder_hidden_states": {0: "B"},
"padding_mask": {0: "B", 2: "H", 3: "W"},
}
if self.pipeline_type.is_video2world():
dynamic_axes["fps"] = {0: "B"}
dynamic_axes["condition_mask"] = {0: "B", 2: "latent_frames", 3: "latent_H", 4: "latent_W"}
return dynamic_axes
def get_input_profile(self, batch_size, image_height, image_width, static_batch, static_shape):
latent_height, latent_width = self.check_dims(batch_size, image_height, image_width)
(
min_batch,
max_batch,
min_image_height,
max_image_height,
min_image_width,
max_image_width,
min_latent_height,
max_latent_height,
min_latent_width,
max_latent_width,
) = self.get_minmax_dims(batch_size, image_height, image_width, static_batch, static_shape)
latent_frames = 24 if self.pipeline_type.is_video2world() else 1
latent_channels = (
self.config["in_channels"] - 1 if self.pipeline_type.is_video2world() else self.config["in_channels"]
)
input_profile = {
"hidden_states": [
(min_batch, latent_channels, latent_frames, min_latent_height, min_latent_width),
(batch_size, latent_channels, latent_frames, latent_height, latent_width),
(max_batch, latent_channels, latent_frames, max_latent_height, max_latent_width),
],
"timestep": [(min_batch,), (batch_size,), (max_batch,)],
"encoder_hidden_states": [
(min_batch, self.text_maxlen, self.config["text_embed_dim"]),
(batch_size, self.text_maxlen, self.config["text_embed_dim"]),
(max_batch, self.text_maxlen, self.config["text_embed_dim"]),
],
"padding_mask": [
(1, 1, min_image_height, min_image_width),
(1, 1, image_height, image_width),
(1, 1, max_image_height, max_image_width),
],
}
if self.pipeline_type.is_video2world():
input_profile["fps"] = [(min_batch,), (batch_size,), (max_batch,)]
input_profile["condition_mask"] = [
(min_batch, 1, latent_frames, min_latent_height, min_latent_width),
(batch_size, 1, latent_frames, latent_height, latent_width),
(max_batch, 1, latent_frames, max_latent_height, max_latent_width),
]
return input_profile
def get_shape_dict(self, batch_size, image_height, image_width):
latent_height, latent_width = self.check_dims(batch_size, image_height, image_width)
# TODO: get latent_frames from infer call
latent_frames = 24 if self.pipeline_type.is_video2world() else 1
latent_channels = (
self.config["in_channels"] - 1 if self.pipeline_type.is_video2world() else self.config["in_channels"]
)
shape_dict = {
"hidden_states": (batch_size, latent_channels, latent_frames, latent_height, latent_width),
"timestep": (batch_size,),
"encoder_hidden_states": (batch_size, self.text_maxlen, self.config["text_embed_dim"]),
"padding_mask": (1, 1, image_height, image_width),
"latent": (batch_size, self.config["in_channels"], latent_frames, latent_height, latent_width),
}
if self.pipeline_type.is_video2world():
shape_dict["fps"] = (batch_size,)
shape_dict["condition_mask"] = (batch_size, 1, latent_frames, latent_height, latent_width)
return shape_dict
def get_sample_input(self, batch_size, image_height, image_width, static_shape):
latent_height, latent_width = self.check_dims(batch_size, image_height, image_width)
dtype = torch.float32
assert not (self.fp16 and self.bf16), "fp16 and bf16 cannot be enabled simultaneously"
tensor_dtype = torch.bfloat16 if self.bf16 else (torch.float16 if self.fp16 else torch.float32)
latent_frames = 1
latent_channels = (
self.config["in_channels"] - 1 if self.pipeline_type.is_video2world() else self.config["in_channels"]
)
sample_input = (
{
"hidden_states": torch.randn(
batch_size,
latent_channels,
latent_frames,
latent_height,
latent_width,
dtype=tensor_dtype,
device=self.device,
),
"timestep": torch.tensor([1.0] * batch_size, dtype=tensor_dtype, device=self.device),
"encoder_hidden_states": torch.randn(
batch_size, self.text_maxlen, self.config["text_embed_dim"], dtype=tensor_dtype, device=self.device
),
"padding_mask": torch.ones(
batch_size, 1, image_height, image_width, dtype=tensor_dtype, device=self.device
),
},
)
if self.pipeline_type.is_video2world():
sample_input[-1]["fps"] = torch.tensor([30] * batch_size, dtype=dtype, device=self.device)
sample_input[-1]["condition_mask"] = torch.randn(
batch_size,
1,
latent_frames,
latent_height,
latent_width,
dtype=tensor_dtype,
device=self.device,
)
return sample_input