10 Commits
Author SHA1 Message Date
Extraltodeus 967b181646 Update nodes.py 2025-05-24 09:36:22 +02:00
Extraltodeus 75644eb9c5 Merge pull request #5 from Extraltodeus/revert-4-update-publish-yaml
Revert "Update Github Action for Publishing to Comfy Registry"
2025-04-29 19:04:07 +02:00
Extraltodeus 870bfda221 Revert "Update Github Action for Publishing to Comfy Registry" 2025-04-29 19:03:54 +02:00
Extraltodeus 9b96958673 Merge pull request #4 from ComfyNodePRs/update-publish-yaml
Update Github Action for Publishing to Comfy Registry
2025-04-29 19:02:03 +02:00
Extraltodeus b43585debc Update README.md 2025-04-29 19:00:55 +02:00
Extraltodeus efc4702b3a Update README.md 2025-04-29 18:59:59 +02:00
snomiao 9378d9d222 chore(publish): update workflow for node publishing with permissions and condition adjustments 2025-01-20 23:06:47 +00:00
Extraltodeus 195e434380 Update README.md 2024-09-23 04:51:36 +02:00
Extraltodeus 5e0aaf5c7c Update README.md 2024-09-23 04:50:26 +02:00
Extraltodeus b9294aea12 Update README.md 2024-09-23 04:49:59 +02:00
5 changed files with 119 additions and 1022 deletions
+68 -54
View File
@@ -15,9 +15,76 @@ All are to be used like any model patching node, right after the model loader.
# Nodes:
## Other nodes
There are now too many nodes for me to just add a screenshot and a bunch of details but it would be a shame not to describe them:
- Perturbed attention guidance: adaptation of PAG as a pre-CFG node.
- Variable CFG: Make you scale vary along the generation
- channel multipliers
- subtract prediction mean: gives more balanced colors
- "flip flop": swap the positive with the negative. Since the order matter, you may chain it with other nodes and go back to the correct order after. For experimental purposes.
- Shape attention (for SDXL) can turn off the input layer 8.
- Support empty uncond: Combined with "menu>advanced>conditioning>set timestep range" at ~65% you can now get a speed boost on any workflow.
- Set timestep range from sigmas: same as the default node except that you're using sigmas instead of step percentage
- [The testing branch](https://github.com/Extraltodeus/pre_cfg_comfy_nodes_for_ComfyUI/tree/testing_wip) has a few more and is the current state of these nodes for me.
## Pre CFG automatic scale
![image](https://github.com/Extraltodeus/pre_cfg_comfy_nodes_for_ComfyUI/assets/15731540/0437bf5e-1864-41ce-b929-654612b648a6)
### mode:
- Automatic CFG: applies the same predictable scaling as my other nodes based on this logic
- Strict scaling: applies a scaling which will always give the exact desired value. This tends to create artifacts and random blurs if carried through the end.
### Support empty uncond:
If you use the already available node named ConditioningSetTimestepRange you can stop generating a negative prediction earlier by letting your negative conditioning go through it while setting it like this:
![image](https://github.com/Extraltodeus/pre_cfg_comfy_nodes_for_ComfyUI/assets/15731540/4bb39087-d02a-4dd9-821d-dc1f43870eb0)
This speeds up your generation speed by two for the steps where there is no negative.
The only issue if you do this is that the CFG function will weight your positive prediction times your CFG scale against nothing and you will get a black image.
"support_empty_uncond" therefore divides your positive prediction by your CFG scale and avoids this issue.
Doing this combination is similar to the "boost" feature of my original automatic CFG node. It can also let you avoid artifacts if you want to use the strict scaling.
If you want to use this option in a chained setup using this node multiple times I recommand to use it only once and on the last.
## Pre CFG perp-neg
![image](https://github.com/Extraltodeus/pre_cfg_comfy_nodes_for_ComfyUI/assets/15731540/606b2ff3-fb81-4964-8e6d-cee97011a623)
Applies the already known [perp-neg logic](https://perp-neg.github.io/).
Code taken and adapted from ComfyAnon implementation.
The context length (added after the screenshot of the node) can be set to a higher value if you are using a tensor rt engine requiring a higher context length.
For more details you can check [my node related to this "Conditioning crop or fill"](https://github.com/Extraltodeus/Uncond-Zero-for-ComfyUI?tab=readme-ov-file#conditioning-crop-or-fill) where I explain a bit more about this.
## Pre CFG sharpening (experimental)
![image](https://github.com/Extraltodeus/pre_cfg_comfy_nodes_for_ComfyUI/assets/15731540/ffca8fae-34b0-44fa-bcd5-dc2ed2c625ca)
Subtract from the current step something from the previous step. This tends to make the images sharper and less saturated.
A negative value can be set.
## Pre CFG exponentiation (experimental)
![image](https://github.com/Extraltodeus/pre_cfg_comfy_nodes_for_ComfyUI/assets/15731540/34367216-eccf-411e-8fab-c63ff0f24331)
A value lower than one will simplify the end result and enhance the saturation / contrasts.
A value higher than one will do the opposite and if pushed too far will most likely make a mess.
## Gradient scaling:
Named like this because I initially wanted to test what would happen if I used, instead of a single CFG scale, a tensor shaped like the latent space with a gradual variation. So, not the kind of gradient used for backpropagation. Then why not try to use masks instead? And what if I could make it so each value will participate so the image would match as close as possible to an input image?
Named like this because I initially wanted to test what would happen if I used, instead of a single CFG scale, a tensor shaped like the latent space with a gradual variation. And then why not try to use masks instead? And what if I could make it so each value will match as closely as possible another input image?
The result is an arithmetic scaling method which does not noticeably slow down the sampling while also scaling the intensity of the values like an "automatic cfg".
@@ -79,56 +146,3 @@ Note:
- Given that this is a non-ml solution, unlike controlnet, it can not tell the difference in between a banana and a person. It simply tries to make the values match the input image. A giraffe is just an apple with different values at a different place.
- It is possible to chain multiple times this node for as long as the sum of all the strength sliders is equal or below one.
- I added two image generators. One simply using RGB sliders and a gradient generator which can also make circular patterns while outputting a mask, to make vignetting easy. You will find them in the "image" category.
## Pre CFG automatic scale
![image](https://github.com/Extraltodeus/pre_cfg_comfy_nodes_for_ComfyUI/assets/15731540/0437bf5e-1864-41ce-b929-654612b648a6)
### mode:
- Automatic CFG: applies the same predictable scaling as my other nodes based on this logic
- Strict scaling: applies a scaling which will always give the exact desired value. This tends to create artifacts and random blurs if carried through the end.
### Support empty uncond:
If you use the already available node named ConditioningSetTimestepRange you can stop generating a negative prediction earlier by letting your negative conditioning go through it while setting it like this:
![image](https://github.com/Extraltodeus/pre_cfg_comfy_nodes_for_ComfyUI/assets/15731540/4bb39087-d02a-4dd9-821d-dc1f43870eb0)
This speeds up your generation speed by two for the steps where there is no negative.
The only issue if you do this is that the CFG function will weight your positive prediction times your CFG scale against nothing and you will get a black image.
"support_empty_uncond" therefore divides your positive prediction by your CFG scale and avoids this issue.
Doing this combination is similar to the "boost" feature of my original automatic CFG node. It can also let you avoid artifacts if you want to use the strict scaling.
If you want to use this option in a chained setup using this node multiple times I recommand to use it only once and on the last.
## Pre CFG perp-neg
![image](https://github.com/Extraltodeus/pre_cfg_comfy_nodes_for_ComfyUI/assets/15731540/606b2ff3-fb81-4964-8e6d-cee97011a623)
Applies the already known [perp-neg logic](https://perp-neg.github.io/).
Code taken and adapted from ComfyAnon implementation.
The context length (added after the screenshot of the node) can be set to a higher value if you are using a tensor rt engine requiring a higher context length.
For more details you can check [my node related to this "Conditioning crop or fill"](https://github.com/Extraltodeus/Uncond-Zero-for-ComfyUI?tab=readme-ov-file#conditioning-crop-or-fill) where I explain a bit more about this.
## Pre CFG sharpening (experimental)
![image](https://github.com/Extraltodeus/pre_cfg_comfy_nodes_for_ComfyUI/assets/15731540/ffca8fae-34b0-44fa-bcd5-dc2ed2c625ca)
Subtract from the current step something from the previous step. This tends to make the images sharper and less saturated.
A negative value can be set.
## Pre CFG exponentiation (experimental)
![image](https://github.com/Extraltodeus/pre_cfg_comfy_nodes_for_ComfyUI/assets/15731540/34367216-eccf-411e-8fab-c63ff0f24331)
A value lower than one will simplify the end result and enhance the saturation / contrasts.
A value higher than one will do the opposite and if pushed too far will most likely make a mess.
+3 -42
View File
@@ -2,80 +2,41 @@ from .nodes import *
NODE_CLASS_MAPPINGS = {}
# try:
# from .skimmed_CFG import cond_skimming_pre_cfg_node
# NODE_CLASS_MAPPINGS["Skimmed CFG"] = cond_skimming_pre_cfg_node
# except:
# pass
NODE_CLASS_MAPPINGS_ADD = {
"Pre CFG automatic scale": automatic_pre_cfg,
"Pre CFG uncond zero": uncondZeroPreCFGNode,
"Pre CFG perp-neg": pre_cfg_perp_neg,
"Pre CFG re-negative": pre_cfg_re_negative,
# "Pre CFG re-negative": pre_cfg_re_negative,
"Pre CFG PAG": perturbed_attention_guidance_pre_cfg_node,
"Pre CFG zero attention": zero_attention_pre_cfg_node,
# "Pre CFG color control": latent_color_control_pre_cfg_node,
"Pre CFG channel multiplier": channel_multiplier_node,
"Pre CFG multiplier": multiply_cond_pre_cfg_node,
"Pre CFG roll latent": PreCFGRollLatentNode,
"Pre CFG mirror flip": PreCFGMirrorFlipLatentNode,
"Pre CFG clamp negative": clamp_sign_uncond_pre_cfg_node,
"Pre CFG clamp negative to denoised relation": clamp_uncond_to_denoised_pre_cfg_node,
"Pre CFG clamp min max": minmax_clamp_pre_cfg_node,
"Pre CFG lerp": lerp_conds_pre_cfg_node,
"Pre CFG norm neg to pos": norm_uncond_to_cond_pre_cfg_node,
"Pre CFG subtract mean": PreCFGsubtractMeanNode,
"Pre CFG variable scaling": variable_scale_pre_cfg_node,
"Pre CFG gradient scaling": gradient_scaling_pre_cfg_node,
"Pre CFG flip flop": flip_flip_conds_pre_cfg_node,
"Pre CFG replace negative channel": replace_uncond_channel_pre_cfg_node,
"Pre CFG merge negative channel": merge_uncond_channel_pre_cfg_node,
"Pre CFG timed CFG rescale": rescale_cfg_during_sigma_pre_cfg_node,
"Pre CFG merge negative channel": merge_uncond_channel_pre_cfg_node,
"Pre CFG sharpening": condDiffSharpeningNode,
"Pre CFG sharpen/blur": condBlurSharpeningNode,
"Pre CFG exponentiation": condExpNode,
"Pre CFG cond boost": boost_std_pre_cfg_node,
"tHe dArK GuiDaNcE": dark_guidance_pre_cfg_node,
"Conditioning set timestep from sigma": ConditioningSetTimestepRangeFromSigma,
"Support empty uncond": support_empty_uncond_pre_cfg_node,
"Shape attention": ShapeAttentionNode,
"Excellent attention": ExlAttentionNode,
"Post CFG subtract mean": PostCFGsubtractMeanNode,
# "Post CFG make a dot": PostCFGDotNode,
"Individual channel selector": individual_channel_selection_node,
"Subtract noise mean": latent_noise_subtract_mean_node,
"Empty RGB image": EmptyRGBImage,
"Gradient RGB image": GradientRGBImage,
"colors test node": colors_test_node,
"gradient batch mask": gradientNoisyLatentMaskBatch,
"Load latent from path": load_latent_for_guidance,
"Latent recombine by channels": latent_recombine_channels,
}
NODE_CLASS_MAPPINGS.update(NODE_CLASS_MAPPINGS_ADD)
for c in [4,8,16,32,64,128]:
NODE_CLASS_MAPPINGS[f"Channel selector for {c} channels"] = type("channel_selection_node", (channel_selection_node,), { "CHANNELS_AMOUNT": c})
try:
from .tester_nodes import *
NODE_CLASS_MAPPINGS["K-K-K-K-KOMBO BREAKER"] = combo_breaker
NODE_CLASS_MAPPINGS["K-K-K-K-KOMBO BREAKER X2"] = combo_breaker_x2
NODE_CLASS_MAPPINGS["K-K-K-K-KOMBO BREAKER 6 bool"] = combo_breaker_6_bool
NODE_CLASS_MAPPINGS["K-K-K-K-KOMBO BREAKER 4 bool"] = combo_breaker_4_bool
NODE_CLASS_MAPPINGS["CFG_TEST"] = cfg_test_node
except:
pass
-66
View File
@@ -1,66 +0,0 @@
import torch
@torch.no_grad()
def get_skimming_mask(x_orig, cond, uncond, cond_scale, return_denoised=False, disable_flipping_filter=False, release_inner_scaling=False):
denoised = x_orig - ((x_orig - uncond) + cond_scale * ((x_orig - cond) - (x_orig - uncond)))
matching_pred_signs = (cond - uncond).sign() == cond.sign()
matching_diff_after = cond.sign() == (cond * cond_scale - uncond * (cond_scale - 1)).sign()
if disable_flipping_filter:
outer_influence = matching_pred_signs & matching_diff_after
else:
deviation_influence = (denoised.sign() == (denoised - x_orig).sign())
outer_influence = matching_pred_signs & matching_diff_after & deviation_influence
if return_denoised:
return outer_influence, denoised
else:
return outer_influence
@torch.no_grad()
def skimmed_CFG(x_orig, cond, uncond, cond_scale, skimming_scale, disable_flipping_filter=False):
outer_influence, denoised = get_skimming_mask(x_orig, cond, uncond, cond_scale, return_denoised=True, disable_flipping_filter=disable_flipping_filter)
low_cfg_denoised_outer = x_orig - ((x_orig - uncond) + skimming_scale * ((x_orig - cond) - (x_orig - uncond)))
low_cfg_denoised_outer_difference = denoised - low_cfg_denoised_outer
cond[outer_influence] = cond[outer_influence] - (low_cfg_denoised_outer_difference[outer_influence] / cond_scale)
return cond
def skimmed_CFG_patch_wrap(model,Skimming_CFG=-1,end_proportion=1,full_skim_negative=True,disable_flipping_filter=False):
@torch.no_grad()
def skimmed_CFG_patch(args):
conds_out = args["conds_out"]
cond_scale = args["cond_scale"]
x_orig = args['input']
if not torch.any(conds_out[1]):
return conds_out
if end_proportion != 1:
c0,c1=conds_out[0].clone(),conds_out[1].clone()
practical_scale = cond_scale if Skimming_CFG < 0 else Skimming_CFG
conds_out[1] = skimmed_CFG(x_orig, conds_out[1], conds_out[0], cond_scale, practical_scale if not full_skim_negative else 0, disable_flipping_filter)
conds_out[0] = skimmed_CFG(x_orig, conds_out[0], conds_out[1], cond_scale, practical_scale, disable_flipping_filter)
if end_proportion != 1:
conds_out[0] = conds_out[0] * end_proportion + c0 * (1 - end_proportion)
conds_out[1] = conds_out[1] * end_proportion + c1 * (1 - end_proportion)
return conds_out
m = model.clone()
m.set_model_sampler_pre_cfg_function(skimmed_CFG_patch)
return m,
# def skimmed_CFG_patch_wrap(model,Skimming_CFG=-1,end_proportion=1,full_skim_negative=False,disable_flipping_filter=False):
# @torch.no_grad()
# def skimmed_CFG_patch(args):
# conds_out = args["conds_out"]
# cond_scale = args["cond_scale"]
# x_orig = args['input']
# if not torch.any(conds_out[1]):
# return conds_out
# if end_proportion != 1:
# c0,c1=conds_out[0].clone(),conds_out[1].clone()
# practical_scale = cond_scale if Skimming_CFG < 0 else Skimming_CFG
# conds_out[1] = skimmed_CFG(x_orig, conds_out[1], conds_out[0], cond_scale, practical_scale if not full_skim_negative else 0, disable_flipping_filter)
# conds_out[0] = skimmed_CFG(x_orig, conds_out[0], conds_out[1], cond_scale, practical_scale, disable_flipping_filter)
# if end_proportion != 1:
# conds_out[0] = conds_out[0] * end_proportion + c0 * (1 - end_proportion)
# conds_out[1] = conds_out[1] * end_proportion + c1 * (1 - end_proportion)
# return conds_out
# m = model.clone()
# m.set_model_sampler_pre_cfg_function(skimmed_CFG_patch)
# return m,
Binary file not shown.
+48 -860
View File
File diff suppressed because it is too large Load Diff