Compare commits

..
19 Commits
Author SHA1 Message Date
yolain 5e0cc2ea71 Upgrade v1.2.6 to ComfyRegistry 2025-01-10 12:50:46 +08:00
yolain a1125b20bc Adding model caching for human segmentation 2025-01-10 12:37:48 +08:00
yolain db14b955a5 Fix widgets not changing when timestep is selected in easy pipeEdit 2025-01-05 11:32:27 +08:00
yolain 6a61c1cf89 Fix missing the "Red rect" Styles when missing nodes 2025-01-03 16:51:00 +08:00
yolain c974a60749 Fix easy batchAny should return list not tuple when batch string 2024-12-31 17:38:38 +08:00
yolain a844119335 Change lark-parser dependency to lark 2024-12-30 11:26:51 +08:00
yolain c22e434e38 Adjust the default value of clip_skip in the easy loaders from -1 to -2 2024-12-30 11:24:13 +08:00
yolain 2c2751a762 Fix it needs to be converted to 3 channels when after adding the background on easy imageRembg 2024-12-27 20:46:16 +08:00
yolain 4f283c3b55 Set the language to match front-end 2024-12-26 19:00:59 +08:00
yolain d68f0804ed Fix the issue of missing the obsidian theme when you are using the new front-end develop version 2024-12-26 18:51:33 +08:00
yolain 9edc20e810 Fix some controlnet bug 2024-12-26 00:51:12 +08:00
yolain 615289f00e Fix forward ipa got an unexpected keyword 'attn_mask' #589 2024-12-26 00:03:22 +08:00
yolain d0f269807e Merge pull request #590 from BobDu/fix-syntax-warn
Fix SyntaxWarning in python 3.12
2024-12-26 00:01:42 +08:00
Bob Du f5efee7f23 fix SyntaxWarning in python 3.12
Signed-off-by: Bob Du <i@bobdu.cc>
2024-12-25 23:28:21 +08:00
yolain b26fcef6d7 Fix the bug caused by adding settings repeatedly when refreshing the page. 2024-12-20 14:09:47 +08:00
yolain 54a7c22296 Fix PromptGen request failure display 2024-12-19 22:06:45 +08:00
yolain 0ab09df6c4 Add add_background of widget on easy imageRembg 2024-12-19 22:05:20 +08:00
yolain aa57e309ba Fix the issue due to set nodes missing custom nodes which their connected, causing canvas to be messed up. #578 2024-12-16 12:58:48 +08:00
yolain d56cbf572d Fix image chooer can not using in a loop #574 2024-12-13 12:40:07 +08:00
28 changed files with 178 additions and 93 deletions
+7
View File
@@ -52,6 +52,13 @@ git clone https://github.com/yolain/ComfyUI-Easy-Use
## 📜 更新日志
**v1.2.6**
- 修复了在缺少自定义节点时缺少 “红色框框” 样式的问题。
- 在一些简单的加载器中,将 `clip_skip` 的默认值从 `-1` 调整为 `-2`。
- 修复因设置节点中缺少相连接的自定义节点而导致弄乱画布的问题
- 修复 'easy imageChooser' 不能循环使用的问题。
**v1.2.5**
- 在 `easy preSamplingCustom` 和 `easy preSamplingAdvanced` 上增加 `enable (GPU=A1111)` 噪波生成模式选择项
+7
View File
@@ -47,6 +47,13 @@ Double-click install.bat to install the required dependencies
## 📜 Changelog
**v1.2.6**
- Fix missing the "Red Rect" styles when you are missing custom nodes.
- Adjust the default value of `clip_skip` from `-1` to `-2` in some easy loaders.
- Fix the issue due to set nodes missing custom nodes which their connected, causing canvas to be messed up.
- Fix the `easy imageChooser` can not using in a loop.
**v1.2.5**
- Added `enable (GPU=A1111)` noise mode on `easy preSamplingCustom` and `easy preSamplingAdvanced`
+1 -1
View File
@@ -1,4 +1,4 @@
__version__ = "1.2.5"
__version__ = "1.2.6"
import yaml
import os
+3 -3
View File
@@ -877,7 +877,7 @@ class fullLoader:
"ckpt_name": (folder_paths.get_filename_list("checkpoints"),),
"config_name": (["Default", ] + folder_paths.get_filename_list("configs"), {"default": "Default"}),
"vae_name": (["Baked VAE"] + folder_paths.get_filename_list("vae"),),
"clip_skip": ("INT", {"default": -1, "min": -24, "max": 0, "step": 1}),
"clip_skip": ("INT", {"default": -2, "min": -24, "max": 0, "step": 1}),
"lora_name": (["None"] + folder_paths.get_filename_list("loras"),),
"lora_model_strength": ("FLOAT", {"default": 1.0, "min": -10.0, "max": 10.0, "step": 0.01}),
@@ -986,7 +986,7 @@ class a1111Loader(fullLoader):
"required": {
"ckpt_name": (checkpoints,),
"vae_name": (["Baked VAE"] + folder_paths.get_filename_list("vae"),),
"clip_skip": ("INT", {"default": -1, "min": -24, "max": 0, "step": 1}),
"clip_skip": ("INT", {"default": -2, "min": -24, "max": 0, "step": 1}),
"lora_name": (loras,),
"lora_model_strength": ("FLOAT", {"default": 1.0, "min": -10.0, "max": 10.0, "step": 0.01}),
@@ -1037,7 +1037,7 @@ class comfyLoader(fullLoader):
"required": {
"ckpt_name": (folder_paths.get_filename_list("checkpoints"),),
"vae_name": (["Baked VAE"] + folder_paths.get_filename_list("vae"),),
"clip_skip": ("INT", {"default": -1, "min": -24, "max": 0, "step": 1}),
"clip_skip": ("INT", {"default": -2, "min": -24, "max": 0, "step": 1}),
"lora_name": (["None"] + folder_paths.get_filename_list("loras"),),
"lora_model_strength": ("FLOAT", {"default": 1.0, "min": -10.0, "max": 10.0, "step": 0.01}),
+39 -16
View File
@@ -1,5 +1,6 @@
import os
import json
import copy
import hashlib
import folder_paths
import torch
@@ -17,7 +18,7 @@ from torchvision.transforms.functional import to_pil_image
from .libs.log import log_node_info
from .libs.utils import AlwaysEqualProxy, ByPassTypeTuple
from .libs.cache import cache, update_cache, remove_cache
from .libs.image import pil2tensor, tensor2pil, ResizeMode, get_new_bounds, RGB2RGBA, image2mask
from .libs.image import pil2tensor, tensor2pil, ResizeMode, get_new_bounds, RGB2RGBA, image2mask, empty_image
from .libs.colorfix import adain_color_fix, wavelet_color_fix
from .libs.chooser import ChooserMessage, ChooserCancelled
from .config import REMBG_DIR, REMBG_MODELS, HUMANPARSING_MODELS, MEDIAPIPE_MODELS, MEDIAPIPE_DIR
@@ -801,10 +802,10 @@ class imageRemBg:
"rem_mode": (("RMBG-2.0", "RMBG-1.4","Inspyrenet"), {"default": "RMBG-1.4"}),
"image_output": (["Hide", "Preview", "Save", "Hide/Save"], {"default": "Preview"}),
"save_prefix": ("STRING", {"default": "ComfyUI"}),
},
"optional":{
"torchscript_jit": ("BOOLEAN", {"default": False}),
"add_background": (["none", "white", "black"], {"default": "none"})
},
"hidden": {"prompt": "PROMPT", "extra_pnginfo": "EXTRA_PNGINFO"},
}
@@ -816,7 +817,8 @@ class imageRemBg:
CATEGORY = "EasyUse/Image"
def remove(self, rem_mode, images, image_output, save_prefix, torchscript_jit=False, prompt=None, extra_pnginfo=None):
def remove(self, rem_mode, images, image_output, save_prefix, torchscript_jit=False, add_background='none',prompt=None, extra_pnginfo=None):
new_images = list()
masks = list()
if rem_mode == "RMBG-2.0":
@@ -911,6 +913,13 @@ class imageRemBg:
new_images = torch.cat(new_images, dim=0)
masks = torch.cat(masks, dim=0)
if add_background != 'none':
_layer = tensor2pil(new_images)
_canvas = Image.new('RGB', _layer.size, (255,255,255) if add_background == 'white' else (0, 0, 0))
_canvas.paste(_layer, mask=_layer)
new_images = pil2tensor(_canvas)
results = easySave(new_images, save_prefix, image_output, prompt, extra_pnginfo)
if image_output in ("Hide", "Hide/Save"):
@@ -956,6 +965,7 @@ class imageChooser(PreviewImage):
def chooser(self, prompt=None, my_unique_id=None, extra_pnginfo=None, **kwargs):
id = my_unique_id[0]
id = id.split('.')[len(id.split('.')) - 1] if "." in id else id
if id not in ChooserMessage.stash:
ChooserMessage.stash[id] = {}
my_stash = ChooserMessage.stash[id]
@@ -1234,10 +1244,14 @@ class humanSegmentation:
from functools import reduce
model_path = get_local_filepath(MEDIAPIPE_MODELS['selfie_multiclass_256x256']['model_url'], MEDIAPIPE_DIR)
model_asset_buffer = None
with open(model_path, "rb") as f:
model_asset_buffer = f.read()
if method in cache:
_, model_asset_buffer = cache["selfie_multiclass_256x256"][1]
else:
model_path = get_local_filepath(MEDIAPIPE_MODELS['selfie_multiclass_256x256']['model_url'], MEDIAPIPE_DIR)
model_asset_buffer = None
with open(model_path, "rb") as f:
model_asset_buffer = f.read()
update_cache(method, 'human_segmentation', (False, model_asset_buffer))
image_segmenter_base_options = mp.tasks.BaseOptions(model_asset_buffer=model_asset_buffer)
options = mp.tasks.vision.ImageSegmenterOptions(
base_options=image_segmenter_base_options,
@@ -1303,10 +1317,15 @@ class humanSegmentation:
mask = torch.cat(ret_masks, dim=0)
elif method == "human_parsing_lip":
from .human_parsing.run_parsing import HumanParsing
onnx_path = os.path.join(folder_paths.models_dir, 'onnx')
model_path = get_local_filepath(HUMANPARSING_MODELS['parsing_lip']['model_url'], onnx_path)
parsing = HumanParsing(model_path=model_path)
if method in cache:
_, parsing = cache[method][1]
else:
from .human_parsing.run_parsing import HumanParsing
onnx_path = os.path.join(folder_paths.models_dir, 'onnx')
model_path = get_local_filepath(HUMANPARSING_MODELS['parsing_lip']['model_url'], onnx_path)
parsing = HumanParsing(model_path=model_path)
update_cache(method, 'human_segmentation', (False, parsing))
model_image = image.squeeze(0)
model_image = model_image.permute((2, 0, 1))
model_image = to_pil_image(model_image)
@@ -1320,11 +1339,15 @@ class humanSegmentation:
output_image, = JoinImageWithAlpha().join_image_with_alpha(image, alpha)
elif method == "human_parts (deeplabv3p)":
from .human_parsing.run_parsing import HumanParts
onnx_path = os.path.join(folder_paths.models_dir, 'onnx')
human_parts_path = os.path.join(onnx_path, 'human-parts')
model_path = get_local_filepath(HUMANPARSING_MODELS['human-parts']['model_url'], human_parts_path)
parsing = HumanParts(model_path=model_path)
if method in cache:
_, parsing = cache[method][1]
else:
from .human_parsing.run_parsing import HumanParts
onnx_path = os.path.join(folder_paths.models_dir, 'onnx')
human_parts_path = os.path.join(onnx_path, 'human-parts')
model_path = get_local_filepath(HUMANPARSING_MODELS['human-parts']['model_url'], human_parts_path)
parsing = HumanParts(model_path=model_path)
update_cache(method, 'human_segmentation', (False, parsing))
ret_images = []
ret_masks = []
+2 -2
View File
@@ -123,9 +123,9 @@ class InstantXFluxIpadapterApply:
# process control image
image_prompt_embeds = self.get_image_embeds(pil_image=pil_image, clip_image_embeds=None)
# set model
is_patched = is_model_pathched(model.model)
# is_patched = is_model_pathched(model.model)
bi = model.clone()
FluxUpdateModules(bi, ip_attn_procs, image_prompt_embeds, is_patched)
FluxUpdateModules(bi, ip_attn_procs, image_prompt_embeds)
return (bi, image)
+37 -16
View File
@@ -2,6 +2,7 @@ import torch
from torch import Tensor, nn
from .math import attention
from ..attention_processor import IPAFluxAttnProcessor2_0
from comfy.ldm.flux.layers import DoubleStreamBlock, SingleStreamBlock
from comfy import model_management as mm
@@ -27,12 +28,13 @@ class DoubleStreamBlockIPA(nn.Module):
self.txt_norm2 = original_block.txt_norm2
self.txt_mlp = original_block.txt_mlp
self.flipped_img_txt = original_block.flipped_img_txt
self.ip_adapter = ip_adapter
self.image_emb = image_emb
self.device = mm.get_torch_device()
def forward(self, img: Tensor, txt: Tensor, vec: Tensor, pe: Tensor, t: Tensor):
def forward(self, img: Tensor, txt: Tensor, vec: Tensor, pe: Tensor, t: Tensor, attn_mask=None):
img_mod1, img_mod2 = self.img_mod(vec)
txt_mod1, txt_mod2 = self.txt_mod(vec)
@@ -52,18 +54,29 @@ class DoubleStreamBlockIPA(nn.Module):
1, 4)
txt_q, txt_k = self.txt_attn.norm(txt_q, txt_k, txt_v)
# run actual attention
attn = attention(torch.cat((txt_q, img_q), dim=2),
torch.cat((txt_k, img_k), dim=2),
torch.cat((txt_v, img_v), dim=2), pe=pe)
if self.flipped_img_txt:
# run actual attention
attn = attention(torch.cat((img_q, txt_q), dim=2),
torch.cat((img_k, txt_k), dim=2),
torch.cat((img_v, txt_v), dim=2),
pe=pe, mask=attn_mask)
txt_attn, img_attn = attn[:, : txt.shape[1]], attn[:, txt.shape[1]:]
img_attn, txt_attn = attn[:, : img.shape[1]], attn[:, img.shape[1]:]
else:
# run actual attention
attn = attention(torch.cat((txt_q, img_q), dim=2),
torch.cat((txt_k, img_k), dim=2),
torch.cat((txt_v, img_v), dim=2),
pe=pe, mask=attn_mask)
ip_hidden_states = self.ip_adapter(self.num_heads, img_q, self.image_emb, t)
if ip_hidden_states is not None:
ip_hidden_states.to(device=self.device)
img_attn = img_attn + ip_hidden_states
txt_attn, img_attn = attn[:, : txt.shape[1]], attn[:, txt.shape[1]:]
for adapter, image in zip(self.ip_adapter, self.image_emb):
# this does a separate attention for each adapter
ip_hidden_states = adapter(self.num_heads, img_q, image, t)
if ip_hidden_states is not None:
ip_hidden_states = ip_hidden_states.to(self.device)
img_attn = img_attn + ip_hidden_states
# calculate the img bloks
img = img + img_mod1.gate * self.img_attn.proj(img_attn)
@@ -109,7 +122,11 @@ class SingleStreamBlockIPA(nn.Module):
self.image_emb = image_emb
self.device = mm.get_torch_device()
def forward(self, x: Tensor, vec: Tensor, pe: Tensor, t: Tensor) -> Tensor:
def add_adapter(self, ip_adapter: IPAFluxAttnProcessor2_0, image_emb):
self.ip_adapter.append(ip_adapter)
self.image_emb.append(image_emb)
def forward(self, x: Tensor, vec: Tensor, pe: Tensor, t: Tensor, attn_mask=None) -> Tensor:
mod, _ = self.modulation(vec)
x_mod = (1 + mod.scale) * self.pre_norm(x) + mod.shift
qkv, mlp = torch.split(self.linear1(x_mod), [3 * self.hidden_size, self.mlp_hidden_dim], dim=-1)
@@ -118,12 +135,16 @@ class SingleStreamBlockIPA(nn.Module):
q, k = self.norm(q, k, v)
# compute attention
attn = attention(q, k, v, pe=pe)
attn = attention(q, k, v, pe=pe, mask=attn_mask)
for adapter, image in zip(self.ip_adapter, self.image_emb):
# this does a separate attention for each adapter
# maybe we want a single joint attention call for all adapters?
ip_hidden_states = adapter(self.num_heads, q, image, t)
if ip_hidden_states is not None:
ip_hidden_states = ip_hidden_states.to(self.device)
attn = attn + ip_hidden_states
ip_hidden_states = self.ip_adapter(self.num_heads, q, self.image_emb, t)
if ip_hidden_states is not None:
ip_hidden_states.to(device=self.device)
attn = attn + ip_hidden_states
# compute activation in mlp stream, cat again and run second linear layer
output = self.linear2(torch.cat((attn, self.mlp_act(mlp)), 2))
x += mod.gate * output
+2 -2
View File
@@ -4,11 +4,11 @@ from torch import Tensor
from comfy.ldm.modules.attention import optimized_attention
import comfy.model_management
def attention(q: Tensor, k: Tensor, v: Tensor, pe: Tensor) -> Tensor:
def attention(q: Tensor, k: Tensor, v: Tensor, pe: Tensor, mask=None) -> Tensor:
q, k = apply_rope(q, k, pe)
heads = q.shape[1]
x = optimized_attention(q, k, v, heads, skip_reshape=True)
x = optimized_attention(q, k, v, heads, skip_reshape=True, mask=mask)
return x
+38 -22
View File
@@ -4,19 +4,33 @@ from .flux.layers import DoubleStreamBlockIPA, SingleStreamBlockIPA
from comfy.ldm.flux.layers import timestep_embedding
from types import MethodType
def FluxUpdateModules(bi, ip_attn_procs, image_emb, is_patched):
def FluxUpdateModules(bi, ip_attn_procs, image_emb):
flux_model = bi.model
bi.add_object_patch(f"diffusion_model.forward_orig", MethodType(forward_orig_ipa, flux_model.diffusion_model))
dsb_count = len(flux_model.diffusion_model.double_blocks)
ssb_count = len(flux_model.diffusion_model.single_blocks)
for i in range(dsb_count):
temp_layer = DoubleStreamBlockIPA(
flux_model.diffusion_model.double_blocks[i], ip_attn_procs[f"double_blocks.{i}"], image_emb)
bi.add_object_patch(f"diffusion_model.double_blocks.{i}",temp_layer)
for i in range(ssb_count):
temp_layer = SingleStreamBlockIPA(
flux_model.diffusion_model.single_blocks[i], ip_attn_procs[f"single_blocks.{i}"], image_emb)
bi.add_object_patch(f"diffusion_model.single_blocks.{i}", temp_layer)
for i, original in enumerate(flux_model.diffusion_model.double_blocks):
patch_name = f"double_blocks.{i}"
maybe_patched_layer = bi.get_model_object(f"diffusion_model.{patch_name}")
# if there's already a patch there, collect its adapters and replace it
procs = [ip_attn_procs[patch_name]]
embs = [image_emb]
if isinstance(maybe_patched_layer, DoubleStreamBlockIPA):
procs = maybe_patched_layer.ip_adapter + procs
embs = maybe_patched_layer.image_emb + embs
# initial ipa models with image embeddings
new_layer = DoubleStreamBlockIPA(original, procs, embs)
# for example, ComfyUI internally uses model.add_patches to add loras
bi.add_object_patch(f"diffusion_model.{patch_name}", new_layer)
for i, original in enumerate(flux_model.diffusion_model.single_blocks):
patch_name = f"single_blocks.{i}"
maybe_patched_layer = bi.get_model_object(f"diffusion_model.{patch_name}")
procs = [ip_attn_procs[patch_name]]
embs = [image_emb]
if isinstance(maybe_patched_layer, SingleStreamBlockIPA):
procs = maybe_patched_layer.ip_adapter + procs
embs = maybe_patched_layer.image_emb + embs
# initial ipa models with image embeddings
new_layer = SingleStreamBlockIPA(original, procs, embs)
bi.add_object_patch(f"diffusion_model.{patch_name}", new_layer)
def is_model_pathched(model):
def test(mod):
@@ -31,6 +45,7 @@ def is_model_pathched(model):
result = test(model)
return result
def forward_orig_ipa(
self,
img: Tensor,
@@ -39,9 +54,10 @@ def forward_orig_ipa(
txt_ids: Tensor,
timesteps: Tensor,
y: Tensor,
guidance: Tensor = None,
guidance: Tensor|None = None,
control=None,
transformer_options={},
attn_mask: Tensor = None,
) -> Tensor:
patches_replace = transformer_options.get("patches_replace", {})
if img.ndim != 3 or txt.ndim != 3:
@@ -67,18 +83,18 @@ def forward_orig_ipa(
def block_wrap(args):
out = {}
if isinstance(block, DoubleStreamBlockIPA): # ipadaper
out["img"], out["txt"] = block(img=args["img"], txt=args["txt"], vec=args["vec"], pe=args["pe"], t=args["timesteps"])
out["img"], out["txt"] = block(img=args["img"], txt=args["txt"], vec=args["vec"], pe=args["pe"], t=args["timesteps"], attn_mask=args.get("attn_mask"))
else:
out["img"], out["txt"] = block(img=args["img"], txt=args["txt"], vec=args["vec"], pe=args["pe"])
out["img"], out["txt"] = block(img=args["img"], txt=args["txt"], vec=args["vec"], pe=args["pe"], attn_mask=args.get("attn_mask"))
return out
out = blocks_replace[("double_block", i)]({"img": img, "txt": txt, "vec": vec, "pe": pe, "timesteps": timesteps}, {"original_block": block_wrap})
out = blocks_replace[("double_block", i)]({"img": img, "txt": txt, "vec": vec, "pe": pe, "timesteps": timesteps, "attn_mask": attn_mask}, {"original_block": block_wrap})
txt = out["txt"]
img = out["img"]
else:
if isinstance(block, DoubleStreamBlockIPA): # ipadaper
img, txt = block(img=img, txt=txt, vec=vec, pe=pe, t=timesteps)
img, txt = block(img=img, txt=txt, vec=vec, pe=pe, t=timesteps, attn_mask=attn_mask)
else:
img, txt = block(img=img, txt=txt, vec=vec, pe=pe)
img, txt = block(img=img, txt=txt, vec=vec, pe=pe, attn_mask=attn_mask)
if control is not None: # Controlnet
control_i = control.get("input")
@@ -94,18 +110,18 @@ def forward_orig_ipa(
def block_wrap(args):
out = {}
if isinstance(block, SingleStreamBlockIPA): # ipadaper
out["img"] = block(args["img"], vec=args["vec"], pe=args["pe"], t=args["timesteps"])
out["img"] = block(args["img"], vec=args["vec"], pe=args["pe"], t=args["timesteps"], attn_mask=args.get("attn_mask"))
else:
out["img"] = block(args["img"], vec=args["vec"], pe=args["pe"])
out["img"] = block(args["img"], vec=args["vec"], pe=args["pe"], attn_mask=args.get("attn_mask"))
return out
out = blocks_replace[("single_block", i)]({"img": img, "vec": vec, "pe": pe, "timesteps": timesteps}, {"original_block": block_wrap})
out = blocks_replace[("single_block", i)]({"img": img, "vec": vec, "pe": pe, "timesteps": timesteps, "attn_mask": attn_mask}, {"original_block": block_wrap})
img = out["img"]
else:
if isinstance(block, SingleStreamBlockIPA): # ipadaper
img = block(img, vec=vec, pe=pe, t=timesteps)
img = block(img, vec=vec, pe=pe, t=timesteps, attn_mask=attn_mask)
else:
img = block(img, vec=vec, pe=pe)
img = block(img, vec=vec, pe=pe, attn_mask=attn_mask)
if control is not None: # Controlnet
control_o = control.get("output")
+1 -1
View File
@@ -296,7 +296,7 @@ class applyKolorsUnet:
def is_kolors_model(model):
unet_config = model.model.model_config.unet_config
unet_config = model.model.model_config.unet_config if hasattr(model, 'model') else None
if unet_config and "adm_in_channels" in unet_config and unet_config["adm_in_channels"] == 5632:
return True
else:
+5 -1
View File
@@ -23,7 +23,11 @@ class easyControlnet:
control_net = patch_controlnet(model, control_net)
else:
if control_net is None:
control_net = easyCache.load_controlnet(control_net_name, scale_soft_weights, use_cache)
if easyCache is not None:
control_net = easyCache.load_controlnet(control_net_name, scale_soft_weights, use_cache)
else:
controlnet_path = folder_paths.get_full_path("controlnet", control_net_name)
control_net = comfy.controlnet.load_controlnet(controlnet_path)
# union controlnet
if union_type is not None:
+4 -5
View File
@@ -42,11 +42,10 @@ class FluxAIAPI:
response = requests.post(url, json=json, headers=headers)
res = response.json()
data = res['data']
if "error" in data:
return data['error']
elif "prompt" in data:
return data['prompt']
if "error" in res:
return res['error']
elif "data" in res and "prompt" in res['data']:
return res['data']['prompt']
fluxaiAPI = FluxAIAPI()
+5
View File
@@ -105,6 +105,11 @@ class blendImage:
return blended_image
def empty_image(width, height, batch_size=1, color=0):
r = torch.full([batch_size, height, width, 1], ((color >> 16) & 0xFF) / 0xFF)
g = torch.full([batch_size, height, width, 1], ((color >> 8) & 0xFF) / 0xFF)
b = torch.full([batch_size, height, width, 1], ((color) & 0xFF) / 0xFF)
return torch.cat((r, g, b), dim=-1)
class ResizeMode(Enum):
+3 -3
View File
@@ -12,8 +12,8 @@ from .utils import install_package
try:
from lark import Lark, Transformer, v_args
except:
print('install lark-parser...')
install_package('lark-parser')
print('install lark...')
install_package('lark')
from lark import Lark, Transformer, v_args
model_path = os.path.join(folder_paths.models_dir, 'prompt_generator')
@@ -185,7 +185,7 @@ class ChinesePromptTranslate(Transformer):
#定义Prompt文法
grammar = """
grammar = r"""
start: sentence
sentence: phrase ("," phrase)*
phrase: emphasis | weight | word | lora | embedding | schedule
+1 -1
View File
@@ -168,7 +168,7 @@ def process(text, seed=None):
replacements_found = True
string = string.replace(f"__{match}__", replacement, 1)
elif '*' in keyword:
subpattern = keyword.replace('*', '.*').replace('+','\+')
subpattern = keyword.replace('*', '.*').replace('+', r'\+')
total_patterns = []
found = False
for k, v in easy_wildcard_dict.items():
Regular → Executable
+7 -4
View File
@@ -1256,7 +1256,6 @@ class batchAnything:
return samples_out
def batch(self, any_1, any_2):
if isinstance(any_1, torch.Tensor) or isinstance(any_2, torch.Tensor):
if any_1 is None:
return (any_2,)
@@ -1271,13 +1270,17 @@ class batchAnything:
return (any_1,)
elif isinstance(any_2, tuple):
return (any_2 + (any_1,),)
return ((any_1, any_2),)
elif isinstance(any_2, list):
return (any_2 + [any_1],)
return ([any_1, any_2],)
elif isinstance(any_2, (str, float, int)):
if any_1 is None:
return (any_2,)
elif isinstance(any_1, tuple):
return (any_1 + (any_2,),)
return ((any_2, any_1),)
elif isinstance(any_1, list):
return (any_1 + [any_2],)
return ([any_2, any_1],)
elif isinstance(any_1, dict) and 'samples' in any_1:
if any_2 is None:
return (any_1,)
@@ -1728,7 +1731,7 @@ class saveText:
if not os.path.isabs(output_file_path):
output_path = os.path.join(self.output_dir, output_path)
base_output = os.path.basename(output_path)
if output_path.endswith("ComfyUI/output") or output_path.endswith("ComfyUI\output"):
if output_path.endswith("ComfyUI/output") or output_path.endswith(r"ComfyUI\output"):
base_output = ""
# Check output destination
+2 -2
View File
@@ -1,9 +1,9 @@
[project]
name = "comfyui-easy-use"
description = "To enhance the usability of ComfyUI, optimizations and integrations have been implemented for several commonly used nodes."
version = "1.2.5"
version = "1.2.6"
license = { file = "LICENSE" }
dependencies = ["diffusers", "accelerate", "clip_interrogator>=0.6.0", "sentencepiece", "lark-parser", "onnxruntime", "spandrel", "opencv-python"]
dependencies = ["diffusers", "accelerate", "clip_interrogator>=0.6.0", "sentencepiece", "lark", "onnxruntime", "spandrel", "opencv-python"]
[project.urls]
Repository = "https://github.com/yolain/ComfyUI-Easy-Use"
+1 -1
View File
@@ -1,7 +1,7 @@
diffusers
accelerate
clip_interrogator>=0.6.0
lark-parser
lark
onnxruntime
opencv-python
sentencepiece
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long