v10.2.0
parent
aac4796fa3
commit
5148b2d02e
|
|
@ -0,0 +1,13 @@
|
|||
# These are supported funding model platforms
|
||||
|
||||
github: [ThereforeGames]
|
||||
patreon: ThereforeGames
|
||||
open_collective: # Replace with a single Open Collective username
|
||||
ko_fi: # Replace with a single Ko-fi username
|
||||
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
|
||||
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
|
||||
liberapay: # Replace with a single Liberapay username
|
||||
issuehunt: # Replace with a single IssueHunt username
|
||||
otechie: # Replace with a single Otechie username
|
||||
lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
|
||||
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
|
||||
|
|
@ -49,7 +49,8 @@
|
|||
"tag_close":"/",
|
||||
"tag_escape":"`",
|
||||
"delimiter":"|",
|
||||
"wizard_delimiter":"🡢"
|
||||
"wizard_delimiter":"🡢",
|
||||
"not_operator":"!"
|
||||
},
|
||||
"templates":
|
||||
{
|
||||
|
|
|
|||
|
|
@ -7,6 +7,6 @@ Unprompted is a powerful templating language written in Python. Unlike most temp
|
|||
- 💬 [Discussion Board](https://github.com/ThereforeGames/unprompted/discussions)
|
||||
- 🔧 [Issue Tracker](https://github.com/ThereforeGames/unprompted/issues)
|
||||
|
||||
Software created by [Therefore Games](https://therefore.games). If you like what I do, you can [support me on <span class="patreon-symbol">┃🔴</span> Patreon](https://patreon.com/thereforegames).
|
||||
Software created by [Therefore Games](https://therefore.games). If you like my work, you can [sponsor the project on ☕ Github](https://github.com/sponsors/ThereforeGames) or [support me on <span class="patreon-symbol">┃🔴</span> Patreon](https://patreon.com/thereforegames). Thank you!
|
||||
|
||||
*Compatible with Python v3.10.6 and WebUI v1.6.0.*
|
||||
|
|
@ -3,7 +3,28 @@ 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.1.5 - 18 October 2023</summary>
|
||||
<details open><summary>10.2.0 - 27 October 2023</summary>
|
||||
|
||||
### Added
|
||||
- New shortcode `[tags]`: Assigns arbitrary metatags that can be used in conjunction with a filter for bypassing the content
|
||||
- New shortcode `[filter_tags]`: Bypasses the content of `[tags]` blocks that do not match the given filter
|
||||
- New shortcode `[logs]`: Atomic version of `[log]` that allows you print multiple messages at once
|
||||
- Blue badge with the number of active Wizard scripts, similar to ControlNet
|
||||
- New setting `Config.syntax.not_operator`: Allows you to change the character used for the "not" operator, defaults to `!` (currently only used for tags)
|
||||
- New guide: "Using Metatags with Your `[choose]` Blocks"
|
||||
|
||||
### Changed
|
||||
- Wizard "auto-include" string now contains name of the current script or shortcode
|
||||
- Shuffle the Unprompted promo on UI load
|
||||
- Minor CSS improvements
|
||||
|
||||
### Fixed
|
||||
- `[override]`: Fixed a syntax error
|
||||
- Fixed an error related to setting `batch_count` > 1 with hires fix enabled
|
||||
|
||||
</details>
|
||||
|
||||
<details><summary>10.1.5 - 18 October 2023</summary>
|
||||
|
||||
### Fixed
|
||||
- Wizard UI: Fixed an issue related to block shortcode content
|
||||
|
|
|
|||
121
docs/GUIDE.md
121
docs/GUIDE.md
|
|
@ -251,4 +251,125 @@ Add an entry called `templates` as shown below:
|
|||
|
||||
The asterisk wildcard represents any prompt. Restart the WebUI and you're all set!
|
||||
|
||||
</details>
|
||||
|
||||
<details><summary>Using Metatags with Your [choose] Blocks</summary>
|
||||
|
||||
In this guide, we will utilize the `[tags]` and `[filter_tags]` shortcodes to create a more dynamic `[choose]` block.
|
||||
|
||||
Let's say we want to generate a random animal. We can use the following prompt:
|
||||
|
||||
```
|
||||
[choose]
|
||||
dog
|
||||
cat
|
||||
lion
|
||||
tiger
|
||||
wolf
|
||||
lizard
|
||||
turtle
|
||||
crocodile
|
||||
newt
|
||||
salamander
|
||||
frog
|
||||
[/choose]
|
||||
```
|
||||
|
||||
But what if we want to generate a random animal that is also a reptile? We could create a separate `[choose]` block for reptiles, but that would be time-consuming and redundant. Instead, we can use the `[tags]` shortcode to filter our options.
|
||||
|
||||
We can sort our animals into three categories: `mammal`, `reptile`, and `amphibian`. Here's how we can do this:
|
||||
|
||||
```
|
||||
[choose]
|
||||
[tags mammal]
|
||||
dog
|
||||
cat
|
||||
lion
|
||||
tiger
|
||||
wolf
|
||||
[/tags]
|
||||
[tags reptile]
|
||||
lizard
|
||||
turtle
|
||||
crocodile
|
||||
[/tags]
|
||||
[tags amphibian]
|
||||
newt
|
||||
salamander
|
||||
frog
|
||||
[/tags]
|
||||
[/choose]
|
||||
```
|
||||
|
||||
Now we can simply write `[filter_tags reptile]` before our `[choose]` block to select a random reptile.
|
||||
|
||||
Note that the `[tags]` shortcode is not limited to use with `[choose]` blocks. You can use it anywhere in your template to create grouped content that can be filtered by `[filter_tags]`.
|
||||
|
||||
We can also write multiple tags in a single `[tags]` block. Both reptiles and amphibians are known for laying eggs, so we can add a `lays_eggs` tag to both of those categories and use it as our filter criteria:
|
||||
|
||||
```
|
||||
[filter_tags lays_eggs]
|
||||
[choose]
|
||||
[tags mammal]
|
||||
dog
|
||||
cat
|
||||
lion
|
||||
tiger
|
||||
wolf
|
||||
[/tags]
|
||||
[tags reptile lays_eggs]
|
||||
lizard
|
||||
turtle
|
||||
crocodile
|
||||
[/tags]
|
||||
[tags amphibian lays_eggs]
|
||||
newt
|
||||
salamander
|
||||
frog
|
||||
[/tags]
|
||||
[/choose]
|
||||
```
|
||||
|
||||
Now it will only select animals that lay eggs - either a reptile or an amphibian.
|
||||
|
||||
For our final example, let's say we want to generate a mammal that is **not** a feline. To achieve this, we will first create `feline` and `canine` genus tags within the mammal category (yes, we can use nested `[tags]`!):
|
||||
|
||||
```
|
||||
[choose]
|
||||
[tags mammal]
|
||||
[tags genus="feline"]
|
||||
cat
|
||||
lion
|
||||
tiger
|
||||
[/tags]
|
||||
[tags genus="canine"]
|
||||
dog
|
||||
wolf
|
||||
[/tags]
|
||||
[/tags]
|
||||
[tags reptile lays_eggs]
|
||||
lizard
|
||||
turtle
|
||||
crocodile
|
||||
[/tags]
|
||||
[tags amphibian lays_eggs]
|
||||
newt
|
||||
salamander
|
||||
frog
|
||||
[/tags]
|
||||
[/choose]
|
||||
```
|
||||
|
||||
Then we update our filter to exclude the `feline` genus using the `!` operator:
|
||||
|
||||
```
|
||||
[filter_tags mammal genus="!feline"]
|
||||
```
|
||||
|
||||
With this setup, we will only get `dog` or `wolf` as a result.
|
||||
|
||||
As you can see, `[tags]` and `[filter_tags]` are very flexible - you can use them to create complex, multi-layered prompts that are easy to maintain.
|
||||
|
||||
For more information on these shortcodes, please consult the [Unprompted Manual](MANUAL.md).
|
||||
|
||||
</details>
|
||||
|
|
@ -987,6 +987,41 @@ Supports the macro `%BASE_DIR%` which will be substituted with an absolute path
|
|||
|
||||
</details>
|
||||
|
||||
<details><summary>[filter_tags]</summary>
|
||||
|
||||
Prepare a list of tags which will be evaluated against subsequent `[tags]` blocks. The content of `[tags]` is bypassed if it does not match your filters.
|
||||
|
||||
Supports the `_extend` parg to add to the existing list of filters instead of replacing it.
|
||||
|
||||
Supports the `_clear` parg to clear all filter rules after the first matching `[tags]` block.
|
||||
|
||||
Supports the `_once` parg to remove an individual tag from the filter after the first match.
|
||||
|
||||
Supports the `_must_match` kwarg that determines the behavior of the filter when using multiple tags:
|
||||
|
||||
- `any` (default): The `[tags]` block must contain at least one matching parg or kwarg.
|
||||
- `all`: The `[tags]` block must contain all matching pargs and kwargs.
|
||||
- `selective`: The `[tags]` block must contain the same pargs. It does **not** have to contain the same kwargs, but if it does, the kwarg values must match.
|
||||
|
||||
Supports `Config.syntax.not_operator` to exclude tags from the filter. For example, if you want to exclude all blocks with the "outdoors" tag, you can do it like this: `[filter_tags !outdoors]`.
|
||||
|
||||
For kwarg tags, the not operator can be used with keys or values as shown:
|
||||
|
||||
- `[filter_tags !location="indoors"]` will exclude all blocks that contain a kwarg with the `location` key
|
||||
- `[filter_tags location="!indoors"]` will exclude all blocks that contain a `location` kwarg with a value of `indoors`
|
||||
|
||||
Supports the `_debug` parg to print some diagnostic information to the console.
|
||||
|
||||
You can clear the filter at any time by calling `[filter_tags]` without any arguments.
|
||||
|
||||
```
|
||||
[filter_tags location="outdoors"]
|
||||
[tags location="indoors"]This will not print[/tags]
|
||||
[tags location="outdoors"]This will print[/tags]
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
<details><summary>[for var "test var" "update var"]</summary>
|
||||
|
||||
Returns the content an arbitrary number of times until the `test` condition returns false.
|
||||
|
|
@ -1196,6 +1231,20 @@ By default, the message context is `DEBUG`. The first positional argument determ
|
|||
|
||||
</details>
|
||||
|
||||
<details><summary>[logs]</summary>
|
||||
|
||||
Prints one or more messages to the console. This is the atomic version of `[log]`.
|
||||
|
||||
By default, the message context is `INFO`. You can change this with the optional `_level` argument.
|
||||
|
||||
Each parg is a message to be printed. You should enclose your message in quotes if it contains spaces.
|
||||
|
||||
```
|
||||
[logs "This is a message" "This is another message" _level="INFO"]
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
<details><summary>[max]</summary>
|
||||
|
||||
Returns the greatest value among the arguments. Supports advanced expressions.
|
||||
|
|
@ -1477,6 +1526,18 @@ The optional `enable_wordnet` keyword argument determines whether WordNet will b
|
|||
|
||||
</details>
|
||||
|
||||
<details><summary>[tags]</summary>
|
||||
|
||||
Assigns arbitrary tags to the content. Supports both parg and kwarg-style tags.
|
||||
|
||||
On its own, this shortcode merely returns the content, but it can be used in conjunction with `[filter_tags]` to bypass the content if the tags don't match your filter rules. See `[filter_tags]` for more information.
|
||||
|
||||
```
|
||||
[tags "tag_one" tag_two="value_two"]A photo of a dog.[/tags]
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
<details><summary>[while variable {_not} {_any} {_is}]</summary>
|
||||
|
||||
Checks whether `variable` is equal to the given value, returning the content repeatedly until the condition is false. This can create an infinite loop if you're not careful.
|
||||
|
|
|
|||
Binary file not shown.
|
After Width: | Height: | Size: 177 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 26 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 12 KiB |
|
|
@ -0,0 +1,50 @@
|
|||
/**
|
||||
* Give a badge on Unprompted Accordion indicating total number of active
|
||||
* wizard scripts.
|
||||
*/
|
||||
(function()
|
||||
{
|
||||
const unprompted_accordions = new Set();
|
||||
|
||||
function update_active_unit_count(accordion)
|
||||
{
|
||||
const span = accordion.querySelector(".label-wrap span");
|
||||
let active_unit_count = 0;
|
||||
accordion.querySelectorAll(".wizard-autoinclude input").forEach(function(checkbox)
|
||||
{
|
||||
if (checkbox.checked)
|
||||
{
|
||||
console.log("found checkbox");
|
||||
active_unit_count++;
|
||||
}
|
||||
});
|
||||
|
||||
if (span.childNodes.length !== 1)
|
||||
{
|
||||
span.removeChild(span.lastChild);
|
||||
}
|
||||
if (active_unit_count > 0)
|
||||
{
|
||||
const div = document.createElement("div");
|
||||
div.classList.add("unprompted-badge");
|
||||
div.innerHTML = `🪄 ${active_unit_count} wizard${active_unit_count > 1 ? "s" : ""}`;
|
||||
span.appendChild(div);
|
||||
}
|
||||
}
|
||||
|
||||
onUiUpdate(() =>
|
||||
{
|
||||
gradioApp().querySelectorAll(".unprompted-accordion").forEach(function(accordion)
|
||||
{
|
||||
if (unprompted_accordions.has(accordion)) return;
|
||||
accordion.querySelectorAll(".wizard-autoinclude input").forEach(function(checkbox)
|
||||
{
|
||||
checkbox.addEventListener("change", function()
|
||||
{
|
||||
update_active_unit_count(accordion);
|
||||
});
|
||||
});
|
||||
unprompted_accordions.add(accordion);
|
||||
});
|
||||
});
|
||||
})();
|
||||
|
|
@ -101,7 +101,7 @@ class Unprompted:
|
|||
self.log.info(f"Finished loading in {time.time()-start_time} seconds.")
|
||||
|
||||
def __init__(self, base_dir="."):
|
||||
self.VERSION = "10.1.5"
|
||||
self.VERSION = "10.2.0"
|
||||
|
||||
self.shortcode_modules = {}
|
||||
self.shortcode_objects = {}
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ import lib_unprompted.shortcodes as shortcodes
|
|||
import lib_unprompted.helpers as helpers
|
||||
from pathlib import Path
|
||||
from enum import IntEnum, auto
|
||||
import sys, os, html
|
||||
import sys, os, html, random
|
||||
|
||||
base_dir = scripts.basedir()
|
||||
|
||||
|
|
@ -288,8 +288,6 @@ class Scripts(scripts.Script):
|
|||
shortcodes_region = [None] * 2
|
||||
shortcodes_dropdown = [None] * 2
|
||||
|
||||
# templates_dropdown = [None] * 2
|
||||
|
||||
def title(self):
|
||||
return "Unprompted"
|
||||
|
||||
|
|
@ -297,8 +295,9 @@ class Scripts(scripts.Script):
|
|||
return scripts.AlwaysVisible
|
||||
|
||||
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):
|
||||
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)
|
||||
|
||||
|
|
@ -308,11 +307,18 @@ class Scripts(scripts.Script):
|
|||
unprompted_seed = gr.Number(label="Unprompted Seed", value=-1)
|
||||
setattr(unprompted_seed, "do_not_save_to_config", True)
|
||||
|
||||
if (os.path.exists(f"{base_dir}/{Unprompted.Config.template_directory}/pro/beautiful_soul_v0.0.1/main{Unprompted.Config.formats.txt}")): is_open = False
|
||||
if (os.path.exists(f"{base_dir}/{Unprompted.Config.template_directory}/pro/beautiful_soul_v0.1.0/main{Unprompted.Config.formats.txt}")): is_open = False
|
||||
else: is_open = True
|
||||
|
||||
promos = []
|
||||
promos.append(f'<a href="https://payhip.com/b/L1uNF" target="_blank"><img src="{get_local_file_dir()}/images/promo_box_beautiful_soul.png" class="thumbnail"></a><h1><strong>Beautiful Soul</strong>: Bring your characters to life.</h1><p>A highly expressive character generator for the A1111 WebUI. With thousands of wildcards and direct ControlNet integration, this is by far our most powerful Unprompted template to date. <strong>Available at half price until November 11th!</strong></p><a href="https://payhip.com/b/L1uNF" target=_blank><button class="gr-button gr-button-lg gr-button-secondary" title="View premium assets for Unprompted">Download Now ➜</button></a>')
|
||||
promos.append(f'<a href="https://payhip.com/b/qLUX9" target="_blank"><img src="{get_local_file_dir()}/images/promo_box_demoncrawl_avatar_generator.png" class="thumbnail"></a><h1>The <strong>DemonCrawl</strong> Pixel Art Avatar Generator</h1><p>Create pixel art portraits in the style of the popular roguelite, <a href="https://demoncrawl.com" _target=blank>DemonCrawl</a>. Includes a custom Stable Diffusion model trained by the game\'s developer, as well as a custom GUI and the ability to randomize your prompts.</p><a href="https://payhip.com/b/qLUX9" target=_blank><button class="gr-button gr-button-lg gr-button-secondary" title="View premium assets for Unprompted">Download Now ➜</button></a>')
|
||||
promos.append(f'<a href="https://payhip.com/b/hdgNR" target="_blank"><img src="{get_local_file_dir()}/images/promo_box_fantasy.png" class="thumbnail"></a><h1>Create beautiful art for your <strong>Fantasy Card Game</strong></h1><p>Generate a wide variety of creatures and characters in the style of a fantasy card game. Perfect for heroes, animals, monsters, and even crazy hybrids.</p><a href="https://payhip.com/b/hdgNR" target=_blank><button class="gr-button gr-button-lg gr-button-secondary" title="View premium assets for Unprompted">Download Now ➜</button></a>')
|
||||
promos.append(f'<a href="https://github.com/ThereforeGames/unprompted" target="_blank"><img src="{get_local_file_dir()}/images/promo_github_star.png" class="thumbnail"></a><h1>Give Unprompted a <strong>star</strong> for visibility</h1><p>Most WebUI users have never heard of Unprompted. You can help more people discover it by giving the repo a ⭐ on Github. Thank you for your support!</p><a href="https://github.com/ThereforeGames/unprompted" target=_blank><button class="gr-button gr-button-lg gr-button-secondary" title="View the Unprompted repo">Visit Github ➜</button></a>')
|
||||
promos.append(f'<a href="https://github.com/sponsors/ThereforeGames" target="_blank"><img src="{get_local_file_dir()}/images/promo_github_sponsor.png" class="thumbnail"></a><h1>Become a Sponsor</h1><p>One of the best ways to support Unprompted is by becoming our Sponsor on Github - sponsors receive access to a private repo containing all of our premium add-ons. <em>(Still setting that up... should be ready soon!)</em></p><a href="https://github.com/sponsors/ThereforeGames" target=_blank><button class="gr-button gr-button-lg gr-button-secondary" title="View the Unprompted repo">Visit Github ➜</button></a>')
|
||||
|
||||
with gr.Accordion("🎉 Promo", open=is_open):
|
||||
plug = gr.HTML(label="plug", elem_id="promo", value=f'<a href="https://payhip.com/b/L1uNF" target="_blank"><img src="{get_local_file_dir()}/images/promo_box_beautiful_soul.png" style="float: left;width: 150px;margin-bottom:10px;"></a><h1 style="font-size: 20px;letter-spacing:0.015em;margin-top:10px;"><strong>Beautiful Soul</strong>: Bring your characters to life.</h1><p style="margin:1em 0;">A highly expressive character generator for the A1111 WebUI. With thousands of wildcards and direct ControlNet integration, this is by far our most powerful Unprompted template to date. <strong>Available at half price until November 11th!</strong></p><a href="https://payhip.com/b/L1uNF" target=_blank><button class="gr-button gr-button-lg gr-button-secondary" title="View premium assets for Unprompted">Download Now ➜</button></a>')
|
||||
plug = gr.HTML(label="plug", elem_id="promo", value=random.choice(promos))
|
||||
|
||||
with gr.Accordion("🧙 Wizard", open=Unprompted.Config.ui.wizard_open):
|
||||
if Unprompted.Config.ui.wizard_enabled:
|
||||
|
|
@ -399,6 +405,7 @@ class Scripts(scripts.Script):
|
|||
wizard_shortcode_parser.register(handler, "wizard", f"{Unprompted.Config.syntax.tag_close}wizard", preprocess)
|
||||
|
||||
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)]
|
||||
|
||||
|
|
@ -413,7 +420,7 @@ class Scripts(scripts.Script):
|
|||
# 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="🪄 Auto-include this in prompt", value=False, elem_classes=["wizard-autoinclude"])
|
||||
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])
|
||||
|
||||
|
|
@ -456,7 +463,7 @@ class Scripts(scripts.Script):
|
|||
# Run the shortcode's UI template to populate
|
||||
Unprompted.shortcode_objects[key].ui(gr)
|
||||
# Auto-include is always the last element
|
||||
gr.Checkbox(label="🪄 Auto-include this in prompt", value=False, elem_classes=["wizard-autoinclude"])
|
||||
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])
|
||||
|
||||
|
|
@ -503,7 +510,7 @@ class Scripts(scripts.Script):
|
|||
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>")
|
||||
|
|
@ -817,6 +824,13 @@ class Scripts(scripts.Script):
|
|||
p.all_prompts[batch_real_index] = prompt_result
|
||||
p.all_negative_prompts[batch_real_index] = negative_prompt_result
|
||||
|
||||
if Unprompted.fix_hires_prompts:
|
||||
Unprompted.log.debug("Synchronizing prompt vars with hr_prompt vars")
|
||||
p.hr_prompt = prompt_result
|
||||
p.hr_negative_prompt = negative_prompt_result
|
||||
p.all_hr_prompts = p.all_prompts
|
||||
p.all_negative_prompts = p.all_negative_prompts
|
||||
|
||||
if (batch_count_index > 0):
|
||||
try:
|
||||
Unprompted.log.debug("Attempting to re-parse and re-activate extra networks...")
|
||||
|
|
@ -832,17 +846,6 @@ class Scripts(scripts.Script):
|
|||
if unprompted_seed != -1:
|
||||
import random
|
||||
random.seed()
|
||||
|
||||
if Unprompted.fix_hires_prompts:
|
||||
Unprompted.log.debug("Synchronizing prompt vars with hr_prompt vars")
|
||||
p.hr_prompt = Unprompted.shortcode_user_vars["prompt"]
|
||||
p.hr_negative_prompt = Unprompted.shortcode_user_vars["negative_prompt"]
|
||||
p.all_hr_prompts = p.all_prompts
|
||||
p.all_hr_negative_prompts = p.all_negative_prompts
|
||||
# SDXL is using hr_prompts instead of hr_all_prompts
|
||||
# TODO: Check if all_hr_prompts is used anywhere else anymore
|
||||
p.hr_prompts = p.all_prompts
|
||||
p.hr_negative_prompts = p.all_negative_prompts
|
||||
else:
|
||||
Unprompted.log.debug("Proceeding to next batch_count batch")
|
||||
# Increment batch index
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@ class Shortcode():
|
|||
del parts[part_index] # Prevent the same choice from being made again
|
||||
final_string += _sep
|
||||
except Exception as e:
|
||||
self.log.exception("Exception while parsing the list of choices")
|
||||
self.log.exception(f"Exception while parsing the list of choices. The partially assembled final string was: {final_string}")
|
||||
pass
|
||||
|
||||
# Reset to original value
|
||||
|
|
|
|||
|
|
@ -0,0 +1,46 @@
|
|||
class Shortcode():
|
||||
def __init__(self,Unprompted):
|
||||
self.Unprompted = Unprompted
|
||||
self.shortcode_overrides = {}
|
||||
self.description = "Tags for filtering content inside of [tags] blocks."
|
||||
self.parg_tags = []
|
||||
self.kwarg_tags = {}
|
||||
self.once = False
|
||||
self.debug = False
|
||||
self.clear = False
|
||||
self.must_match = "any"
|
||||
|
||||
def run_atomic(self, pargs, kwargs, context):
|
||||
_extend = self.Unprompted.parse_arg("_extend",False)
|
||||
self.debug = self.Unprompted.parse_arg("_debug",False)
|
||||
self.once = self.Unprompted.parse_arg("_once",False)
|
||||
self.clear = self.Unprompted.parse_arg("_clear",False)
|
||||
self.must_match = self.Unprompted.parse_arg("_must_match","any")
|
||||
|
||||
if _extend:
|
||||
self.parg_tags.extend(pargs)
|
||||
self.kwarg_tags.update(kwargs)
|
||||
else:
|
||||
self.parg_tags = pargs
|
||||
self.kwarg_tags = kwargs
|
||||
|
||||
if self.debug:
|
||||
self.log.info(f"Parg tags: {self.parg_tags}")
|
||||
self.log.info(f"Kwarg tags: {self.kwarg_tags}")
|
||||
|
||||
return("")
|
||||
|
||||
def cleanup(self):
|
||||
self.parg_tags = []
|
||||
self.kwarg_tags = {}
|
||||
self.once = False
|
||||
self.clear = False
|
||||
self.must_match = "any"
|
||||
self.debug = False
|
||||
|
||||
def ui(self,gr):
|
||||
gr.Textbox(label="Arbitrary tag filters 🡢 verbatim",max_lines=1,placeholder='location=outdoors nature')
|
||||
gr.Checkbox(label="Clear all filters after first matching tag block 🡢 _clear",value=False)
|
||||
gr.Checkbox(label="Match each tag only once 🡢 _once",value=False)
|
||||
gr.Radio(label="Rules for what is considered a matching block 🡢 _must_match",choices=["any","all","selective"])
|
||||
gr.Checkbox(label="Debug 🡢 _debug",value=False)
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
class Shortcode():
|
||||
def __init__(self, Unprompted):
|
||||
self.Unprompted = Unprompted
|
||||
self.description = "Prints one or more messages to the console."
|
||||
|
||||
def run_atomic(self, pargs, kwargs, context):
|
||||
_level = self.Unprompted.parse_arg("_level","info")
|
||||
log_func = getattr(self.log,_level.lower())
|
||||
for parg in pargs:
|
||||
log_func(self.Unprompted.parse_advanced(parg,context))
|
||||
|
||||
return ("")
|
||||
|
||||
def ui(self, gr):
|
||||
gr.Textbox(label="Arbitrary messages as pargs 🡢 verbatim",max_lines=1,placeholder='"message one" "message two goes here"')
|
||||
gr.Dropdown(label="Log level 🡢 _level",choices=["debug","info","warning","error","critical"],value="info")
|
||||
|
|
@ -5,7 +5,7 @@ class Shortcode():
|
|||
|
||||
def run_block(self, pargs, kwargs, context,content):
|
||||
# self.shortcode_overrides.update(kwargs)
|
||||
self.Unprompted.shortcode_objects["overrides"][pargs[0]] = content
|
||||
self.Unprompted.shortcode_objects["overrides"].shortcode_overrides[pargs[0]] = self.Unprompted.parse_advanced(content,context)
|
||||
return("")
|
||||
|
||||
def ui(self,gr):
|
||||
|
|
|
|||
|
|
@ -0,0 +1,101 @@
|
|||
class Shortcode():
|
||||
def __init__(self,Unprompted):
|
||||
self.Unprompted = Unprompted
|
||||
self.description = "Applies one or more metatags to be evaluated with [filter_tags] for bypassing the content."
|
||||
|
||||
def preprocess_block(self, pargs, kwargs, context):
|
||||
return True
|
||||
|
||||
def run_block(self, pargs, kwargs, context,content):
|
||||
# self.shortcode_overrides.update(kwargs)
|
||||
filter_obj = self.Unprompted.shortcode_objects["filter_tags"]
|
||||
failed_test = False
|
||||
matched_one = False
|
||||
|
||||
for orig_parg_tag in filter_obj.parg_tags:
|
||||
parg_tag = orig_parg_tag
|
||||
if self.Unprompted.is_system_arg(parg_tag): continue
|
||||
# Check if the tag begins with a hyphen for "negative" matching
|
||||
elif parg_tag.startswith(self.Unprompted.Config.syntax.not_operator):
|
||||
is_not = True
|
||||
parg_tag = parg_tag[1:]
|
||||
else: is_not = False
|
||||
|
||||
if parg_tag not in pargs:
|
||||
if is_not:
|
||||
if filter_obj.once: filter_obj.parg_tags.remove(orig_parg_tag)
|
||||
matched_one = True
|
||||
continue
|
||||
if filter_obj.must_match == "any": continue
|
||||
else:
|
||||
failed_test = True
|
||||
break
|
||||
else:
|
||||
if is_not:
|
||||
if filter_obj.must_match != "any":
|
||||
failed_test = True
|
||||
break
|
||||
else:
|
||||
if filter_obj.once: filter_obj.parg_tags.remove(parg_tag)
|
||||
matched_one = True
|
||||
|
||||
for orig_kwarg_tag in filter_obj.kwarg_tags:
|
||||
kwarg_tag = orig_kwarg_tag
|
||||
|
||||
if self.Unprompted.is_system_arg(kwarg_tag): continue
|
||||
elif kwarg_tag.startswith(self.Unprompted.Config.syntax.not_operator):
|
||||
key_is_not = True
|
||||
kwarg_tag = kwarg_tag[1:]
|
||||
else: key_is_not = False
|
||||
|
||||
# Support "not" operator for kwarg value:
|
||||
if isinstance(filter_obj.kwarg_tags[orig_kwarg_tag], str) and filter_obj.kwarg_tags[orig_kwarg_tag].startswith(self.Unprompted.Config.syntax.not_operator):
|
||||
val_is_not = True
|
||||
kwarg_val = filter_obj.kwarg_tags[orig_kwarg_tag][1:]
|
||||
else:
|
||||
val_is_not = False
|
||||
kwarg_val = filter_obj.kwarg_tags[orig_kwarg_tag]
|
||||
|
||||
if kwarg_tag not in kwargs:
|
||||
if key_is_not:
|
||||
if filter_obj.once: filter_obj.kwarg_tags.pop(orig_kwarg_tag)
|
||||
matched_one = True
|
||||
continue
|
||||
if filter_obj.must_match != "all": continue
|
||||
else:
|
||||
failed_test = True
|
||||
break
|
||||
|
||||
if kwargs[kwarg_tag] != kwarg_val:
|
||||
if val_is_not:
|
||||
if filter_obj.once: filter_obj.kwarg_tags.pop(orig_kwarg_tag)
|
||||
matched_one = True
|
||||
continue
|
||||
elif filter_obj.must_match == "any": continue
|
||||
else:
|
||||
failed_test = True
|
||||
break
|
||||
else:
|
||||
if val_is_not:
|
||||
if filter_obj.must_match != "any":
|
||||
failed_test = True
|
||||
break
|
||||
else:
|
||||
if filter_obj.once: filter_obj.kwarg_tags.pop(kwarg_tag)
|
||||
matched_one = True
|
||||
|
||||
# Return content in the event of success or no filters
|
||||
if (matched_one and not failed_test) or (not filter_obj.parg_tags and not filter_obj.kwarg_tags):
|
||||
if filter_obj.debug: self.log.info(f"Matched tags block: {pargs} {kwargs}")
|
||||
|
||||
# Reset filter tags
|
||||
if filter_obj.clear:
|
||||
filter_obj.cleanup()
|
||||
|
||||
return self.Unprompted.parse_alt_tags(content, context)
|
||||
|
||||
if filter_obj.debug: self.log.info(f"Failed tags block: {pargs} {kwargs}")
|
||||
return ""
|
||||
|
||||
def ui(self,gr):
|
||||
gr.Textbox(label="Arbitrary tags 🡢 verbatim",max_lines=1,placeholder="nature")
|
||||
55
style.css
55
style.css
|
|
@ -48,6 +48,44 @@ details[open]
|
|||
display: block;
|
||||
}
|
||||
|
||||
#promo .thumbnail
|
||||
{
|
||||
float: left;
|
||||
width: 150px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
#promo h1
|
||||
{
|
||||
font-size: 20px;
|
||||
letter-spacing: 0.015em;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
#promo p
|
||||
{
|
||||
margin: 1em 0;
|
||||
}
|
||||
|
||||
#promo .gr-button
|
||||
{
|
||||
transition: 0.1s;
|
||||
display: inline-block;
|
||||
padding: 0.25em 0.75em;
|
||||
font-weight: bold;
|
||||
color: var(--background-fill-primary);
|
||||
border-radius: 0.5em;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
background-color: var(--body-text-color);
|
||||
}
|
||||
|
||||
#promo .gr-button:hover
|
||||
{
|
||||
background-color: var(--checkbox-background-color-selected);
|
||||
color: var(--body-text-color);
|
||||
}
|
||||
|
||||
.gradio-group div .wizard-autoinclude
|
||||
{
|
||||
margin-top: 20px;
|
||||
|
|
@ -65,11 +103,26 @@ details[open]
|
|||
top: -10px;
|
||||
}
|
||||
|
||||
.wizard-autoinclude span
|
||||
.wizard-autoinclude input[type="checkbox"]:checked+span
|
||||
{
|
||||
color: var(--checkbox-background-color-selected);
|
||||
font-weight: 1000;
|
||||
}
|
||||
|
||||
.unprompted-badge
|
||||
{
|
||||
display: inline-block;
|
||||
padding: 0.25em 0.75em;
|
||||
font-size: 0.75em;
|
||||
font-weight: bold;
|
||||
color: white;
|
||||
border-radius: 0.5em;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
margin-left: var(--size-2);
|
||||
background-color: var(--checkbox-background-color-selected);
|
||||
}
|
||||
|
||||
.patreon-symbol
|
||||
{
|
||||
letter-spacing: -7px;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,2 @@
|
|||
[# A decent starting point to upscale images using the Tile model for ControlNet.]
|
||||
[sets sampler="DPM++ 3M SDE" denoising_strength=0.3 cfg_scale=2 cn_0_enabled=1 cn_0_pixel_perfect=0 cn_0_module=tile_resample cn_0_model=tile cn_0_weight=1.15 cn_0_control_mode=2]
|
||||
Loading…
Reference in New Issue