diff --git a/comfy/clip_config_bigg.json b/comfy/clip_config_bigg.json index 32d82ff39..35261deef 100644 --- a/comfy/clip_config_bigg.json +++ b/comfy/clip_config_bigg.json @@ -5,7 +5,7 @@ "attention_dropout": 0.0, "bos_token_id": 0, "dropout": 0.0, - "eos_token_id": 2, + "eos_token_id": 49407, "hidden_act": "gelu", "hidden_size": 1280, "initializer_factor": 1.0, diff --git a/comfy/clip_model.py b/comfy/clip_model.py index 14f43c568..3c67b737a 100644 --- a/comfy/clip_model.py +++ b/comfy/clip_model.py @@ -1,5 +1,6 @@ import torch from comfy.ldm.modules.attention import optimized_attention_for_device +import comfy.ops class CLIPAttention(torch.nn.Module): def __init__(self, embed_dim, heads, dtype, device, operations): @@ -71,13 +72,13 @@ class CLIPEncoder(torch.nn.Module): return x, intermediate class CLIPEmbeddings(torch.nn.Module): - def __init__(self, embed_dim, vocab_size=49408, num_positions=77, dtype=None, device=None): + def __init__(self, embed_dim, vocab_size=49408, num_positions=77, dtype=None, device=None, operations=None): super().__init__() - self.token_embedding = torch.nn.Embedding(vocab_size, embed_dim, dtype=dtype, device=device) - self.position_embedding = torch.nn.Embedding(num_positions, embed_dim, dtype=dtype, device=device) + self.token_embedding = operations.Embedding(vocab_size, embed_dim, dtype=dtype, device=device) + self.position_embedding = operations.Embedding(num_positions, embed_dim, dtype=dtype, device=device) - def forward(self, input_tokens): - return self.token_embedding(input_tokens) + self.position_embedding.weight + def forward(self, input_tokens, dtype=torch.float32): + return self.token_embedding(input_tokens, out_dtype=dtype) + comfy.ops.cast_to(self.position_embedding.weight, dtype=dtype, device=input_tokens.device) class CLIPTextModel_(torch.nn.Module): @@ -87,14 +88,15 @@ class CLIPTextModel_(torch.nn.Module): heads = config_dict["num_attention_heads"] intermediate_size = config_dict["intermediate_size"] intermediate_activation = config_dict["hidden_act"] + self.eos_token_id = config_dict["eos_token_id"] super().__init__() - self.embeddings = CLIPEmbeddings(embed_dim, dtype=torch.float32, device=device) + self.embeddings = CLIPEmbeddings(embed_dim, dtype=dtype, device=device, operations=operations) self.encoder = CLIPEncoder(num_layers, embed_dim, heads, intermediate_size, intermediate_activation, dtype, device, operations) self.final_layer_norm = operations.LayerNorm(embed_dim, dtype=dtype, device=device) - def forward(self, input_tokens, attention_mask=None, intermediate_output=None, final_layer_norm_intermediate=True): - x = self.embeddings(input_tokens) + def forward(self, input_tokens, attention_mask=None, intermediate_output=None, final_layer_norm_intermediate=True, dtype=torch.float32): + x = self.embeddings(input_tokens, dtype=dtype) mask = None if attention_mask is not None: mask = 1.0 - attention_mask.to(x.dtype).reshape((attention_mask.shape[0], 1, -1, attention_mask.shape[-1])).expand(attention_mask.shape[0], 1, attention_mask.shape[-1], attention_mask.shape[-1]) @@ -111,7 +113,7 @@ class CLIPTextModel_(torch.nn.Module): if i is not None and final_layer_norm_intermediate: i = self.final_layer_norm(i) - pooled_output = x[torch.arange(x.shape[0], device=x.device), input_tokens.to(dtype=torch.int, device=x.device).argmax(dim=-1),] + pooled_output = x[torch.arange(x.shape[0], device=x.device), (torch.round(input_tokens).to(dtype=torch.int, device=x.device) == self.eos_token_id).int().argmax(dim=-1),] return x, i, pooled_output class CLIPTextModel(torch.nn.Module): @@ -153,11 +155,11 @@ class CLIPVisionEmbeddings(torch.nn.Module): num_patches = (image_size // patch_size) ** 2 num_positions = num_patches + 1 - self.position_embedding = torch.nn.Embedding(num_positions, embed_dim, dtype=dtype, device=device) + self.position_embedding = operations.Embedding(num_positions, embed_dim, dtype=dtype, device=device) def forward(self, pixel_values): embeds = self.patch_embedding(pixel_values).flatten(2).transpose(1, 2) - return torch.cat([self.class_embedding.to(embeds.device).expand(pixel_values.shape[0], 1, -1), embeds], dim=1) + self.position_embedding.weight.to(embeds.device) + return torch.cat([comfy.ops.cast_to_input(self.class_embedding, embeds).expand(pixel_values.shape[0], 1, -1), embeds], dim=1) + comfy.ops.cast_to_input(self.position_embedding.weight, embeds) class CLIPVision(torch.nn.Module): @@ -169,7 +171,7 @@ class CLIPVision(torch.nn.Module): intermediate_size = config_dict["intermediate_size"] intermediate_activation = config_dict["hidden_act"] - self.embeddings = CLIPVisionEmbeddings(embed_dim, config_dict["num_channels"], config_dict["patch_size"], config_dict["image_size"], dtype=torch.float32, device=device, operations=operations) + self.embeddings = CLIPVisionEmbeddings(embed_dim, config_dict["num_channels"], config_dict["patch_size"], config_dict["image_size"], dtype=dtype, device=device, operations=operations) self.pre_layrnorm = operations.LayerNorm(embed_dim) self.encoder = CLIPEncoder(num_layers, embed_dim, heads, intermediate_size, intermediate_activation, dtype, device, operations) self.post_layernorm = operations.LayerNorm(embed_dim) diff --git a/comfy/ldm/audio/dit.py b/comfy/ldm/audio/dit.py index 1c1112c5e..4d2185be8 100644 --- a/comfy/ldm/audio/dit.py +++ b/comfy/ldm/audio/dit.py @@ -9,6 +9,7 @@ from einops import rearrange from torch import nn from torch.nn import functional as F import math +import comfy.ops class FourierFeatures(nn.Module): def __init__(self, in_features, out_features, std=1., dtype=None, device=None): @@ -18,7 +19,7 @@ class FourierFeatures(nn.Module): [out_features // 2, in_features], dtype=dtype, device=device)) def forward(self, input): - f = 2 * math.pi * input @ self.weight.T.to(dtype=input.dtype, device=input.device) + f = 2 * math.pi * input @ comfy.ops.cast_to_input(self.weight.T, input) return torch.cat([f.cos(), f.sin()], dim=-1) # norms @@ -38,9 +39,9 @@ class LayerNorm(nn.Module): def forward(self, x): beta = self.beta - if self.beta is not None: - beta = beta.to(dtype=x.dtype, device=x.device) - return F.layer_norm(x, x.shape[-1:], weight=self.gamma.to(dtype=x.dtype, device=x.device), bias=beta) + if beta is not None: + beta = comfy.ops.cast_to_input(beta, x) + return F.layer_norm(x, x.shape[-1:], weight=comfy.ops.cast_to_input(self.gamma, x), bias=beta) class GLU(nn.Module): def __init__( @@ -123,7 +124,9 @@ class RotaryEmbedding(nn.Module): scale_base = 512, interpolation_factor = 1., base = 10000, - base_rescale_factor = 1. + base_rescale_factor = 1., + dtype=None, + device=None, ): super().__init__() # proposed by reddit user bloc97, to rescale rotary embeddings to longer sequence length without fine-tuning @@ -131,8 +134,8 @@ class RotaryEmbedding(nn.Module): # https://www.reddit.com/r/LocalLLaMA/comments/14lz7j5/ntkaware_scaled_rope_allows_llama_models_to_have/ base *= base_rescale_factor ** (dim / (dim - 2)) - inv_freq = 1. / (base ** (torch.arange(0, dim, 2).float() / dim)) - self.register_buffer('inv_freq', inv_freq) + # inv_freq = 1. / (base ** (torch.arange(0, dim, 2).float() / dim)) + self.register_buffer('inv_freq', torch.empty((dim // 2,), device=device, dtype=dtype)) assert interpolation_factor >= 1. self.interpolation_factor = interpolation_factor @@ -161,14 +164,14 @@ class RotaryEmbedding(nn.Module): t = t / self.interpolation_factor - freqs = torch.einsum('i , j -> i j', t, self.inv_freq.to(dtype=dtype, device=device)) + freqs = torch.einsum('i , j -> i j', t, comfy.ops.cast_to_input(self.inv_freq, t)) freqs = torch.cat((freqs, freqs), dim = -1) if self.scale is None: return freqs, 1. power = (torch.arange(seq_len, device = device) - (seq_len // 2)) / self.scale_base - scale = self.scale.to(dtype=dtype, device=device) ** rearrange(power, 'n -> n 1') + scale = comfy.ops.cast_to_input(self.scale, t) ** rearrange(power, 'n -> n 1') scale = torch.cat((scale, scale), dim = -1) return freqs, scale @@ -568,7 +571,7 @@ class ContinuousTransformer(nn.Module): self.project_out = operations.Linear(dim, dim_out, bias=False, dtype=dtype, device=device) if dim_out is not None else nn.Identity() if rotary_pos_emb: - self.rotary_pos_emb = RotaryEmbedding(max(dim_heads // 2, 32)) + self.rotary_pos_emb = RotaryEmbedding(max(dim_heads // 2, 32), device=device, dtype=dtype) else: self.rotary_pos_emb = None diff --git a/comfy/ldm/aura/mmdit.py b/comfy/ldm/aura/mmdit.py index c465619bd..9956d3638 100644 --- a/comfy/ldm/aura/mmdit.py +++ b/comfy/ldm/aura/mmdit.py @@ -8,6 +8,7 @@ import torch.nn as nn import torch.nn.functional as F from comfy.ldm.modules.attention import optimized_attention +import comfy.ops def modulate(x, shift, scale): return x * (1 + scale.unsqueeze(1)) + shift.unsqueeze(1) @@ -409,7 +410,7 @@ class MMDiT(nn.Module): pad_h = (self.patch_size - H % self.patch_size) % self.patch_size pad_w = (self.patch_size - W % self.patch_size) % self.patch_size - x = torch.nn.functional.pad(x, (0, pad_w, 0, pad_h), mode='reflect') + x = torch.nn.functional.pad(x, (0, pad_w, 0, pad_h), mode='circular') x = x.view( B, C, @@ -427,7 +428,7 @@ class MMDiT(nn.Module): max_dim = max(h, w) cur_dim = self.h_max - pos_encoding = self.positional_encoding.reshape(1, cur_dim, cur_dim, -1).to(device=x.device, dtype=x.dtype) + pos_encoding = comfy.ops.cast_to_input(self.positional_encoding.reshape(1, cur_dim, cur_dim, -1), x) if max_dim > cur_dim: pos_encoding = F.interpolate(pos_encoding.movedim(-1, 1), (max_dim, max_dim), mode="bilinear").movedim(1, -1) @@ -455,7 +456,7 @@ class MMDiT(nn.Module): t = timestep c = self.cond_seq_linear(c_seq) # B, T_c, D - c = torch.cat([self.register_tokens.to(device=c.device, dtype=c.dtype).repeat(c.size(0), 1, 1), c], dim=1) + c = torch.cat([comfy.ops.cast_to_input(self.register_tokens, c).repeat(c.size(0), 1, 1), c], dim=1) global_cond = self.t_embedder(t, x.dtype) # B, D diff --git a/comfy/ldm/cascade/common.py b/comfy/ldm/cascade/common.py index 124902c09..3eaa0c821 100644 --- a/comfy/ldm/cascade/common.py +++ b/comfy/ldm/cascade/common.py @@ -19,14 +19,7 @@ import torch import torch.nn as nn from comfy.ldm.modules.attention import optimized_attention - -class Linear(torch.nn.Linear): - def reset_parameters(self): - return None - -class Conv2d(torch.nn.Conv2d): - def reset_parameters(self): - return None +import comfy.ops class OptimizedAttention(nn.Module): def __init__(self, c, nhead, dropout=0.0, dtype=None, device=None, operations=None): @@ -78,13 +71,13 @@ class GlobalResponseNorm(nn.Module): "from https://github.com/facebookresearch/ConvNeXt-V2/blob/3608f67cc1dae164790c5d0aead7bf2d73d9719b/models/utils.py#L105" def __init__(self, dim, dtype=None, device=None): super().__init__() - self.gamma = nn.Parameter(torch.zeros(1, 1, 1, dim, dtype=dtype, device=device)) - self.beta = nn.Parameter(torch.zeros(1, 1, 1, dim, dtype=dtype, device=device)) + self.gamma = nn.Parameter(torch.empty(1, 1, 1, dim, dtype=dtype, device=device)) + self.beta = nn.Parameter(torch.empty(1, 1, 1, dim, dtype=dtype, device=device)) def forward(self, x): Gx = torch.norm(x, p=2, dim=(1, 2), keepdim=True) Nx = Gx / (Gx.mean(dim=-1, keepdim=True) + 1e-6) - return self.gamma.to(device=x.device, dtype=x.dtype) * (x * Nx) + self.beta.to(device=x.device, dtype=x.dtype) + x + return comfy.ops.cast_to_input(self.gamma, x) * (x * Nx) + comfy.ops.cast_to_input(self.beta, x) + x class ResBlock(nn.Module): diff --git a/comfy/ldm/hydit/models.py b/comfy/ldm/hydit/models.py index bde9687e2..c70dbf92a 100644 --- a/comfy/ldm/hydit/models.py +++ b/comfy/ldm/hydit/models.py @@ -4,6 +4,7 @@ import torch import torch.nn as nn import torch.nn.functional as F +import comfy.ops from comfy.ldm.modules.diffusionmodules.mmdit import Mlp, TimestepEmbedder, PatchEmbed, RMSNorm from comfy.ldm.modules.diffusionmodules.util import timestep_embedding from torch.utils import checkpoint @@ -234,7 +235,7 @@ class HunYuanDiT(nn.Module): if self.use_style_cond: # Here we use a default learned embedder layer for future extension. - self.style_embedder = nn.Embedding(1, hidden_size, dtype=dtype, device=device) + self.style_embedder = operations.Embedding(1, hidden_size, dtype=dtype, device=device) self.extra_in_dim += hidden_size # Text embedding for `add` @@ -321,7 +322,7 @@ class HunYuanDiT(nn.Module): b_t5, l_t5, c_t5 = text_states_t5.shape text_states_t5 = self.mlp_t5(text_states_t5.view(-1, c_t5)).view(b_t5, l_t5, -1) - padding = self.text_embedding_padding.to(text_states) + padding = comfy.ops.cast_to_input(self.text_embedding_padding, text_states) text_states[:,-self.text_len:] = torch.where(text_states_mask[:,-self.text_len:].unsqueeze(2), text_states[:,-self.text_len:], padding[:self.text_len]) text_states_t5[:,-self.text_len_t5:] = torch.where(text_states_t5_mask[:,-self.text_len_t5:].unsqueeze(2), text_states_t5[:,-self.text_len_t5:], padding[self.text_len:]) @@ -354,7 +355,7 @@ class HunYuanDiT(nn.Module): if self.use_style_cond: if style is None: style = torch.zeros((extra_vec.shape[0],), device=x.device, dtype=torch.int) - style_embedding = self.style_embedder(style) + style_embedding = self.style_embedder(style, out_dtype=x.dtype) extra_vec = torch.cat([extra_vec, style_embedding], dim=1) # Concatenate all extra vectors diff --git a/comfy/ldm/hydit/poolers.py b/comfy/ldm/hydit/poolers.py index 2c6e46e67..f5e5b406f 100644 --- a/comfy/ldm/hydit/poolers.py +++ b/comfy/ldm/hydit/poolers.py @@ -1,8 +1,8 @@ import torch import torch.nn as nn import torch.nn.functional as F -from comfy.ldm.modules.attention import optimized_attention #TODO - +from comfy.ldm.modules.attention import optimized_attention +import comfy.ops class AttentionPool(nn.Module): def __init__(self, spacial_dim: int, embed_dim: int, num_heads: int, output_dim: int = None, dtype=None, device=None, operations=None): @@ -19,7 +19,7 @@ class AttentionPool(nn.Module): x = x[:,:self.positional_embedding.shape[0] - 1] x = x.permute(1, 0, 2) # NLC -> LNC x = torch.cat([x.mean(dim=0, keepdim=True), x], dim=0) # (L+1)NC - x = x + self.positional_embedding[:, None, :].to(dtype=x.dtype, device=x.device) # (L+1)NC + x = x + comfy.ops.cast_to_input(self.positional_embedding[:, None, :], x) # (L+1)NC q = self.q_proj(x[:1]) k = self.k_proj(x) diff --git a/comfy/ldm/modules/diffusionmodules/mmdit.py b/comfy/ldm/modules/diffusionmodules/mmdit.py index f37f7ff77..ea1b5aa05 100644 --- a/comfy/ldm/modules/diffusionmodules/mmdit.py +++ b/comfy/ldm/modules/diffusionmodules/mmdit.py @@ -8,6 +8,7 @@ import torch.nn as nn from .. import attention from einops import rearrange, repeat from .util import timestep_embedding +import comfy.ops def default(x, y): if x is not None: @@ -69,12 +70,14 @@ class PatchEmbed(nn.Module): bias: bool = True, strict_img_size: bool = True, dynamic_img_pad: bool = True, + padding_mode='circular', dtype=None, device=None, operations=None, ): super().__init__() self.patch_size = (patch_size, patch_size) + self.padding_mode = padding_mode if img_size is not None: self.img_size = (img_size, img_size) self.grid_size = tuple([s // p for s, p in zip(self.img_size, self.patch_size)]) @@ -110,7 +113,7 @@ class PatchEmbed(nn.Module): if self.dynamic_img_pad: pad_h = (self.patch_size[0] - H % self.patch_size[0]) % self.patch_size[0] pad_w = (self.patch_size[1] - W % self.patch_size[1]) % self.patch_size[1] - x = torch.nn.functional.pad(x, (0, pad_w, 0, pad_h), mode='reflect') + x = torch.nn.functional.pad(x, (0, pad_w, 0, pad_h), mode=self.padding_mode) x = self.proj(x) if self.flatten: x = x.flatten(2).transpose(1, 2) # NCHW -> NLC @@ -924,7 +927,7 @@ class MMDiT(nn.Module): context = self.context_processor(context) hw = x.shape[-2:] - x = self.x_embedder(x) + self.cropped_pos_embed(hw, device=x.device).to(dtype=x.dtype, device=x.device) + x = self.x_embedder(x) + comfy.ops.cast_to_input(self.cropped_pos_embed(hw, device=x.device), x) c = self.t_embedder(t, dtype=x.dtype) # (N, D) if y is not None and self.y_embedder is not None: y = self.y_embedder(y) # (N, D) diff --git a/comfy/ldm/modules/diffusionmodules/openaimodel.py b/comfy/ldm/modules/diffusionmodules/openaimodel.py index ba8fc2c4a..6535e899c 100644 --- a/comfy/ldm/modules/diffusionmodules/openaimodel.py +++ b/comfy/ldm/modules/diffusionmodules/openaimodel.py @@ -809,7 +809,7 @@ class UNetModel(nn.Module): self.out = nn.Sequential( operations.GroupNorm(32, ch, dtype=self.dtype, device=device), nn.SiLU(), - zero_module(operations.conv_nd(dims, model_channels, out_channels, 3, padding=1, dtype=self.dtype, device=device)), + operations.conv_nd(dims, model_channels, out_channels, 3, padding=1, dtype=self.dtype, device=device), ) if self.predict_codebook_ids: self.id_predictor = nn.Sequential( diff --git a/comfy/ops.py b/comfy/ops.py index 0f1ceb574..47e8d7a9d 100644 --- a/comfy/ops.py +++ b/comfy/ops.py @@ -19,14 +19,27 @@ import torch import comfy.model_management -def cast_bias_weight(s, input): + +def cast_to(weight, dtype=None, device=None, non_blocking=False): + return weight.to(device=device, dtype=dtype, non_blocking=non_blocking) + +def cast_to_input(weight, input, non_blocking=False): + return cast_to(weight, input.dtype, input.device, non_blocking=non_blocking) + +def cast_bias_weight(s, input=None, dtype=None, device=None): + if input is not None: + if dtype is None: + dtype = input.dtype + if device is None: + device = input.device + bias = None - non_blocking = comfy.model_management.device_should_use_non_blocking(input.device) + non_blocking = comfy.model_management.device_should_use_non_blocking(device) if s.bias is not None: - bias = s.bias.to(device=input.device, dtype=input.dtype, non_blocking=non_blocking) + bias = cast_to(s.bias, dtype, device, non_blocking=non_blocking) if s.bias_function is not None: bias = s.bias_function(bias) - weight = s.weight.to(device=input.device, dtype=input.dtype, non_blocking=non_blocking) + weight = cast_to(s.weight, dtype, device, non_blocking=non_blocking) if s.weight_function is not None: weight = s.weight_function(weight) return weight, bias @@ -168,6 +181,26 @@ class disable_weight_init: else: return super().forward(*args, **kwargs) + class Embedding(torch.nn.Embedding, CastWeightBiasOp): + def reset_parameters(self): + self.bias = None + return None + + def forward_comfy_cast_weights(self, input, out_dtype=None): + output_dtype = out_dtype + if self.weight.dtype == torch.float16 or self.weight.dtype == torch.bfloat16: + out_dtype = None + weight, bias = cast_bias_weight(self, device=input.device, dtype=out_dtype) + return torch.nn.functional.embedding(input, weight, self.padding_idx, self.max_norm, self.norm_type, self.scale_grad_by_freq, self.sparse).to(dtype=output_dtype) + + def forward(self, *args, **kwargs): + if self.comfy_cast_weights: + return self.forward_comfy_cast_weights(*args, **kwargs) + else: + if "out_dtype" in kwargs: + kwargs.pop("out_dtype") + return super().forward(*args, **kwargs) + @classmethod def conv_nd(s, dims, *args, **kwargs): if dims == 2: @@ -202,3 +235,6 @@ class manual_cast(disable_weight_init): class ConvTranspose1d(disable_weight_init.ConvTranspose1d): comfy_cast_weights = True + + class Embedding(disable_weight_init.Embedding): + comfy_cast_weights = True diff --git a/comfy/sd1_clip.py b/comfy/sd1_clip.py index c7bc1e4dc..d32121d1b 100644 --- a/comfy/sd1_clip.py +++ b/comfy/sd1_clip.py @@ -94,7 +94,8 @@ class SDClipModel(torch.nn.Module, ClipTokenWeightEncoder): with open(textmodel_json_config) as f: config = json.load(f) - self.transformer = model_class(config, dtype, device, comfy.ops.manual_cast) + self.operations = comfy.ops.manual_cast + self.transformer = model_class(config, dtype, device, self.operations) self.num_layers = self.transformer.num_layers self.max_length = max_length @@ -140,15 +141,13 @@ class SDClipModel(torch.nn.Module, ClipTokenWeightEncoder): def set_up_textual_embeddings(self, tokens, current_embeds): out_tokens = [] - next_new_token = token_dict_size = current_embeds.weight.shape[0] - 1 + next_new_token = token_dict_size = current_embeds.weight.shape[0] embedding_weights = [] for x in tokens: tokens_temp = [] for y in x: if isinstance(y, numbers.Integral): - if y == token_dict_size: #EOS token - y = -1 tokens_temp += [int(y)] else: if y.shape[0] == current_embeds.weight.shape[1]: @@ -163,12 +162,11 @@ class SDClipModel(torch.nn.Module, ClipTokenWeightEncoder): n = token_dict_size if len(embedding_weights) > 0: - new_embedding = torch.nn.Embedding(next_new_token + 1, current_embeds.weight.shape[1], device=current_embeds.weight.device, dtype=current_embeds.weight.dtype) - new_embedding.weight[:token_dict_size] = current_embeds.weight[:-1] + new_embedding = self.operations.Embedding(next_new_token + 1, current_embeds.weight.shape[1], device=current_embeds.weight.device, dtype=current_embeds.weight.dtype) + new_embedding.weight[:token_dict_size] = current_embeds.weight for x in embedding_weights: new_embedding.weight[n] = x n += 1 - new_embedding.weight[n] = current_embeds.weight[-1] #EOS embedding self.transformer.set_input_embeddings(new_embedding) processed_tokens = [] @@ -197,7 +195,7 @@ class SDClipModel(torch.nn.Module, ClipTokenWeightEncoder): if self.enable_attention_masks: attention_mask_model = attention_mask - outputs = self.transformer(tokens, attention_mask_model, intermediate_output=self.layer_idx, final_layer_norm_intermediate=self.layer_norm_hidden_state) + outputs = self.transformer(tokens, attention_mask_model, intermediate_output=self.layer_idx, final_layer_norm_intermediate=self.layer_norm_hidden_state, dtype=torch.float32) self.transformer.set_input_embeddings(backup_embeds) if self.layer == "last": diff --git a/comfy/sd1_clip_config.json b/comfy/sd1_clip_config.json index 0158a1fd5..3ba8c6b5b 100644 --- a/comfy/sd1_clip_config.json +++ b/comfy/sd1_clip_config.json @@ -6,7 +6,7 @@ "attention_dropout": 0.0, "bos_token_id": 0, "dropout": 0.0, - "eos_token_id": 2, + "eos_token_id": 49407, "hidden_act": "quick_gelu", "hidden_size": 768, "initializer_factor": 1.0, diff --git a/comfy/text_encoders/bert.py b/comfy/text_encoders/bert.py index b76e76660..fc9bac1d2 100644 --- a/comfy/text_encoders/bert.py +++ b/comfy/text_encoders/bert.py @@ -1,5 +1,6 @@ import torch from comfy.ldm.modules.attention import optimized_attention_for_device +import comfy.ops class BertAttention(torch.nn.Module): def __init__(self, embed_dim, heads, dtype, device, operations): @@ -86,19 +87,19 @@ class BertEncoder(torch.nn.Module): class BertEmbeddings(torch.nn.Module): def __init__(self, vocab_size, max_position_embeddings, type_vocab_size, pad_token_id, embed_dim, layer_norm_eps, dtype, device, operations): super().__init__() - self.word_embeddings = torch.nn.Embedding(vocab_size, embed_dim, padding_idx=pad_token_id, dtype=dtype, device=device) - self.position_embeddings = torch.nn.Embedding(max_position_embeddings, embed_dim, dtype=dtype, device=device) - self.token_type_embeddings = torch.nn.Embedding(type_vocab_size, embed_dim, dtype=dtype, device=device) + self.word_embeddings = operations.Embedding(vocab_size, embed_dim, padding_idx=pad_token_id, dtype=dtype, device=device) + self.position_embeddings = operations.Embedding(max_position_embeddings, embed_dim, dtype=dtype, device=device) + self.token_type_embeddings = operations.Embedding(type_vocab_size, embed_dim, dtype=dtype, device=device) self.LayerNorm = operations.LayerNorm(embed_dim, eps=layer_norm_eps, dtype=dtype, device=device) - def forward(self, input_tokens, token_type_ids=None): - x = self.word_embeddings(input_tokens) - x += self.position_embeddings.weight[:x.shape[1]] + def forward(self, input_tokens, token_type_ids=None, dtype=None): + x = self.word_embeddings(input_tokens, out_dtype=dtype) + x += comfy.ops.cast_to_input(self.position_embeddings.weight[:x.shape[1]], x) if token_type_ids is not None: - x += self.token_type_embeddings(token_type_ids) + x += self.token_type_embeddings(token_type_ids, out_dtype=x.dtype) else: - x += self.token_type_embeddings.weight[0] + x += comfy.ops.cast_to_input(self.token_type_embeddings.weight[0], x) x = self.LayerNorm(x) return x @@ -112,8 +113,8 @@ class BertModel_(torch.nn.Module): self.embeddings = BertEmbeddings(config_dict["vocab_size"], config_dict["max_position_embeddings"], config_dict["type_vocab_size"], config_dict["pad_token_id"], embed_dim, layer_norm_eps, dtype, device, operations) self.encoder = BertEncoder(config_dict["num_hidden_layers"], embed_dim, config_dict["intermediate_size"], config_dict["num_attention_heads"], layer_norm_eps, dtype, device, operations) - def forward(self, input_tokens, attention_mask=None, intermediate_output=None, final_layer_norm_intermediate=True): - x = self.embeddings(input_tokens) + def forward(self, input_tokens, attention_mask=None, intermediate_output=None, final_layer_norm_intermediate=True, dtype=None): + x = self.embeddings(input_tokens, dtype=dtype) mask = None if attention_mask is not None: mask = 1.0 - attention_mask.to(x.dtype).reshape((attention_mask.shape[0], 1, -1, attention_mask.shape[-1])).expand(attention_mask.shape[0], 1, attention_mask.shape[-1], attention_mask.shape[-1]) diff --git a/comfy/text_encoders/hydit.py b/comfy/text_encoders/hydit.py index ac0c893bc..9dfa288b1 100644 --- a/comfy/text_encoders/hydit.py +++ b/comfy/text_encoders/hydit.py @@ -52,8 +52,8 @@ class HyditTokenizer: class HyditModel(torch.nn.Module): def __init__(self, device="cpu", dtype=None): super().__init__() - self.hydit_clip = HyditBertModel() - self.mt5xl = MT5XLModel() + self.hydit_clip = HyditBertModel(dtype=dtype) + self.mt5xl = MT5XLModel(dtype=dtype) self.dtypes = set() if dtype is not None: diff --git a/comfy/text_encoders/sd2_clip_config.json b/comfy/text_encoders/sd2_clip_config.json index 85cec832b..00893cfdc 100644 --- a/comfy/text_encoders/sd2_clip_config.json +++ b/comfy/text_encoders/sd2_clip_config.json @@ -5,7 +5,7 @@ "attention_dropout": 0.0, "bos_token_id": 0, "dropout": 0.0, - "eos_token_id": 2, + "eos_token_id": 49407, "hidden_act": "gelu", "hidden_size": 1024, "initializer_factor": 1.0, diff --git a/comfy/text_encoders/t5.py b/comfy/text_encoders/t5.py index ba628478d..a1420c6cd 100644 --- a/comfy/text_encoders/t5.py +++ b/comfy/text_encoders/t5.py @@ -1,6 +1,7 @@ import torch import math from comfy.ldm.modules.attention import optimized_attention_for_device +import comfy.ops class T5LayerNorm(torch.nn.Module): def __init__(self, hidden_size, eps=1e-6, dtype=None, device=None, operations=None): @@ -11,7 +12,7 @@ class T5LayerNorm(torch.nn.Module): def forward(self, x): variance = x.pow(2).mean(-1, keepdim=True) x = x * torch.rsqrt(variance + self.variance_epsilon) - return self.weight.to(device=x.device, dtype=x.dtype) * x + return comfy.ops.cast_to_input(self.weight, x) * x activations = { "gelu_pytorch_tanh": lambda a: torch.nn.functional.gelu(a, approximate="tanh"), @@ -82,7 +83,7 @@ class T5Attention(torch.nn.Module): if relative_attention_bias: self.relative_attention_num_buckets = 32 self.relative_attention_max_distance = 128 - self.relative_attention_bias = torch.nn.Embedding(self.relative_attention_num_buckets, self.num_heads, device=device) + self.relative_attention_bias = operations.Embedding(self.relative_attention_num_buckets, self.num_heads, device=device, dtype=dtype) @staticmethod def _relative_position_bucket(relative_position, bidirectional=True, num_buckets=32, max_distance=128): @@ -132,7 +133,7 @@ class T5Attention(torch.nn.Module): relative_buckets += torch.where(is_small, relative_position, relative_position_if_large) return relative_buckets - def compute_bias(self, query_length, key_length, device): + def compute_bias(self, query_length, key_length, device, dtype): """Compute binned relative position bias""" context_position = torch.arange(query_length, dtype=torch.long, device=device)[:, None] memory_position = torch.arange(key_length, dtype=torch.long, device=device)[None, :] @@ -143,7 +144,7 @@ class T5Attention(torch.nn.Module): num_buckets=self.relative_attention_num_buckets, max_distance=self.relative_attention_max_distance, ) - values = self.relative_attention_bias(relative_position_bucket) # shape (query_length, key_length, num_heads) + values = self.relative_attention_bias(relative_position_bucket, out_dtype=dtype) # shape (query_length, key_length, num_heads) values = values.permute([2, 0, 1]).unsqueeze(0) # shape (1, num_heads, query_length, key_length) return values @@ -152,7 +153,7 @@ class T5Attention(torch.nn.Module): k = self.k(x) v = self.v(x) if self.relative_attention_bias is not None: - past_bias = self.compute_bias(x.shape[1], x.shape[1], x.device) + past_bias = self.compute_bias(x.shape[1], x.shape[1], x.device, x.dtype) if past_bias is not None: if mask is not None: @@ -199,7 +200,7 @@ class T5Stack(torch.nn.Module): self.final_layer_norm = T5LayerNorm(model_dim, dtype=dtype, device=device, operations=operations) # self.dropout = nn.Dropout(config.dropout_rate) - def forward(self, x, attention_mask=None, intermediate_output=None, final_layer_norm_intermediate=True): + def forward(self, x, attention_mask=None, intermediate_output=None, final_layer_norm_intermediate=True, dtype=None): mask = None if attention_mask is not None: mask = 1.0 - attention_mask.to(x.dtype).reshape((attention_mask.shape[0], 1, -1, attention_mask.shape[-1])).expand(attention_mask.shape[0], 1, attention_mask.shape[-1], attention_mask.shape[-1]) @@ -225,7 +226,7 @@ class T5(torch.nn.Module): self.encoder = T5Stack(self.num_layers, model_dim, model_dim, config_dict["d_ff"], config_dict["dense_act_fn"], config_dict["is_gated_act"], config_dict["num_heads"], config_dict["model_type"] != "umt5", dtype, device, operations) self.dtype = dtype - self.shared = torch.nn.Embedding(config_dict["vocab_size"], model_dim, device=device) + self.shared = operations.Embedding(config_dict["vocab_size"], model_dim, device=device, dtype=dtype) def get_input_embeddings(self): return self.shared @@ -234,5 +235,7 @@ class T5(torch.nn.Module): self.shared = embeddings def forward(self, input_ids, *args, **kwargs): - x = self.shared(input_ids) + x = self.shared(input_ids, out_dtype=kwargs.get("dtype", torch.float32)) + if self.dtype not in [torch.float32, torch.float16, torch.bfloat16]: + x = torch.nan_to_num(x) #Fix for fp8 T5 base return self.encoder(x, *args, **kwargs) diff --git a/node_helpers.py b/node_helpers.py index fee628790..4b38bfff8 100644 --- a/node_helpers.py +++ b/node_helpers.py @@ -25,7 +25,7 @@ def pillow(fn, arg): finally: if prev_value is not None: ImageFile.LOAD_TRUNCATED_IMAGES = prev_value - return x + return x def hasher(): hashfuncs = {