From 8a40e30d08d4bd2fc9b3b8b5d697abfda7d31bc0 Mon Sep 17 00:00:00 2001 From: Robert Barron Date: Sun, 30 Jul 2023 01:22:00 -0700 Subject: add support for whitespace after the number in constructions like [foo:bar: 0.5 ] and (foo : 0.5 ) --- modules/prompt_parser.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'modules/prompt_parser.py') diff --git a/modules/prompt_parser.py b/modules/prompt_parser.py index 203ae1ac..8169a459 100644 --- a/modules/prompt_parser.py +++ b/modules/prompt_parser.py @@ -19,7 +19,7 @@ prompt: (emphasized | scheduled | alternate | plain | WHITESPACE)* !emphasized: "(" prompt ")" | "(" prompt ":" prompt ")" | "[" prompt "]" -scheduled: "[" [prompt ":"] prompt ":" [WHITESPACE] NUMBER "]" +scheduled: "[" [prompt ":"] prompt ":" [WHITESPACE] NUMBER [WHITESPACE] "]" alternate: "[" prompt ("|" prompt)+ "]" WHITESPACE: /\s+/ plain: /([^\\\[\]():|]|\\.)+/ @@ -60,11 +60,11 @@ def get_learned_conditioning_prompt_schedules(prompts, steps): class CollectSteps(lark.Visitor): def scheduled(self, tree): - tree.children[-1] = float(tree.children[-1]) - if tree.children[-1] < 1: - tree.children[-1] *= steps - tree.children[-1] = min(steps, int(tree.children[-1])) - res.append(tree.children[-1]) + tree.children[-2] = float(tree.children[-2]) + if tree.children[-2] < 1: + tree.children[-2] *= steps + tree.children[-2] = min(steps, int(tree.children[-2])) + res.append(tree.children[-2]) def alternate(self, tree): res.extend(range(1, steps+1)) @@ -75,7 +75,7 @@ def get_learned_conditioning_prompt_schedules(prompts, steps): def at_step(step, tree): class AtStep(lark.Transformer): def scheduled(self, args): - before, after, _, when = args + before, after, _, when, _ = args yield before or () if step <= when else after def alternate(self, args): yield next(args[(step - 1)%len(args)]) @@ -333,7 +333,7 @@ re_attention = re.compile(r""" \\| \(| \[| -:([+-]?[.\d]+)\)| +:\s*([+-]?[.\d]+)\s*\)| \)| ]| [^\\()\[\]:]+| -- cgit v1.2.3 From b6596cdb19414cdb31a762e4c4ffbdce17d2d6e9 Mon Sep 17 00:00:00 2001 From: catboxanon <122327233+catboxanon@users.noreply.github.com> Date: Fri, 4 Aug 2023 13:26:37 -0400 Subject: Prompt parser: account for empty field in alternating words syntax --- modules/prompt_parser.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'modules/prompt_parser.py') diff --git a/modules/prompt_parser.py b/modules/prompt_parser.py index 8169a459..32d214e3 100644 --- a/modules/prompt_parser.py +++ b/modules/prompt_parser.py @@ -20,7 +20,7 @@ prompt: (emphasized | scheduled | alternate | plain | WHITESPACE)* | "(" prompt ":" prompt ")" | "[" prompt "]" scheduled: "[" [prompt ":"] prompt ":" [WHITESPACE] NUMBER [WHITESPACE] "]" -alternate: "[" prompt ("|" prompt)+ "]" +alternate: "[" prompt ("|" [prompt])+ "]" WHITESPACE: /\s+/ plain: /([^\\\[\]():|]|\\.)+/ %import common.SIGNED_NUMBER -> NUMBER @@ -53,6 +53,10 @@ def get_learned_conditioning_prompt_schedules(prompts, steps): [[3, '((a][:b:c '], [10, '((a][:b:c d']] >>> g("[a|(b:1.1)]") [[1, 'a'], [2, '(b:1.1)'], [3, 'a'], [4, '(b:1.1)'], [5, 'a'], [6, '(b:1.1)'], [7, 'a'], [8, '(b:1.1)'], [9, 'a'], [10, '(b:1.1)']] + >>> g("[fe|]male") + [[1, 'female'], [2, 'male'], [3, 'female'], [4, 'male'], [5, 'female'], [6, 'male'], [7, 'female'], [8, 'male'], [9, 'female'], [10, 'male']] + >>> g("[fe|||]male") + [[1, 'female'], [2, 'male'], [3, 'male'], [4, 'male'], [5, 'female'], [6, 'male'], [7, 'male'], [8, 'male'], [9, 'female'], [10, 'male']] """ def collect_steps(steps, tree): @@ -78,7 +82,8 @@ def get_learned_conditioning_prompt_schedules(prompts, steps): before, after, _, when, _ = args yield before or () if step <= when else after def alternate(self, args): - yield next(args[(step - 1)%len(args)]) + args = ["" if not arg else arg for arg in args] + yield args[(step - 1) % len(args)] def start(self, args): def flatten(x): if type(x) == str: -- cgit v1.2.3 From d1ba46b6e15d2f2917e7d392955c8c6f988527ba Mon Sep 17 00:00:00 2001 From: Robert Barron Date: Wed, 9 Aug 2023 07:46:30 -0700 Subject: allow first pass and hires pass to use a single prompt to do different prompt editing, hires is 1.0..2.0: relative time range is [1..2] absolute time range is [steps+1..steps+hire_steps], e.g. with 30 steps and 20 hires steps, '20' is 2/3rds through first pass, and 40 is halfway through hires pass --- modules/processing.py | 20 ++++++++++++-------- modules/prompt_parser.py | 41 +++++++++++++++++++++++++++++++---------- modules/shared.py | 1 + 3 files changed, 44 insertions(+), 18 deletions(-) (limited to 'modules/prompt_parser.py') diff --git a/modules/processing.py b/modules/processing.py index 31745006..0750b299 100644 --- a/modules/processing.py +++ b/modules/processing.py @@ -319,12 +319,14 @@ class StableDiffusionProcessing: self.all_prompts = [shared.prompt_styles.apply_styles_to_prompt(x, self.styles) for x in self.all_prompts] self.all_negative_prompts = [shared.prompt_styles.apply_negative_styles_to_prompt(x, self.styles) for x in self.all_negative_prompts] - def cached_params(self, required_prompts, steps, extra_network_data): + def cached_params(self, required_prompts, steps, hires_steps, extra_network_data, use_old_scheduling): """Returns parameters that invalidate the cond cache if changed""" return ( required_prompts, steps, + hires_steps, + use_old_scheduling, opts.CLIP_stop_at_last_layers, shared.sd_model.sd_checkpoint_info, extra_network_data, @@ -334,7 +336,7 @@ class StableDiffusionProcessing: self.height, ) - def get_conds_with_caching(self, function, required_prompts, steps, caches, extra_network_data): + def get_conds_with_caching(self, function, required_prompts, steps, hires_steps, caches, extra_network_data): """ Returns the result of calling function(shared.sd_model, required_prompts, steps) using a cache to store the result if the same arguments have been used before. @@ -347,7 +349,7 @@ class StableDiffusionProcessing: caches is a list with items described above. """ - cached_params = self.cached_params(required_prompts, steps, extra_network_data) + cached_params = self.cached_params(required_prompts, steps, hires_steps, extra_network_data, shared.opts.use_old_scheduling) for cache in caches: if cache[0] is not None and cached_params == cache[0]: @@ -356,7 +358,7 @@ class StableDiffusionProcessing: cache = caches[0] with devices.autocast(): - cache[1] = function(shared.sd_model, required_prompts, steps) + cache[1] = function(shared.sd_model, required_prompts, steps, hires_steps, shared.opts.use_old_scheduling) cache[0] = cached_params return cache[1] @@ -367,8 +369,9 @@ class StableDiffusionProcessing: sampler_config = sd_samplers.find_sampler_config(self.sampler_name) self.step_multiplier = 2 if sampler_config and sampler_config.options.get("second_order", False) else 1 - self.uc = self.get_conds_with_caching(prompt_parser.get_learned_conditioning, negative_prompts, self.steps * self.step_multiplier, [self.cached_uc], self.extra_network_data) - self.c = self.get_conds_with_caching(prompt_parser.get_multicond_learned_conditioning, prompts, self.steps * self.step_multiplier, [self.cached_c], self.extra_network_data) + self.firstpass_steps = self.steps * self.step_multiplier + self.uc = self.get_conds_with_caching(prompt_parser.get_learned_conditioning, negative_prompts, self.firstpass_steps, None, [self.cached_uc], self.extra_network_data) + self.c = self.get_conds_with_caching(prompt_parser.get_multicond_learned_conditioning, prompts, self.firstpass_steps, None, [self.cached_c], self.extra_network_data) def parse_extra_network_prompts(self): self.prompts, self.extra_network_data = extra_networks.parse_prompts(self.prompts) @@ -1225,8 +1228,9 @@ class StableDiffusionProcessingTxt2Img(StableDiffusionProcessing): hr_prompts = prompt_parser.SdConditioning(self.hr_prompts, width=self.hr_upscale_to_x, height=self.hr_upscale_to_y) hr_negative_prompts = prompt_parser.SdConditioning(self.hr_negative_prompts, width=self.hr_upscale_to_x, height=self.hr_upscale_to_y, is_negative_prompt=True) - self.hr_uc = self.get_conds_with_caching(prompt_parser.get_learned_conditioning, hr_negative_prompts, self.steps * self.step_multiplier, [self.cached_hr_uc, self.cached_uc], self.hr_extra_network_data) - self.hr_c = self.get_conds_with_caching(prompt_parser.get_multicond_learned_conditioning, hr_prompts, self.steps * self.step_multiplier, [self.cached_hr_c, self.cached_c], self.hr_extra_network_data) + hires_steps = (self.hr_second_pass_steps or self.steps) * self.step_multiplier + self.hr_uc = self.get_conds_with_caching(prompt_parser.get_learned_conditioning, hr_negative_prompts, self.firstpass_steps, hires_steps, [self.cached_hr_uc, self.cached_uc], self.hr_extra_network_data) + self.hr_c = self.get_conds_with_caching(prompt_parser.get_multicond_learned_conditioning, hr_prompts, self.firstpass_steps, hires_steps, [self.cached_hr_c, self.cached_c], self.hr_extra_network_data) def setup_conds(self): super().setup_conds() diff --git a/modules/prompt_parser.py b/modules/prompt_parser.py index 32d214e3..e8c41f38 100644 --- a/modules/prompt_parser.py +++ b/modules/prompt_parser.py @@ -26,7 +26,7 @@ plain: /([^\\\[\]():|]|\\.)+/ %import common.SIGNED_NUMBER -> NUMBER """) -def get_learned_conditioning_prompt_schedules(prompts, steps): +def get_learned_conditioning_prompt_schedules(prompts, base_steps, hires_steps=None, use_old_scheduling=False): """ >>> g = lambda p: get_learned_conditioning_prompt_schedules([p], 10)[0] >>> g("test") @@ -57,18 +57,39 @@ def get_learned_conditioning_prompt_schedules(prompts, steps): [[1, 'female'], [2, 'male'], [3, 'female'], [4, 'male'], [5, 'female'], [6, 'male'], [7, 'female'], [8, 'male'], [9, 'female'], [10, 'male']] >>> g("[fe|||]male") [[1, 'female'], [2, 'male'], [3, 'male'], [4, 'male'], [5, 'female'], [6, 'male'], [7, 'male'], [8, 'male'], [9, 'female'], [10, 'male']] + >>> g = lambda p: get_learned_conditioning_prompt_schedules([p], 10, 10)[0] + >>> g("a [b:.5] c") + [[10, 'a b c']] + >>> g("a [b:1.5] c") + [[5, 'a c'], [10, 'a b c']] """ + if hires_steps is None or use_old_scheduling: + int_offset = 0 + flt_offset = 0 + steps = base_steps + else: + int_offset = base_steps + flt_offset = 1.0 + steps = hires_steps + def collect_steps(steps, tree): res = [steps] class CollectSteps(lark.Visitor): def scheduled(self, tree): - tree.children[-2] = float(tree.children[-2]) - if tree.children[-2] < 1: - tree.children[-2] *= steps - tree.children[-2] = min(steps, int(tree.children[-2])) - res.append(tree.children[-2]) + s = tree.children[-2] + v = float(s) + if use_old_scheduling: + v = v*steps if v<1 else v + else: + if "." in s: + v = (v - flt_offset) * steps + else: + v = (v - int_offset) + tree.children[-2] = min(steps, int(v)) + if tree.children[-2] >= 1: + res.append(tree.children[-2]) def alternate(self, tree): res.extend(range(1, steps+1)) @@ -134,7 +155,7 @@ class SdConditioning(list): -def get_learned_conditioning(model, prompts: SdConditioning | list[str], steps): +def get_learned_conditioning(model, prompts: SdConditioning | list[str], steps, hires_steps=None, use_old_scheduling=False): """converts a list of prompts into a list of prompt schedules - each schedule is a list of ScheduledPromptConditioning, specifying the comdition (cond), and the sampling step at which this condition is to be replaced by the next one. @@ -154,7 +175,7 @@ def get_learned_conditioning(model, prompts: SdConditioning | list[str], steps): """ res = [] - prompt_schedules = get_learned_conditioning_prompt_schedules(prompts, steps) + prompt_schedules = get_learned_conditioning_prompt_schedules(prompts, steps, hires_steps, use_old_scheduling) cache = {} for prompt, prompt_schedule in zip(prompts, prompt_schedules): @@ -229,7 +250,7 @@ class MulticondLearnedConditioning: self.batch: List[List[ComposableScheduledPromptConditioning]] = batch -def get_multicond_learned_conditioning(model, prompts, steps) -> MulticondLearnedConditioning: +def get_multicond_learned_conditioning(model, prompts, steps, hires_steps=None, use_old_scheduling=False) -> MulticondLearnedConditioning: """same as get_learned_conditioning, but returns a list of ScheduledPromptConditioning along with the weight objects for each prompt. For each prompt, the list is obtained by splitting the prompt using the AND separator. @@ -238,7 +259,7 @@ def get_multicond_learned_conditioning(model, prompts, steps) -> MulticondLearne res_indexes, prompt_flat_list, prompt_indexes = get_multicond_prompt_list(prompts) - learned_conditioning = get_learned_conditioning(model, prompt_flat_list, steps) + learned_conditioning = get_learned_conditioning(model, prompt_flat_list, steps, hires_steps, use_old_scheduling) res = [] for indexes in res_indexes: diff --git a/modules/shared.py b/modules/shared.py index 078e8135..a605b08b 100644 --- a/modules/shared.py +++ b/modules/shared.py @@ -516,6 +516,7 @@ options_templates.update(options_section(('compatibility', "Compatibility"), { "use_old_hires_fix_width_height": OptionInfo(False, "For hires fix, use width/height sliders to set final resolution rather than first pass (disables Upscale by, Resize width/height to)."), "dont_fix_second_order_samplers_schedule": OptionInfo(False, "Do not fix prompt schedule for second order samplers."), "hires_fix_use_firstpass_conds": OptionInfo(False, "For hires fix, calculate conds of second pass using extra networks of first pass."), + "use_old_scheduling": OptionInfo(False, "Use old prompt where first pass and hires both used the same timeline, and < 1 meant relative and >= 1 meant absolute"), })) options_templates.update(options_section(('interrogate', "Interrogate"), { -- cgit v1.2.3 From 61c1261e4e50385aab68b84c0f886911466044bb Mon Sep 17 00:00:00 2001 From: XDOneDude <106700244+XDOneDude@users.noreply.github.com> Date: Fri, 18 Aug 2023 21:56:15 -0400 Subject: more grammar fixes --- modules/processing.py | 24 ++++++++++++------------ modules/prompt_parser.py | 2 +- 2 files changed, 13 insertions(+), 13 deletions(-) (limited to 'modules/prompt_parser.py') diff --git a/modules/processing.py b/modules/processing.py index e62db62f..0315e1fd 100755 --- a/modules/processing.py +++ b/modules/processing.py @@ -386,14 +386,14 @@ class StableDiffusionProcessing: return self.token_merging_ratio or opts.token_merging_ratio def setup_prompts(self): - if type(self.prompt) == list: + if isinstance(self.prompt,list): self.all_prompts = self.prompt - elif type(self.negative_prompt) == list: + elif isinstance(self.negative_prompt, list): self.all_prompts = [self.prompt] * len(self.negative_prompt) else: self.all_prompts = self.batch_size * self.n_iter * [self.prompt] - if type(self.negative_prompt) == list: + if isinstance(self.negative_prompt, list): self.all_negative_prompts = self.negative_prompt else: self.all_negative_prompts = [self.negative_prompt] * len(self.all_prompts) @@ -512,10 +512,10 @@ class Processed: self.s_noise = p.s_noise self.s_min_uncond = p.s_min_uncond self.sampler_noise_scheduler_override = p.sampler_noise_scheduler_override - self.prompt = self.prompt if type(self.prompt) != list else self.prompt[0] - self.negative_prompt = self.negative_prompt if type(self.negative_prompt) != list else self.negative_prompt[0] - self.seed = int(self.seed if type(self.seed) != list else self.seed[0]) if self.seed is not None else -1 - self.subseed = int(self.subseed if type(self.subseed) != list else self.subseed[0]) if self.subseed is not None else -1 + self.prompt = self.prompt if not isinstance(self.prompt, list) else self.prompt[0] + self.negative_prompt = self.negative_prompt if not isinstance(self.negative_prompt, list) else self.negative_prompt[0] + self.seed = int(self.seed if not isinstance(self.seed, list) else self.seed[0]) if self.seed is not None else -1 + self.subseed = int(self.subseed if not isinstance(self.subseed, list) else self.subseed[0]) if self.subseed is not None else -1 self.is_using_inpainting_conditioning = p.is_using_inpainting_conditioning self.all_prompts = all_prompts or p.all_prompts or [self.prompt] @@ -741,7 +741,7 @@ def process_images(p: StableDiffusionProcessing) -> Processed: def process_images_inner(p: StableDiffusionProcessing) -> Processed: """this is the main loop that both txt2img and img2img use; it calls func_init once inside all the scopes and func_sample once per batch""" - if type(p.prompt) == list: + if isinstance(p.prompt, list): assert(len(p.prompt) > 0) else: assert p.prompt is not None @@ -772,12 +772,12 @@ def process_images_inner(p: StableDiffusionProcessing) -> Processed: p.setup_prompts() - if type(seed) == list: + if isinstance(seed, list): p.all_seeds = seed else: p.all_seeds = [int(seed) + (x if p.subseed_strength == 0 else 0) for x in range(len(p.all_prompts))] - if type(subseed) == list: + if isinstance(subseed, list): p.all_subseeds = subseed else: p.all_subseeds = [int(subseed) + x for x in range(len(p.all_prompts))] @@ -1268,12 +1268,12 @@ class StableDiffusionProcessingTxt2Img(StableDiffusionProcessing): if self.hr_negative_prompt == '': self.hr_negative_prompt = self.negative_prompt - if type(self.hr_prompt) == list: + if isinstance(self.hr_prompt, list): self.all_hr_prompts = self.hr_prompt else: self.all_hr_prompts = self.batch_size * self.n_iter * [self.hr_prompt] - if type(self.hr_negative_prompt) == list: + if isinstance(self.hr_negative_prompt, list): self.all_hr_negative_prompts = self.hr_negative_prompt else: self.all_hr_negative_prompts = self.batch_size * self.n_iter * [self.hr_negative_prompt] diff --git a/modules/prompt_parser.py b/modules/prompt_parser.py index 32d214e3..e811ae99 100644 --- a/modules/prompt_parser.py +++ b/modules/prompt_parser.py @@ -86,7 +86,7 @@ def get_learned_conditioning_prompt_schedules(prompts, steps): yield args[(step - 1) % len(args)] def start(self, args): def flatten(x): - if type(x) == str: + if isinstance(x, str): yield x else: for gen in x: -- cgit v1.2.3