From 860894d83f7a309971e26438e1d086055bb6336d Mon Sep 17 00:00:00 2001 From: FizzleDorf <1fizzledorf@gmail.com> Date: Fri, 1 Dec 2023 09:15:05 -0500 Subject: [PATCH 1/6] seed scheduling added --- comfy/sample.py | 36 +++++++++++++++++++++++------------- 1 file changed, 23 insertions(+), 13 deletions(-) diff --git a/comfy/sample.py b/comfy/sample.py index 034db97ee88..4e28f2ec813 100644 --- a/comfy/sample.py +++ b/comfy/sample.py @@ -6,22 +6,32 @@ import math import numpy as np -def prepare_noise(latent_image, seed, noise_inds=None): +def prepare_noise(latent_image, seeds, noise_inds=None): """ - creates random noise given a latent image and a seed. - optional arg skip can be used to skip and discard x number of noise generations for a given seed + Creates random noise given a latent image and a seed or a list of seeds. + Optional arg noise_inds can be used to select specific noise indices. """ - generator = torch.manual_seed(seed) - if noise_inds is None: - return torch.randn(latent_image.size(), dtype=latent_image.dtype, layout=latent_image.layout, generator=generator, device="cpu") - - unique_inds, inverse = np.unique(noise_inds, return_inverse=True) + num_latents = latent_image.size(0) + + if not isinstance(seeds, list): + seeds = [seeds] + + generator = torch.Generator() + generator.manual_seed(seeds[0]) # Use the first seed as the default generator seed + noises = [] - for i in range(unique_inds[-1]+1): - noise = torch.randn([1] + list(latent_image.size())[1:], dtype=latent_image.dtype, layout=latent_image.layout, generator=generator, device="cpu") - if i in unique_inds: - noises.append(noise) - noises = [noises[i] for i in inverse] + + for i in range(num_latents): + if i < len(seeds): # Use the provided seeds if available + seed = seeds[i] + else: + seed = torch.randint(0, 2**32, (1,)).item() # Generate a random seed for additional latents + generator.manual_seed(seed) + print("seed:", seed) + noise = torch.randn([1] + list(latent_image.size())[1:], dtype=latent_image.dtype, layout=latent_image.layout, device="cpu", generator=generator) + noises.append(noise) + + noises = [noises[i] for i in range(num_latents)] noises = torch.cat(noises, axis=0) return noises From aeedf7f6a87385918a06b4c8d2403008680dee53 Mon Sep 17 00:00:00 2001 From: FizzleDorf <1fizzledorf@gmail.com> Date: Fri, 1 Dec 2023 20:20:17 -0500 Subject: [PATCH 2/6] switched subsequent latent seeds for INT inputs to increment --- comfy/sample.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/comfy/sample.py b/comfy/sample.py index 4e28f2ec813..a19af0cb815 100644 --- a/comfy/sample.py +++ b/comfy/sample.py @@ -24,10 +24,13 @@ def prepare_noise(latent_image, seeds, noise_inds=None): for i in range(num_latents): if i < len(seeds): # Use the provided seeds if available seed = seeds[i] - else: - seed = torch.randint(0, 2**32, (1,)).item() # Generate a random seed for additional latents + else: + seed = seeds[-1] + i # Increment the last seed for additional latents + + #else: maybe add this add a toggle or dropdown? + # seed = torch.randint(0, 2**32, (1,)).item() # Generate a random seed for additional latents generator.manual_seed(seed) - print("seed:", seed) + print("seed:", seed) #get rid of this after testing noise = torch.randn([1] + list(latent_image.size())[1:], dtype=latent_image.dtype, layout=latent_image.layout, device="cpu", generator=generator) noises.append(noise) From 9328cd4098987d3a1a1882e52599c315ec8b2857 Mon Sep 17 00:00:00 2001 From: FizzleDorf <1fizzledorf@gmail.com> Date: Sun, 3 Dec 2023 12:56:33 -0500 Subject: [PATCH 3/6] fixed random indent --- comfy/sample.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/comfy/sample.py b/comfy/sample.py index a19af0cb815..c2b924f51d3 100644 --- a/comfy/sample.py +++ b/comfy/sample.py @@ -24,7 +24,7 @@ def prepare_noise(latent_image, seeds, noise_inds=None): for i in range(num_latents): if i < len(seeds): # Use the provided seeds if available seed = seeds[i] - else: + else: seed = seeds[-1] + i # Increment the last seed for additional latents #else: maybe add this add a toggle or dropdown? From 093bb323d82d33fae67ab85c2f76cf6e19cdb720 Mon Sep 17 00:00:00 2001 From: FizzleDorf <1fizzledorf@gmail.com> Date: Mon, 4 Dec 2023 01:28:00 -0500 Subject: [PATCH 4/6] added selector to ksamplers for choosing batch_behavior --- comfy/sample.py | 23 +++++++++++++---------- nodes.py | 15 ++++++++------- 2 files changed, 21 insertions(+), 17 deletions(-) diff --git a/comfy/sample.py b/comfy/sample.py index c2b924f51d3..09f3785c848 100644 --- a/comfy/sample.py +++ b/comfy/sample.py @@ -6,10 +6,9 @@ import math import numpy as np -def prepare_noise(latent_image, seeds, noise_inds=None): +def prepare_noise(latent_image, seeds, batch_behavior = "randomize"): """ - Creates random noise given a latent image and a seed or a list of seeds. - Optional arg noise_inds can be used to select specific noise indices. + Creates noise based on the batch behavior, a latent image and a seed or a list of seeds. """ num_latents = latent_image.size(0) @@ -21,16 +20,20 @@ def prepare_noise(latent_image, seeds, noise_inds=None): noises = [] - for i in range(num_latents): - if i < len(seeds): # Use the provided seeds if available + for i in range(num_latents): + if i < len(seeds): # Use the provided seeds if available then follow behavior seed = seeds[i] - else: - seed = seeds[-1] + i # Increment the last seed for additional latents + elif batch_behavior == "randomize" : + seed = torch.randint(0, 2 ** 32, (1,)).item() + elif batch_behavior == "fixed": + seed = seeds[-1] + elif batch_behavior == "increment": + seed = seeds[-1] + i + else : + seed = seeds[-1] - i - #else: maybe add this add a toggle or dropdown? - # seed = torch.randint(0, 2**32, (1,)).item() # Generate a random seed for additional latents generator.manual_seed(seed) - print("seed:", seed) #get rid of this after testing + print("seed:", seed) noise = torch.randn([1] + list(latent_image.size())[1:], dtype=latent_image.dtype, layout=latent_image.layout, device="cpu", generator=generator) noises.append(noise) diff --git a/nodes.py b/nodes.py index 24e591fdde8..e65ddbcc32e 100644 --- a/nodes.py +++ b/nodes.py @@ -1252,13 +1252,12 @@ def set_mask(self, samples, mask): s["noise_mask"] = mask.reshape((-1, 1, mask.shape[-2], mask.shape[-1])) return (s,) -def common_ksampler(model, seed, steps, cfg, sampler_name, scheduler, positive, negative, latent, denoise=1.0, disable_noise=False, start_step=None, last_step=None, force_full_denoise=False): +def common_ksampler(model, seed, steps, cfg, sampler_name, scheduler, positive, negative, latent, denoise=1.0, batch_behavior = "randomize", disable_noise=False, start_step=None, last_step=None, force_full_denoise=False): latent_image = latent["samples"] if disable_noise: noise = torch.zeros(latent_image.size(), dtype=latent_image.dtype, layout=latent_image.layout, device="cpu") else: - batch_inds = latent["batch_index"] if "batch_index" in latent else None - noise = comfy.sample.prepare_noise(latent_image, seed, batch_inds) + noise = comfy.sample.prepare_noise(latent_image, seed, batch_behavior) noise_mask = None if "noise_mask" in latent: @@ -1279,6 +1278,7 @@ def INPUT_TYPES(s): return {"required": {"model": ("MODEL",), "seed": ("INT", {"default": 0, "min": 0, "max": 0xffffffffffffffff}), + "batch_behavior": (["randomize", "fixed", "increment", "decrement"],), "steps": ("INT", {"default": 20, "min": 1, "max": 10000}), "cfg": ("FLOAT", {"default": 8.0, "min": 0.0, "max": 100.0, "step":0.1, "round": 0.01}), "sampler_name": (comfy.samplers.KSampler.SAMPLERS, ), @@ -1295,8 +1295,8 @@ def INPUT_TYPES(s): CATEGORY = "sampling" - def sample(self, model, seed, steps, cfg, sampler_name, scheduler, positive, negative, latent_image, denoise=1.0): - return common_ksampler(model, seed, steps, cfg, sampler_name, scheduler, positive, negative, latent_image, denoise=denoise) + def sample(self, model, seed, batch_behavior, steps, cfg, sampler_name, scheduler, positive, negative, latent_image, denoise=1.0): + return common_ksampler(model, seed, steps, cfg, sampler_name, scheduler, positive, negative, latent_image, denoise=denoise, batch_behavior=batch_behavior) class KSamplerAdvanced: @classmethod @@ -1305,6 +1305,7 @@ def INPUT_TYPES(s): {"model": ("MODEL",), "add_noise": (["enable", "disable"], ), "noise_seed": ("INT", {"default": 0, "min": 0, "max": 0xffffffffffffffff}), + "batch_behavior": (["randomize", "fixed", "increment", "decrement"],), "steps": ("INT", {"default": 20, "min": 1, "max": 10000}), "cfg": ("FLOAT", {"default": 8.0, "min": 0.0, "max": 100.0, "step":0.1, "round": 0.01}), "sampler_name": (comfy.samplers.KSampler.SAMPLERS, ), @@ -1323,14 +1324,14 @@ def INPUT_TYPES(s): CATEGORY = "sampling" - def sample(self, model, add_noise, noise_seed, steps, cfg, sampler_name, scheduler, positive, negative, latent_image, start_at_step, end_at_step, return_with_leftover_noise, denoise=1.0): + def sample(self, model, add_noise, noise_seed, batch_behavior, steps, cfg, sampler_name, scheduler, positive, negative, latent_image, start_at_step, end_at_step, return_with_leftover_noise, denoise=1.0): force_full_denoise = True if return_with_leftover_noise == "enable": force_full_denoise = False disable_noise = False if add_noise == "disable": disable_noise = True - return common_ksampler(model, noise_seed, steps, cfg, sampler_name, scheduler, positive, negative, latent_image, denoise=denoise, disable_noise=disable_noise, start_step=start_at_step, last_step=end_at_step, force_full_denoise=force_full_denoise) + return common_ksampler(model, noise_seed, steps, cfg, sampler_name, scheduler, positive, negative, latent_image, denoise=denoise, batch_behavior=batch_behavior, disable_noise=disable_noise, start_step=start_at_step, last_step=end_at_step, force_full_denoise=force_full_denoise) class SaveImage: def __init__(self): From 724ed6a98fc68a02a2e385a8c7771b8851f098f8 Mon Sep 17 00:00:00 2001 From: FizzleDorf <1fizzledorf@gmail.com> Date: Fri, 26 Jan 2024 16:52:20 +0900 Subject: [PATCH 5/6] sent batch behaviour to bottom of the KSampler options so it doesn't mess up existing KSamplers in workflows --- nodes.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nodes.py b/nodes.py index cc4ddf515c2..a1002ec9030 100644 --- a/nodes.py +++ b/nodes.py @@ -1334,7 +1334,6 @@ def INPUT_TYPES(s): return {"required": {"model": ("MODEL",), "seed": ("INT", {"default": 0, "min": 0, "max": 0xffffffffffffffff}), - "batch_behavior": (["randomize", "fixed", "increment", "decrement"],), "steps": ("INT", {"default": 20, "min": 1, "max": 10000}), "cfg": ("FLOAT", {"default": 8.0, "min": 0.0, "max": 100.0, "step":0.1, "round": 0.01}), "sampler_name": (comfy.samplers.KSampler.SAMPLERS, ), @@ -1343,6 +1342,7 @@ def INPUT_TYPES(s): "negative": ("CONDITIONING", ), "latent_image": ("LATENT", ), "denoise": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 1.0, "step": 0.01}), + "batch_behavior": (["randomize", "fixed", "increment", "decrement"],), } } @@ -1361,7 +1361,6 @@ def INPUT_TYPES(s): {"model": ("MODEL",), "add_noise": (["enable", "disable"], ), "noise_seed": ("INT", {"default": 0, "min": 0, "max": 0xffffffffffffffff}), - "batch_behavior": (["randomize", "fixed", "increment", "decrement"],), "steps": ("INT", {"default": 20, "min": 1, "max": 10000}), "cfg": ("FLOAT", {"default": 8.0, "min": 0.0, "max": 100.0, "step":0.1, "round": 0.01}), "sampler_name": (comfy.samplers.KSampler.SAMPLERS, ), @@ -1372,6 +1371,7 @@ def INPUT_TYPES(s): "start_at_step": ("INT", {"default": 0, "min": 0, "max": 10000}), "end_at_step": ("INT", {"default": 10000, "min": 0, "max": 10000}), "return_with_leftover_noise": (["disable", "enable"], ), + "batch_behavior": (["randomize", "fixed", "increment", "decrement"],), } } From 1e4e2e122f694fae10e85e1e37bc7ccc27b191c6 Mon Sep 17 00:00:00 2001 From: FizzleDorf <1fizzledorf@gmail.com> Date: Fri, 26 Jan 2024 21:57:28 +0900 Subject: [PATCH 6/6] matched random noise as close as possible with python to control after generate --- comfy/sample.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/comfy/sample.py b/comfy/sample.py index cd8408322a3..ffbaaeb00e1 100644 --- a/comfy/sample.py +++ b/comfy/sample.py @@ -3,6 +3,7 @@ import comfy.samplers import comfy.conds import comfy.utils +import random import math import numpy as np @@ -24,7 +25,7 @@ def prepare_noise(latent_image, seeds, batch_behavior = "randomize"): if i < len(seeds): # Use the provided seeds if available then follow behavior seed = seeds[i] elif batch_behavior == "randomize" : - seed = torch.randint(0, 2 ** 32, (1,)).item() + seed = int(random.random() * 99999999999999) elif batch_behavior == "fixed": seed = seeds[-1] elif batch_behavior == "increment":