CLIP Loaders
This commit is contained in:
@@ -12,12 +12,17 @@ import comfy.model_patcher
|
||||
import folder_paths
|
||||
|
||||
from .ops import GGMLTensor, GGMLOps
|
||||
from .dequant import dequantize_tensor
|
||||
|
||||
# Add a custom key for files ending in .gguf
|
||||
# Add a custom keys for files ending in .gguf
|
||||
if "unet_gguf" not in folder_paths.folder_names_and_paths:
|
||||
orig = folder_paths.folder_names_and_paths.get("diffusion_models", folder_paths.folder_names_and_paths.get("unet", [[], set()]))
|
||||
folder_paths.folder_names_and_paths["unet_gguf"] = (orig[0], {".gguf"})
|
||||
|
||||
if "clip_gguf" not in folder_paths.folder_names_and_paths:
|
||||
orig = folder_paths.folder_names_and_paths.get("clip", [[], set()])
|
||||
folder_paths.folder_names_and_paths["clip_gguf"] = (orig[0], {".gguf"})
|
||||
|
||||
def gguf_sd_loader(path):
|
||||
"""
|
||||
Read state dict as fake tensors
|
||||
@@ -42,6 +47,41 @@ def gguf_sd_loader(path):
|
||||
print("\n")
|
||||
return sd
|
||||
|
||||
# for remapping llama.cpp -> original key names
|
||||
clip_sd_map = {
|
||||
"enc.": "encoder.",
|
||||
".blk.": ".block.",
|
||||
"token_embd": "shared",
|
||||
"output_norm": "final_layer_norm",
|
||||
"attn_q": "layer.0.SelfAttention.q",
|
||||
"attn_k": "layer.0.SelfAttention.k",
|
||||
"attn_v": "layer.0.SelfAttention.v",
|
||||
"attn_o": "layer.0.SelfAttention.o",
|
||||
"attn_norm": "layer.0.layer_norm",
|
||||
"attn_rel_b": "layer.0.SelfAttention.relative_attention_bias",
|
||||
"ffn_up": "layer.1.DenseReluDense.wi_1",
|
||||
"ffn_down": "layer.1.DenseReluDense.wo",
|
||||
"ffn_gate": "layer.1.DenseReluDense.wi_0",
|
||||
"ffn_norm": "layer.1.layer_norm",
|
||||
}
|
||||
# weights that should be dequantized on load
|
||||
clip_sd_dequant = {
|
||||
"shared.weight",
|
||||
}
|
||||
|
||||
def gguf_clip_loader(path):
|
||||
raw_sd = gguf_sd_loader(path)
|
||||
assert "enc.blk.23.ffn_up.weight" in raw_sd, "Invalid Text Encoder!"
|
||||
sd = {}
|
||||
for k,v in raw_sd.items():
|
||||
for s,d in clip_sd_map.items():
|
||||
k = k.replace(s,d)
|
||||
if k in clip_sd_dequant:
|
||||
v = dequantize_tensor(v, torch.float32).to(torch.float16)
|
||||
v = GGMLTensor(v, tensor_type=gguf.GGMLQuantizationType.F16, tensor_shape=v.shape)
|
||||
sd[k] = v
|
||||
return sd
|
||||
|
||||
# TODO: Temporary fix for now
|
||||
class GGUFModelPatcher(comfy.model_patcher.ModelPatcher):
|
||||
def calculate_weight(self, patches, weight, key):
|
||||
@@ -96,6 +136,86 @@ class UnetLoaderGGUF:
|
||||
model = GGUFModelPatcher.clone(model)
|
||||
return (model,)
|
||||
|
||||
clip_name_dict = {
|
||||
"stable_diffusion": comfy.sd.CLIPType.STABLE_DIFFUSION,
|
||||
"stable_cascade": comfy.sd.CLIPType.STABLE_CASCADE,
|
||||
"stable_audio": comfy.sd.CLIPType.STABLE_AUDIO,
|
||||
"sdxl": comfy.sd.CLIPType.STABLE_DIFFUSION,
|
||||
"sd3": comfy.sd.CLIPType.SD3,
|
||||
"flux": comfy.sd.CLIPType.FLUX,
|
||||
}
|
||||
|
||||
class CLIPLoaderGGUF:
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"clip_name": (s.get_filename_list(),),
|
||||
"type": (["stable_diffusion", "stable_cascade", "sd3", "stable_audio"],),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("CLIP",)
|
||||
FUNCTION = "load_clip"
|
||||
CATEGORY = "bootleg"
|
||||
TITLE = "CLIPLoader (GGUF)"
|
||||
|
||||
@classmethod
|
||||
def get_filename_list(s):
|
||||
files = []
|
||||
files += folder_paths.get_filename_list("clip")
|
||||
files += folder_paths.get_filename_list("clip_gguf")
|
||||
return sorted(files)
|
||||
|
||||
def load_data(self, ckpt_paths):
|
||||
clip_data = []
|
||||
for p in ckpt_paths:
|
||||
if p.endswith(".gguf"):
|
||||
clip_data.append(gguf_clip_loader(p))
|
||||
else:
|
||||
sd = comfy.utils.load_torch_file(p, safe_load=True)
|
||||
clip_data.append(
|
||||
{k:GGMLTensor(v, tensor_type=gguf.GGMLQuantizationType.F16, tensor_shape=v.shape) for k,v in sd.items()}
|
||||
)
|
||||
return clip_data
|
||||
|
||||
def load_patcher(self, clip_paths, clip_type, clip_data):
|
||||
clip = comfy.sd.load_text_encoder_state_dicts(
|
||||
clip_type = clip_type,
|
||||
state_dicts = clip_data,
|
||||
model_options = {"custom_operations": GGMLOps},
|
||||
embedding_directory = folder_paths.get_folder_paths("embeddings"),
|
||||
)
|
||||
clip.patcher = GGUFModelPatcher.clone(clip.patcher)
|
||||
return clip
|
||||
|
||||
def load_clip(self, clip_name, type="stable_diffusion"):
|
||||
clip_path = folder_paths.get_full_path("clip", clip_name)
|
||||
clip_type = clip_name_dict.get(type, comfy.sd.CLIPType.STABLE_DIFFUSION)
|
||||
return (self.load_patcher([clip_path], clip_type, self.load_data([clip_path])),)
|
||||
|
||||
class DualCLIPLoaderGGUF(CLIPLoaderGGUF):
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"clip_name1": (s.get_filename_list(), ),
|
||||
"clip_name2": (s.get_filename_list(), ),
|
||||
"type": (["sdxl", "sd3", "flux"], ),
|
||||
}
|
||||
}
|
||||
|
||||
TITLE = "DualCLIPLoader (GGUF)"
|
||||
|
||||
def load_clip(self, clip_name1, clip_name2, type):
|
||||
clip_path1 = folder_paths.get_full_path("clip", clip_name1)
|
||||
clip_path2 = folder_paths.get_full_path("clip", clip_name2)
|
||||
clip_paths = [clip_path1, clip_path2]
|
||||
clip_type = clip_name_dict.get(type, comfy.sd.CLIPType.STABLE_DIFFUSION)
|
||||
return (self.load_patcher(clip_paths, clip_type, self.load_data(clip_paths)),)
|
||||
|
||||
NODE_CLASS_MAPPINGS = {
|
||||
"UnetLoaderGGUF": UnetLoaderGGUF,
|
||||
"CLIPLoaderGGUF": CLIPLoaderGGUF,
|
||||
"DualCLIPLoaderGGUF": DualCLIPLoaderGGUF,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user