From 90d23170f882e12167e16648cece63b48aae47b5 Mon Sep 17 00:00:00 2001 From: Vladimir Mandic Date: Thu, 16 May 2024 20:04:31 -0400 Subject: [PATCH] apply styles/wildcards within batch and keep random seed --- extensions-builtin/sdnext-modernui | 2 +- modules/processing.py | 39 ++++++++++++------- modules/styles.py | 62 +++++++++++++++++++++--------- modules/ui.py | 2 +- 4 files changed, 72 insertions(+), 33 deletions(-) diff --git a/extensions-builtin/sdnext-modernui b/extensions-builtin/sdnext-modernui index 4e4466c86..cc54cdfd9 160000 --- a/extensions-builtin/sdnext-modernui +++ b/extensions-builtin/sdnext-modernui @@ -1 +1 @@ -Subproject commit 4e4466c86201101de4ae56026869999d1847fa73 +Subproject commit cc54cdfd9ed8fdef4524073b89639601fcabc399 diff --git a/modules/processing.py b/modules/processing.py index 11bcc5040..ff38de4fe 100644 --- a/modules/processing.py +++ b/modules/processing.py @@ -212,6 +212,7 @@ def process_images(p: StableDiffusionProcessing) -> Processed: def process_init(p: StableDiffusionProcessing): seed = get_fixed_seed(p.seed) subseed = get_fixed_seed(p.subseed) + """ if type(p.prompt) == list: p.all_prompts = [shared.prompt_styles.apply_styles_to_prompt(x, p.styles) for x in p.prompt] else: @@ -220,20 +221,32 @@ def process_init(p: StableDiffusionProcessing): p.all_negative_prompts = [shared.prompt_styles.apply_negative_styles_to_prompt(x, p.styles) for x in p.negative_prompt] else: p.all_negative_prompts = p.batch_size * p.n_iter * [shared.prompt_styles.apply_negative_styles_to_prompt(p.negative_prompt, p.styles)] - if type(seed) == list: - p.all_seeds = seed - else: - if shared.opts.sequential_seed: - p.all_seeds = [int(seed) + (x if p.subseed_strength == 0 else 0) for x in range(len(p.all_prompts))] + """ + reset_prompts = False + if p.all_prompts is None: + p.all_prompts = p.prompt if isinstance(p.prompt, list) else p.batch_size * p.n_iter * [p.prompt] + reset_prompts = True + if p.all_negative_prompts is None: + p.all_negative_prompts = p.negative_prompt if isinstance(p.negative_prompt, list) else p.batch_size * p.n_iter * [p.negative_prompt] + reset_prompts = True + if p.all_seeds is None: + reset_prompts = True + if type(seed) == list: + p.all_seeds = seed else: - p.all_seeds = [] - for i in range(len(p.all_prompts)): - seed = get_fixed_seed(p.seed) - p.all_seeds.append(int(seed) + (i if p.subseed_strength == 0 else 0)) - if type(subseed) == list: - p.all_subseeds = subseed - else: - p.all_subseeds = [int(subseed) + x for x in range(len(p.all_prompts))] + if shared.opts.sequential_seed: + p.all_seeds = [int(seed) + (x if p.subseed_strength == 0 else 0) for x in range(len(p.all_prompts))] + else: + p.all_seeds = [] + for i in range(len(p.all_prompts)): + seed = get_fixed_seed(p.seed) + p.all_seeds.append(int(seed) + (i if p.subseed_strength == 0 else 0)) + if type(subseed) == list: + p.all_subseeds = subseed + else: + p.all_subseeds = [int(subseed) + x for x in range(len(p.all_prompts))] + if reset_prompts: + p.all_prompts, p.all_negative_prompts = shared.prompt_styles.apply_styles_to_prompts(p.all_prompts, p.all_negative_prompts, p.styles, p.all_seeds) def process_images_inner(p: StableDiffusionProcessing) -> Processed: diff --git a/modules/styles.py b/modules/styles.py index ef985e148..5ffb5e468 100644 --- a/modules/styles.py +++ b/modules/styles.py @@ -42,7 +42,7 @@ def apply_styles_to_prompt(prompt, styles): return prompt -def apply_file_wildcards(prompt, replaced = [], not_found = [], recursion=0): +def apply_file_wildcards(prompt, replaced = [], not_found = [], recursion=0, seed=-1): def check_files(prompt, wildcard, files): for file in files: if wildcard == os.path.splitext(os.path.basename(file))[0] if os.path.sep not in wildcard else wildcard in file: @@ -74,13 +74,15 @@ def apply_file_wildcards(prompt, replaced = [], not_found = [], recursion=0): not_found.remove(m) elif not found and m not in not_found: not_found.append(m) - prompt, replaced, not_found = apply_file_wildcards(prompt, replaced, not_found, recursion) # recursive until we get early return + prompt, replaced, not_found = apply_file_wildcards(prompt, replaced, not_found, recursion, seed) # recursive until we get early return return prompt, replaced, not_found -def apply_wildcards_to_prompt(prompt, all_wildcards): +def apply_wildcards_to_prompt(prompt, all_wildcards, seed=-1, silent=False): if len(prompt) == 0: return prompt + if seed > 0: + random.seed(seed) replaced = {} t0 = time.time() for style_wildcards in all_wildcards: @@ -88,19 +90,20 @@ def apply_wildcards_to_prompt(prompt, all_wildcards): for wildcard in wildcards: try: what, words = wildcard.split("=", 1) - words = [x.strip() for x in words.split(",") if len(x.strip()) > 0] - word = random.choice(words) - prompt = prompt.replace(what, word) - replaced[what] = word + if what in prompt: + words = [x.strip() for x in words.split(",") if len(x.strip()) > 0] + word = random.choice(words) + prompt = prompt.replace(what, word) + replaced[what] = word except Exception as e: shared.log.error(f'Wildcards: wildcard="{wildcard}" error={e}') t1 = time.time() - prompt, replaced_file, not_found = apply_file_wildcards(prompt, [], []) + prompt, replaced_file, not_found = apply_file_wildcards(prompt, [], [], seed) t2 = time.time() - if replaced: - shared.log.info(f'Wildcards applied: {replaced} path="{shared.opts.wildcards_dir}" type=style time={t1-t0:.2f}') - if len(replaced_file) > 0 or len(not_found) > 0: - shared.log.info(f'Wildcards applied: {replaced_file} missing: {not_found} path="{shared.opts.wildcards_dir}" type=file time={t2-t2:.2f} ') + if replaced and not silent: + shared.log.debug(f'Wildcards applied: {replaced} path="{shared.opts.wildcards_dir}" type=style time={t1-t0:.2f}') + if (len(replaced_file) > 0 or len(not_found) > 0) and not silent: + shared.log.debug(f'Wildcards applied: {replaced_file} missing: {not_found} path="{shared.opts.wildcards_dir}" type=file time={t2-t2:.2f} ') return prompt @@ -129,7 +132,7 @@ def apply_styles_to_extra(p, style: Style): reference_style = get_reference_style() extra = parse_generation_parameters(reference_style) if shared.opts.extra_network_reference else {} - style_extra = apply_wildcards_to_prompt(style.extra, [style.wildcards]) + style_extra = apply_wildcards_to_prompt(style.extra, [style.wildcards], silent=True) extra.update(parse_generation_parameters(style_extra)) extra.pop('Prompt', None) extra.pop('Negative prompt', None) @@ -246,19 +249,42 @@ class StyleDatabase: def get_style_prompts(self, styles): if styles is None or not isinstance(styles, list): - shared.log.error(f'Invalid styles: {styles}') + shared.log.error(f'Styles invalid: {styles}') return [] return [self.find_style(x).prompt for x in styles] def get_negative_style_prompts(self, styles): if styles is None or not isinstance(styles, list): - shared.log.error(f'Invalid styles: {styles}') + shared.log.error(f'Styles invalid: {styles}') return [] return [self.find_style(x).negative_prompt for x in styles] + def apply_styles_to_prompts(self, prompts, negatives, styles, seeds): + if styles is None or not isinstance(styles, list): + shared.log.error(f'Styles invalid styles: {styles}') + return prompts + if prompts is None or not isinstance(prompts, list): + shared.log.error(f'Styles invalid prompts: {prompts}') + return prompts + if seeds is None or not isinstance(prompts, list): + shared.log.error(f'Styles invalid seeds: {seeds}') + return prompts + parsed_positive = [] + parsed_negative = [] + for i in range(len(prompts)): + prompt = prompts[i] + prompt = apply_styles_to_prompt(prompt, [self.find_style(x).prompt for x in styles]) + prompt = apply_wildcards_to_prompt(prompt, [self.find_style(x).wildcards for x in styles], seeds[i]) + parsed_positive.append(prompt) + prompt = negatives[i] + prompt = apply_styles_to_prompt(prompt, [self.find_style(x).negative_prompt for x in styles]) + prompt = apply_wildcards_to_prompt(prompt, [self.find_style(x).wildcards for x in styles], seeds[i]) + parsed_negative.append(prompt) + return parsed_positive, parsed_negative + def apply_styles_to_prompt(self, prompt, styles): if styles is None or not isinstance(styles, list): - shared.log.error(f'Invalid styles: {styles}') + shared.log.error(f'Styles invalid: {styles}') return prompt prompt = apply_styles_to_prompt(prompt, [self.find_style(x).prompt for x in styles]) prompt = apply_wildcards_to_prompt(prompt, [self.find_style(x).wildcards for x in styles]) @@ -266,7 +292,7 @@ class StyleDatabase: def apply_negative_styles_to_prompt(self, prompt, styles): if styles is None or not isinstance(styles, list): - shared.log.error(f'Invalid styles: {styles}') + shared.log.error(f'Styles invalid: {styles}') return prompt prompt = apply_styles_to_prompt(prompt, [self.find_style(x).negative_prompt for x in styles]) prompt = apply_wildcards_to_prompt(prompt, [self.find_style(x).wildcards for x in styles]) @@ -274,7 +300,7 @@ class StyleDatabase: def apply_styles_to_extra(self, p): if p.styles is None or not isinstance(p.styles, list): - shared.log.error(f'Invalid styles: {p.styles}') + shared.log.error(f'Styles invalid: {p.styles}') return for style in p.styles: s = self.find_style(style) diff --git a/modules/ui.py b/modules/ui.py index 71819947a..4332a57ea 100644 --- a/modules/ui.py +++ b/modules/ui.py @@ -278,7 +278,7 @@ def create_ui(startup_timer = None): shutdown_submit = gr.Button(value="Shutdown server", variant='primary', elem_id="shutdown_submit") unload_sd_model = gr.Button(value='Unload checkpoint', variant='primary', elem_id="sett_unload_sd_model") reload_sd_model = gr.Button(value='Reload checkpoint', variant='primary', elem_id="sett_reload_sd_model") - enable_profiling = gr.Button(value='Start profiling', variant='primary', elem_id="start_profiling") + enable_profiling = gr.Button(value='Start profiling', variant='primary', elem_id="enable_profiling") with gr.Tabs(elem_id="system") as system_tabs: global ui_system_tabs # pylint: disable=global-statement