ColabWan / models /kandinsky5 /kandinsky /generation_utils.py
1ripon1's picture
Upload folder using huggingface_hub
7344bef verified
Raw
History Blame Contribute Delete
20.4 kB
import os
os.environ["TOKENIZERS_PARALLELISM"] = "False"
import torch
from tqdm import tqdm
from .models.utils import fast_sta_nabla
import torchvision.transforms.functional as F
def get_sparse_params(conf, batch_embeds, device):
assert conf.model.dit_params.patch_size[0] == 1
T, H, W, _ = batch_embeds["visual"].shape
T, H, W = (
T // conf.model.dit_params.patch_size[0],
H // conf.model.dit_params.patch_size[1],
W // conf.model.dit_params.patch_size[2],
)
if conf.model.attention.type == "nabla":
sta_mask = fast_sta_nabla(T, H // 8, W // 8, conf.model.attention.wT,
conf.model.attention.wH, conf.model.attention.wW, device=device)
sparse_params = {
"sta_mask": sta_mask.unsqueeze_(0).unsqueeze_(0),
"attention_type": conf.model.attention.type,
"to_fractal": True,
"P": conf.model.attention.P,
"wT": conf.model.attention.wT,
"wW": conf.model.attention.wW,
"wH": conf.model.attention.wH,
"add_sta": conf.model.attention.add_sta,
"visual_shape": (T, H, W),
"method": getattr(conf.model.attention, "method", "topcdf"),
}
else:
sparse_params = None
return sparse_params
def adaptive_mean_std_normalization(source, reference):
source_mean = source.mean(dim=(1,2,3),keepdim=True)
source_std = source.std(dim=(1,2,3),keepdim=True)
#magic constants - limit changes in latents
clump_mean_low = 0.05
clump_mean_high = 0.1
clump_std_low = 0.1
clump_std_high = 0.25
reference_mean = torch.clamp(reference.mean(), source_mean - clump_mean_low, source_mean + clump_mean_high)
reference_std = torch.clamp(reference.std(), source_std - clump_std_low, source_std + clump_std_high)
# normalization
normalized = (source - source_mean) / source_std
normalized = normalized * reference_std + reference_mean
return normalized
def normalize_first_frame(latents, reference_frames=5, clump_values=False):
latents_copy = latents.clone()
samples = latents_copy
if samples.shape[0] <= 1:
return (latents, "Only one frame, no normalization needed")
nFr = 4
first_frames = samples[:nFr]
reference_frames_data = samples[nFr:nFr+min(reference_frames, samples.shape[0]-1)]
# print("First frame stats - Mean:", first_frames.mean(dim=(1,2,3)), "Std: ", first_frames.std(dim=(1,2,3)))
# print(f"Reference frames stats - Mean: {reference_frames_data.mean().item():.4f}, Std: {reference_frames_data.std().item():.4f}")
normalized_first = adaptive_mean_std_normalization(first_frames, reference_frames_data)
if clump_values:
min_val = reference_frames_data.min()
max_val = reference_frames_data.max()
normalized_first = torch.clamp(normalized_first, min_val, max_val)
samples[:nFr] = normalized_first
return samples
@torch.no_grad()
def get_velocity(
dit,
x,
t,
text_embeds,
null_text_embeds,
visual_rope_pos,
text_rope_pos,
null_text_rope_pos,
guidance_weight,
conf,
sparse_params=None,
attention_mask=None,
null_attention_mask=None,
joint_pass=False,
):
with torch._dynamo.utils.disable_cache_limit():
if joint_pass and abs(guidance_weight - 1.0) > 1e-6:
outputs = dit(
[x, x],
[text_embeds["text_embeds"], null_text_embeds["text_embeds"]],
[text_embeds["pooled_embed"], null_text_embeds["pooled_embed"]],
t * 1000,
[visual_rope_pos, visual_rope_pos],
[text_rope_pos, null_text_rope_pos],
scale_factor=[conf.metrics.scale_factor, conf.metrics.scale_factor],
sparse_params=[sparse_params, sparse_params],
attention_mask=[attention_mask, null_attention_mask],
)
if outputs is None:
return None
pred_velocity, uncond_pred_velocity = outputs
pred_velocity = uncond_pred_velocity + guidance_weight * (
pred_velocity - uncond_pred_velocity
)
else:
pred_velocity = dit(
x,
text_embeds["text_embeds"],
text_embeds["pooled_embed"],
t * 1000,
visual_rope_pos,
text_rope_pos,
scale_factor=conf.metrics.scale_factor,
sparse_params=sparse_params,
attention_mask=attention_mask,
)
if pred_velocity is None:
return None
if abs(guidance_weight - 1.0) > 1e-6:
uncond_pred_velocity = dit(
x,
null_text_embeds["text_embeds"],
null_text_embeds["pooled_embed"],
t * 1000,
visual_rope_pos,
null_text_rope_pos,
scale_factor=conf.metrics.scale_factor,
sparse_params=sparse_params,
attention_mask=null_attention_mask,
)
if uncond_pred_velocity is None:
return None
pred_velocity = uncond_pred_velocity + guidance_weight * (
pred_velocity - uncond_pred_velocity
)
return pred_velocity
@torch.no_grad()
def generate(
model,
device,
img,
num_steps,
text_embeds,
null_text_embeds,
visual_rope_pos,
text_rope_pos,
null_text_rope_pos,
guidance_weight,
scheduler_scale,
first_frames,
conf,
progress=False,
seed=6554,
attention_mask=None,
null_attention_mask=None,
callback=None,
interrupt_check=None,
joint_pass=False,
):
sparse_params = get_sparse_params(conf, {"visual": img}, device)
timesteps = torch.linspace(1, 0, num_steps + 1, device=device)
timesteps = scheduler_scale * timesteps / (1 + (scheduler_scale - 1) * timesteps)
if callback is not None:
callback(-1, None, True, override_num_inference_steps=num_steps)
step_iter = zip(timesteps[:-1], torch.diff(timesteps))
if progress:
step_iter = tqdm(step_iter, total=num_steps)
for step_idx, (timestep, timestep_diff) in enumerate(step_iter):
if interrupt_check is not None and interrupt_check():
return None
time = timestep.unsqueeze(0)
if model.visual_cond:
visual_cond = torch.zeros_like(img)
visual_cond_mask = torch.zeros(
[*img.shape[:-1], 1], dtype=img.dtype, device=img.device
)
if first_frames is not None:
first_frames = first_frames.to(device=visual_cond.device, dtype=visual_cond.dtype)
img[:1] = first_frames
visual_cond_mask[:1] = 1
model_input = torch.cat([img, visual_cond, visual_cond_mask], dim=-1)
else:
model_input = img
pred_velocity = get_velocity(
model,
model_input,
time,
text_embeds,
null_text_embeds,
visual_rope_pos,
text_rope_pos,
null_text_rope_pos,
guidance_weight,
conf,
sparse_params=sparse_params,
attention_mask=attention_mask,
null_attention_mask=null_attention_mask,
joint_pass=joint_pass,
)
if pred_velocity is None:
return None
img[..., :pred_velocity.shape[-1]] += timestep_diff * pred_velocity
if callback is not None:
latents_preview = None
if visual_rope_pos is not None and len(visual_rope_pos) > 0:
duration = int(visual_rope_pos[0].numel())
if duration > 0 and img.shape[0] % duration == 0:
batch = img.shape[0] // duration
latents_preview = (
img.reshape(batch, duration, img.shape[1], img.shape[2], img.shape[3])
.permute(0, 4, 1, 2, 3)
.detach()
)[0]
callback(step_idx, latents_preview, False)
# NOTE: remove extra channels that can be added in Image Editing (I2I)
return img[..., :pred_velocity.shape[-1]]
def resize_video(video, visual_size):
height, width = video.shape[-2:]
nearest_height, nearest_width = visual_size
scale_factor = min(height / nearest_height, width / nearest_width)
video = F.resize(video, (int(height / scale_factor), int(width / scale_factor)))
height, width = video.shape[-2:]
video = F.crop(
video,
(height - nearest_height) // 2,
(width - nearest_width) // 2,
nearest_height,
nearest_width,
)
return video
def encode_video(data, vae, image_vae): # batch, channels, time, h, w
if image_vae:
assert data.shape[2] == 1
data = vae.encode(data[:, :, 0]).latent_dist.sample()[:, :, None]
else:
data = vae.encode(data)[0]
data *= vae.config.scaling_factor
return data.permute(0, 2, 3, 4, 1) # batch, time, h, w, channels
def generate_sample(
shape,
caption,
dit,
vae,
conf,
text_embedder,
num_steps=25,
guidance_weight=5.0,
scheduler_scale=1,
negative_caption="",
seed=6554,
device="cuda",
vae_device="cuda",
text_embedder_device="cuda",
progress=True,
joint_pass=False,
callback=None,
interrupt_check=None,
):
bs, duration, height, width, dim = shape
g = torch.Generator(device="cuda")
g.manual_seed(seed)
img = torch.randn(bs * duration, height, width, dim, device=device, generator=g, dtype=torch.bfloat16)
if duration == 1:
type_of_content = "image"
else:
type_of_content = "video"
with torch.no_grad():
bs_text_embed, text_cu_seqlens, attention_mask = text_embedder.encode(
[caption], type_of_content=type_of_content
)
bs_null_text_embed, null_text_cu_seqlens, null_attention_mask = text_embedder.encode(
[negative_caption], type_of_content=type_of_content
)
for key in bs_text_embed:
bs_text_embed[key] = bs_text_embed[key].to(device=device)
bs_null_text_embed[key] = bs_null_text_embed[key].to(device=device)
if attention_mask is not None:
attention_mask = attention_mask.to(device=device)
if null_attention_mask is not None:
null_attention_mask = null_attention_mask.to(device=device)
text_cu_seqlens = text_cu_seqlens.to(device=device)[-1].item()
null_text_cu_seqlens = null_text_cu_seqlens.to(device=device)[-1].item()
visual_rope_pos = [
torch.arange(duration),
torch.arange(shape[-3] // conf.model.dit_params.patch_size[1]),
torch.arange(shape[-2] // conf.model.dit_params.patch_size[2]),
]
text_rope_pos = torch.arange(text_cu_seqlens)
null_text_rope_pos = torch.arange(null_text_cu_seqlens)
with torch.no_grad():
with torch.autocast(device_type="cuda", dtype=torch.bfloat16):
latent_visual = generate(
dit,
device,
img,
num_steps,
bs_text_embed,
bs_null_text_embed,
visual_rope_pos,
text_rope_pos,
null_text_rope_pos,
guidance_weight,
scheduler_scale,
None,
conf,
seed=seed,
progress=progress,
attention_mask=attention_mask,
null_attention_mask=null_attention_mask,
callback=callback,
interrupt_check=interrupt_check,
joint_pass=joint_pass,
)
if latent_visual is None:
return None
with torch.no_grad():
with torch.autocast(device_type="cuda", dtype=torch.bfloat16):
images = latent_visual.reshape(
bs,
-1,
latent_visual.shape[-3],
latent_visual.shape[-2],
latent_visual.shape[-1],
)
images = images.to(device=vae_device)
images = (images / vae.config.scaling_factor).permute(0, 4, 1, 2, 3)
images = vae.decode(images).sample
images = ((images.clamp(-1.0, 1.0) + 1.0) * 127.5).to(torch.uint8)
return images
def generate_sample_ti2i(
shape,
caption,
dit,
vae,
conf,
text_embedder,
num_steps=25,
guidance_weight=5.0,
scheduler_scale=1,
negative_caption="",
seed=6554,
device="cuda",
vae_device="cuda",
text_embedder_device="cuda",
progress=True,
image_vae=False,
image=None,
joint_pass=False,
callback=None,
interrupt_check=None
):
bs, duration, height, width, dim = shape
g = torch.Generator(device="cuda")
g.manual_seed(seed)
img = torch.randn(bs * duration, height, width, dim, device=device, generator=g, dtype=torch.bfloat16)
if duration == 1:
if image is None:
type_of_content = "image"
else:
type_of_content = 'image_edit'
else:
type_of_content = "video"
if image is not None:
image = [resize_video(image, (height * 8, width * 8))]
if dit.instruct_type == 'channel':
if image is not None:
edit_latent = [(i.to(device=vae_device, dtype=torch.bfloat16) / 127.5 - 1.0) for i in image]
edit_latent = torch.cat([encode_video(i[:,:,None], vae, image_vae).squeeze(0) for i in edit_latent], 0)
edit_latent = torch.cat([edit_latent, torch.ones_like(img[...,:1])],-1)
else:
edit_latent = torch.cat([torch.zeros_like(img), torch.zeros_like(img[...,:1])],-1)
img = torch.cat([img, edit_latent],dim=-1)
with torch.no_grad():
bs_text_embed, text_cu_seqlens, attention_mask = text_embedder.encode(
[caption], type_of_content=type_of_content, images=image
)
bs_null_text_embed, null_text_cu_seqlens, null_attention_mask = text_embedder.encode(
[negative_caption], type_of_content=type_of_content, images=image
)
for key in bs_text_embed:
bs_text_embed[key] = bs_text_embed[key].to(device=device,dtype=torch.bfloat16)
bs_null_text_embed[key] = bs_null_text_embed[key].to(device=device,dtype=torch.bfloat16)
if attention_mask is not None:
attention_mask = attention_mask.to(device=device)
if null_attention_mask is not None:
null_attention_mask = null_attention_mask.to(device=device)
text_cu_seqlens = text_cu_seqlens.to(device=device)[-1].item()
null_text_cu_seqlens = null_text_cu_seqlens.to(device=device)[-1].item()
visual_rope_pos = [
torch.arange(duration),
torch.arange(shape[-3] // conf.model.dit_params.patch_size[1]),
torch.arange(shape[-2] // conf.model.dit_params.patch_size[2]),
]
text_rope_pos = torch.arange(text_cu_seqlens)
null_text_rope_pos = torch.arange(null_text_cu_seqlens)
with torch.no_grad():
with torch.autocast(device_type="cuda", dtype=torch.bfloat16):
latent_visual = generate(
dit,
device,
img,
num_steps,
bs_text_embed,
bs_null_text_embed,
visual_rope_pos,
text_rope_pos,
null_text_rope_pos,
guidance_weight,
scheduler_scale,
None,
conf,
seed=seed,
progress=progress,
attention_mask=attention_mask,
null_attention_mask=null_attention_mask,
callback=callback,
interrupt_check=interrupt_check,
joint_pass=joint_pass,
)
if latent_visual is None:
return None
with torch.no_grad():
with torch.autocast(device_type="cuda", dtype=torch.bfloat16):
images = latent_visual.reshape(
bs,
-1,
latent_visual.shape[-3],
latent_visual.shape[-2],
latent_visual.shape[-1],
)
images = images.to(device=vae_device)
images = (images / vae.config.scaling_factor).permute(0, 4, 1, 2, 3)
if image_vae:
images = images[:,:,0]
images = vae.decode(images).sample
images = ((images.clamp(-1.0, 1.0) + 1.0) * 127.5).to(torch.uint8)
return images
def generate_sample_i2v(
shape,
caption,
dit,
vae,
conf,
text_embedder,
images,
num_steps=50,
guidance_weight=5.0,
scheduler_scale=1,
negative_caption="",
seed=6554,
device="cuda",
vae_device="cuda",
progress=True,
callback=None,
joint_pass=False,
interrupt_check=None
):
text_embedder.embedder.mode = "i2v"
bs, duration, height, width, dim = shape
g = torch.Generator(device="cuda")
g.manual_seed(seed)
img = torch.randn(bs * duration, height, width, dim, device=device, generator=g, dtype=torch.bfloat16)
if duration == 1:
type_of_content = "image"
else:
type_of_content = "video"
with torch.no_grad():
bs_text_embed, text_cu_seqlens, attention_mask = text_embedder.encode(
[caption], type_of_content=type_of_content
)
bs_null_text_embed, null_text_cu_seqlens, null_attention_mask = text_embedder.encode(
[negative_caption], type_of_content=type_of_content
)
for key in bs_text_embed:
bs_text_embed[key] = bs_text_embed[key].to(device=device)
bs_null_text_embed[key] = bs_null_text_embed[key].to(device=device)
if attention_mask is not None:
attention_mask = attention_mask.to(device=device)
if null_attention_mask is not None:
null_attention_mask = null_attention_mask.to(device=device)
text_cu_seqlens = text_cu_seqlens.to(device=device)[-1].item()
null_text_cu_seqlens = null_text_cu_seqlens.to(device=device)[-1].item()
visual_rope_pos = [
torch.arange(duration),
torch.arange(shape[-3] // conf.model.dit_params.patch_size[1]),
torch.arange(shape[-2] // conf.model.dit_params.patch_size[2]),
]
text_rope_pos = torch.arange(text_cu_seqlens)
null_text_rope_pos = torch.arange(null_text_cu_seqlens)
first_frames = images
with torch.no_grad():
with torch.autocast(device_type="cuda", dtype=torch.bfloat16):
latent_visual = generate(
dit,
device,
img,
num_steps,
bs_text_embed,
bs_null_text_embed,
visual_rope_pos,
text_rope_pos,
null_text_rope_pos,
guidance_weight,
scheduler_scale,
first_frames,
conf,
seed=seed,
progress=progress,
attention_mask=attention_mask,
null_attention_mask=null_attention_mask,
callback=callback,
interrupt_check=interrupt_check,
joint_pass=joint_pass,
)
if latent_visual is None:
return None
if images is not None:
images = images.to(device=latent_visual.device, dtype=latent_visual.dtype)
latent_visual[:1] = images
latent_visual = normalize_first_frame(latent_visual)
with torch.no_grad():
with torch.autocast(device_type="cuda", dtype=torch.bfloat16):
images = latent_visual.reshape(
bs,
-1,
latent_visual.shape[-3],
latent_visual.shape[-2],
latent_visual.shape[-1],
)
images = images.to(device=vae_device)
images = (images / vae.config.scaling_factor).permute(0, 4, 1, 2, 3)
images = vae.decode(images).sample
images = ((images.clamp(-1.0, 1.0) + 1.0) * 127.5).to(torch.uint8)
return images