Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
997daf65f0 | ||
|
|
dd93eb32e7 |
@@ -1,24 +0,0 @@
|
||||
name: Publish to Comfy registry
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- master
|
||||
paths:
|
||||
- "pyproject.toml"
|
||||
|
||||
jobs:
|
||||
publish-node:
|
||||
name: Publish Custom Node to registry
|
||||
runs-on: ubuntu-latest
|
||||
# if this is a forked repository. Skipping the workflow.
|
||||
if: github.event.repository.fork == false
|
||||
steps:
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v4
|
||||
- name: Publish Custom Node
|
||||
uses: Comfy-Org/publish-node-action@main
|
||||
with:
|
||||
## Add your own personal access token to your Github Repository secrets and reference it here.
|
||||
personal_access_token: ${{ secrets.REGISTRY_ACCESS_TOKEN }}
|
||||
@@ -162,3 +162,4 @@ cython_debug/
|
||||
#.idea/
|
||||
exclude.txt
|
||||
copytoww.bat
|
||||
train_tools
|
||||
@@ -1,209 +0,0 @@
|
||||
import torch
|
||||
import math
|
||||
import torch.nn.functional as F
|
||||
from comfy.ldm.modules.attention import optimized_attention
|
||||
from .utils import tensor_to_size
|
||||
|
||||
class Attn2Replace:
|
||||
def __init__(self, callback=None, **kwargs):
|
||||
self.callback = [callback]
|
||||
self.kwargs = [kwargs]
|
||||
|
||||
def add(self, callback, **kwargs):
|
||||
self.callback.append(callback)
|
||||
self.kwargs.append(kwargs)
|
||||
|
||||
for key, value in kwargs.items():
|
||||
setattr(self, key, value)
|
||||
|
||||
def __call__(self, q, k, v, extra_options):
|
||||
dtype = q.dtype
|
||||
out = optimized_attention(q, k, v, extra_options["n_heads"])
|
||||
sigma = extra_options["sigmas"].detach().cpu()[0].item() if 'sigmas' in extra_options else 999999999.9
|
||||
|
||||
for i, callback in enumerate(self.callback):
|
||||
if sigma <= self.kwargs[i]["sigma_start"] and sigma >= self.kwargs[i]["sigma_end"]:
|
||||
out = out + callback(out, q, k, v, extra_options, **self.kwargs[i])
|
||||
|
||||
return out.to(dtype=dtype)
|
||||
|
||||
def ipadapter_attention(out, q, k, v, extra_options, module_key='', ipadapter=None, weight=1.0, cond=None, cond_alt=None, uncond=None, weight_type="linear", mask=None, sigma_start=0.0, sigma_end=1.0, unfold_batch=False, embeds_scaling='V only', **kwargs):
|
||||
dtype = q.dtype
|
||||
cond_or_uncond = extra_options["cond_or_uncond"]
|
||||
block_type = extra_options["block"][0]
|
||||
#block_id = extra_options["block"][1]
|
||||
t_idx = extra_options["transformer_index"]
|
||||
layers = 11 if '101_to_k_ip' in ipadapter.ip_layers.to_kvs else 16
|
||||
k_key = module_key + "_to_k_ip"
|
||||
v_key = module_key + "_to_v_ip"
|
||||
|
||||
# extra options for AnimateDiff
|
||||
ad_params = extra_options['ad_params'] if "ad_params" in extra_options else None
|
||||
|
||||
b = q.shape[0]
|
||||
seq_len = q.shape[1]
|
||||
batch_prompt = b // len(cond_or_uncond)
|
||||
_, _, oh, ow = extra_options["original_shape"]
|
||||
|
||||
if weight_type == 'ease in':
|
||||
weight = weight * (0.05 + 0.95 * (1 - t_idx / layers))
|
||||
elif weight_type == 'ease out':
|
||||
weight = weight * (0.05 + 0.95 * (t_idx / layers))
|
||||
elif weight_type == 'ease in-out':
|
||||
weight = weight * (0.05 + 0.95 * (1 - abs(t_idx - (layers/2)) / (layers/2)))
|
||||
elif weight_type == 'reverse in-out':
|
||||
weight = weight * (0.05 + 0.95 * (abs(t_idx - (layers/2)) / (layers/2)))
|
||||
elif weight_type == 'weak input' and block_type == 'input':
|
||||
weight = weight * 0.2
|
||||
elif weight_type == 'weak middle' and block_type == 'middle':
|
||||
weight = weight * 0.2
|
||||
elif weight_type == 'weak output' and block_type == 'output':
|
||||
weight = weight * 0.2
|
||||
elif weight_type == 'strong middle' and (block_type == 'input' or block_type == 'output'):
|
||||
weight = weight * 0.2
|
||||
elif isinstance(weight, dict):
|
||||
if t_idx not in weight:
|
||||
return 0
|
||||
|
||||
if weight_type == "style transfer precise":
|
||||
if layers == 11 and t_idx == 3:
|
||||
uncond = cond
|
||||
cond = cond * 0
|
||||
elif layers == 16 and (t_idx == 4 or t_idx == 5):
|
||||
uncond = cond
|
||||
cond = cond * 0
|
||||
elif weight_type == "composition precise":
|
||||
if layers == 11 and t_idx != 3:
|
||||
uncond = cond
|
||||
cond = cond * 0
|
||||
elif layers == 16 and (t_idx != 4 and t_idx != 5):
|
||||
uncond = cond
|
||||
cond = cond * 0
|
||||
|
||||
weight = weight[t_idx]
|
||||
|
||||
if cond_alt is not None and t_idx in cond_alt:
|
||||
cond = cond_alt[t_idx]
|
||||
del cond_alt
|
||||
|
||||
if unfold_batch:
|
||||
# Check AnimateDiff context window
|
||||
if ad_params is not None and ad_params["sub_idxs"] is not None:
|
||||
if isinstance(weight, torch.Tensor):
|
||||
weight = tensor_to_size(weight, ad_params["full_length"])
|
||||
weight = torch.Tensor(weight[ad_params["sub_idxs"]])
|
||||
if torch.all(weight == 0):
|
||||
return 0
|
||||
weight = weight.repeat(len(cond_or_uncond), 1, 1) # repeat for cond and uncond
|
||||
elif weight == 0:
|
||||
return 0
|
||||
|
||||
# if image length matches or exceeds full_length get sub_idx images
|
||||
if cond.shape[0] >= ad_params["full_length"]:
|
||||
cond = torch.Tensor(cond[ad_params["sub_idxs"]])
|
||||
uncond = torch.Tensor(uncond[ad_params["sub_idxs"]])
|
||||
# otherwise get sub_idxs images
|
||||
else:
|
||||
cond = tensor_to_size(cond, ad_params["full_length"])
|
||||
uncond = tensor_to_size(uncond, ad_params["full_length"])
|
||||
cond = cond[ad_params["sub_idxs"]]
|
||||
uncond = uncond[ad_params["sub_idxs"]]
|
||||
else:
|
||||
if isinstance(weight, torch.Tensor):
|
||||
weight = tensor_to_size(weight, batch_prompt)
|
||||
if torch.all(weight == 0):
|
||||
return 0
|
||||
weight = weight.repeat(len(cond_or_uncond), 1, 1) # repeat for cond and uncond
|
||||
elif weight == 0:
|
||||
return 0
|
||||
|
||||
cond = tensor_to_size(cond, batch_prompt)
|
||||
uncond = tensor_to_size(uncond, batch_prompt)
|
||||
|
||||
k_cond = ipadapter.ip_layers.to_kvs[k_key](cond)
|
||||
k_uncond = ipadapter.ip_layers.to_kvs[k_key](uncond)
|
||||
v_cond = ipadapter.ip_layers.to_kvs[v_key](cond)
|
||||
v_uncond = ipadapter.ip_layers.to_kvs[v_key](uncond)
|
||||
else:
|
||||
# TODO: should we always convert the weights to a tensor?
|
||||
if isinstance(weight, torch.Tensor):
|
||||
weight = tensor_to_size(weight, batch_prompt)
|
||||
if torch.all(weight == 0):
|
||||
return 0
|
||||
weight = weight.repeat(len(cond_or_uncond), 1, 1) # repeat for cond and uncond
|
||||
elif weight == 0:
|
||||
return 0
|
||||
|
||||
k_cond = ipadapter.ip_layers.to_kvs[k_key](cond).repeat(batch_prompt, 1, 1)
|
||||
k_uncond = ipadapter.ip_layers.to_kvs[k_key](uncond).repeat(batch_prompt, 1, 1)
|
||||
v_cond = ipadapter.ip_layers.to_kvs[v_key](cond).repeat(batch_prompt, 1, 1)
|
||||
v_uncond = ipadapter.ip_layers.to_kvs[v_key](uncond).repeat(batch_prompt, 1, 1)
|
||||
|
||||
if len(cond_or_uncond) == 3: # TODO: conxl, I need to check this
|
||||
ip_k = torch.cat([(k_cond, k_uncond, k_cond)[i] for i in cond_or_uncond], dim=0)
|
||||
ip_v = torch.cat([(v_cond, v_uncond, v_cond)[i] for i in cond_or_uncond], dim=0)
|
||||
else:
|
||||
ip_k = torch.cat([(k_cond, k_uncond)[i] for i in cond_or_uncond], dim=0)
|
||||
ip_v = torch.cat([(v_cond, v_uncond)[i] for i in cond_or_uncond], dim=0)
|
||||
|
||||
if embeds_scaling == 'K+mean(V) w/ C penalty':
|
||||
scaling = float(ip_k.shape[2]) / 1280.0
|
||||
weight = weight * scaling
|
||||
ip_k = ip_k * weight
|
||||
ip_v_mean = torch.mean(ip_v, dim=1, keepdim=True)
|
||||
ip_v = (ip_v - ip_v_mean) + ip_v_mean * weight
|
||||
out_ip = optimized_attention(q, ip_k, ip_v, extra_options["n_heads"])
|
||||
del ip_v_mean
|
||||
elif embeds_scaling == 'K+V w/ C penalty':
|
||||
scaling = float(ip_k.shape[2]) / 1280.0
|
||||
weight = weight * scaling
|
||||
ip_k = ip_k * weight
|
||||
ip_v = ip_v * weight
|
||||
out_ip = optimized_attention(q, ip_k, ip_v, extra_options["n_heads"])
|
||||
elif embeds_scaling == 'K+V':
|
||||
ip_k = ip_k * weight
|
||||
ip_v = ip_v * weight
|
||||
out_ip = optimized_attention(q, ip_k, ip_v, extra_options["n_heads"])
|
||||
else:
|
||||
#ip_v = ip_v * weight
|
||||
out_ip = optimized_attention(q, ip_k, ip_v, extra_options["n_heads"])
|
||||
out_ip = out_ip * weight # I'm doing this to get the same results as before
|
||||
|
||||
if mask is not None:
|
||||
mask_h = oh / math.sqrt(oh * ow / seq_len)
|
||||
mask_h = int(mask_h) + int((seq_len % int(mask_h)) != 0)
|
||||
mask_w = seq_len // mask_h
|
||||
|
||||
# check if using AnimateDiff and sliding context window
|
||||
if (mask.shape[0] > 1 and ad_params is not None and ad_params["sub_idxs"] is not None):
|
||||
# if mask length matches or exceeds full_length, get sub_idx masks
|
||||
if mask.shape[0] >= ad_params["full_length"]:
|
||||
mask = torch.Tensor(mask[ad_params["sub_idxs"]])
|
||||
mask = F.interpolate(mask.unsqueeze(1), size=(mask_h, mask_w), mode="bilinear").squeeze(1)
|
||||
else:
|
||||
mask = F.interpolate(mask.unsqueeze(1), size=(mask_h, mask_w), mode="bilinear").squeeze(1)
|
||||
mask = tensor_to_size(mask, ad_params["full_length"])
|
||||
mask = mask[ad_params["sub_idxs"]]
|
||||
else:
|
||||
mask = F.interpolate(mask.unsqueeze(1), size=(mask_h, mask_w), mode="bilinear").squeeze(1)
|
||||
mask = tensor_to_size(mask, batch_prompt)
|
||||
|
||||
mask = mask.repeat(len(cond_or_uncond), 1, 1)
|
||||
mask = mask.view(mask.shape[0], -1, 1).repeat(1, 1, out.shape[2])
|
||||
|
||||
# covers cases where extreme aspect ratios can cause the mask to have a wrong size
|
||||
mask_len = mask_h * mask_w
|
||||
if mask_len < seq_len:
|
||||
pad_len = seq_len - mask_len
|
||||
pad1 = pad_len // 2
|
||||
pad2 = pad_len - pad1
|
||||
mask = F.pad(mask, (0, 0, pad1, pad2), value=0.0)
|
||||
elif mask_len > seq_len:
|
||||
crop_start = (mask_len - seq_len) // 2
|
||||
mask = mask[:, crop_start:crop_start+seq_len, :]
|
||||
|
||||
out_ip = out_ip * mask
|
||||
|
||||
#out = out + out_ip
|
||||
|
||||
return out_ip.to(dtype=dtype)
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,275 +0,0 @@
|
||||
import math
|
||||
import torch
|
||||
import torch.nn as nn
|
||||
from einops import rearrange
|
||||
from einops.layers.torch import Rearrange
|
||||
|
||||
|
||||
# FFN
|
||||
def FeedForward(dim, mult=4):
|
||||
inner_dim = int(dim * mult)
|
||||
return nn.Sequential(
|
||||
nn.LayerNorm(dim),
|
||||
nn.Linear(dim, inner_dim, bias=False),
|
||||
nn.GELU(),
|
||||
nn.Linear(inner_dim, dim, bias=False),
|
||||
)
|
||||
|
||||
|
||||
def reshape_tensor(x, heads):
|
||||
bs, length, width = x.shape
|
||||
# (bs, length, width) --> (bs, length, n_heads, dim_per_head)
|
||||
x = x.view(bs, length, heads, -1)
|
||||
# (bs, length, n_heads, dim_per_head) --> (bs, n_heads, length, dim_per_head)
|
||||
x = x.transpose(1, 2)
|
||||
# (bs, n_heads, length, dim_per_head) --> (bs*n_heads, length, dim_per_head)
|
||||
x = x.reshape(bs, heads, length, -1)
|
||||
return x
|
||||
|
||||
|
||||
class PerceiverAttention(nn.Module):
|
||||
def __init__(self, *, dim, dim_head=64, heads=8):
|
||||
super().__init__()
|
||||
self.scale = dim_head**-0.5
|
||||
self.dim_head = dim_head
|
||||
self.heads = heads
|
||||
inner_dim = dim_head * heads
|
||||
|
||||
self.norm1 = nn.LayerNorm(dim)
|
||||
self.norm2 = nn.LayerNorm(dim)
|
||||
|
||||
self.to_q = nn.Linear(dim, inner_dim, bias=False)
|
||||
self.to_kv = nn.Linear(dim, inner_dim * 2, bias=False)
|
||||
self.to_out = nn.Linear(inner_dim, dim, bias=False)
|
||||
|
||||
def forward(self, x, latents):
|
||||
"""
|
||||
Args:
|
||||
x (torch.Tensor): image features
|
||||
shape (b, n1, D)
|
||||
latent (torch.Tensor): latent features
|
||||
shape (b, n2, D)
|
||||
"""
|
||||
x = self.norm1(x)
|
||||
latents = self.norm2(latents)
|
||||
|
||||
b, l, _ = latents.shape
|
||||
|
||||
q = self.to_q(latents)
|
||||
kv_input = torch.cat((x, latents), dim=-2)
|
||||
k, v = self.to_kv(kv_input).chunk(2, dim=-1)
|
||||
|
||||
q = reshape_tensor(q, self.heads)
|
||||
k = reshape_tensor(k, self.heads)
|
||||
v = reshape_tensor(v, self.heads)
|
||||
|
||||
# attention
|
||||
scale = 1 / math.sqrt(math.sqrt(self.dim_head))
|
||||
weight = (q * scale) @ (k * scale).transpose(-2, -1) # More stable with f16 than dividing afterwards
|
||||
weight = torch.softmax(weight.float(), dim=-1).type(weight.dtype)
|
||||
out = weight @ v
|
||||
|
||||
out = out.permute(0, 2, 1, 3).reshape(b, l, -1)
|
||||
|
||||
return self.to_out(out)
|
||||
|
||||
|
||||
class Resampler(nn.Module):
|
||||
def __init__(
|
||||
self,
|
||||
dim=1024,
|
||||
depth=8,
|
||||
dim_head=64,
|
||||
heads=16,
|
||||
num_queries=8,
|
||||
embedding_dim=768,
|
||||
output_dim=1024,
|
||||
ff_mult=4,
|
||||
max_seq_len: int = 257, # CLIP tokens + CLS token
|
||||
apply_pos_emb: bool = False,
|
||||
num_latents_mean_pooled: int = 0, # number of latents derived from mean pooled representation of the sequence
|
||||
):
|
||||
super().__init__()
|
||||
self.pos_emb = nn.Embedding(max_seq_len, embedding_dim) if apply_pos_emb else None
|
||||
|
||||
self.latents = nn.Parameter(torch.randn(1, num_queries, dim) / dim**0.5)
|
||||
|
||||
self.proj_in = nn.Linear(embedding_dim, dim)
|
||||
|
||||
self.proj_out = nn.Linear(dim, output_dim)
|
||||
self.norm_out = nn.LayerNorm(output_dim)
|
||||
|
||||
self.to_latents_from_mean_pooled_seq = (
|
||||
nn.Sequential(
|
||||
nn.LayerNorm(dim),
|
||||
nn.Linear(dim, dim * num_latents_mean_pooled),
|
||||
Rearrange("b (n d) -> b n d", n=num_latents_mean_pooled),
|
||||
)
|
||||
if num_latents_mean_pooled > 0
|
||||
else None
|
||||
)
|
||||
|
||||
self.layers = nn.ModuleList([])
|
||||
for _ in range(depth):
|
||||
self.layers.append(
|
||||
nn.ModuleList(
|
||||
[
|
||||
PerceiverAttention(dim=dim, dim_head=dim_head, heads=heads),
|
||||
FeedForward(dim=dim, mult=ff_mult),
|
||||
]
|
||||
)
|
||||
)
|
||||
|
||||
def forward(self, x):
|
||||
if self.pos_emb is not None:
|
||||
n, device = x.shape[1], x.device
|
||||
pos_emb = self.pos_emb(torch.arange(n, device=device))
|
||||
x = x + pos_emb
|
||||
|
||||
latents = self.latents.repeat(x.size(0), 1, 1)
|
||||
|
||||
x = self.proj_in(x)
|
||||
|
||||
if self.to_latents_from_mean_pooled_seq:
|
||||
meanpooled_seq = masked_mean(x, dim=1, mask=torch.ones(x.shape[:2], device=x.device, dtype=torch.bool))
|
||||
meanpooled_latents = self.to_latents_from_mean_pooled_seq(meanpooled_seq)
|
||||
latents = torch.cat((meanpooled_latents, latents), dim=-2)
|
||||
|
||||
for attn, ff in self.layers:
|
||||
latents = attn(x, latents) + latents
|
||||
latents = ff(latents) + latents
|
||||
|
||||
latents = self.proj_out(latents)
|
||||
return self.norm_out(latents)
|
||||
|
||||
|
||||
def masked_mean(t, *, dim, mask=None):
|
||||
if mask is None:
|
||||
return t.mean(dim=dim)
|
||||
|
||||
denom = mask.sum(dim=dim, keepdim=True)
|
||||
mask = rearrange(mask, "b n -> b n 1")
|
||||
masked_t = t.masked_fill(~mask, 0.0)
|
||||
|
||||
return masked_t.sum(dim=dim) / denom.clamp(min=1e-5)
|
||||
|
||||
|
||||
class FacePerceiverResampler(nn.Module):
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
dim=768,
|
||||
depth=4,
|
||||
dim_head=64,
|
||||
heads=16,
|
||||
embedding_dim=1280,
|
||||
output_dim=768,
|
||||
ff_mult=4,
|
||||
):
|
||||
super().__init__()
|
||||
|
||||
self.proj_in = nn.Linear(embedding_dim, dim)
|
||||
self.proj_out = nn.Linear(dim, output_dim)
|
||||
self.norm_out = nn.LayerNorm(output_dim)
|
||||
self.layers = nn.ModuleList([])
|
||||
for _ in range(depth):
|
||||
self.layers.append(
|
||||
nn.ModuleList(
|
||||
[
|
||||
PerceiverAttention(dim=dim, dim_head=dim_head, heads=heads),
|
||||
FeedForward(dim=dim, mult=ff_mult),
|
||||
]
|
||||
)
|
||||
)
|
||||
|
||||
def forward(self, latents, x):
|
||||
x = self.proj_in(x)
|
||||
for attn, ff in self.layers:
|
||||
latents = attn(x, latents) + latents
|
||||
latents = ff(latents) + latents
|
||||
latents = self.proj_out(latents)
|
||||
return self.norm_out(latents)
|
||||
|
||||
|
||||
class MLPProjModel(nn.Module):
|
||||
def __init__(self, cross_attention_dim=1024, clip_embeddings_dim=1024):
|
||||
super().__init__()
|
||||
|
||||
self.proj = nn.Sequential(
|
||||
nn.Linear(clip_embeddings_dim, clip_embeddings_dim),
|
||||
nn.GELU(),
|
||||
nn.Linear(clip_embeddings_dim, cross_attention_dim),
|
||||
nn.LayerNorm(cross_attention_dim)
|
||||
)
|
||||
|
||||
def forward(self, image_embeds):
|
||||
clip_extra_context_tokens = self.proj(image_embeds)
|
||||
return clip_extra_context_tokens
|
||||
|
||||
class MLPProjModelFaceId(nn.Module):
|
||||
def __init__(self, cross_attention_dim=768, id_embeddings_dim=512, num_tokens=4):
|
||||
super().__init__()
|
||||
|
||||
self.cross_attention_dim = cross_attention_dim
|
||||
self.num_tokens = num_tokens
|
||||
|
||||
self.proj = nn.Sequential(
|
||||
nn.Linear(id_embeddings_dim, id_embeddings_dim*2),
|
||||
nn.GELU(),
|
||||
nn.Linear(id_embeddings_dim*2, cross_attention_dim*num_tokens),
|
||||
)
|
||||
self.norm = nn.LayerNorm(cross_attention_dim)
|
||||
|
||||
def forward(self, id_embeds):
|
||||
x = self.proj(id_embeds)
|
||||
x = x.reshape(-1, self.num_tokens, self.cross_attention_dim)
|
||||
x = self.norm(x)
|
||||
return x
|
||||
|
||||
class ProjModelFaceIdPlus(nn.Module):
|
||||
def __init__(self, cross_attention_dim=768, id_embeddings_dim=512, clip_embeddings_dim=1280, num_tokens=4):
|
||||
super().__init__()
|
||||
|
||||
self.cross_attention_dim = cross_attention_dim
|
||||
self.num_tokens = num_tokens
|
||||
|
||||
self.proj = nn.Sequential(
|
||||
nn.Linear(id_embeddings_dim, id_embeddings_dim*2),
|
||||
nn.GELU(),
|
||||
nn.Linear(id_embeddings_dim*2, cross_attention_dim*num_tokens),
|
||||
)
|
||||
self.norm = nn.LayerNorm(cross_attention_dim)
|
||||
|
||||
self.perceiver_resampler = FacePerceiverResampler(
|
||||
dim=cross_attention_dim,
|
||||
depth=4,
|
||||
dim_head=64,
|
||||
heads=cross_attention_dim // 64,
|
||||
embedding_dim=clip_embeddings_dim,
|
||||
output_dim=cross_attention_dim,
|
||||
ff_mult=4,
|
||||
)
|
||||
|
||||
def forward(self, id_embeds, clip_embeds, scale=1.0, shortcut=False):
|
||||
x = self.proj(id_embeds)
|
||||
x = x.reshape(-1, self.num_tokens, self.cross_attention_dim)
|
||||
x = self.norm(x)
|
||||
out = self.perceiver_resampler(x, clip_embeds)
|
||||
if shortcut:
|
||||
out = x + scale * out
|
||||
return out
|
||||
|
||||
class ImageProjModel(nn.Module):
|
||||
def __init__(self, cross_attention_dim=1024, clip_embeddings_dim=1024, clip_extra_context_tokens=4):
|
||||
super().__init__()
|
||||
|
||||
self.cross_attention_dim = cross_attention_dim
|
||||
self.clip_extra_context_tokens = clip_extra_context_tokens
|
||||
self.proj = nn.Linear(clip_embeddings_dim, self.clip_extra_context_tokens * cross_attention_dim)
|
||||
self.norm = nn.LayerNorm(cross_attention_dim)
|
||||
|
||||
def forward(self, image_embeds):
|
||||
embeds = image_embeds
|
||||
x = self.proj(embeds).reshape(-1, self.clip_extra_context_tokens, self.cross_attention_dim)
|
||||
x = self.norm(x)
|
||||
return x
|
||||
@@ -1,266 +0,0 @@
|
||||
import re
|
||||
import torch
|
||||
import os
|
||||
import folder_paths
|
||||
from comfy.clip_vision import clip_preprocess, Output
|
||||
import comfy.utils
|
||||
import comfy.model_management as model_management
|
||||
try:
|
||||
import torchvision.transforms.v2 as T
|
||||
except ImportError:
|
||||
import torchvision.transforms as T
|
||||
|
||||
def get_clipvision_file(preset):
|
||||
preset = preset.lower()
|
||||
clipvision_list = folder_paths.get_filename_list("clip_vision")
|
||||
|
||||
if preset.startswith("vit-g"):
|
||||
pattern = r'(ViT.bigG.14.*39B.b160k|ipadapter.*sdxl|sdxl.*model\.(bin|safetensors))'
|
||||
else:
|
||||
pattern = r'(ViT.H.14.*s32B.b79K|ipadapter.*sd15|sd1.?5.*model\.(bin|safetensors))'
|
||||
clipvision_file = [e for e in clipvision_list if re.search(pattern, e, re.IGNORECASE)]
|
||||
|
||||
clipvision_file = folder_paths.get_full_path("clip_vision", clipvision_file[0]) if clipvision_file else None
|
||||
|
||||
return clipvision_file
|
||||
|
||||
def get_ipadapter_file(preset, is_sdxl):
|
||||
preset = preset.lower()
|
||||
ipadapter_list = folder_paths.get_filename_list("ipadapter")
|
||||
is_insightface = False
|
||||
lora_pattern = None
|
||||
|
||||
if preset.startswith("light"):
|
||||
if is_sdxl:
|
||||
raise Exception("light model is not supported for SDXL")
|
||||
pattern = r'sd15.light.v11\.(safetensors|bin)$'
|
||||
# if v11 is not found, try with the old version
|
||||
if not [e for e in ipadapter_list if re.search(pattern, e, re.IGNORECASE)]:
|
||||
pattern = r'sd15.light\.(safetensors|bin)$'
|
||||
elif preset.startswith("standard"):
|
||||
if is_sdxl:
|
||||
pattern = r'ip.adapter.sdxl.vit.h\.(safetensors|bin)$'
|
||||
else:
|
||||
pattern = r'ip.adapter.sd15\.(safetensors|bin)$'
|
||||
elif preset.startswith("vit-g"):
|
||||
if is_sdxl:
|
||||
pattern = r'ip.adapter.sdxl\.(safetensors|bin)$'
|
||||
else:
|
||||
pattern = r'sd15.vit.g\.(safetensors|bin)$'
|
||||
elif preset.startswith("plus ("):
|
||||
if is_sdxl:
|
||||
pattern = r'plus.sdxl.vit.h\.(safetensors|bin)$'
|
||||
else:
|
||||
pattern = r'ip.adapter.plus.sd15\.(safetensors|bin)$'
|
||||
elif preset.startswith("plus face"):
|
||||
if is_sdxl:
|
||||
pattern = r'plus.face.sdxl.vit.h\.(safetensors|bin)$'
|
||||
else:
|
||||
pattern = r'plus.face.sd15\.(safetensors|bin)$'
|
||||
elif preset.startswith("full"):
|
||||
if is_sdxl:
|
||||
raise Exception("full face model is not supported for SDXL")
|
||||
pattern = r'full.face.sd15\.(safetensors|bin)$'
|
||||
elif preset.startswith("faceid portrait ("):
|
||||
if is_sdxl:
|
||||
pattern = r'portrait.sdxl\.(safetensors|bin)$'
|
||||
else:
|
||||
pattern = r'portrait.v11.sd15\.(safetensors|bin)$'
|
||||
# if v11 is not found, try with the old version
|
||||
if not [e for e in ipadapter_list if re.search(pattern, e, re.IGNORECASE)]:
|
||||
pattern = r'portrait.sd15\.(safetensors|bin)$'
|
||||
is_insightface = True
|
||||
elif preset.startswith("faceid portrait unnorm"):
|
||||
if is_sdxl:
|
||||
pattern = r'portrait.sdxl.unnorm\.(safetensors|bin)$'
|
||||
else:
|
||||
raise Exception("portrait unnorm model is not supported for SD1.5")
|
||||
is_insightface = True
|
||||
elif preset == "faceid":
|
||||
if is_sdxl:
|
||||
pattern = r'faceid.sdxl\.(safetensors|bin)$'
|
||||
lora_pattern = r'faceid.sdxl.lora\.safetensors$'
|
||||
else:
|
||||
pattern = r'faceid.sd15\.(safetensors|bin)$'
|
||||
lora_pattern = r'faceid.sd15.lora\.safetensors$'
|
||||
is_insightface = True
|
||||
elif preset.startswith("faceid plus -"):
|
||||
if is_sdxl:
|
||||
raise Exception("faceid plus model is not supported for SDXL")
|
||||
pattern = r'faceid.plus.sd15\.(safetensors|bin)$'
|
||||
lora_pattern = r'faceid.plus.sd15.lora\.safetensors$'
|
||||
is_insightface = True
|
||||
elif preset.startswith("faceid plus v2"):
|
||||
if is_sdxl:
|
||||
pattern = r'faceid.plusv2.sdxl\.(safetensors|bin)$'
|
||||
lora_pattern = r'faceid.plusv2.sdxl.lora\.safetensors$'
|
||||
else:
|
||||
pattern = r'faceid.plusv2.sd15\.(safetensors|bin)$'
|
||||
lora_pattern = r'faceid.plusv2.sd15.lora\.safetensors$'
|
||||
is_insightface = True
|
||||
# Community's models
|
||||
elif preset.startswith("composition"):
|
||||
if is_sdxl:
|
||||
pattern = r'plus.composition.sdxl\.safetensors$'
|
||||
else:
|
||||
pattern = r'plus.composition.sd15\.safetensors$'
|
||||
else:
|
||||
raise Exception(f"invalid type '{preset}'")
|
||||
|
||||
ipadapter_file = [e for e in ipadapter_list if re.search(pattern, e, re.IGNORECASE)]
|
||||
ipadapter_file = folder_paths.get_full_path("ipadapter", ipadapter_file[0]) if ipadapter_file else None
|
||||
|
||||
return ipadapter_file, is_insightface, lora_pattern
|
||||
|
||||
def get_lora_file(pattern):
|
||||
lora_list = folder_paths.get_filename_list("loras")
|
||||
lora_file = [e for e in lora_list if re.search(pattern, e, re.IGNORECASE)]
|
||||
lora_file = folder_paths.get_full_path("loras", lora_file[0]) if lora_file else None
|
||||
|
||||
return lora_file
|
||||
|
||||
def ipadapter_model_loader(file):
|
||||
model = comfy.utils.load_torch_file(file, safe_load=True)
|
||||
|
||||
if file.lower().endswith(".safetensors"):
|
||||
st_model = {"image_proj": {}, "ip_adapter": {}}
|
||||
for key in model.keys():
|
||||
if key.startswith("image_proj."):
|
||||
st_model["image_proj"][key.replace("image_proj.", "")] = model[key]
|
||||
elif key.startswith("ip_adapter."):
|
||||
st_model["ip_adapter"][key.replace("ip_adapter.", "")] = model[key]
|
||||
model = st_model
|
||||
del st_model
|
||||
|
||||
if not "ip_adapter" in model.keys() or not model["ip_adapter"]:
|
||||
raise Exception("invalid IPAdapter model {}".format(file))
|
||||
|
||||
if 'plusv2' in file.lower():
|
||||
model["faceidplusv2"] = True
|
||||
|
||||
if 'unnorm' in file.lower():
|
||||
model["portraitunnorm"] = True
|
||||
|
||||
return model
|
||||
|
||||
def insightface_loader(provider):
|
||||
try:
|
||||
from insightface.app import FaceAnalysis
|
||||
except ImportError as e:
|
||||
raise Exception(e)
|
||||
|
||||
path = os.path.join(folder_paths.models_dir, "insightface")
|
||||
model = FaceAnalysis(name="buffalo_l", root=path, providers=[provider + 'ExecutionProvider',])
|
||||
model.prepare(ctx_id=0, det_size=(640, 640))
|
||||
return model
|
||||
|
||||
def encode_image_masked(clip_vision, image, mask=None, batch_size=0, size=224):
|
||||
model_management.load_model_gpu(clip_vision.patcher)
|
||||
outputs = Output()
|
||||
|
||||
if batch_size == 0:
|
||||
batch_size = image.shape[0]
|
||||
elif batch_size > image.shape[0]:
|
||||
batch_size = image.shape[0]
|
||||
|
||||
image_batch = torch.split(image, batch_size, dim=0)
|
||||
|
||||
for img in image_batch:
|
||||
img = img.to(clip_vision.load_device)
|
||||
|
||||
pixel_values = clip_preprocess(img.to(clip_vision.load_device), size=size).float()
|
||||
|
||||
# TODO: support for multiple masks
|
||||
if mask is not None:
|
||||
pixel_values = pixel_values * mask.to(clip_vision.load_device)
|
||||
|
||||
out = clip_vision.model(pixel_values=pixel_values, intermediate_output=-2)
|
||||
|
||||
if not hasattr(outputs, "last_hidden_state"):
|
||||
outputs["last_hidden_state"] = out[0].to(model_management.intermediate_device())
|
||||
outputs["image_embeds"] = out[2].to(model_management.intermediate_device())
|
||||
outputs["penultimate_hidden_states"] = out[1].to(model_management.intermediate_device())
|
||||
else:
|
||||
outputs["last_hidden_state"] = torch.cat((outputs["last_hidden_state"], out[0].to(model_management.intermediate_device())), dim=0)
|
||||
outputs["image_embeds"] = torch.cat((outputs["image_embeds"], out[2].to(model_management.intermediate_device())), dim=0)
|
||||
outputs["penultimate_hidden_states"] = torch.cat((outputs["penultimate_hidden_states"], out[1].to(model_management.intermediate_device())), dim=0)
|
||||
|
||||
del img, pixel_values, out
|
||||
torch.cuda.empty_cache()
|
||||
|
||||
return outputs
|
||||
|
||||
def tensor_to_size(source, dest_size):
|
||||
if isinstance(dest_size, torch.Tensor):
|
||||
dest_size = dest_size.shape[0]
|
||||
source_size = source.shape[0]
|
||||
|
||||
if source_size < dest_size:
|
||||
shape = [dest_size - source_size] + [1]*(source.dim()-1)
|
||||
source = torch.cat((source, source[-1:].repeat(shape)), dim=0)
|
||||
elif source_size > dest_size:
|
||||
source = source[:dest_size]
|
||||
|
||||
return source
|
||||
|
||||
def min_(tensor_list):
|
||||
# return the element-wise min of the tensor list.
|
||||
x = torch.stack(tensor_list)
|
||||
mn = x.min(axis=0)[0]
|
||||
return torch.clamp(mn, min=0)
|
||||
|
||||
def max_(tensor_list):
|
||||
# return the element-wise max of the tensor list.
|
||||
x = torch.stack(tensor_list)
|
||||
mx = x.max(axis=0)[0]
|
||||
return torch.clamp(mx, max=1)
|
||||
|
||||
# From https://github.com/Jamy-L/Pytorch-Contrast-Adaptive-Sharpening/
|
||||
def contrast_adaptive_sharpening(image, amount):
|
||||
img = T.functional.pad(image, (1, 1, 1, 1)).cpu()
|
||||
|
||||
a = img[..., :-2, :-2]
|
||||
b = img[..., :-2, 1:-1]
|
||||
c = img[..., :-2, 2:]
|
||||
d = img[..., 1:-1, :-2]
|
||||
e = img[..., 1:-1, 1:-1]
|
||||
f = img[..., 1:-1, 2:]
|
||||
g = img[..., 2:, :-2]
|
||||
h = img[..., 2:, 1:-1]
|
||||
i = img[..., 2:, 2:]
|
||||
|
||||
# Computing contrast
|
||||
cross = (b, d, e, f, h)
|
||||
mn = min_(cross)
|
||||
mx = max_(cross)
|
||||
|
||||
diag = (a, c, g, i)
|
||||
mn2 = min_(diag)
|
||||
mx2 = max_(diag)
|
||||
mx = mx + mx2
|
||||
mn = mn + mn2
|
||||
|
||||
# Computing local weight
|
||||
inv_mx = torch.reciprocal(mx)
|
||||
amp = inv_mx * torch.minimum(mn, (2 - mx))
|
||||
|
||||
# scaling
|
||||
amp = torch.sqrt(amp)
|
||||
w = - amp * (amount * (1/5 - 1/8) + 1/8)
|
||||
div = torch.reciprocal(1 + 4*w)
|
||||
|
||||
output = ((b + d + f + h)*w + e) * div
|
||||
output = torch.nan_to_num(output)
|
||||
output = output.clamp(0, 1)
|
||||
|
||||
return output
|
||||
|
||||
def tensor_to_image(tensor):
|
||||
image = tensor.mul(255).clamp(0, 255).byte().cpu()
|
||||
image = image[..., [2, 1, 0]].numpy()
|
||||
return image
|
||||
|
||||
def image_to_tensor(image):
|
||||
tensor = torch.clamp(torch.from_numpy(image).float() / 255., 0, 1)
|
||||
tensor = tensor[..., [2, 1, 0]]
|
||||
return tensor
|
||||
@@ -1,46 +1,25 @@
|
||||

|
||||

|
||||
|
||||
## Recent changes
|
||||
* [2024-07-21] 感谢来自yiwangsimple对Mac修复和测试的分支 https://github.com/yiwangsimple/ComfyUI-Kolors-MZ
|
||||
* [2024-07-21] 新增MZ_ChatGLM3TextEncodeAdvanceV2节点
|
||||
* [2024-07-18] IPA相关节点已在ComfyUI_IPAdapter_plus中支持
|
||||
* [2024-07-17] 新增支持IPAdapter_plus的加载器和高级应用节点 MZ_KolorsCLIPVisionLoader,MZ_IPAdapterModelLoaderKolors,MZ_IPAdapterAdvancedKolors
|
||||
* [2024-07-14] 删除自动兼容ControlNet, 新增MZ_KolorsControlNetPatch节点
|
||||

|
||||
|
||||
## ComfyUI上Kolors的实现
|
||||
ComfyUI上Kolors的实现
|
||||
|
||||
参考自 https://github.com/kijai/ComfyUI-KwaiKolorsWrapper
|
||||
|
||||
使用ComfyUI原生采样
|
||||
|
||||
工作流在examples/workflow.png中获取
|
||||
|
||||
### UNET模型下载
|
||||
|
||||
|
||||
unet模型放置在 models/unet/ 文件夹下
|
||||
下载地址:
|
||||
https://huggingface.co/Kwai-Kolors/Kolors/blob/main/unet/diffusion_pytorch_model.fp16.safetensors
|
||||
|
||||
模型主页: https://huggingface.co/Kwai-Kolors/Kolors
|
||||
|
||||
下载地址: https://huggingface.co/Kwai-Kolors/Kolors/resolve/main/unet/diffusion_pytorch_model.fp16.safetensors
|
||||
|
||||
|
||||
### ChatGLM3模型下载
|
||||
chatglm3放置在 models/LLM/ 文件夹下
|
||||
|
||||
模型主页: https://huggingface.co/Kijai/ChatGLM3-safetensors
|
||||
|
||||
下载地址: https://huggingface.co/Kijai/ChatGLM3-safetensors/resolve/main/chatglm3-fp16.safetensors
|
||||
下载地址:
|
||||
https://huggingface.co/Kijai/ChatGLM3-safetensors/blob/main/chatglm3-fp16.safetensors
|
||||
|
||||
|
||||
### 官方IP-Adapter-Plus模型下载地址
|
||||
模型主页: https://huggingface.co/Kwai-Kolors/Kolors-IP-Adapter-Plus
|
||||
|
||||
https://huggingface.co/Kwai-Kolors/Kolors-IP-Adapter-Plus/resolve/main/ip_adapter_plus_general.bin 下载至 models/ipadapter/
|
||||
|
||||
https://huggingface.co/Kwai-Kolors/Kolors-IP-Adapter-Plus/resolve/main/image_encoder/pytorch_model.bin 下载至 models/clip_vision/
|
||||
|
||||
|
||||
## Implementation of Kolors on ComfyUI
|
||||
Implementation of Kolors on ComfyUI
|
||||
|
||||
Reference from https://github.com/kijai/ComfyUI-KwaiKolorsWrapper
|
||||
|
||||
@@ -49,60 +28,26 @@ Using ComfyUI Native Sampling
|
||||
The workflow is obtained in examples/workflow.png
|
||||
|
||||
|
||||
### UNET model download
|
||||
The unet model is placed in the models/unet/ folder
|
||||
|
||||
Model homepage: https://huggingface.co/Kwai-Kolors/Kolors
|
||||
|
||||
Download link:
|
||||
https://huggingface.co/Kwai-Kolors/Kolors/resolve/main/unet/diffusion_pytorch_model.fp16.safetensors
|
||||
https://huggingface.co/Kwai-Kolors/Kolors/blob/main/unet/diffusion_pytorch_model.fp16.safetensors
|
||||
|
||||
|
||||
### ChatGLM3 model download
|
||||
The chatglm3 is placed in the models/LLM/ folder
|
||||
|
||||
Model homepage: https://huggingface.co/Kijai/ChatGLM3-safetensors
|
||||
|
||||
Download link:
|
||||
https://huggingface.co/Kijai/ChatGLM3-safetensors/resolve/main/chatglm3-fp16.safetensors
|
||||
https://huggingface.co/Kijai/ChatGLM3-safetensors/tree/main
|
||||
|
||||
|
||||
### Official IP-Adapter-Plus model download link
|
||||
|
||||
Model homepage: https://huggingface.co/Kwai-Kolors/Kolors-IP-Adapter-Plus
|
||||
|
||||
https://huggingface.co/Kwai-Kolors/Kolors-IP-Adapter-Plus/resolve/main/ip_adapter_plus_general.bin Download to models/ipadapter/
|
||||
|
||||
https://huggingface.co/Kwai-Kolors/Kolors-IP-Adapter-Plus/resolve/main/image_encoder/pytorch_model.bin Download to models/clip_vision/
|
||||
|
||||
|
||||
## FAQ
|
||||
Error occurred when executing MZ_ChatGLM3Loader: 'ChatGLMModel' object has no attribute 'transformer'
|
||||
|
||||
Mac用户无法使用(Mac users cannot use)
|
||||
+ Mac用户可移步至[ComfyUI-Kolors-MZ](https://github.com/yiwangsimple/ComfyUI-Kolors-MZ) (Mac users can go to [ComfyUI-Kolors-MZ](https://github.com/yiwangsimple/ComfyUI-Kolors-MZ) )
|
||||
|
||||
和IPAdapter有关的错误(Errors related to IPAdapter)
|
||||
+ 确保ComfyUI本体和ComfyUI_IPAdapter_plus已经更新到最新版本(Make sure ComfyUI ontology and ComfyUI_IPAdapter_plus are updated to the latest version)
|
||||
|
||||
|
||||
name 'round_up' is not defined
|
||||
+ 参考:https://github.com/THUDM/ChatGLM2-6B/issues/272#issuecomment-1632164243 , 使用 pip install cpm_kernels 或者 pip install -U cpm_kernels 更新 cpm_kernels
|
||||
|
||||
module 'comfy.model_detection' has no attribute 'unet_prefix_from_state_dict'
|
||||
+ 更新ComfyUI本体到最新版本(Update ComfyUI ontology to the latest version)
|
||||
检查ChatGLM3Loader节点选择的模型是否已经正确下载
|
||||
|
||||
RuntimeError: Only Tensors of floating point dtype can require gradients
|
||||
+ 尝试使用fp16版本的模型: https://huggingface.co/Kijai/ChatGLM3-safetensors/blob/main/chatglm3-fp16.safetensors
|
||||
|
||||
Error occurred when executing MZ_ChatGLM3Loader: 'ChatGLMModel' object has no attribute 'transformer'
|
||||
+ 检查ChatGLM3Loader节点选择的模型是否已经正确下载
|
||||
|
||||
|
||||
## Credits
|
||||
|
||||
- [Kolors](https://github.com/Kwai-Kolors/Kolors)
|
||||
- [ComfyUI](https://github.com/comfyanonymous/ComfyUI)
|
||||
- [ComfyUI_IPAdapter_plus](https://github.com/cubiq/ComfyUI_IPAdapter_plus)
|
||||
尝试使用fp16版本的模型: https://huggingface.co/Kijai/ChatGLM3-safetensors/blob/main/chatglm3-fp16.safetensors
|
||||
|
||||
## Star History
|
||||
|
||||
@@ -116,15 +61,7 @@ Error occurred when executing MZ_ChatGLM3Loader: 'ChatGLMModel' object has no at
|
||||
|
||||
|
||||
## Contact
|
||||
- 微信Wechat: minrszone
|
||||
- 绿泡泡: minrszone
|
||||
- Bilibili: [minus_zone](https://space.bilibili.com/5950992)
|
||||
- 小红书: [MinusZoneAI](https://www.xiaohongshu.com/user/profile/5f072e990000000001005472)
|
||||
|
||||
## Stargazers
|
||||
[](https://github.com/MinusZoneAI/ComfyUI-Kolors-MZ/stargazers)
|
||||
|
||||
|
||||
## Sponsorship
|
||||
<img src="https://github.com/user-attachments/assets/a7ef9684-4911-45b6-8071-a9b433dca6af" width="200"/>
|
||||
|
||||
|
||||
- 爱发电: [MinusZoneAI](https://afdian.net/@MinusZoneAI)
|
||||
|
||||
+39
-149
@@ -12,25 +12,42 @@ NODE_CLASS_MAPPINGS = {
|
||||
NODE_DISPLAY_NAME_MAPPINGS = {
|
||||
}
|
||||
|
||||
MAX_RESOLUTION = 16384
|
||||
|
||||
AUTHOR_NAME = "MinusZone"
|
||||
CATEGORY_NAME = f"{AUTHOR_NAME} - Kolors"
|
||||
folder_paths.add_model_folder_path(
|
||||
"LLM", os.path.join(folder_paths.models_dir, "LLM"))
|
||||
|
||||
|
||||
class MZ_FakeCond:
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"seed": ("INT", {"default": 0}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("CONDITIONING", )
|
||||
RETURN_NAMES = ("prompt", )
|
||||
FUNCTION = "encode"
|
||||
CATEGORY = CATEGORY_NAME
|
||||
|
||||
def encode(self, **kwargs):
|
||||
from . import mz_kolors_core
|
||||
importlib.reload(mz_kolors_core)
|
||||
return mz_kolors_core.MZ_FakeCond_call(kwargs)
|
||||
|
||||
|
||||
NODE_CLASS_MAPPINGS["MZ_FakeCond"] = MZ_FakeCond
|
||||
NODE_DISPLAY_NAME_MAPPINGS[
|
||||
"MZ_FakeCond"] = f"{AUTHOR_NAME} - FakeCond"
|
||||
|
||||
|
||||
class MZ_ChatGLM3Loader:
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
# from .mz_kolors_utils import Utils
|
||||
# llm_dir = os.path.join(Utils.get_models_path(), "LLM")
|
||||
from .mz_kolors_utils import Utils
|
||||
llm_dir = os.path.join(Utils.get_models_path(), "LLM")
|
||||
# print("llm_dir:", llm_dir)
|
||||
llm_models = folder_paths.get_filename_list("LLM")
|
||||
|
||||
# 筛选safetensors结尾的文件
|
||||
llm_models = [
|
||||
model for model in llm_models if model.endswith("safetensors")]
|
||||
llm_models = Utils.listdir_models(llm_dir)
|
||||
|
||||
return {"required": {
|
||||
"chatglm3_checkpoint": (llm_models,),
|
||||
@@ -51,13 +68,14 @@ NODE_CLASS_MAPPINGS["MZ_ChatGLM3Loader"] = MZ_ChatGLM3Loader
|
||||
NODE_DISPLAY_NAME_MAPPINGS["MZ_ChatGLM3Loader"] = f"{AUTHOR_NAME} - ChatGLM3Loader"
|
||||
|
||||
|
||||
class MZ_ChatGLM3TextEncodeV2:
|
||||
class MZ_ChatGLM3TextEncode:
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"chatglm3_model": ("CHATGLM3MODEL", ),
|
||||
"text": ("STRING", {"multiline": True, "dynamicPrompts": True}),
|
||||
"hid_proj": ("TorchLinear", ),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,89 +87,24 @@ class MZ_ChatGLM3TextEncodeV2:
|
||||
def encode(self, **kwargs):
|
||||
from . import mz_kolors_core
|
||||
importlib.reload(mz_kolors_core)
|
||||
return mz_kolors_core.MZ_ChatGLM3TextEncodeV2_call(kwargs)
|
||||
return mz_kolors_core.MZ_ChatGLM3TextEncode_call(kwargs)
|
||||
|
||||
|
||||
NODE_CLASS_MAPPINGS["MZ_ChatGLM3_V2"] = MZ_ChatGLM3TextEncodeV2
|
||||
NODE_CLASS_MAPPINGS["MZ_ChatGLM3"] = MZ_ChatGLM3TextEncode
|
||||
NODE_DISPLAY_NAME_MAPPINGS[
|
||||
"MZ_ChatGLM3_V2"] = f"{AUTHOR_NAME} - ChatGLM3TextEncodeV2"
|
||||
"MZ_ChatGLM3"] = f"{AUTHOR_NAME} - ChatGLM3TextEncode"
|
||||
|
||||
|
||||
class MZ_ChatGLM3Embeds2Conditioning:
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"kolors_embeds": ("KOLORS_EMBEDS", ),
|
||||
"width": ("INT", {"default": 1024.0, "min": 0, "max": MAX_RESOLUTION}),
|
||||
"height": ("INT", {"default": 1024.0, "min": 0, "max": MAX_RESOLUTION}),
|
||||
"crop_w": ("INT", {"default": 0, "min": 0, "max": MAX_RESOLUTION}),
|
||||
"crop_h": ("INT", {"default": 0, "min": 0, "max": MAX_RESOLUTION}),
|
||||
"target_width": ("INT", {"default": 1024.0, "min": 0, "max": MAX_RESOLUTION}),
|
||||
"target_height": ("INT", {"default": 1024.0, "min": 0, "max": MAX_RESOLUTION}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("CONDITIONING", "CONDITIONING",)
|
||||
RETURN_NAMES = ("positive", "negative",)
|
||||
|
||||
FUNCTION = "embeds2conditioning"
|
||||
CATEGORY = CATEGORY_NAME
|
||||
|
||||
def embeds2conditioning(self, **kwargs):
|
||||
from . import mz_kolors_core
|
||||
importlib.reload(mz_kolors_core)
|
||||
return mz_kolors_core.MZ_ChatGLM3Embeds2Conditioning_call(kwargs)
|
||||
|
||||
|
||||
NODE_CLASS_MAPPINGS["MZ_ChatGLM3Embeds2Conditioning"] = MZ_ChatGLM3Embeds2Conditioning
|
||||
NODE_DISPLAY_NAME_MAPPINGS[
|
||||
"MZ_ChatGLM3Embeds2Conditioning"] = f"{AUTHOR_NAME} - ChatGLM3Embeds2Conditioning"
|
||||
|
||||
|
||||
# for 2048 resolution
|
||||
class MZ_ChatGLM3TextEncodeAdvanceV2:
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"chatglm3_model": ("CHATGLM3MODEL", ),
|
||||
"text": ("STRING", {"multiline": True, "dynamicPrompts": True}),
|
||||
"width": ("INT", {"default": 1024.0, "min": 0, "max": MAX_RESOLUTION}),
|
||||
"height": ("INT", {"default": 1024.0, "min": 0, "max": MAX_RESOLUTION}),
|
||||
"crop_w": ("INT", {"default": 0, "min": 0, "max": MAX_RESOLUTION}),
|
||||
"crop_h": ("INT", {"default": 0, "min": 0, "max": MAX_RESOLUTION}),
|
||||
"target_width": ("INT", {"default": 1024.0, "min": 0, "max": MAX_RESOLUTION}),
|
||||
"target_height": ("INT", {"default": 1024.0, "min": 0, "max": MAX_RESOLUTION}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("CONDITIONING",)
|
||||
|
||||
FUNCTION = "encode"
|
||||
CATEGORY = CATEGORY_NAME
|
||||
|
||||
def encode(self, **kwargs):
|
||||
from . import mz_kolors_core
|
||||
importlib.reload(mz_kolors_core)
|
||||
return mz_kolors_core.MZ_ChatGLM3TextEncodeV2_call(kwargs)
|
||||
|
||||
|
||||
NODE_CLASS_MAPPINGS["MZ_ChatGLM3_Advance_V2"] = MZ_ChatGLM3TextEncodeAdvanceV2
|
||||
NODE_DISPLAY_NAME_MAPPINGS[
|
||||
"MZ_ChatGLM3_Advance_V2"] = f"{AUTHOR_NAME} - ChatGLM3TextEncodeAdvanceV2"
|
||||
|
||||
|
||||
class MZ_KolorsUNETLoaderV2():
|
||||
class MZ_KolorsUNETLoader():
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {"required": {
|
||||
"unet_name": (folder_paths.get_filename_list("unet"), ),
|
||||
}}
|
||||
|
||||
RETURN_TYPES = ("MODEL",)
|
||||
RETURN_TYPES = ("MODEL", "TorchLinear")
|
||||
|
||||
RETURN_NAMES = ("model",)
|
||||
RETURN_NAMES = ("model", "hid_proj")
|
||||
|
||||
FUNCTION = "load_unet"
|
||||
|
||||
@@ -160,72 +113,9 @@ class MZ_KolorsUNETLoaderV2():
|
||||
def load_unet(self, **kwargs):
|
||||
from . import mz_kolors_core
|
||||
importlib.reload(mz_kolors_core)
|
||||
return mz_kolors_core.MZ_KolorsUNETLoaderV2_call(kwargs)
|
||||
return mz_kolors_core.MZ_KolorsUNETLoader_call(kwargs)
|
||||
|
||||
|
||||
NODE_CLASS_MAPPINGS["MZ_KolorsUNETLoaderV2"] = MZ_KolorsUNETLoaderV2
|
||||
NODE_CLASS_MAPPINGS["MZ_KolorsUNETLoader"] = MZ_KolorsUNETLoader
|
||||
NODE_DISPLAY_NAME_MAPPINGS[
|
||||
"MZ_KolorsUNETLoaderV2"] = f"{AUTHOR_NAME} - KolorsUNETLoaderV2"
|
||||
|
||||
|
||||
class MZ_KolorsControlNetPatch:
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"control_net": ("CONTROL_NET", ),
|
||||
"model": ("MODEL", ),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("CONTROL_NET",)
|
||||
|
||||
FUNCTION = "start"
|
||||
CATEGORY = CATEGORY_NAME
|
||||
|
||||
def start(self, **kwargs):
|
||||
from . import mz_kolors_core
|
||||
importlib.reload(mz_kolors_core)
|
||||
return mz_kolors_core.MZ_KolorsControlNetPatch_call(kwargs)
|
||||
|
||||
|
||||
NODE_CLASS_MAPPINGS["MZ_KolorsControlNetPatch"] = MZ_KolorsControlNetPatch
|
||||
NODE_DISPLAY_NAME_MAPPINGS[
|
||||
"MZ_KolorsControlNetPatch"] = f"{AUTHOR_NAME} - KolorsControlNetPatch"
|
||||
|
||||
|
||||
class MZ_KolorsCLIPVisionLoader:
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {"required": {"clip_name": (folder_paths.get_filename_list("clip_vision"), ),
|
||||
}}
|
||||
RETURN_TYPES = ("CLIP_VISION",)
|
||||
FUNCTION = "load_clip"
|
||||
|
||||
CATEGORY = CATEGORY_NAME + "/Legacy"
|
||||
|
||||
def load_clip(self, **kwargs):
|
||||
from . import mz_kolors_core
|
||||
importlib.reload(mz_kolors_core)
|
||||
return mz_kolors_core.MZ_KolorsCLIPVisionLoader_call(kwargs)
|
||||
|
||||
|
||||
NODE_CLASS_MAPPINGS["MZ_KolorsCLIPVisionLoader"] = MZ_KolorsCLIPVisionLoader
|
||||
NODE_DISPLAY_NAME_MAPPINGS["MZ_KolorsCLIPVisionLoader"] = f"{AUTHOR_NAME} - KolorsCLIPVisionLoader - Legacy"
|
||||
|
||||
|
||||
from .ComfyUI_IPAdapter_plus.IPAdapterPlus import IPAdapterAdvanced, IPAdapterModelLoader
|
||||
|
||||
IPAdapterModelLoader.CATEGORY = CATEGORY_NAME + "/Legacy"
|
||||
NODE_CLASS_MAPPINGS["MZ_IPAdapterModelLoaderKolors"] = IPAdapterModelLoader
|
||||
NODE_DISPLAY_NAME_MAPPINGS[
|
||||
"MZ_IPAdapterModelLoaderKolors"] = f"IPAdapterModelLoader(kolors) - Legacy"
|
||||
|
||||
IPAdapterAdvanced.CATEGORY = CATEGORY_NAME + "/Legacy"
|
||||
NODE_CLASS_MAPPINGS["MZ_IPAdapterAdvancedKolors"] = IPAdapterAdvanced
|
||||
NODE_DISPLAY_NAME_MAPPINGS[
|
||||
"MZ_IPAdapterAdvancedKolors"] = f"IPAdapterAdvanced(kolors) - Legacy"
|
||||
|
||||
from . import mz_kolors_legacy
|
||||
NODE_CLASS_MAPPINGS.update(mz_kolors_legacy.NODE_CLASS_MAPPINGS)
|
||||
NODE_DISPLAY_NAME_MAPPINGS.update(mz_kolors_legacy.NODE_DISPLAY_NAME_MAPPINGS)
|
||||
"MZ_KolorsUNETLoader"] = f"{AUTHOR_NAME} - Kolors UNET Loader"
|
||||
|
||||
@@ -15,26 +15,6 @@ logger = logging.get_logger(__name__)
|
||||
try:
|
||||
from cpm_kernels.kernels.base import LazyKernelCModule, KernelFunction, round_up
|
||||
|
||||
import cpm_kernels.library.base
|
||||
|
||||
original_windows_find_lib = cpm_kernels.library.base.windows_find_lib
|
||||
|
||||
def windows_find_lib(name):
|
||||
result = original_windows_find_lib(name)
|
||||
if result is not None:
|
||||
return result
|
||||
import torch
|
||||
import os
|
||||
torch_dir = os.path.dirname(torch.__file__)
|
||||
torch_lib_dir = os.path.join(torch_dir, "lib")
|
||||
|
||||
for name in os.listdir(torch_lib_dir):
|
||||
if name.startswith(name) and name.lower().endswith(".dll"):
|
||||
return os.path.join(torch_lib_dir, name)
|
||||
|
||||
return None
|
||||
cpm_kernels.library.base.windows_find_lib = windows_find_lib
|
||||
|
||||
class Kernel:
|
||||
def __init__(self, code: bytes, function_names: List[str]):
|
||||
self.code = code
|
||||
@@ -157,11 +137,8 @@ class QuantizedLinear(torch.nn.Module):
|
||||
self.weight = torch.round(weight / self.weight_scale[:, None]).to(torch.int8)
|
||||
if weight_bit_width == 4:
|
||||
self.weight = compress_int4_weight(self.weight)
|
||||
|
||||
try:
|
||||
self.weight = Parameter(self.weight.to(device), requires_grad=False)
|
||||
except:
|
||||
self.weight.to(device, dtype=self.weight.dtype)
|
||||
|
||||
self.weight = Parameter(self.weight.to(device), requires_grad=False)
|
||||
self.weight_scale = Parameter(self.weight_scale.to(device), requires_grad=False)
|
||||
self.bias = Parameter(bias.to(device), requires_grad=False) if bias is not None else None
|
||||
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
{
|
||||
"attention_dropout": 0.0,
|
||||
"dropout": 0.0,
|
||||
"hidden_act": "quick_gelu",
|
||||
"hidden_size": 1024,
|
||||
"image_size": 336,
|
||||
"initializer_factor": 1.0,
|
||||
"initializer_range": 0.02,
|
||||
"intermediate_size": 4096,
|
||||
"layer_norm_eps": 1e-05,
|
||||
"model_type": "clip_vision_model",
|
||||
"num_attention_heads": 16,
|
||||
"num_channels": 3,
|
||||
"num_hidden_layers": 24,
|
||||
"patch_size": 14,
|
||||
"projection_dim": 768,
|
||||
"torch_dtype": "float32"
|
||||
}
|
||||
|
||||
|
Before Width: | Height: | Size: 485 KiB After Width: | Height: | Size: 485 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 718 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 1.1 MiB |
Binary file not shown.
|
Before Width: | Height: | Size: 1.1 MiB |
@@ -12,6 +12,25 @@ class Kolors(comfy.supported_models.SDXL):
|
||||
"adm_in_channels": 5632,
|
||||
"use_temporal_attention": False,
|
||||
}
|
||||
|
||||
def process_clip_state_dict(self, state_dict):
|
||||
raise NotImplementedError("Kolors does not support clip state dict processing")
|
||||
return state_dict
|
||||
|
||||
|
||||
def process_clip_state_dict_for_saving(self, state_dict):
|
||||
raise NotImplementedError("Kolors does not support clip state dict processing")
|
||||
return state_dict
|
||||
|
||||
|
||||
def clip_target(self):
|
||||
raise NotImplementedError("Kolors does not support clip target")
|
||||
# return supported_models_base.ClipTarget(sdxl_clip.SDXLTokenizer, sdxl_clip.SDXLClipModel)
|
||||
|
||||
|
||||
|
||||
if Kolors not in comfy.supported_models.models:
|
||||
comfy.supported_models.models += [Kolors]
|
||||
|
||||
|
||||
def kolors_unet_config_from_diffusers_unet(state_dict, dtype=None):
|
||||
@@ -71,15 +90,8 @@ def kolors_unet_config_from_diffusers_unet(state_dict, dtype=None):
|
||||
|
||||
class apply_kolors:
|
||||
def __enter__(self):
|
||||
import comfy.supported_models
|
||||
self.old_supported_models = comfy.supported_models.models
|
||||
comfy.supported_models.models = [Kolors]
|
||||
|
||||
self.old_unet_config_from_diffusers_unet = model_detection.unet_config_from_diffusers_unet
|
||||
model_detection.unet_config_from_diffusers_unet = kolors_unet_config_from_diffusers_unet
|
||||
|
||||
def __exit__(self, type, value, traceback):
|
||||
model_detection.unet_config_from_diffusers_unet = self.old_unet_config_from_diffusers_unet
|
||||
|
||||
import comfy.supported_models
|
||||
comfy.supported_models.models = self.old_supported_models
|
||||
@@ -1,258 +0,0 @@
|
||||
import os
|
||||
from types import MethodType
|
||||
import warnings
|
||||
from comfy.model_detection import *
|
||||
import comfy.model_detection as model_detection
|
||||
import comfy.supported_models
|
||||
import comfy.utils
|
||||
|
||||
import torch
|
||||
from comfy import model_base
|
||||
from comfy.model_base import sdxl_pooled, CLIPEmbeddingNoiseAugmentation, Timestep, ModelType
|
||||
|
||||
|
||||
from comfy.ldm.modules.diffusionmodules.openaimodel import UNetModel
|
||||
|
||||
|
||||
# try:
|
||||
# import comfy.samplers as samplers
|
||||
# original_CFGGuider_inner_set_conds = samplers.CFGGuider.set_conds
|
||||
|
||||
# def patched_set_conds(self, positive, negative):
|
||||
# if isinstance(self.model_patcher.model, KolorsSDXL):
|
||||
# import copy
|
||||
# if "control" in positive[0][1]:
|
||||
# if hasattr(positive[0][1]["control"], "control_model"):
|
||||
# if positive[0][1]["control"].control_model.label_emb.shape[1] == 5632:
|
||||
# return
|
||||
|
||||
|
||||
# warnings.warn("该方法不再维护")
|
||||
# positive = copy.deepcopy(positive)
|
||||
# negative = copy.deepcopy(negative)
|
||||
# hid_proj = self.model_patcher.model.encoder_hid_proj
|
||||
# if hid_proj is not None:
|
||||
# positive[0][0] = hid_proj(positive[0][0])
|
||||
# negative[0][0] = hid_proj(negative[0][0])
|
||||
|
||||
# if "control" in positive[0][1]:
|
||||
# if hasattr(positive[0][1]["control"], "control_model"):
|
||||
# positive[0][1]["control"].control_model.label_emb = self.model_patcher.model.diffusion_model.label_emb
|
||||
|
||||
# if "control" in negative[0][1]:
|
||||
# if hasattr(negative[0][1]["control"], "control_model"):
|
||||
# negative[0][1]["control"].control_model.label_emb = self.model_patcher.model.diffusion_model.label_emb
|
||||
|
||||
# return original_CFGGuider_inner_set_conds(self, positive, negative)
|
||||
|
||||
# samplers.CFGGuider.set_conds = patched_set_conds
|
||||
# except ImportError:
|
||||
# print("CFGGuider not found, skipping patching")
|
||||
|
||||
|
||||
class KolorsUNetModel(UNetModel):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
self.encoder_hid_proj = nn.Linear(
|
||||
4096, 2048, bias=True)
|
||||
|
||||
def forward(self, *args, **kwargs):
|
||||
with torch.cuda.amp.autocast(enabled=True):
|
||||
if "context" in kwargs:
|
||||
kwargs["context"] = self.encoder_hid_proj(
|
||||
kwargs["context"])
|
||||
|
||||
# if "y" in kwargs:
|
||||
# if kwargs["y"].shape[1] == 2816:
|
||||
# # 扩展至5632
|
||||
# kwargs["y"] = torch.cat(
|
||||
# torch.zeros(kwargs["y"].shape[0], 2816).to(kwargs["y"].device), kwargs["y"], dim=1)
|
||||
|
||||
result = super().forward(*args, **kwargs)
|
||||
return result
|
||||
|
||||
|
||||
class KolorsSDXL(model_base.SDXL):
|
||||
def __init__(self, model_config, model_type=ModelType.EPS, device=None):
|
||||
model_config.sampling_settings["beta_schedule"] = "linear"
|
||||
model_config.sampling_settings["linear_start"] = 0.00085
|
||||
model_config.sampling_settings["linear_end"] = 0.014
|
||||
model_config.sampling_settings["timesteps"] = 1100
|
||||
model_type = ModelType.EPS
|
||||
model_base.BaseModel.__init__(
|
||||
self, model_config, model_type, device=device, unet_model=KolorsUNetModel)
|
||||
self.embedder = Timestep(256)
|
||||
self.noise_augmentor = CLIPEmbeddingNoiseAugmentation(
|
||||
**{"noise_schedule_config": {"timesteps": 1100, "beta_schedule": "linear", "linear_start": 0.00085, "linear_end": 0.014}, "timestep_dim": 1280})
|
||||
|
||||
def encode_adm(self, **kwargs):
|
||||
clip_pooled = sdxl_pooled(kwargs, self.noise_augmentor)
|
||||
width = kwargs.get("width", 768)
|
||||
height = kwargs.get("height", 768)
|
||||
crop_w = kwargs.get("crop_w", 0)
|
||||
crop_h = kwargs.get("crop_h", 0)
|
||||
target_width = kwargs.get("target_width", width)
|
||||
target_height = kwargs.get("target_height", height)
|
||||
|
||||
out = []
|
||||
out.append(self.embedder(torch.Tensor([height])))
|
||||
out.append(self.embedder(torch.Tensor([width])))
|
||||
out.append(self.embedder(torch.Tensor([crop_h])))
|
||||
out.append(self.embedder(torch.Tensor([crop_w])))
|
||||
out.append(self.embedder(torch.Tensor([target_height])))
|
||||
out.append(self.embedder(torch.Tensor([target_width])))
|
||||
flat = torch.flatten(torch.cat(out)).unsqueeze(
|
||||
dim=0).repeat(clip_pooled.shape[0], 1)
|
||||
return torch.cat((clip_pooled.to(flat.device), flat), dim=1)
|
||||
|
||||
|
||||
class KolorsSupported(comfy.supported_models.SDXL):
|
||||
unet_config = {
|
||||
"model_channels": 320,
|
||||
"use_linear_in_transformer": True,
|
||||
"transformer_depth": [0, 0, 2, 2, 10, 10],
|
||||
"context_dim": 2048,
|
||||
"adm_in_channels": 5632,
|
||||
"use_temporal_attention": False,
|
||||
}
|
||||
|
||||
def get_model(self, state_dict, prefix="", device=None):
|
||||
out = KolorsSDXL(self, model_type=self.model_type(
|
||||
state_dict, prefix), device=device,)
|
||||
out.__class__ = model_base.SDXL
|
||||
if self.inpaint_model():
|
||||
out.set_inpaint()
|
||||
return out
|
||||
|
||||
|
||||
def kolors_unet_config_from_diffusers_unet(state_dict, dtype=None):
|
||||
match = {}
|
||||
transformer_depth = []
|
||||
|
||||
attn_res = 1
|
||||
down_blocks = count_blocks(state_dict, "down_blocks.{}")
|
||||
for i in range(down_blocks):
|
||||
attn_blocks = count_blocks(
|
||||
state_dict, "down_blocks.{}.attentions.".format(i) + '{}')
|
||||
res_blocks = count_blocks(
|
||||
state_dict, "down_blocks.{}.resnets.".format(i) + '{}')
|
||||
for ab in range(attn_blocks):
|
||||
transformer_count = count_blocks(
|
||||
state_dict, "down_blocks.{}.attentions.{}.transformer_blocks.".format(i, ab) + '{}')
|
||||
transformer_depth.append(transformer_count)
|
||||
if transformer_count > 0:
|
||||
match["context_dim"] = state_dict["down_blocks.{}.attentions.{}.transformer_blocks.0.attn2.to_k.weight".format(
|
||||
i, ab)].shape[1]
|
||||
|
||||
attn_res *= 2
|
||||
if attn_blocks == 0:
|
||||
for i in range(res_blocks):
|
||||
transformer_depth.append(0)
|
||||
|
||||
match["transformer_depth"] = transformer_depth
|
||||
|
||||
match["model_channels"] = state_dict["conv_in.weight"].shape[0]
|
||||
match["in_channels"] = state_dict["conv_in.weight"].shape[1]
|
||||
match["adm_in_channels"] = None
|
||||
if "class_embedding.linear_1.weight" in state_dict:
|
||||
match["adm_in_channels"] = state_dict["class_embedding.linear_1.weight"].shape[1]
|
||||
elif "add_embedding.linear_1.weight" in state_dict:
|
||||
match["adm_in_channels"] = state_dict["add_embedding.linear_1.weight"].shape[1]
|
||||
|
||||
Kolors = {'use_checkpoint': False, 'image_size': 32, 'out_channels': 4, 'use_spatial_transformer': True, 'legacy': False,
|
||||
'num_classes': 'sequential', 'adm_in_channels': 5632, 'dtype': dtype, 'in_channels': 4, 'model_channels': 320,
|
||||
'num_res_blocks': [2, 2, 2], 'transformer_depth': [0, 0, 2, 2, 10, 10], 'channel_mult': [1, 2, 4], 'transformer_depth_middle': 10,
|
||||
'use_linear_in_transformer': True, 'context_dim': 2048, 'num_head_channels': 64, 'transformer_depth_output': [0, 0, 0, 2, 2, 2, 10, 10, 10],
|
||||
'use_temporal_attention': False, 'use_temporal_resblock': False}
|
||||
|
||||
supported_models = [Kolors]
|
||||
|
||||
for unet_config in supported_models:
|
||||
matches = True
|
||||
for k in match:
|
||||
if match[k] != unet_config[k]:
|
||||
print("key {} does not match".format(
|
||||
k), match[k], "||", unet_config[k])
|
||||
matches = False
|
||||
break
|
||||
if matches:
|
||||
return convert_config(unet_config)
|
||||
return None
|
||||
|
||||
|
||||
import comfy.ldm.modules.diffusionmodules.openaimodel
|
||||
from torch import nn
|
||||
|
||||
|
||||
def load_clipvision_336_from_sd(sd, prefix="", convert_keys=False):
|
||||
from comfy.clip_vision import ClipVisionModel, convert_to_transformers
|
||||
|
||||
json_config = os.path.join(os.path.dirname(
|
||||
os.path.realpath(__file__)), "clip_vit_336", "config.json")
|
||||
|
||||
clip = ClipVisionModel(json_config)
|
||||
|
||||
m, u = clip.load_sd(sd)
|
||||
if len(m) > 0:
|
||||
logging.warning("missing clip vision: {}".format(m))
|
||||
u = set(u)
|
||||
keys = list(sd.keys())
|
||||
for k in keys:
|
||||
if k not in u:
|
||||
t = sd.pop(k)
|
||||
del t
|
||||
|
||||
# def vis_forward(self, pixel_values, attention_mask=None, intermediate_output=None):
|
||||
# pixel_values = nn.functional.interpolate(
|
||||
# pixel_values, size=(336, 336), mode='bilinear', align_corners=False)
|
||||
# x = self.embeddings(pixel_values)
|
||||
# x = self.pre_layrnorm(x)
|
||||
# # TODO: attention_mask?
|
||||
# x, i = self.encoder(
|
||||
# x, mask=None, intermediate_output=intermediate_output)
|
||||
# pooled_output = self.post_layernorm(x[:, 0, :])
|
||||
# return x, i, pooled_output
|
||||
|
||||
# clip.model.vision_model.forward = MethodType(
|
||||
# vis_forward, clip.model.vision_model
|
||||
# )
|
||||
|
||||
return clip
|
||||
|
||||
|
||||
class apply_kolors:
|
||||
def __enter__(self):
|
||||
import comfy.ldm.modules.diffusionmodules.openaimodel
|
||||
import comfy.utils
|
||||
import comfy.clip_vision
|
||||
|
||||
self.original_load_clipvision_from_sd = comfy.clip_vision.load_clipvision_from_sd
|
||||
comfy.clip_vision.load_clipvision_from_sd = load_clipvision_336_from_sd
|
||||
|
||||
self.original_UNET_MAP_BASIC = comfy.utils.UNET_MAP_BASIC.copy()
|
||||
comfy.utils.UNET_MAP_BASIC.add(
|
||||
("encoder_hid_proj.weight", "encoder_hid_proj.weight"),
|
||||
)
|
||||
comfy.utils.UNET_MAP_BASIC.add(
|
||||
("encoder_hid_proj.bias", "encoder_hid_proj.bias"),
|
||||
)
|
||||
|
||||
self.original_unet_config_from_diffusers_unet = model_detection.unet_config_from_diffusers_unet
|
||||
model_detection.unet_config_from_diffusers_unet = kolors_unet_config_from_diffusers_unet
|
||||
|
||||
import comfy.supported_models
|
||||
self.original_supported_models = comfy.supported_models.models
|
||||
comfy.supported_models.models = [KolorsSupported]
|
||||
|
||||
def __exit__(self, type, value, traceback):
|
||||
import comfy.ldm.modules.diffusionmodules.openaimodel
|
||||
import comfy.utils
|
||||
comfy.utils.UNET_MAP_BASIC = self.original_UNET_MAP_BASIC
|
||||
|
||||
model_detection.unet_config_from_diffusers_unet = self.original_unet_config_from_diffusers_unet
|
||||
|
||||
import comfy.supported_models
|
||||
comfy.supported_models.models = self.original_supported_models
|
||||
|
||||
import comfy.clip_vision
|
||||
comfy.clip_vision.load_clipvision_from_sd = self.original_load_clipvision_from_sd
|
||||
+103
-150
@@ -5,16 +5,13 @@ import json
|
||||
import os
|
||||
import random
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
from types import MethodType
|
||||
|
||||
import torch
|
||||
import folder_paths
|
||||
import comfy.model_management as mm
|
||||
|
||||
|
||||
def chatglm3_text_encode(chatglm3_model, prompt):
|
||||
def KolorsTextEncode(chatglm3_model, prompt):
|
||||
device = mm.get_torch_device()
|
||||
offload_device = mm.unet_offload_device()
|
||||
mm.unload_all_models()
|
||||
@@ -27,6 +24,14 @@ def chatglm3_text_encode(chatglm3_model, prompt):
|
||||
|
||||
prompt = re.sub(r'\{([^{}]*)\}', choose_random_option, prompt)
|
||||
|
||||
if "|" in prompt:
|
||||
prompt = prompt.split("|")
|
||||
|
||||
if prompt is not None and isinstance(prompt, str):
|
||||
batch_size = 1
|
||||
elif prompt is not None and isinstance(prompt, list):
|
||||
batch_size = len(prompt)
|
||||
|
||||
# Define tokenizers and text encoders
|
||||
tokenizer = chatglm3_model['tokenizer']
|
||||
text_encoder = chatglm3_model['text_encoder']
|
||||
@@ -64,13 +69,15 @@ def chatglm3_text_encode(chatglm3_model, prompt):
|
||||
return prompt_embeds, text_proj
|
||||
|
||||
|
||||
import importlib
|
||||
|
||||
|
||||
def MZ_ChatGLM3Loader_call(args):
|
||||
# from .mz_kolors_utils import Utils
|
||||
# llm_dir = os.path.join(Utils.get_models_path(), "LLM")
|
||||
from .mz_kolors_utils import Utils
|
||||
llm_dir = os.path.join(Utils.get_models_path(), "LLM")
|
||||
chatglm3_checkpoint = args.get("chatglm3_checkpoint")
|
||||
|
||||
chatglm3_checkpoint_path = folder_paths.get_full_path(
|
||||
'LLM', chatglm3_checkpoint)
|
||||
chatglm3_checkpoint_path = os.path.join(llm_dir, chatglm3_checkpoint)
|
||||
|
||||
if not os.path.exists(chatglm3_checkpoint_path):
|
||||
raise RuntimeError(
|
||||
@@ -80,6 +87,8 @@ def MZ_ChatGLM3Loader_call(args):
|
||||
from .chatglm3.modeling_chatglm import ChatGLMModel
|
||||
from .chatglm3.tokenization_chatglm import ChatGLMTokenizer
|
||||
|
||||
from .mz_kolors_utils import Utils
|
||||
|
||||
offload_device = mm.unet_offload_device()
|
||||
|
||||
text_encoder_config = os.path.join(
|
||||
@@ -91,7 +100,6 @@ def MZ_ChatGLM3Loader_call(args):
|
||||
|
||||
from comfy.utils import load_torch_file
|
||||
from contextlib import nullcontext
|
||||
is_accelerate_available = False
|
||||
try:
|
||||
from accelerate import init_empty_weights
|
||||
from accelerate.utils import set_module_tensor_to_device
|
||||
@@ -105,13 +113,6 @@ def MZ_ChatGLM3Loader_call(args):
|
||||
print("torch version:", torch.__version__)
|
||||
text_encoder = ChatGLMModel(text_encoder_config).eval()
|
||||
if '4bit' in chatglm3_checkpoint:
|
||||
try:
|
||||
import cpm_kernels
|
||||
except ImportError:
|
||||
print("Installing cpm_kernels...")
|
||||
subprocess.run(
|
||||
[sys.executable, "-m", "pip", "install", "cpm_kernels"], check=True)
|
||||
pass
|
||||
text_encoder.quantize(4)
|
||||
elif '8bit' in chatglm3_checkpoint:
|
||||
text_encoder.quantize(8)
|
||||
@@ -121,8 +122,7 @@ def MZ_ChatGLM3Loader_call(args):
|
||||
set_module_tensor_to_device(
|
||||
text_encoder, key, device=offload_device, value=text_encoder_sd[key])
|
||||
else:
|
||||
print("WARNING: Accelerate not available, use load_state_dict load model")
|
||||
text_encoder.load_state_dict(text_encoder_sd)
|
||||
text_encoder.load_state_dict()
|
||||
|
||||
tokenizer_path = os.path.join(
|
||||
os.path.dirname(__file__), 'configs', "tokenizer")
|
||||
@@ -131,162 +131,115 @@ def MZ_ChatGLM3Loader_call(args):
|
||||
return ({"text_encoder": text_encoder, "tokenizer": tokenizer},)
|
||||
|
||||
|
||||
def MZ_ChatGLM3TextEncodeV2_call(args):
|
||||
def MZ_ChatGLM3TextEncode_call(args):
|
||||
|
||||
text = args.get("text")
|
||||
chatglm3_model = args.get("chatglm3_model")
|
||||
prompt_embeds, pooled_output = chatglm3_text_encode(
|
||||
|
||||
prompt_embeds, pooled_output = KolorsTextEncode(
|
||||
chatglm3_model,
|
||||
text,
|
||||
)
|
||||
extra_kwargs = {
|
||||
"pooled_output": pooled_output,
|
||||
}
|
||||
extra_cond_keys = [
|
||||
"width",
|
||||
"height",
|
||||
"crop_w",
|
||||
"crop_h",
|
||||
"target_width",
|
||||
"target_height"
|
||||
]
|
||||
for key, value in args.items():
|
||||
if key in extra_cond_keys:
|
||||
extra_kwargs[key] = value
|
||||
|
||||
from torch import nn
|
||||
hid_proj: nn.Linear = args.get("hid_proj")
|
||||
|
||||
prompt_embeds = hid_proj(prompt_embeds)
|
||||
|
||||
return ([[
|
||||
prompt_embeds,
|
||||
# {"pooled_output": pooled_output},
|
||||
extra_kwargs
|
||||
{"pooled_output": pooled_output},
|
||||
]], )
|
||||
|
||||
|
||||
def MZ_ChatGLM3Embeds2Conditioning_call(args):
|
||||
kolors_embeds = args.get("kolors_embeds")
|
||||
def load_unet_state_dict(sd): # load unet in diffusers or regular format
|
||||
from comfy import model_management, model_detection
|
||||
import comfy.utils
|
||||
|
||||
# kolors_embeds = {
|
||||
# 'prompt_embeds': prompt_embeds,
|
||||
# 'negative_prompt_embeds': negative_prompt_embeds,
|
||||
# 'pooled_prompt_embeds': text_proj,
|
||||
# 'negative_pooled_prompt_embeds': negative_text_proj
|
||||
# }
|
||||
# Allow loading unets from checkpoint files
|
||||
checkpoint = False
|
||||
diffusion_model_prefix = model_detection.unet_prefix_from_state_dict(sd)
|
||||
temp_sd = comfy.utils.state_dict_prefix_replace(
|
||||
sd, {diffusion_model_prefix: ""}, filter_keys=True)
|
||||
if len(temp_sd) > 0:
|
||||
sd = temp_sd
|
||||
checkpoint = True
|
||||
|
||||
positive = [[
|
||||
kolors_embeds['prompt_embeds'],
|
||||
{
|
||||
"pooled_output": kolors_embeds['pooled_prompt_embeds'],
|
||||
"width": args.get("width"),
|
||||
"height": args.get("height"),
|
||||
"crop_w": args.get("crop_w"),
|
||||
"crop_h": args.get("crop_h"),
|
||||
"target_width": args.get("target_width"),
|
||||
"target_height": args.get("target_height")
|
||||
}
|
||||
]]
|
||||
parameters = comfy.utils.calculate_parameters(sd)
|
||||
unet_dtype = model_management.unet_dtype(model_params=parameters)
|
||||
load_device = model_management.get_torch_device()
|
||||
|
||||
negative = [[
|
||||
kolors_embeds['negative_prompt_embeds'],
|
||||
{
|
||||
"pooled_output": kolors_embeds['negative_pooled_prompt_embeds'],
|
||||
}
|
||||
]]
|
||||
from torch import nn
|
||||
hid_proj: nn.Linear = None
|
||||
if True:
|
||||
model_config = model_detection.model_config_from_diffusers_unet(sd)
|
||||
if model_config is None:
|
||||
return None
|
||||
|
||||
return (positive, negative)
|
||||
diffusers_keys = comfy.utils.unet_to_diffusers(
|
||||
model_config.unet_config)
|
||||
|
||||
new_sd = {}
|
||||
for k in diffusers_keys:
|
||||
if k in sd:
|
||||
new_sd[diffusers_keys[k]] = sd.pop(k)
|
||||
else:
|
||||
print("{} {}".format(diffusers_keys[k], k))
|
||||
|
||||
encoder_hid_proj_weight = sd.pop("encoder_hid_proj.weight")
|
||||
encoder_hid_proj_bias = sd.pop("encoder_hid_proj.bias")
|
||||
hid_proj = nn.Linear(
|
||||
encoder_hid_proj_weight.shape[1], encoder_hid_proj_weight.shape[0])
|
||||
hid_proj.weight.data = encoder_hid_proj_weight
|
||||
hid_proj.bias.data = encoder_hid_proj_bias
|
||||
hid_proj = hid_proj.to(load_device)
|
||||
|
||||
offload_device = model_management.unet_offload_device()
|
||||
unet_dtype = model_management.unet_dtype(
|
||||
model_params=parameters, supported_dtypes=model_config.supported_inference_dtypes)
|
||||
manual_cast_dtype = model_management.unet_manual_cast(
|
||||
unet_dtype, load_device, model_config.supported_inference_dtypes)
|
||||
model_config.set_inference_dtype(unet_dtype, manual_cast_dtype)
|
||||
model = model_config.get_model(new_sd, "")
|
||||
model = model.to(offload_device)
|
||||
model.load_model_weights(new_sd, "")
|
||||
left_over = sd.keys()
|
||||
if len(left_over) > 0:
|
||||
print("left over keys in unet: {}".format(left_over))
|
||||
return comfy.model_patcher.ModelPatcher(model, load_device=load_device, offload_device=offload_device), hid_proj
|
||||
|
||||
|
||||
def MZ_KolorsUNETLoaderV2_call(kwargs):
|
||||
def MZ_KolorsUNETLoader_call(kwargs):
|
||||
|
||||
from . import hook_comfyui_kolors_v2
|
||||
import comfy.sd
|
||||
|
||||
with hook_comfyui_kolors_v2.apply_kolors():
|
||||
from . import hook_comfyui
|
||||
# with hook_comfyui.apply_kolors():
|
||||
if True:
|
||||
unet_name = kwargs.get("unet_name")
|
||||
unet_path = folder_paths.get_full_path("unet", unet_name)
|
||||
import comfy.utils
|
||||
sd = comfy.utils.load_torch_file(unet_path)
|
||||
model = comfy.sd.load_unet_state_dict(sd)
|
||||
comfy.mz_log("add_embedding.linear_1.weight", sd["add_embedding.linear_1.weight"])
|
||||
# add_embedding_linear_1_weight : torch.Size([1280, 5632])
|
||||
add_embedding_linear_1_weight = sd["add_embedding.linear_1.weight"]
|
||||
# new_add_embedding_linear_1_weight : torch.Size([1280, 2816])
|
||||
new_add_embedding_linear_1_weight = add_embedding_linear_1_weight[:, :2816]
|
||||
sd["add_embedding.linear_1.weight"] = new_add_embedding_linear_1_weight
|
||||
|
||||
model, hid_proj = load_unet_state_dict(sd)
|
||||
if model is None:
|
||||
raise RuntimeError(
|
||||
"ERROR: Could not detect model type of: {}".format(unet_path))
|
||||
|
||||
return (model, )
|
||||
return (model, hid_proj)
|
||||
|
||||
|
||||
from comfy.cldm.cldm import ControlNet
|
||||
from comfy.controlnet import ControlLora
|
||||
def MZ_FakeCond_call(kwargs):
|
||||
import torch
|
||||
# cond: torch.Size([1, 77, ])
|
||||
cond = torch.zeros(2, 256, 4096)
|
||||
# torch.Size([1, 1280])
|
||||
pool = torch.zeros(2, 4096)
|
||||
|
||||
|
||||
def MZ_KolorsControlNetPatch_call(kwargs):
|
||||
from . import hook_comfyui_kolors_v2
|
||||
model = kwargs.get("model")
|
||||
control_net = kwargs.get("control_net")
|
||||
import comfy.controlnet
|
||||
if isinstance(control_net, ControlLora):
|
||||
del_keys = []
|
||||
for k in control_net.control_weights:
|
||||
if k.startswith("label_emb.0.0."):
|
||||
del_keys.append(k)
|
||||
|
||||
for k in del_keys:
|
||||
control_net.control_weights.pop(k)
|
||||
|
||||
super_pre_run = ControlLora.pre_run
|
||||
super_copy = ControlLora.copy
|
||||
|
||||
super_forward = ControlNet.forward
|
||||
|
||||
def KolorsControlNet_forward(self, x, hint, timesteps, context, **kwargs):
|
||||
with torch.cuda.amp.autocast(enabled=True):
|
||||
context = model.model.diffusion_model.encoder_hid_proj(context)
|
||||
return super_forward(self, x, hint, timesteps, context, **kwargs)
|
||||
|
||||
def KolorsControlLora_pre_run(self, *args, **kwargs):
|
||||
result = super_pre_run(self, *args, **kwargs)
|
||||
|
||||
if hasattr(self, "control_model"):
|
||||
self.control_model.forward = MethodType(
|
||||
KolorsControlNet_forward, self.control_model)
|
||||
return result
|
||||
|
||||
control_net.pre_run = MethodType(
|
||||
KolorsControlLora_pre_run, control_net)
|
||||
|
||||
def KolorsControlLora_copy(self, *args, **kwargs):
|
||||
c = super_copy(self, *args, **kwargs)
|
||||
c.pre_run = MethodType(
|
||||
KolorsControlLora_pre_run, c)
|
||||
return c
|
||||
|
||||
control_net.copy = MethodType(
|
||||
KolorsControlLora_copy, control_net)
|
||||
|
||||
elif isinstance(control_net, comfy.controlnet.ControlNet):
|
||||
model_label_emb = model.model.diffusion_model.label_emb
|
||||
|
||||
control_net.control_model.label_emb = model_label_emb
|
||||
|
||||
control_net.control_model_wrapped.model.label_emb = model_label_emb
|
||||
|
||||
super_forward = ControlNet.forward
|
||||
|
||||
def KolorsControlNet_forward(self, x, hint, timesteps, context, **kwargs):
|
||||
with torch.cuda.amp.autocast(enabled=True):
|
||||
context = model.model.diffusion_model.encoder_hid_proj(context)
|
||||
return super_forward(self, x, hint, timesteps, context, **kwargs)
|
||||
|
||||
control_net.control_model.forward = MethodType(
|
||||
KolorsControlNet_forward, control_net.control_model)
|
||||
|
||||
else:
|
||||
raise NotImplementedError(
|
||||
f"Type {control_net} not supported for KolorsControlNetPatch")
|
||||
|
||||
return (control_net,)
|
||||
|
||||
|
||||
def MZ_KolorsCLIPVisionLoader_call(kwargs):
|
||||
import comfy.clip_vision
|
||||
from . import hook_comfyui_kolors_v2
|
||||
clip_name = kwargs.get("clip_name")
|
||||
clip_path = folder_paths.get_full_path("clip_vision", clip_name)
|
||||
with hook_comfyui_kolors_v2.apply_kolors():
|
||||
clip_vision = comfy.clip_vision.load(clip_path)
|
||||
return (clip_vision,)
|
||||
return ([[
|
||||
cond,
|
||||
{"pooled_output": pool},
|
||||
]],)
|
||||
|
||||
@@ -1,226 +0,0 @@
|
||||
|
||||
|
||||
import gc
|
||||
import json
|
||||
import os
|
||||
import random
|
||||
import re
|
||||
|
||||
import torch
|
||||
import folder_paths
|
||||
import comfy.model_management as mm
|
||||
from . import mz_kolors_core
|
||||
|
||||
|
||||
def MZ_ChatGLM3TextEncode_call(args):
|
||||
|
||||
text = args.get("text")
|
||||
chatglm3_model = args.get("chatglm3_model")
|
||||
|
||||
prompt_embeds, pooled_output = mz_kolors_core.chatglm3_text_encode(
|
||||
chatglm3_model,
|
||||
text,
|
||||
)
|
||||
|
||||
from torch import nn
|
||||
hid_proj: nn.Linear = args.get("hid_proj")
|
||||
|
||||
if hid_proj.weight.dtype != prompt_embeds.dtype:
|
||||
with torch.cuda.amp.autocast(dtype=hid_proj.weight.dtype):
|
||||
prompt_embeds = hid_proj(prompt_embeds)
|
||||
else:
|
||||
prompt_embeds = hid_proj(prompt_embeds)
|
||||
|
||||
return ([[
|
||||
prompt_embeds,
|
||||
{"pooled_output": pooled_output},
|
||||
]], )
|
||||
|
||||
|
||||
def load_unet_state_dict(sd): # load unet in diffusers or regular format
|
||||
from comfy import model_management, model_detection
|
||||
import comfy.utils
|
||||
|
||||
# Allow loading unets from checkpoint files
|
||||
checkpoint = False
|
||||
diffusion_model_prefix = model_detection.unet_prefix_from_state_dict(sd)
|
||||
temp_sd = comfy.utils.state_dict_prefix_replace(
|
||||
sd, {diffusion_model_prefix: ""}, filter_keys=True)
|
||||
if len(temp_sd) > 0:
|
||||
sd = temp_sd
|
||||
checkpoint = True
|
||||
|
||||
parameters = comfy.utils.calculate_parameters(sd)
|
||||
unet_dtype = model_management.unet_dtype(model_params=parameters)
|
||||
load_device = model_management.get_torch_device()
|
||||
|
||||
from torch import nn
|
||||
hid_proj: nn.Linear = None
|
||||
if True:
|
||||
model_config = model_detection.model_config_from_diffusers_unet(sd)
|
||||
if model_config is None:
|
||||
return None
|
||||
|
||||
diffusers_keys = comfy.utils.unet_to_diffusers(
|
||||
model_config.unet_config)
|
||||
|
||||
new_sd = {}
|
||||
for k in diffusers_keys:
|
||||
if k in sd:
|
||||
new_sd[diffusers_keys[k]] = sd.pop(k)
|
||||
else:
|
||||
print("{} {}".format(diffusers_keys[k], k))
|
||||
|
||||
encoder_hid_proj_weight = sd.pop("encoder_hid_proj.weight")
|
||||
encoder_hid_proj_bias = sd.pop("encoder_hid_proj.bias")
|
||||
hid_proj = nn.Linear(
|
||||
encoder_hid_proj_weight.shape[1], encoder_hid_proj_weight.shape[0])
|
||||
hid_proj.weight.data = encoder_hid_proj_weight
|
||||
hid_proj.bias.data = encoder_hid_proj_bias
|
||||
hid_proj = hid_proj.to(load_device)
|
||||
|
||||
offload_device = model_management.unet_offload_device()
|
||||
unet_dtype = model_management.unet_dtype(
|
||||
model_params=parameters, supported_dtypes=model_config.supported_inference_dtypes)
|
||||
manual_cast_dtype = model_management.unet_manual_cast(
|
||||
unet_dtype, load_device, model_config.supported_inference_dtypes)
|
||||
model_config.set_inference_dtype(unet_dtype, manual_cast_dtype)
|
||||
model = model_config.get_model(new_sd, "")
|
||||
model = model.to(offload_device)
|
||||
model.load_model_weights(new_sd, "")
|
||||
left_over = sd.keys()
|
||||
if len(left_over) > 0:
|
||||
print("left over keys in unet: {}".format(left_over))
|
||||
return comfy.model_patcher.ModelPatcher(model, load_device=load_device, offload_device=offload_device), hid_proj
|
||||
|
||||
|
||||
def MZ_KolorsUNETLoader_call(kwargs):
|
||||
|
||||
from . import hook_comfyui_kolors_v1
|
||||
with hook_comfyui_kolors_v1.apply_kolors():
|
||||
unet_name = kwargs.get("unet_name")
|
||||
unet_path = folder_paths.get_full_path("unet", unet_name)
|
||||
import comfy.utils
|
||||
sd = comfy.utils.load_torch_file(unet_path)
|
||||
model, hid_proj = load_unet_state_dict(sd)
|
||||
if model is None:
|
||||
raise RuntimeError(
|
||||
"ERROR: Could not detect model type of: {}".format(unet_path))
|
||||
return (model, hid_proj)
|
||||
|
||||
|
||||
def MZ_FakeCond_call(kwargs):
|
||||
import torch
|
||||
cond = torch.zeros(2, 256, 4096)
|
||||
pool = torch.zeros(2, 4096)
|
||||
|
||||
dtype = kwargs.get("dtype")
|
||||
if dtype == "fp16":
|
||||
print("fp16")
|
||||
cond = cond.half()
|
||||
pool = pool.half()
|
||||
elif dtype == "bf16":
|
||||
print("bf16")
|
||||
cond = cond.bfloat16()
|
||||
pool = pool.bfloat16()
|
||||
else:
|
||||
print("fp32")
|
||||
cond = cond.float()
|
||||
pool = pool.float()
|
||||
|
||||
return ([[
|
||||
cond,
|
||||
{"pooled_output": pool},
|
||||
]],)
|
||||
|
||||
|
||||
NODE_CLASS_MAPPINGS = {
|
||||
}
|
||||
|
||||
|
||||
NODE_DISPLAY_NAME_MAPPINGS = {
|
||||
}
|
||||
|
||||
AUTHOR_NAME = "MinusZone"
|
||||
CATEGORY_NAME = f"{AUTHOR_NAME} - Kolors"
|
||||
|
||||
|
||||
class MZ_ChatGLM3TextEncode:
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"chatglm3_model": ("CHATGLM3MODEL", ),
|
||||
"text": ("STRING", {"multiline": True, "dynamicPrompts": True}),
|
||||
"hid_proj": ("TorchLinear", ),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("CONDITIONING",)
|
||||
|
||||
FUNCTION = "encode"
|
||||
CATEGORY = CATEGORY_NAME + "/Legacy"
|
||||
|
||||
def encode(self, **kwargs):
|
||||
return MZ_ChatGLM3TextEncode_call(kwargs)
|
||||
|
||||
|
||||
NODE_CLASS_MAPPINGS["MZ_ChatGLM3"] = MZ_ChatGLM3TextEncode
|
||||
NODE_DISPLAY_NAME_MAPPINGS[
|
||||
"MZ_ChatGLM3"] = f"{AUTHOR_NAME} - ChatGLM3TextEncode"
|
||||
|
||||
|
||||
class MZ_KolorsUNETLoader():
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {"required": {
|
||||
"unet_name": (folder_paths.get_filename_list("unet"), ),
|
||||
}}
|
||||
|
||||
RETURN_TYPES = ("MODEL", "TorchLinear")
|
||||
|
||||
RETURN_NAMES = ("model", "hid_proj")
|
||||
|
||||
FUNCTION = "load_unet"
|
||||
|
||||
CATEGORY = CATEGORY_NAME + "/Legacy"
|
||||
|
||||
def load_unet(self, **kwargs):
|
||||
return MZ_KolorsUNETLoader_call(kwargs)
|
||||
|
||||
|
||||
NODE_CLASS_MAPPINGS["MZ_KolorsUNETLoader"] = MZ_KolorsUNETLoader
|
||||
NODE_DISPLAY_NAME_MAPPINGS[
|
||||
"MZ_KolorsUNETLoader"] = f"{AUTHOR_NAME} - Kolors UNET Loader"
|
||||
|
||||
|
||||
class MZ_FakeCond:
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"seed": ("INT", {"default": 0}),
|
||||
"dtype": ([
|
||||
"fp32",
|
||||
"fp16",
|
||||
"bf16",
|
||||
],),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("CONDITIONING", )
|
||||
RETURN_NAMES = ("prompt", )
|
||||
FUNCTION = "encode"
|
||||
CATEGORY = CATEGORY_NAME
|
||||
|
||||
def encode(self, **kwargs):
|
||||
return MZ_FakeCond_call(kwargs)
|
||||
|
||||
|
||||
try:
|
||||
if os.environ.get("MZ_DEV", None) is not None:
|
||||
NODE_CLASS_MAPPINGS["MZ_FakeCond"] = MZ_FakeCond
|
||||
NODE_DISPLAY_NAME_MAPPINGS[
|
||||
"MZ_FakeCond"] = f"{AUTHOR_NAME} - FakeCond"
|
||||
except ImportError:
|
||||
pass
|
||||
+56
-2
@@ -927,9 +927,63 @@ class Utils:
|
||||
m for m in source_model_zoo_json if tags_filter in m["tags"]]
|
||||
|
||||
return source_model_zoo_json
|
||||
|
||||
|
||||
|
||||
modelscope_models_map = {
|
||||
|
||||
"llama3": {
|
||||
"Meta-Llama-3-8B-Instruct.Q4_K_M.gguf": {
|
||||
"url": "https://www.modelscope.cn/api/v1/models/wailovet/MinusZoneAIModels/repo?Revision=master&FilePath=Meta-Llama-3-8B-Instruct-GGUF%2FMeta-Llama-3-8B-Instruct.Q4_K_M.gguf",
|
||||
"output": "modelscope_models/Meta-Llama-3-8B-Instruct-GGUF/Meta-Llama-3-8B-Instruct.Q4_K_M.gguf",
|
||||
"SHA256": "647a2b64cbcdbe670432d0502ebb2592b36dd364d51a9ef7a1387b7a4365781f",
|
||||
},
|
||||
},
|
||||
"llava": {
|
||||
"ggml_bakllava-1/ggml-model-q5_k.gguf": {
|
||||
"url": "https://www.modelscope.cn/api/v1/models/wailovet/MinusZoneAIModels/repo?Revision=master&FilePath=ggml_bakllava-1%2Fggml-model-q5_k.gguf",
|
||||
"output": "modelscope_models/ggml_bakllava-1/ggml-model-q5_k.gguf",
|
||||
"SHA256": "c93de1376be9b6977cc94d252a3d165d6059e07b528de0fa762534d9599b27d6",
|
||||
},
|
||||
"ggml_llava-v1.5-7b/ggml-model-q4_k.gguf": {
|
||||
"url": "https://www.modelscope.cn/api/v1/models/wailovet/MinusZoneAIModels/repo?Revision=master&FilePath=ggml_llava-v1.5-7b%2Fggml-model-q4_k.gguf",
|
||||
"output": "modelscope_models/ggml_llava-v1.5-7b/ggml-model-q4_k.gguf",
|
||||
"SHA256": "7ac9c2f7b8d76cc7f3118cdf0953ebab7a7a9b12bad5dbe237219d2ab61765ea",
|
||||
},
|
||||
"ggml_bakllava-1/mmproj-model-f16.gguf": {
|
||||
"url": "https://www.modelscope.cn/api/v1/models/wailovet/MinusZoneAIModels/repo?Revision=master&FilePath=ggml_bakllava-1%2Fmmproj-model-f16.gguf",
|
||||
"output": "modelscope_models/ggml_bakllava-1/mmproj-model-f16.gguf",
|
||||
"SHA256": "2e467eba710002839e0966d5e329942bb836eabd4e787bc713b07eff1d8ea13b"
|
||||
},
|
||||
"ggml_llava-v1.5-7b/mmproj-model-f16.gguf": {
|
||||
"url": "https://www.modelscope.cn/api/v1/models/wailovet/MinusZoneAIModels/repo?Revision=master&FilePath=ggml_llava-v1.5-7b%2Fmmproj-model-f16.gguf",
|
||||
"output": "modelscope_models/ggml_llava-v1.5-7b/mmproj-model-f16.gguf",
|
||||
"SHA256": "b7c8ff0f58fca47d28ba92c4443adf8653f3349282cb8d9e6911f22d9b3814fe"
|
||||
},
|
||||
"llava-v1.6-vicuna-13b-gguf/llava-v1.6-vicuna-13b.Q5_K_M.gguf": {
|
||||
"url": "https://www.modelscope.cn/api/v1/models/wailovet/MinusZoneAIModels/repo?Revision=master&FilePath=llava-v1.6-vicuna-13b-gguf%2Fllava-v1.6-vicuna-13b.Q5_K_M.gguf",
|
||||
"output": "modelscope_models/llava-v1.6-vicuna-13b-gguf/llava-v1.6-vicuna-13b.Q5_K_M.gguf",
|
||||
"SHA256": "fac8ecd642ac1c2dd8ef8fb6d6daac349293051b468f5fdc21921b94dfb2916a",
|
||||
},
|
||||
"llava-v1.6-vicuna-13b-gguf/mmproj-model-f16.gguf": {
|
||||
"url": "https://www.modelscope.cn/api/v1/models/wailovet/MinusZoneAIModels/repo?Revision=master&FilePath=llava-v1.6-vicuna-13b-gguf%2Fmmproj-model-f16.gguf",
|
||||
"output": "modelscope_models/llava-v1.6-vicuna-13b-gguf/mmproj-model-f16.gguf",
|
||||
"SHA256": "9860fbc162d6df40d12f32211aed11ab4826e16e473e6fff595496b9943872e2"
|
||||
},
|
||||
"llava-1.6-mistral-7b-gguf/llava-v1.6-mistral-7b.Q5_K_M.gguf": {
|
||||
"url": "https://www.modelscope.cn/api/v1/models/wailovet/MinusZoneAIModels/repo?Revision=master&FilePath=llava-1.6-mistral-7b-gguf%2Fllava-v1.6-mistral-7b.Q5_K_M.gguf",
|
||||
"output": "modelscope_models/llava-1.6-mistral-7b-gguf/llava-v1.6-mistral-7b.Q5_K_M.gguf",
|
||||
"SHA256": "b1d37fc65ecb80aa8f1ce185bf4d7605bc3c5cc5bcc77a160c3a1b0377631112",
|
||||
},
|
||||
"llava-1.6-mistral-7b-gguf/mmproj-model-f16.gguf": {
|
||||
"url": "https://www.modelscope.cn/api/v1/models/wailovet/MinusZoneAIModels/repo?Revision=master&FilePath=llava-1.6-mistral-7b-gguf%2Fmmproj-model-f16.gguf",
|
||||
"output": "modelscope_models/llava-1.6-mistral-7b-gguf/mmproj-model-f16.gguf",
|
||||
"SHA256": "00205ee8a0d7a381900cd031e43105f86aa0d8c07bf329851e85c71a26632d16",
|
||||
},
|
||||
},
|
||||
"phi3": {
|
||||
"Phi-3-mini-4k-instruct-q4.gguf": {
|
||||
"url": "https://www.modelscope.cn/api/v1/models/wailovet/MinusZoneAIModels/repo?Revision=master&FilePath=Phi-3-mini-4k-instruct-gguf%2FPhi-3-mini-4k-instruct-q4.gguf",
|
||||
"output": "modelscope_models/Phi-3-mini-4k-instruct-gguf/Phi-3-mini-4k-instruct-q4.gguf",
|
||||
"SHA256": "1cd9a9df07350196623f93bf4829cf228959e07ad32f787b8fdd7f5956f5b9de"
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
[project]
|
||||
name = "comfyui-kolors-mz"
|
||||
description = "Implementation of Kolors on ComfyUI\nReference from [a/https://github.com/kijai/ComfyUI-KwaiKolorsWrapper](https://github.com/kijai/ComfyUI-KwaiKolorsWrapper)\nUsing ComfyUI Native Sampling"
|
||||
version = "1.0.0"
|
||||
license = "LICENSE"
|
||||
|
||||
[project.urls]
|
||||
Repository = "https://github.com/MinusZoneAI/ComfyUI-Kolors-MZ"
|
||||
# Used by Comfy Registry https://comfyregistry.org
|
||||
|
||||
[tool.comfy]
|
||||
PublisherId = "wailovet"
|
||||
DisplayName = "ComfyUI-Kolors-MZ"
|
||||
Icon = ""
|
||||
Reference in New Issue
Block a user