Skip to content

Commit

Permalink
v10.6.0
Browse files Browse the repository at this point in the history
  • Loading branch information
ThereforeGames committed Dec 1, 2023
1 parent 46b0ead commit 2d4a184
Show file tree
Hide file tree
Showing 10 changed files with 153 additions and 73 deletions.
3 changes: 3 additions & 0 deletions config.json
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,9 @@
"enabled":true,
"open":false,
"wizard_enabled":true,
"wizard_shortcodes":true,
"wizard_templates":true,
"wizard_capture":true,
"wizard_open":false,
"wizard_default_shortcode":"txt2mask",
"dry_run_open":false,
Expand Down
20 changes: 19 additions & 1 deletion docs/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,25 @@ All notable changes to this project will be documented in this file.

For more details on new features, please check the [Manual](./MANUAL.md).

<details open><summary>10.5.0 - 25 November 2023</summary>
<details open><summary>10.6.0 - 1 December 2023</summary>

### Added
- New settings `Config.ui.wizard_shortcodes`, `Config.ui.wizard_templates`, `Config.ui.wizard_capture`: Allows you to disable certain Wizard tabs in order to improve WebUI performance
- `[max]` and `[min]`: Supports the `_key` parg to return the key of the max/min value instead of the value itself
- `[max]` and `[min]`: Can now parse values given as a list separated by `Config.syntax.delimiter`
- `[get]`: Supports the `_key` kwarg to return the names of requested variables instead of their values
- `[get]`: Supports the `_regex` kwarg to return the values of matching variables

### Changed
- `[set]`: Now parses the value of the first parg, allowing you to use shortcodes in evaluating the variable name
- `[get]`: The default value of `_sep` is now `Config.syntax.delimiter` instead of space

### Fixed
- `[faceswap]`: Fixed `embedding_path` processing

</details>

<details><summary>10.5.0 - 25 November 2023</summary>

### About
This update introduces global variables, several image processing shortcodes and improvements to some included templates and presets. The image features were motivated by Unprompted's integration with [BooruDatasetTagManager](https://github.com/starik222/BooruDatasetTagManager/pull/89) (my own PR.) For example, you can use `[image_info]` to assess image quality and influence the results of the Autotagger. Enjoy!
Expand Down
8 changes: 8 additions & 0 deletions docs/MANUAL.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,14 @@ If you encounter any confusing, incomplete, or out-of-date information here, ple

## ❔ Known Issues

<details><summary>WebUI slowdowns</summary>

Due to the nature of Gradio, creating many UI elements leads to performance issues in the WebUI. This may be resolved in Gradio 4, as [suggested here](https://github.com/gradio-app/gradio/issues/4841#issuecomment-1632141732).

In the meantime, you can improve performance by disabling Wizard tabs you do not use. For example, you can disable the Shortcodes tab by setting `ui.wizard_shortcodes` to false in `config_user.json`.

</details>

<details><summary>Compatibility with ControlNet</summary>

To achieve compatibility between Unprompted and ControlNet, you must manually rename the `unprompted` extension folder to `_unprompted`. This is due to [a limitation in the Automatic1111 extension framework](https://github.com/AUTOMATIC1111/stable-diffusion-webui/issues/8011) whereby priority is determined alphabetically.
Expand Down
2 changes: 1 addition & 1 deletion lib_unprompted/shared.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ def handler(keyword, pargs, kwargs, context, content):
self.log.info(f"Finished loading in {time.time()-start_time} seconds.")

def __init__(self, base_dir="."):
self.VERSION = "10.5.0"
self.VERSION = "10.6.0"

self.shortcode_modules = {}
self.shortcode_objects = {}
Expand Down
98 changes: 51 additions & 47 deletions scripts/unprompted.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,10 +116,11 @@ def parse_children(obj, result):
# Skip special fields
if block_name == "file":
this_val = f"{Unprompted.Config.syntax.delimiter}".join([str(e.name) for e in gr_obj.value])
else: this_val = gr_obj.value
else:
this_val = gr_obj.value
if (arg_name == "prompt"): continue

this_val = Unprompted.make_alt_tags(html.escape(str(helpers.autocast(this_val)).replace("\"","\'"),quote = False))
this_val = Unprompted.make_alt_tags(html.escape(str(helpers.autocast(this_val)).replace("\"", "\'"), quote=False))

if " " in this_val: this_val = f"\"{this_val}\"" # Enclose in quotes if necessary
result += f" {arg_name}={this_val}"
Expand Down Expand Up @@ -299,7 +300,7 @@ def show(self, is_img2img):
def ui(self, is_img2img):
mode_string = "img2img" if is_img2img else "txt2img"
with gr.Group():
with gr.Accordion("Unprompted", open=Unprompted.Config.ui.open, elem_classes=["unprompted-accordion",mode_string]):
with gr.Accordion("Unprompted", open=Unprompted.Config.ui.open, elem_classes=["unprompted-accordion", mode_string]):
with gr.Row(equal_height=True):
is_enabled = gr.Checkbox(label="Enabled", value=gradio_enabled_checkbox_workaround)

Expand Down Expand Up @@ -364,7 +365,7 @@ def handler(keyword, pargs, kwargs, context, content):
obj = gr.Image(label=this_label, value=content, type="filepath", interactive=True, info=_info, show_label=_show_label)
elif (block_name == "file"):
if len(content) < 1: content = None
file_types = helpers.ensure(kwargs["_file_types"].split(Unprompted.Config.syntax.delimiter),list) if "_file_types" in kwargs else None
file_types = helpers.ensure(kwargs["_file_types"].split(Unprompted.Config.syntax.delimiter), list) if "_file_types" in kwargs else None

obj = gr.File(label=this_label, value=content, interactive=True, info=_info, show_label=_show_label, file_count=kwargs["_file_count"] if "_file_count" in kwargs else "single", file_types=file_types)

Expand All @@ -390,7 +391,7 @@ def handler(keyword, pargs, kwargs, context, content):
elif pargs[0] == "row":
block = gr.Row(equal_height=pargs["_equal_height"] if "_equal_height" in pargs else False)
elif pargs[0] == "column":
block = gr.Column(scale=int(pargs["_scale"]) if "_scale" in pargs else 1)
block = gr.Column(scale=int(pargs["_scale"]) if "_scale" in pargs else 1)

with block:
# Unprompted.parse_alt_tags(content, None, wizard_shortcode_parser)
Expand All @@ -411,7 +412,7 @@ def handler(keyword, pargs, kwargs, context):
wizard_shortcode_parser.register(handler, "base_dir")

with gr.Tabs():

self.filtered_templates = Unprompted.wizard_groups[WizardModes.TEMPLATES][int(is_img2img)]
self.filtered_shortcodes = Unprompted.wizard_groups[WizardModes.SHORTCODES][int(is_img2img)]

Expand All @@ -426,7 +427,7 @@ def wizard_add_template(show_me=False):
# Render the text file's UI with special parser object
wizard_shortcode_parser.parse(file.read())
# Auto-include is always the last element
gr.Checkbox(label=f"🪄 Auto-include {self.dropdown_item_name} in prompt", value=False, elem_classes=["wizard-autoinclude",mode_string])
gr.Checkbox(label=f"🪄 Auto-include {self.dropdown_item_name} in prompt", value=False, elem_classes=["wizard-autoinclude", mode_string])
# Add event listeners
wizard_prep_event_listeners(self.filtered_templates[filename])
Unprompted.log.debug(f"Added {'img2img' if is_img2img else 'txt2img'} Wizard Template: {self.dropdown_item_name}")
Expand Down Expand Up @@ -460,7 +461,7 @@ def wizard_add_template(show_me=False):
def wizard_populate_shortcodes(region, first_load=False):
if not first_load:
Unprompted.load_shortcodes()
Unprompted.log.warning("Sorry, Gradio is presently incapable of dynamically creating UI elements. You must restart the WebUI to see new shortcodes in the Wizard. This is expected to change in a future release: https://github.com/gradio-app/gradio/issues/4689")
Unprompted.log.warning("Sorry, Gradio is presently incapable of dynamically creating UI elements. You must restart the WebUI to see new shortcodes in the Wizard. This is expected to change in a future release: https://github.com/gradio-app/gradio/issues/4689")
return ""

with region:
Expand All @@ -472,7 +473,7 @@ def wizard_populate_shortcodes(region, first_load=False):
# Run the shortcode's UI template to populate
Unprompted.shortcode_objects[key].ui(gr)
# Auto-include is always the last element
gr.Checkbox(label=f"🪄 Auto-include [{key}] in prompt", value=False, elem_classes=["wizard-autoinclude",mode_string])
gr.Checkbox(label=f"🪄 Auto-include [{key}] in prompt", value=False, elem_classes=["wizard-autoinclude", mode_string])
# Add event listeners
wizard_prep_event_listeners(self.filtered_shortcodes[key])

Expand All @@ -484,54 +485,59 @@ def wizard_refresh_templates():
Unprompted.log.debug("Refreshing the Wizard Templates...")
Unprompted.log.warning("Sorry, Gradio is presently incapable of dynamically creating UI elements. You must restart the WebUI to update Wizard templates. This is expected to change in a future release: https://github.com/gradio-app/gradio/issues/4689")
return ""
Unprompted.wizard_template_names.clear()
Unprompted.wizard_template_files.clear()
Unprompted.wizard_template_kwargs.clear()
return wizard_populate_templates(self.templates_region[int(is_img2img)])
if Unprompted.Config.ui.wizard_templates:
Unprompted.wizard_template_names.clear()
Unprompted.wizard_template_files.clear()
Unprompted.wizard_template_kwargs.clear()
return wizard_populate_templates(self.templates_region[int(is_img2img)])
return ""

def wizard_refresh_shortcodes():
Unprompted.log.debug("Refreshing the Wizard Shortcodes...")
return wizard_populate_shortcodes(self.shortcodes_region[int(is_img2img)])

with gr.Tab("Templates"):
with gr.Row():
self.templates_dropdown[int(is_img2img)] = gr.Dropdown(choices=[], label="Select template:", type="index", info="These are your GUI templates - you can think of them like custom scripts, except you can run an unlimited number of them at the same time.")
templates_refresh = ToolButton(value='\U0001f504', elem_id=f"templates-refresh")
templates_refresh.click(fn=wizard_refresh_templates) # , outputs=self.templates_dropdown[int(is_img2img)]
if Unprompted.Config.ui.wizard_templates:
with gr.Tab("Templates"):
with gr.Row():
self.templates_dropdown[int(is_img2img)] = gr.Dropdown(choices=[], label="Select template:", type="index", info="These are your GUI templates - you can think of them like custom scripts, except you can run an unlimited number of them at the same time.")
templates_refresh = ToolButton(value='\U0001f504', elem_id=f"templates-refresh")
templates_refresh.click(fn=wizard_refresh_templates) # , outputs=self.templates_dropdown[int(is_img2img)]

self.templates_region[int(is_img2img)] = gr.Blocks()
wizard_populate_templates(self.templates_region[int(is_img2img)], True)
self.templates_region[int(is_img2img)] = gr.Blocks()
wizard_populate_templates(self.templates_region[int(is_img2img)], True)

self.templates_dropdown[int(is_img2img)].choices = Unprompted.wizard_template_names
self.templates_dropdown[int(is_img2img)].choices = Unprompted.wizard_template_names

wizard_template_btn = gr.Button(value="🧠 Generate Shortcode")
wizard_template_btn = gr.Button(value="🧠 Generate Shortcode")

with gr.Tab("Shortcodes"):
shortcode_list = list(Unprompted.shortcode_objects.keys())
with gr.Row():
self.shortcodes_dropdown[int(is_img2img)] = gr.Dropdown(choices=shortcode_list, label="Select shortcode:", value=Unprompted.Config.ui.wizard_default_shortcode, info="GUI for setting up any shortcode in Unprompted. More engaging than reading the manual!")
shortcodes_refresh = ToolButton(value='\U0001f504', elemn_id=f"shortcodes-refresh")
shortcodes_refresh.click(fn=wizard_refresh_shortcodes) # , outputs=self.shortcodes_dropdown[int(is_img2img)]
if Unprompted.Config.ui.wizard_shortcodes:
with gr.Tab("Shortcodes"):
shortcode_list = list(Unprompted.shortcode_objects.keys())
with gr.Row():
self.shortcodes_dropdown[int(is_img2img)] = gr.Dropdown(choices=shortcode_list, label="Select shortcode:", value=Unprompted.Config.ui.wizard_default_shortcode, info="GUI for setting up any shortcode in Unprompted. More engaging than reading the manual!")
shortcodes_refresh = ToolButton(value='\U0001f504', elemn_id=f"shortcodes-refresh")
shortcodes_refresh.click(fn=wizard_refresh_shortcodes) # , outputs=self.shortcodes_dropdown[int(is_img2img)]

self.shortcodes_region[int(is_img2img)] = gr.Blocks()
wizard_populate_shortcodes(self.shortcodes_region[int(is_img2img)], True)
self.shortcodes_region[int(is_img2img)] = gr.Blocks()
wizard_populate_shortcodes(self.shortcodes_region[int(is_img2img)], True)

wizard_shortcode_btn = gr.Button(value="🧠 Generate Shortcode")
wizard_shortcode_btn = gr.Button(value="🧠 Generate Shortcode")

with gr.Tab("Capture"):
gr.Markdown(value="This assembles Unprompted code with the WebUI settings for the last image you generated. You can save the code to your `templates` folder and `[call]` it later, or send it to someone as 'preset' for foolproof image reproduction.<br><br>**⚠️ Important:** <em>When you change your inference settings, you must generate an image before Unprompted can detect the changes. This is due to a limitation in the WebUI extension framework.</em>")
# wizard_capture_include_inference = gr.Checkbox(label="Include inference settings",value=True)
wizard_capture_include_inference = gr.Radio(label="Include inference settings:", choices=["none", "simple", "verbose"], value="simple", interactive=True)
wizard_capture_include_prompt = gr.Radio(label="Include prompt:", choices=["none", "original", "postprocessed"], value="original", interactive=True)
wizard_capture_include_neg_prompt = gr.Radio(label="Include negative prompt:", choices=["none", "original", "postprocessed"], value="original", interactive=True)
wizard_capture_include_model = gr.Checkbox(label="Include model", value=False)
wizard_capture_add_template_block = gr.Checkbox(label="Add [template] block", value=False)
wizard_capture_btn = gr.Button(value="Generate code for my last image")
if Unprompted.Config.ui.wizard_capture:
with gr.Tab("Capture"):
gr.Markdown(value="This assembles Unprompted code with the WebUI settings for the last image you generated. You can save the code to your `templates` folder and `[call]` it later, or send it to someone as 'preset' for foolproof image reproduction.<br><br>**⚠️ Important:** <em>When you change your inference settings, you must generate an image before Unprompted can detect the changes. This is due to a limitation in the WebUI extension framework.</em>")
# wizard_capture_include_inference = gr.Checkbox(label="Include inference settings",value=True)
wizard_capture_include_inference = gr.Radio(label="Include inference settings:", choices=["none", "simple", "verbose"], value="simple", interactive=True)
wizard_capture_include_prompt = gr.Radio(label="Include prompt:", choices=["none", "original", "postprocessed"], value="original", interactive=True)
wizard_capture_include_neg_prompt = gr.Radio(label="Include negative prompt:", choices=["none", "original", "postprocessed"], value="original", interactive=True)
wizard_capture_include_model = gr.Checkbox(label="Include model", value=False)
wizard_capture_add_template_block = gr.Checkbox(label="Add [template] block", value=False)
wizard_capture_btn = gr.Button(value="Generate code for my last image")

wizard_result = gr.HTML(label="wizard_result", value="", elem_id="unprompted_result")
wizard_template_btn.click(fn=wizard_generate_template, inputs=[self.templates_dropdown[int(is_img2img)], gr.Variable(value=is_img2img), gr.Variable(value="<strong>RESULT:</strong> ")], outputs=wizard_result)
wizard_shortcode_btn.click(fn=wizard_generate_shortcode, inputs=[self.shortcodes_dropdown[int(is_img2img)], gr.Variable(value=is_img2img), gr.Variable(value="<strong>RESULT:</strong> ")], outputs=wizard_result)
wizard_capture_btn.click(fn=wizard_generate_capture, inputs=[wizard_capture_include_inference, wizard_capture_include_prompt, wizard_capture_include_neg_prompt, wizard_capture_include_model, wizard_capture_add_template_block], outputs=wizard_result)
if Unprompted.Config.ui.wizard_templates: wizard_template_btn.click(fn=wizard_generate_template, inputs=[self.templates_dropdown[int(is_img2img)], gr.Variable(value=is_img2img), gr.Variable(value="<strong>RESULT:</strong> ")], outputs=wizard_result)
if Unprompted.Config.ui.wizard_shortcodes: wizard_shortcode_btn.click(fn=wizard_generate_shortcode, inputs=[self.shortcodes_dropdown[int(is_img2img)], gr.Variable(value=is_img2img), gr.Variable(value="<strong>RESULT:</strong> ")], outputs=wizard_result)
if Unprompted.Config.ui.wizard_capture: wizard_capture_btn.click(fn=wizard_generate_capture, inputs=[wizard_capture_include_inference, wizard_capture_include_prompt, wizard_capture_include_neg_prompt, wizard_capture_include_model, wizard_capture_add_template_block], outputs=wizard_result)

else:
gr.HTML(label="wizard_debug", value="You have disabled the Wizard in your config.")
Expand Down Expand Up @@ -569,13 +575,12 @@ def open_folder(path):
with gr.Tab("🎓 Guides"):
guide = gr.Markdown(value=get_markdown("docs/GUIDE.md"))


def reload_unprompted():
Unprompted.log.debug("Reloading Unprompted...")
Unprompted.log.debug("Reloading `config.json`...")
Unprompted.cfg_dict, Unprompted.Config = parse_config(base_dir)
Unprompted.load_shortcodes()
# self.shortcodes_dropdown[int(is_img2img)].update(choices=wizard_refresh_shortcodes())
# self.shortcodes_dropdown[int(is_img2img)].update(choices=wizard_refresh_shortcodes())
# self.templates_dropdown[int(is_img2img)].update(choices=wizard_refresh_templates())
Unprompted.log.debug("Reload completed!")

Expand Down Expand Up @@ -777,7 +782,6 @@ def process(self, p, is_enabled=True, unprompted_seed=-1, match_main_seed=True,
Unprompted.shortcode_user_vars["batch_size_index"] += 1
Unprompted.shortcode_user_vars["batch_real_index"] += 1


if Unprompted.fix_hires_prompts:
Unprompted.log.debug("Synchronizing prompt vars with hr_prompt vars")
p.hr_prompt = prompt_result
Expand Down Expand Up @@ -903,4 +907,4 @@ def postprocess(self, p, processed, is_enabled=True, unprompted_seed=-1, match_m

self.allow_postprocess = True

return processed
return processed
Loading

0 comments on commit 2d4a184

Please sign in to comment.