v6.0.0
parent
3e50472878
commit
4786902851
|
|
@ -133,7 +133,5 @@ dmypy.json
|
|||
/templates/*
|
||||
# Default Templates
|
||||
!/templates/common
|
||||
!/templates/examples
|
||||
!/templates/human
|
||||
# clipseg weights
|
||||
/lib/clipseg/weights/*
|
||||
85
README.md
85
README.md
|
|
@ -1,85 +0,0 @@
|
|||
<p align="center">
|
||||
<img src="https://user-images.githubusercontent.com/95403634/206286547-53f22ebf-e5fc-4bbd-8bad-53b9cb17ae64.png">
|
||||
</p>
|
||||
|
||||
<p align="center"><strong>Links:</strong> 📣 <a href="./docs/ANNOUNCEMENTS.md">Announcements</a> | 📘 <a href="./docs/MANUAL.md">Manual</a> | ⏱ <a href="./docs/CHANGELOG.md">Changelog</a> | 🎓 <a href="./docs/GUIDE.md">Starter Guide</a></p>
|
||||
|
||||
## Introduction
|
||||
|
||||
**Unprompted is a powerful templating language written in Python.**
|
||||
|
||||
Unlike most templating languages, Unprompted was designed for **maximum readibility with natural language.** It is built around `[shortcodes]` and inspired by the likes of BBCode.
|
||||
|
||||
You can use Unprompted as a standalone library (e.g. `unprompted_dry.py`) or as an extension for [AUTOMATIC1111's Stable Diffusion Web UI](https://github.com/AUTOMATIC1111/stable-diffusion-webui). The extension allows you to create expressive, re-usable prompt templates that are both versatile and easy on the eyes.
|
||||
|
||||
## Features
|
||||
|
||||
- **Dozens of shortcodes** provided out of the box - there are `[if]` conditionals, powerful `[file]` imports, `[for]` loops and everything else the prompting enthusiast could possibly want
|
||||
- Easily extendable with **custom shortcodes**
|
||||
- Simple creation of `.txt` templates that can be organized according to your preferences
|
||||
- Supports recursion, nested shortcodes, advanced logic operators, custom configs, pretty much all the good stuff one might expect from a modern language
|
||||
- Supports **numerous Stable Diffusion variables** such as `negative_prompt` and `cfg_scale`
|
||||
- Includes a growing list of examples that demonstrate advanced functionality, such as **customizing the weight of a choice list** and **applying emphasis to a random part of your prompt**
|
||||
- Comprehensive documentation that is always up-to-date
|
||||
- Free
|
||||
- Developed by a human
|
||||
|
||||
## Installation
|
||||
|
||||
1. Visit the **Extensions** tab of Automatic's WebUI.
|
||||
2. Visit the **Available** subtab.
|
||||
3. Uncheck the "ads" filter and press the **Load from** button.
|
||||
4. Scroll down to **Unprompted** and press the **Install** button.
|
||||
|
||||
## Usage
|
||||
|
||||
First, try the included demo template by entering the following as your prompt:
|
||||
|
||||
`[file human/main]`
|
||||
|
||||
This is a simple "person generator" that automatically chooses characteristics like hair color, race, and posture.
|
||||
|
||||
The `[file]` shortcode will look in `unprompted/templates` for the specified text file (in this case `unprompted/templates/human/main.txt`.) You do not need to enter the file extension.
|
||||
|
||||
**Example output:**
|
||||
|
||||

|
||||
|
||||
## Next Steps
|
||||
|
||||
Once you have verified that Unprompted is installed and running correctly, you have a couple options:
|
||||
|
||||
1. You can visit the 🎓 [Starter Guide](./docs/GUIDE.md) for a crash course on creating your own templates
|
||||
2. Or dive into the deep end by exploring the comprehensive 📘 [Manual](./docs/MANUAL.md)
|
||||
|
||||
## Premium Templates
|
||||
|
||||
While Unprompted is completely free to use, we do offer **Premium Template add-ons** that demonstrate some of the software's more advanced functionality.
|
||||
|
||||
<img align="left" src="https://i.ibb.co/1MSpHL4/Fantasy-Card-Template2.png" width=150>
|
||||
|
||||
### [Fantasy Card Template](https://payhip.com/b/hdgNR)
|
||||
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.
|
||||
<br/>
|
||||
<br/>
|
||||
<br/>
|
||||
<br/>
|
||||
<br/>
|
||||
<br/>
|
||||
<br/>
|
||||
<br/>
|
||||
Purchases help fund this project. Your support is greatly appreciated! ❤️
|
||||
|
||||
## Acknowledgements
|
||||
|
||||
A big "thank you" to the authors of the following libraries that Unprompted depends on:
|
||||
|
||||
- [Python Shortcodes](https://www.dmulholl.com/dev/shortcodes.html) by Darren Mulholland
|
||||
- [Simple Eval](https://github.com/danthedeckie/simpleeval) by @danthedeckie
|
||||
- [Casefy](https://github.com/dmlls/python-casefy) by @dmlls
|
||||
- [CLIPseg](https://github.com/timojl/clipseg) by uddecke, Timo and Ecker, Alexander
|
||||
|
||||
|
||||
## 🔧 Found a problem? [Open an Issue.](https://github.com/ThereforeGames/unprompted/issues)
|
||||
|
||||
## 💬 For discussion and template sharing, use [the Discussion Board.](https://github.com/ThereforeGames/unprompted/discussions)
|
||||
|
|
@ -3,6 +3,27 @@ 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><summary>6.0.0 - 25 January 2023</summary>
|
||||
|
||||
### Added
|
||||
- You can now change the active SD checkpoint with `[set sd_model]`
|
||||
- New `[instance2mask]` shortcode by WeberSamuel (PR #48)
|
||||
- New `[invert_mask]` shortcode by WeberSamuel (PR #48)
|
||||
- New `[enable_multi_images]` shortcode by WeberSamuel (PR #48)
|
||||
- The `[txt2mask]` shortcode now supports GPU (PR #48)
|
||||
- New `[txt2mask]` arguments: `neg_precision`, `neg_padding`, and `neg_smoothing` by WeberSamuel (PR #48)
|
||||
- The `[txt2mask]` argument `show` will also append a segmentation mask (PR #48)
|
||||
- New UI option `Unprompted Seed` allows you to reproduce images that feature shortcodes with randomness, such as `[choose]`
|
||||
|
||||
### Changed
|
||||
- Wizard Function default values are no longer written to ui-config.json
|
||||
- Fixed `[img2img]` syntax for compatibility with latest A1111
|
||||
- Fixed a rounding issue with Wizard shortcode number fields
|
||||
- The Manual and Starter Guide have been reorganized into collapsible sections
|
||||
- Moved all included templates into `templates\common` for simplicity
|
||||
|
||||
</details>
|
||||
|
||||
<details><summary>5.2.0 - 24 January 2023</summary>
|
||||
|
||||
### Added
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
# Starter Guide
|
||||
|
||||
Let's walk through the process of making your own templates for Unprompted. It's fun and easy.
|
||||
Your first Unprompted template. It's a big step, I know. You feeling nervous? A sense of tremendous pressure maybe? Don't worry, it's not that hard to set this thing up.
|
||||
|
||||
For the purposes of this guide, we will construct a basic "human generator" similar to the one that is included with the repo download.
|
||||
|
||||
## 1) Create the entry point
|
||||
<details><summary>Step 1: Create the entry point</summary>
|
||||
|
||||
In the root directory of the WebUI app, navigate to `extensions/unprompted/templates`. This is where all your templates belong - you can organize the files here in any way you like.
|
||||
|
||||
|
|
@ -30,7 +30,9 @@ You can check the information underneath the resulting picture to confirm that S
|
|||
|
||||
Cool! Now let's proceed to the good stuff...
|
||||
|
||||
## 2) Using the \[choose\] shortcode
|
||||
</details>
|
||||
|
||||
<details><summary>Step 2: Using the [choose] shortcode</summary>
|
||||
|
||||
Let's ask Unprompted to choose between a man and a woman. This is easy to do:
|
||||
|
||||
|
|
@ -76,7 +78,9 @@ Yes, we are using a `[file]` shortcode inside of another file. This is perhaps o
|
|||
|
||||
Next, let's check out some other shortcodes we can use.
|
||||
|
||||
## 3) Managing Stable Diffusion options with \[set\]
|
||||
</details>
|
||||
|
||||
<details><summary>Step 3: Managing Stable Diffusion options with [set]</summary>
|
||||
|
||||
Unprompted has the ability to manage variables using `[set]` and `[get]`. You can create your own variables or even adjust the system variables used by the image generator.
|
||||
|
||||
|
|
@ -95,7 +99,9 @@ For improved image quality, we can also force a CFG scale of 7 and turn on the "
|
|||
|
||||
Now no matter how we change the UI, our template will continue using these optimized values.
|
||||
|
||||
## 4) Overriding parts of the template
|
||||
</details>
|
||||
|
||||
<details><summary>Step 4: Overriding parts of the template</summary>
|
||||
|
||||
Imagine a situation where you want the randomness a template offers, but you need to lock in a certain word or phrase of your choosing.
|
||||
|
||||
|
|
@ -123,7 +129,9 @@ That's it, now you've got pandas!
|
|||
|
||||
In the final section, we will learn about some more advanced functions.
|
||||
|
||||
## 5) Conditional shortcodes
|
||||
</details>
|
||||
|
||||
<details><summary>Step 5: Conditional shortcodes</summary>
|
||||
|
||||
The last subject I want to discuss are the conditional shortcodes `[if]` and `[chance]`. These will evaluate given variable(s) in deciding what to output.
|
||||
|
||||
|
|
@ -147,12 +155,16 @@ Finally, if we want to make this occur only 75% of the time, we introduce `[chan
|
|||
|
||||
He'd like to congratulate you on making it this far.
|
||||
|
||||
## In conclusion
|
||||
</details>
|
||||
|
||||
<details><summary>GG no RE</summary>
|
||||
|
||||
I hope you found this starter guide useful and now have a better idea of what Unprompted brings to the table!
|
||||
|
||||
We have only scratched the surface here - when you're ready to do a deeper dive, please check out the full documentation here:
|
||||
We have only scratched the surface here - when you're ready to do a deeper dive, please check out the full documentation here (or simply click on the Manual tab if you're inside of the app itself):
|
||||
|
||||
[Unprompted Manual](MANUAL.md)
|
||||
|
||||
Good luck!
|
||||
Good luck!
|
||||
|
||||
</details>
|
||||
525
docs/MANUAL.md
525
docs/MANUAL.md
|
|
@ -2,45 +2,11 @@
|
|||
|
||||
Shortcode syntax is subject to change based on community feedback.
|
||||
|
||||
## Adding New Shortcodes
|
||||
If you encounter any confusing, incomplete, or out-of-date information here, please do not hesitate to open an issue. I appreciate it!
|
||||
|
||||
Shortcodes are loaded as Python modules from `unprompted/shortcodes`. You can make your own shortcodes by creating files there (preferably within the `/custom` subdirectory.)
|
||||
## Proficiency
|
||||
|
||||
The shortcode name is defined by the filename, e.g. `override.py` will give you the ability to use `[override]`. Shortcode filenames should be unique.
|
||||
|
||||
A shortcode is structured as follows:
|
||||
|
||||
```
|
||||
class Shortcode():
|
||||
"""A description of the shortcode goes here."""
|
||||
def __init__(self,Unprompted):
|
||||
self.Unprompted = Unprompted
|
||||
|
||||
def run_block(self, pargs, kwargs, context,content):
|
||||
|
||||
return("")
|
||||
|
||||
def cleanup(self):
|
||||
|
||||
return("")
|
||||
```
|
||||
|
||||
The `__init__` function gives the shortcode access to our main Unprompted object, and it's where you should declare any unique variables for your shortcode.
|
||||
|
||||
The `run_block` function contains the main logic for your shortcode. It has access to these special variables (the following documentation was pulled from the [Python Shortcodes](https://www.dmulholl.com/dev/shortcodes.html) library, on which Unprompted depends):
|
||||
|
||||
- `pargs`: a list of the shortcode's positional arguments.
|
||||
- `kwargs`: a dictionary of the shortcode's keyword arguments.
|
||||
- `context`: an optional arbitrary context object supplied by the caller.
|
||||
- `content`: the string within the shortcode tags, e.g. `[tag]content[/tag]`
|
||||
|
||||
Positional and keyword arguments are passed as strings. The function itself should return a string which will replace the shortcode in the parsed text.
|
||||
|
||||
The `cleanup` function runs at the end of the processing chain. You can free any unnecessary variables from memory here.
|
||||
|
||||
For more details, please examine the code of the stock shortcodes.
|
||||
|
||||
## Atomic vs Block Shortcodes
|
||||
<details><summary>Atomic vs Block Shortcodes</summary>
|
||||
|
||||
Unprompted supports two types of shortcodes:
|
||||
|
||||
|
|
@ -61,7 +27,9 @@ def run_atomic(self, pargs, kwargs, context):
|
|||
|
||||
Atomic shortcodes do not receive a `content` variable.
|
||||
|
||||
## Understanding the Processing Chain
|
||||
</details>
|
||||
|
||||
<details><summary>Understanding the Processing Chain</summary>
|
||||
|
||||
It is important to understand that **inner shortcodes are processed before outer shortcodes**.
|
||||
|
||||
|
|
@ -79,7 +47,9 @@ In Unprompted, `another_var` will equal 0 regardless of the outcome of the `if`
|
|||
|
||||
The following section offers a solution.
|
||||
|
||||
## Secondary Shortcode Tags
|
||||
</details>
|
||||
|
||||
<details><summary>Secondary Shortcode Tags</summary>
|
||||
|
||||
Unprompted allows you to write tags using `{}` instead of `[]` to defer processing.
|
||||
|
||||
|
|
@ -94,7 +64,7 @@ This way, the inner shortcode is not processed until *after* it is returned by t
|
|||
Secondary shortcode tags give us a couple additional benefits:
|
||||
|
||||
- If your shortcode is computationally expensive, you can avoid running it unless the outer shortcode succeeds. This is good for performance.
|
||||
- **You can pass them as arguments in shortcodes that support it.** For example, if you want to run the `[chance]` shortcode with dynamic probability, you can do it like this: `[chance _probability="{get my_var}"]content[/chance]`
|
||||
- **You can pass them as arguments in shortcodes that support it.** For example, if you want to run the `[chance]` shortcode with dynamic probability, you can do it like this: `[chance "{get my_var}"]content[/chance]`
|
||||
|
||||
Secondary shortcode tags can have infinite nested depth. The number of `{}` around a shortcode indicates its nested level. Consider this example:
|
||||
|
||||
|
|
@ -124,7 +94,9 @@ wow
|
|||
|
||||
Rinse and repeat until no `{}` remain.
|
||||
|
||||
## Advanced expressions
|
||||
</details>
|
||||
|
||||
<details><summary>Advanced Expressions</summary>
|
||||
|
||||
Most shortcodes support programming-style evaluation via the [simpleeval library](https://github.com/danthedeckie/simpleeval).
|
||||
|
||||
|
|
@ -148,7 +120,9 @@ You can even mix advanced expressions with shortcodes. Check this out:
|
|||
|
||||
For more information on constructing advanced expressions, check the documentation linked above.
|
||||
|
||||
## Escaping characters
|
||||
</details>
|
||||
|
||||
<details><summary>Escaping Characters</summary>
|
||||
|
||||
Use the backtick to print a shortcode as a literal part of your prompt. This may be useful if you wish to take advantage of the prompt editing features of the A1111 WebUI (which are denoted with square brackets and could thus conflict with Unprompted shortcodes.)
|
||||
|
||||
|
|
@ -160,7 +134,23 @@ Also note: if a shortcode is undefined, Unprompted will print it as a literal as
|
|||
Photo of a `[cat|dog]
|
||||
```
|
||||
|
||||
## Why some shortcode arguments begin with an _underscore
|
||||
</details>
|
||||
|
||||
<details><summary>System Variables</summary>
|
||||
|
||||
In addition to all of the Stable Diffusion variables exposed by Automatic1111's WebUI, Unprompted gives you access to the following variables:
|
||||
|
||||
### batch_index
|
||||
|
||||
An integer that correponds to your progress in a batch run. For example, if your batch count is set to 5, then `batch_index` will return a value from 0 to 4.
|
||||
|
||||
### sd_model
|
||||
|
||||
You can set this variable to the name of a Stable Diffusion checkpoint, and Unprompted will load that checkpoint at the start of inference. This variable is powered by the WebUI's `get_closet_checkpoint_match()` function, which means that your model name does not have to be 100% accurate - but you should strive to use a string that's as accurate as possible.
|
||||
|
||||
</details>
|
||||
|
||||
<details><summary>Why some shortcode arguments begin with an _underscore</summary>
|
||||
|
||||
We use underscores to denote optional system arguments in shortcodes that may also accept dynamic, user-defined arguments.
|
||||
|
||||
|
|
@ -174,8 +164,12 @@ In short, if the argument begins with `_`, the program will assume it is a syste
|
|||
|
||||
That said, we're still ironing out the methodology for underscores - at the moment, some arguments may use underscores where it isn't strictly necessary. If you find any such cases feel free to open an Issue or Discussion Thread about it.
|
||||
|
||||
</details>
|
||||
|
||||
## The Wizard
|
||||
|
||||
<details><summary>What is the Wizard?</summary>
|
||||
|
||||
The Unprompted WebUI extension has a dedicated panel called the Wizard. It is a GUI-based shortcode builder.
|
||||
|
||||
Pressing **"Generate Shortcode"** will assemble a ready-to-use block of code that you can add to your prompts.
|
||||
|
|
@ -184,7 +178,9 @@ Alternatively, you can enable `Auto-include this in prompt` which will add the s
|
|||
|
||||
The Wizard includes two distinct modes: Shortcodes and Functions.
|
||||
|
||||
### Shortcodes Mode
|
||||
</details>
|
||||
|
||||
<details><summary>Shortcodes Mode</summary>
|
||||
|
||||
This mode presents you with a list of all shortcodes that have a `ui()` block in their source code.
|
||||
|
||||
|
|
@ -212,7 +208,9 @@ There are a few reserved argument names that will modify the Wizard's behavior:
|
|||
- `str`: This will inject the field's value into the shortcode, enclosing it in quotation marks.
|
||||
- `int`: This will inject the field's value into the shortcode, casting it as an integer.
|
||||
|
||||
### Functions Mode
|
||||
</details>
|
||||
|
||||
<details><summary>Functions Mode</summary>
|
||||
|
||||
This mode presents you with a list of txt files inside your `Unprompted/templates` directory that begin with a `[template]` block.
|
||||
|
||||
|
|
@ -232,7 +230,9 @@ The `[set]` block supports `_ui` which determines the type of UI element to rend
|
|||
- `dropdown`: A dropdown menu that is populated by the `_choices` argument, constructed as a delimited list.
|
||||
- `slider`: Limits selection to a range of numbers. You must also specify `_minimum`, `_maximum` and `_step` (step size, normally 1) for this element to work properly.
|
||||
|
||||
## The config file
|
||||
</details>
|
||||
|
||||
<details><summary>The config file</summary>
|
||||
|
||||
Various aspects of Unprompted's behavior are controlled through `unprompted/config.json`.
|
||||
|
||||
|
|
@ -301,20 +301,11 @@ The main purpose of this setting is for hardcoding shortcodes you want to run ev
|
|||
|
||||
Same as above, but for the negative prompt.
|
||||
|
||||
## System Variables
|
||||
</details>
|
||||
|
||||
In addition to all of the Stable Diffusion variables exposed by Automatic1111's WebUI, Unprompted gives you access to the following variables:
|
||||
|
||||
### batch_index
|
||||
|
||||
An integer that correponds to your progress in a batch run. For example, if your batch count is set to 5, then `batch_index` will return a value from 0 to 4.
|
||||
|
||||
## Stable Diffusion Shortcodes
|
||||
|
||||
This section describes all of the included shortcodes which are specifically designed for use with the A1111 WebUI.
|
||||
|
||||
### [file2mask]
|
||||
## Shortcodes
|
||||
|
||||
<<<<<<< Updated upstream
|
||||
Allows you to modify or replace your img2img mask with arbitrary files.
|
||||
|
||||
Supports the `mode` argument which determines how the file mask will behave alongside the existing mask:
|
||||
|
|
@ -534,18 +525,22 @@ The content and `negative_mask` both support the vertical pipe delimiter (`|`) w
|
|||
```
|
||||
|
||||
## Basic Shortcodes
|
||||
=======
|
||||
<details><summary>Basic Shortcodes</summary>
|
||||
>>>>>>> Stashed changes
|
||||
|
||||
This section describes all of the included basic shortcodes and their functionality.
|
||||
|
||||
### [#]
|
||||
<details><summary>[#]</summary>
|
||||
|
||||
Use this to write comments in your templates. Comments are ultimately discarded by Unprompted and will not affect your final output.
|
||||
|
||||
```
|
||||
[# This is my comment.]
|
||||
```
|
||||
</details>
|
||||
|
||||
### [##]
|
||||
<details><summary>[##]</summary>
|
||||
|
||||
Same as `[#]` but for multiline comments.
|
||||
|
||||
|
|
@ -557,7 +552,9 @@ I can't believe it, we're doing 3 lines of text!
|
|||
[/##]
|
||||
```
|
||||
|
||||
### [after step(int)]
|
||||
</details>
|
||||
|
||||
<details><summary>[after step(int)]</summary>
|
||||
|
||||
Processes the content after the main task is complete.
|
||||
|
||||
|
|
@ -573,7 +570,9 @@ Photo of a cat
|
|||
[/after]
|
||||
```
|
||||
|
||||
### [array name(str)]
|
||||
</details>
|
||||
|
||||
<details><summary>[array name(str)]</summary>
|
||||
|
||||
Manages a group or list of values.
|
||||
|
||||
|
|
@ -625,12 +624,15 @@ Supports `_find` which will return the index of the first matching value in the
|
|||
|
||||
Supports `_shuffle` which will randomize the order of the array.
|
||||
|
||||
</details>
|
||||
|
||||
### [case]
|
||||
<details><summary>[case]</summary>
|
||||
|
||||
See `[switch]`.
|
||||
|
||||
### [casing type]
|
||||
</details>
|
||||
|
||||
<details><summary>[casing type]</summary>
|
||||
|
||||
Converts the casing of content to the selected type. Possible types:
|
||||
|
||||
|
|
@ -656,7 +658,9 @@ For more information on these types, consult the [casefy docs](https://github.co
|
|||
Result: WHY AM I SCREAMING
|
||||
```
|
||||
|
||||
### [chance int {_sides}]
|
||||
</details>
|
||||
|
||||
<details><summary>[chance int {_sides}]</summary>
|
||||
|
||||
Returns the content if the integer you passed is greater than or equal to a randomly generated number between 1 and 100.
|
||||
|
||||
|
|
@ -666,7 +670,9 @@ You can change the upper boundary by specifying the optional `_sides` argument.
|
|||
[chance 25]I will show up in your prompt 25% of the time.[/chance]
|
||||
```
|
||||
|
||||
### [choose]
|
||||
</details>
|
||||
|
||||
<details><summary>[choose]</summary>
|
||||
|
||||
Randomly returns one of multiple options, as delimited by the vertical pipe or newline character.
|
||||
|
||||
|
|
@ -686,7 +692,7 @@ Supports the optional `_weighted` argument, which allows you to customize the pr
|
|||
[/choose]
|
||||
```
|
||||
|
||||
If you skip a weight value--e.g. `3|Apple|Strawberry`--then the option (Strawberry) will automatically have a weight value of 1.
|
||||
If you skip a weight value--e.g. `3|Apple|Strawberry`--then the following option (Strawberry) will automatically have a weight value of 1.
|
||||
|
||||
The weight value dictates the number of times that an option is added to the master list of choices, which is then shuffled and picked from at random. So, if your content is `2|Blue|3|Red|Green` the master list becomes `Blue,Blue,Red,Red,Red,Green`.
|
||||
|
||||
|
|
@ -694,7 +700,9 @@ The weight value dictates the number of times that an option is added to the mas
|
|||
[choose]red|yellow|blue|green[/choose]
|
||||
```
|
||||
|
||||
### [config]
|
||||
</details>
|
||||
|
||||
<details><summary>[config]</summary>
|
||||
|
||||
Updates your Unprompted settings with the content for the duration of a run. Generally you would put this at the top of a template.
|
||||
|
||||
|
|
@ -712,7 +720,9 @@ Do not enter a file extension, `.json` is assumed.
|
|||
[config]./my_custom_settings[/config]
|
||||
```
|
||||
|
||||
### [do until(str)]
|
||||
</details>
|
||||
|
||||
<details><summary>[do until(str)]</summary>
|
||||
|
||||
Do-until style loop. The content is processed, then the `until` expression is evaluated - if it's true, the content is processed again. Repeat until `until` is false.
|
||||
|
||||
|
|
@ -724,7 +734,9 @@ Do-until style loop. The content is processed, then the `until` expression is ev
|
|||
[/do]
|
||||
```
|
||||
|
||||
### [elif]
|
||||
</details>
|
||||
|
||||
<details><summary>[elif]</summary>
|
||||
|
||||
Shorthand "else if." Equivalent to `[else]{if my_var="something"}content{/if}[/else]`.
|
||||
|
||||
|
|
@ -734,7 +746,9 @@ Shorthand "else if." Equivalent to `[else]{if my_var="something"}content{/if}[/e
|
|||
[elif my_var=5]Return this content![/elif]
|
||||
```
|
||||
|
||||
### [else]
|
||||
</details>
|
||||
|
||||
<details><summary>[else]</summary>
|
||||
|
||||
Returns content if a previous conditional shortcode (e.g. `[if]` or `[chance]`) failed its check, otherwise discards content.
|
||||
|
||||
|
|
@ -744,7 +758,9 @@ Returns content if a previous conditional shortcode (e.g. `[if]` or `[chance]`)
|
|||
[if my_var=0]Print something[/if][else]It turns out my_var did not equal 0.[/else]
|
||||
```
|
||||
|
||||
### [eval]
|
||||
</details>
|
||||
|
||||
<details><summary>[eval]</summary>
|
||||
|
||||
Parses the content using the simpleeval library, returning the result. Particularly useful for arithmetic.
|
||||
|
||||
|
|
@ -754,7 +770,9 @@ simpleeval is designed to prevent the security risks of Python's stock `eval` fu
|
|||
[eval]5 + 5[/eval]
|
||||
```
|
||||
|
||||
### [file path(str)]
|
||||
</details>
|
||||
|
||||
<details><summary>[file path(str)]</summary>
|
||||
|
||||
Processes the content of `path` (including any shortcodes therein) and returns the result.
|
||||
|
||||
|
|
@ -774,7 +792,9 @@ The file is expected to be `utf-8` encoding. You can change this with the option
|
|||
[file my_template/common/adjective]
|
||||
```
|
||||
|
||||
### [filelist path(str)]
|
||||
</details>
|
||||
|
||||
<details><summary>[filelist path(str)]</summary>
|
||||
|
||||
Returns a delimited string containing the full paths of all files in a given path.
|
||||
|
||||
|
|
@ -786,7 +806,9 @@ Supports the optional `_delimiter` argument which lets you specify the separator
|
|||
[filelist "C:/my_pictures/*.*"]
|
||||
```
|
||||
|
||||
### [for var "test var" "update var"]
|
||||
</details>
|
||||
|
||||
<details><summary>[for var "test var" "update var"]</summary>
|
||||
|
||||
Returns the content an arbitrary number of times until the `test` condition returns false.
|
||||
|
||||
|
|
@ -802,7 +824,9 @@ Current value of i: {get i}
|
|||
[/for]
|
||||
```
|
||||
|
||||
### [get variable]
|
||||
</details>
|
||||
|
||||
<details><summary>[get variable]</summary>
|
||||
|
||||
Returns the value of `variable`.
|
||||
|
||||
|
|
@ -820,7 +844,9 @@ You can change the default separator with `_sep`.
|
|||
My name is [get name]
|
||||
```
|
||||
|
||||
### [if variable {_not} {_any} {_is}]
|
||||
</details>
|
||||
|
||||
<details><summary>[if variable {_not} {_any} {_is}]</summary>
|
||||
|
||||
Checks whether `variable` is equal to the given value, returning the content if true, otherwise discarding the content.
|
||||
|
||||
|
|
@ -843,7 +869,9 @@ Supports [advanced expressions](#advanced-expressions) - useful for testing comp
|
|||
[if "subject is 'man' or subject is 'woman'"]wearing a shirt[/if]
|
||||
```
|
||||
|
||||
### [info]
|
||||
</details>
|
||||
|
||||
<details><summary>[info]</summary>
|
||||
|
||||
Prints metadata about the content. You must pass the type(s) of data as positional arguments.
|
||||
|
||||
|
|
@ -862,7 +890,9 @@ Supports `clip_count` for retrieving the number of CLIP tokens in the content (i
|
|||
Result: 5
|
||||
```
|
||||
|
||||
### [length]
|
||||
</details>
|
||||
|
||||
<details><summary>[length]</summary>
|
||||
|
||||
Returns the number of items in a delimited string.
|
||||
|
||||
|
|
@ -877,7 +907,9 @@ Supports the optional `_max` argument which caps the value returned by this shor
|
|||
Result: 3
|
||||
```
|
||||
|
||||
### [max]
|
||||
</details>
|
||||
|
||||
<details><summary>[max]</summary>
|
||||
|
||||
Returns the greatest value among the arguments. Supports advanced expressions.
|
||||
|
||||
|
|
@ -889,7 +921,9 @@ Returns the greatest value among the arguments. Supports advanced expressions.
|
|||
Result: 500
|
||||
```
|
||||
|
||||
### [min]
|
||||
</details>
|
||||
|
||||
<details><summary>[min]</summary>
|
||||
|
||||
Returns the smallest value among the arguments. Supports advanced expressions.
|
||||
|
||||
|
|
@ -901,7 +935,9 @@ Returns the smallest value among the arguments. Supports advanced expressions.
|
|||
Result: 2
|
||||
```
|
||||
|
||||
### [override variable]
|
||||
</details>
|
||||
|
||||
<details><summary>[override variable]</summary>
|
||||
|
||||
Forces `variable` to equal the given value when attempting to `[set]` it.
|
||||
|
||||
|
|
@ -913,7 +949,9 @@ In the example below, `my_variable` will equal "panda" after running the `[set]`
|
|||
[override my_variable="panda"][set my_variable]fox[/set]
|
||||
```
|
||||
|
||||
### [random {_min} {_max} {_float}]
|
||||
</details>
|
||||
|
||||
<details><summary>[random {_min} {_max} {_float}]</summary>
|
||||
|
||||
Returns a random integer between 0 and the given integer, e.g. `[random 2]` will return 0, 1, or 2.
|
||||
|
||||
|
|
@ -925,7 +963,9 @@ If you pass `_float` into this shortcode, it will support decimal numbers instea
|
|||
[set restore_faces][random 1][/set]
|
||||
```
|
||||
|
||||
### [repeat times(int) {_sep}]
|
||||
</details>
|
||||
|
||||
<details><summary>[repeat times(int) {_sep}]</summary>
|
||||
|
||||
Processes and returns the content a number of `times`.
|
||||
|
||||
|
|
@ -940,7 +980,9 @@ Variable is currently: {set my_var _out _append}1</set>
|
|||
[/repeat]
|
||||
```
|
||||
|
||||
### [replace]
|
||||
</details>
|
||||
|
||||
<details><summary>[replace]</summary>
|
||||
|
||||
Updates the content using argument pairings as replacement logic.
|
||||
|
||||
|
|
@ -959,7 +1001,9 @@ A photo of red flowers.
|
|||
Result: A photo of purple marbles.
|
||||
```
|
||||
|
||||
### [set {_append} {_prepend}]
|
||||
</details>
|
||||
|
||||
<details><summary>[set {_append} {_prepend}]</summary>
|
||||
|
||||
Sets a variable to the given content.
|
||||
|
||||
|
|
@ -981,7 +1025,9 @@ Supports all Stable Diffusion variables that are exposed via Automatic's Script
|
|||
[set my_var]This is the value of my_var[/set]
|
||||
```
|
||||
|
||||
### [sets]
|
||||
</details>
|
||||
|
||||
<details><summary>[sets]</summary>
|
||||
|
||||
The atomic version of `[set]` that allows you to set multiple variables at once.
|
||||
|
||||
|
|
@ -991,7 +1037,9 @@ This shortcode processes your arguments with `[set]` directly, meaning you can t
|
|||
[sets var_a=10 var_b=something var_c=500]
|
||||
```
|
||||
|
||||
### [substring {start} {end} {step} {unit}]
|
||||
</details>
|
||||
|
||||
<details><summary>[substring {start} {end} {step} {unit}]</summary>
|
||||
|
||||
Returns a slice of the content as determined by the keyword arguments.
|
||||
|
||||
|
|
@ -1010,7 +1058,9 @@ Returns a slice of the content as determined by the keyword arguments.
|
|||
Result: photo of a
|
||||
```
|
||||
|
||||
### [switch var(str)]
|
||||
</details>
|
||||
|
||||
<details><summary>[switch var(str)]</summary>
|
||||
|
||||
Allows you to run different logic blocks with inner case statements that match the value of the given `var`.
|
||||
|
||||
|
|
@ -1025,7 +1075,9 @@ Allows you to run different logic blocks with inner case statements that match t
|
|||
[/switch]
|
||||
```
|
||||
|
||||
### [while variable {_not} {_any} {_is}]
|
||||
</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.
|
||||
|
||||
|
|
@ -1056,7 +1108,9 @@ Advanced expression demo:
|
|||
[/while]
|
||||
```
|
||||
|
||||
### [unset variable]
|
||||
</details>
|
||||
|
||||
<details><summary>[unset variable]</summary>
|
||||
|
||||
Removes one or more variables from memory.
|
||||
|
||||
|
|
@ -1066,3 +1120,292 @@ Note that variables are automatically deleted at the end of each run - you do **
|
|||
[set var_a=10 var_b="something"]
|
||||
[unset var_a var_b]
|
||||
```
|
||||
<<<<<<< Updated upstream
|
||||
=======
|
||||
|
||||
</details>
|
||||
</details>
|
||||
|
||||
<details><summary>Stable Diffusion Shortcodes</summary>
|
||||
|
||||
This section describes all of the included shortcodes which are specifically designed for use with the A1111 WebUI.
|
||||
|
||||
<details><summary>[file2mask]</summary>
|
||||
|
||||
Allows you to modify or replace your img2img mask with arbitrary files.
|
||||
|
||||
Supports the `mode` argument which determines how the file mask will behave alongside the existing mask:
|
||||
- `add` will overlay the two masks. This is the default value.
|
||||
- `discard` will scrap the existing mask entirely.
|
||||
- `subtract` will remove the file mask region from the existing mask region.
|
||||
|
||||
Supports the optional `_show` positional argument which will append the final mask to your generation output window.
|
||||
|
||||
```
|
||||
Walter White[file2mask "C:/pictures/my_mask.png"]
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
<details><summary>[img2img]</summary>
|
||||
|
||||
Used within the `[after]` block to append an img2img task to your generation.
|
||||
|
||||
The image resulting from your main prompt (e.g. the txt2img result) will be used as the initial image for `[img2img]`.
|
||||
|
||||
While this shortcode does not take any arguments, most img2img settings can be set in advance. **Does not currently support batch_size or batch_count** - coming soon!
|
||||
|
||||
```
|
||||
Photo of a cat
|
||||
[after]
|
||||
{sets prompt="Photo of a dog" denoising_strength=0.75}
|
||||
{img2img}
|
||||
[/after]
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
<details><summary>[img2img_autosize]</summary>
|
||||
|
||||
Automatically adjusts the width and height parameters in img2img mode based on the proportions of the input image.
|
||||
|
||||
Stable Diffuion generates images in sizes divisible by 64 pixels. If your initial image is something like 504x780, this shortcode will set the width and height to 512x768.
|
||||
|
||||
Supports `target_size` which is the minimum possible size of either dimension. Defaults to 512.
|
||||
|
||||
Supports `only_full_res` which, if true, will bypass this shortcode unless the "full resolution inpainting" setting is enabled. Defaults to false.
|
||||
|
||||
```
|
||||
[img2img_autosize] Photo of a cat
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
<details><summary>[init_image path(str)]</summary>
|
||||
|
||||
Loads an image from the given `path` and sets it as the initial image for use with img2img.
|
||||
|
||||
Note that `path` must be an absolute path, including the file extension.
|
||||
|
||||
If the given `path` ends with the `*` wildcard, `[init_image]` will choose a random file in that directory.
|
||||
|
||||
**Important:** At the moment, you still have to select an image in the WebUI before pressing Generate, or this shortcode will throw an error. You can select any image - it doesn't matter what it is, just as long as the field isn't empty.
|
||||
|
||||
```
|
||||
[init_image "C:/pictures/my_image.png"]
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
<details><summary>[invert_mask]</summary>
|
||||
|
||||
Inverts the mask. Great in combination with `[txt2mask]` and `[instance2mask]`.
|
||||
|
||||
</details>
|
||||
|
||||
<details><summary>[instance2mask]</summary>
|
||||
|
||||
Uses Mask R-CNN (an instance segmentation model) to predict instances. The found instances are mask. Different from `[txt2mask]` as it allows to run the inpainting for each found instance individually. This is useful, when using high resolution inpainting. This shortcode only works in the img2img tab of the A1111 WebUI.
|
||||
**Important:** If per_instance is used it is assumed to be the last operator changing the mask.
|
||||
|
||||
The supported classes of instances are:
|
||||
- `person`
|
||||
- `bicycle`
|
||||
- `car`
|
||||
- `motorcycle`
|
||||
- `airplane`
|
||||
- `bus`
|
||||
- `train`
|
||||
- `truck`
|
||||
- `boat`
|
||||
- `traffic light`
|
||||
- `fire hydrant`
|
||||
- `stop sign`
|
||||
- `parking meter`
|
||||
- `bench`
|
||||
- `bird`
|
||||
- `cat`
|
||||
- `dog`
|
||||
- `horse`
|
||||
- `sheep`
|
||||
- `cow`
|
||||
- `elephant`
|
||||
- `bear`
|
||||
- `zebra`
|
||||
- `giraffe`
|
||||
- `backpack`
|
||||
- `umbrella`
|
||||
- `handbag`
|
||||
- `tie`
|
||||
- `suitcase`
|
||||
- `frisbee`
|
||||
- `skis`
|
||||
- `snowboard`
|
||||
- `sports ball`
|
||||
- `kite`
|
||||
- `baseball bat`
|
||||
- `baseball glove`
|
||||
- `skateboard`
|
||||
- `surfboard`
|
||||
- `tennis racket`
|
||||
- `bottle`
|
||||
- `wine glass`
|
||||
- `cup`
|
||||
- `fork`
|
||||
- `knife`
|
||||
- `spoon`
|
||||
- `bowl`
|
||||
- `banana`
|
||||
- `apple`
|
||||
- `sandwich`
|
||||
- `orange`
|
||||
- `broccoli`
|
||||
- `carrot`
|
||||
- `hot dog`
|
||||
- `pizza`
|
||||
- `donut`
|
||||
- `cake`
|
||||
- `chair`
|
||||
- `couch`
|
||||
- `potted plant`
|
||||
- `bed`
|
||||
- `dining table`
|
||||
- `toilet`
|
||||
- `tv`
|
||||
- `laptop`
|
||||
- `mouse`
|
||||
- `remote`
|
||||
- `keyboard`
|
||||
- `cell phone`
|
||||
- `microwave`
|
||||
- `oven`
|
||||
- `toaster`
|
||||
- `sink`
|
||||
- `refrigerator`
|
||||
- `book`
|
||||
- `clock`
|
||||
- `vase`
|
||||
- `scissors`
|
||||
- `teddy bear`
|
||||
- `hair drier`
|
||||
- `toothbrush`
|
||||
|
||||
Supports the `mode` argument which determines how the text mask will behave alongside a brush mask:
|
||||
- `add` will overlay the two masks. This is the default value.
|
||||
- `discard` will ignore the brush mask entirely.
|
||||
- `subtract` will remove the brush mask region from the text mask region.
|
||||
- `refine` will limit the inital mask to the selected instances.
|
||||
|
||||
Supports the optional `mask_precision` argument which determines the confidence of the instance mask. Default is 0.5, max value is 1.0. Lowering this value means you may select more than you intend per instance (instances may overlap).
|
||||
|
||||
Supports the optional `instance_precision` argument which determines the classification thresshold for instances to be masked. Reduce this, if instances are not detected successfully. Default is 0.85, max value is 1.0. Lowering this value can lead to wrongly classied areas.
|
||||
|
||||
Supports the optional `padding` argument which increases the radius of the instance masks by a given number of pixels.
|
||||
|
||||
Supports the optional `smoothing` argument which refines the boundaries of the mask, allowing you to create a smoother selection. Default is 0. Try a value of 20 or greater if you find that your masks are blocky.
|
||||
|
||||
Supports the optional `select` argument which defines how many instances to mask. Default value is 0, which means all instances.
|
||||
|
||||
Supports the optional `select_mode` argument which specifies which instances are selected:
|
||||
- `overlap` will select the instances starting with the instance that has the greatest absolute brushed mask in it.
|
||||
- `overlap relative` behaves similar to `overlap` but normalizes the areas by the size of the instance.
|
||||
- `greatest area` will select the greatest instances by pixels first.
|
||||
- `random` will select instances in a random order
|
||||
Defaults to `overlap`.
|
||||
|
||||
Supports the optional `show` positional argument which will append the final masks to your generation output window and for debug purposes a combined instance segmentation image.
|
||||
|
||||
Supports the optional `per_instance` positional argument which will render and append the selected masks individually. Leading to better results if full resolution inpainting is used.
|
||||
|
||||
```
|
||||
[instance2mask]clock[/txt2mask]
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
<details><summary>[enable_multi_images]</summary>
|
||||
This is a helper shortcode that should be used if multiple init images, multiple masks or in combination with instance2mask per_instance should be used. Use this shortcode at the very end of the prompt, such that it can gather the correct init images and masks. Note that this operator will change the batch_size and batch_count (n_iter).
|
||||
|
||||
</details>
|
||||
|
||||
<details><summary>[txt2mask]</summary>
|
||||
|
||||
A port of [the script](https://github.com/ThereforeGames/txt2mask) by the same name, `[txt2mask]` allows you to create a region for inpainting based only on the text content (as opposed to the brush tool.) This shortcode only works in the img2img tab of the A1111 WebUI.
|
||||
|
||||
Supports the `mode` argument which determines how the text mask will behave alongside a brush mask:
|
||||
- `add` will overlay the two masks. This is the default value.
|
||||
- `discard` will ignore the brush mask entirely.
|
||||
- `subtract` will remove the brush mask region from the text mask region.
|
||||
|
||||
Supports the optional `precision` argument which determines the confidence of the mask. Default is 100, max value is 255. Lowering this value means you may select more than you intend.
|
||||
|
||||
Supports the optional `padding` argument which increases the radius of your selection by a given number of pixels.
|
||||
|
||||
Supports the optional `smoothing` argument which refines the boundaries of the mask, allowing you to create a smoother selection. Default is 20. Try increasing this value if you find that your masks are looking blocky.
|
||||
|
||||
Supports the optional `size_var` argument which will cause the shortcode to calculate the region occupied by your mask selection as a percentage of the total canvas. That value is stored into the variable you specify. For example: `[txt2mask size_var=test]face[/txt2mask]` if "face" takes up 40% of the canvas, then the `test` variable will become 0.4.
|
||||
|
||||
Supports the optional `negative_mask` argument which will subtract areas from the content mask.
|
||||
|
||||
Supports the optional `neg_precision` argument which determines the confidence of the negative mask. Default is 100, max value is 255. Lowering this value means you may select more than you intend.
|
||||
|
||||
Supports the optional `neg_padding` which is the same as `padding` but for the negative prompts.
|
||||
|
||||
Supports the optional `neg_smoothing` which is the same as `smoothing` but for the negative prompts.
|
||||
|
||||
Supports the optional `save` argument which will output the final mask as a PNG image to the given filepath.
|
||||
|
||||
Supports the optional `show` positional argument which will append the final mask to your generation output window.
|
||||
|
||||
Supports the optional `legacy_weights` positional argument which will utilize the original CLIPseg weights. By default, `[txt2mask]` will use the [refined weights](https://github.com/timojl/clipseg#new-fine-grained-weights).
|
||||
|
||||
The content and `negative_mask` both support the vertical pipe delimiter (`|`) which allows you to specify multiple subjects for masking.
|
||||
|
||||
```
|
||||
[txt2mask]head and shoulders[/txt2mask]Walter White
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
</details>
|
||||
|
||||
<details><summary>Adding New Shortcodes</summary>
|
||||
|
||||
Shortcodes are loaded as Python modules from `unprompted/shortcodes`. You can make your own shortcodes by creating files there (preferably within the `/custom` subdirectory.)
|
||||
|
||||
The shortcode name is defined by the filename, e.g. `override.py` will give you the ability to use `[override]`. Shortcode filenames should be unique.
|
||||
|
||||
A shortcode is structured as follows:
|
||||
|
||||
```
|
||||
class Shortcode():
|
||||
"""A description of the shortcode goes here."""
|
||||
def __init__(self,Unprompted):
|
||||
self.Unprompted = Unprompted
|
||||
|
||||
def run_block(self, pargs, kwargs, context,content):
|
||||
|
||||
return("")
|
||||
|
||||
def cleanup(self):
|
||||
|
||||
return("")
|
||||
```
|
||||
|
||||
The `__init__` function gives the shortcode access to our main Unprompted object, and it's where you should declare any unique variables for your shortcode.
|
||||
|
||||
The `run_block` function contains the main logic for your shortcode. It has access to these special variables (the following documentation was pulled from the [Python Shortcodes](https://www.dmulholl.com/dev/shortcodes.html) library, on which Unprompted depends):
|
||||
|
||||
- `pargs`: a list of the shortcode's positional arguments.
|
||||
- `kwargs`: a dictionary of the shortcode's keyword arguments.
|
||||
- `context`: an optional arbitrary context object supplied by the caller.
|
||||
- `content`: the string within the shortcode tags, e.g. `[tag]content[/tag]`
|
||||
|
||||
Positional and keyword arguments are passed as strings. The function itself should return a string which will replace the shortcode in the parsed text.
|
||||
|
||||
The `cleanup` function runs at the end of the processing chain. You can free any unnecessary variables from memory here.
|
||||
|
||||
For more details, please examine the code of the stock shortcodes.
|
||||
|
||||
</details>
|
||||
>>>>>>> Stashed changes
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ import sys
|
|||
|
||||
class Unprompted:
|
||||
def __init__(self, base_dir="."):
|
||||
self.VERSION = "5.2.0"
|
||||
self.VERSION = "6.0.0"
|
||||
|
||||
print(f"(Unprompted v{self.VERSION} by Therefore Games)")
|
||||
self.log("Initializing Unprompted object...",False,"SETUP")
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import gradio as gr
|
|||
import modules.scripts as scripts
|
||||
from modules.processing import process_images,fix_seed,Processed
|
||||
from modules.shared import opts, cmd_opts, state, Options
|
||||
from modules import sd_models
|
||||
import lib_unprompted.shortcodes as shortcodes
|
||||
from pathlib import Path
|
||||
from enum import IntEnum,auto
|
||||
|
|
@ -105,7 +106,7 @@ def wizard_generate_shortcode(option,is_img2img,prepend="",append=""):
|
|||
result += " " + str(gr_obj.value)
|
||||
elif (block_name=="checkbox"):
|
||||
if gr_obj.value: result += " " + arg_name
|
||||
elif (block_name=="number"): result += f" {arg_name}={int(gr_obj.value)}"
|
||||
elif (block_name=="number"): result += f" {arg_name}={Unprompted.autocast(gr_obj.value)}"
|
||||
elif (block_name=="textbox"):
|
||||
if len(gr_obj.value) > 0: result += f" {arg_name}=\"{gr_obj.value}\""
|
||||
else: result += f" {arg_name}=\"{gr_obj.value}\""
|
||||
|
|
@ -148,6 +149,9 @@ class Scripts(scripts.Script):
|
|||
with gr.Accordion("Unprompted", open=Unprompted.Config.ui.open):
|
||||
is_enabled = gr.Checkbox(label="Enabled",value=gradio_enabled_checkbox_workaround)
|
||||
|
||||
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/fantasy_card/main{Unprompted.Config.txt_format}")): is_open = False
|
||||
else: is_open = True
|
||||
|
||||
|
|
@ -174,13 +178,16 @@ class Scripts(scripts.Script):
|
|||
if (block_name == "textbox"):
|
||||
if "_placeholder" in kwargs: this_placeholder = kwargs["_placeholder"]
|
||||
else: this_placeholder = str(content)
|
||||
gr.Textbox(label=this_label,max_lines=1,placeholder=this_placeholder)
|
||||
elif (block_name == "checkbox"): gr.Checkbox(label=this_label,value=bool(content))
|
||||
elif (block_name == "number"): gr.Number(label=this_label,value=int(content),interactive=True)
|
||||
elif (block_name == "dropdown"): gr.Dropdown(label=this_label,choices=kwargs["_choices"].split(self.Unprompted.Config.syntax.delimiter))
|
||||
elif (block_name == "radio"): gr.Radio(label=this_label,choices=kwargs["_choices"].split(self.Unprompted.Config.syntax_delimiter),interactive=True)
|
||||
obj = gr.Textbox(label=this_label,max_lines=1,placeholder=this_placeholder)
|
||||
elif (block_name == "checkbox"):
|
||||
obj = gr.Checkbox(label=this_label,value=bool(int(content)))
|
||||
elif (block_name == "number"): obj = gr.Number(label=this_label,value=int(content),interactive=True)
|
||||
elif (block_name == "dropdown"): obj = gr.Dropdown(label=this_label,choices=kwargs["_choices"].split(self.Unprompted.Config.syntax.delimiter))
|
||||
elif (block_name == "radio"): obj = gr.Radio(label=this_label,choices=kwargs["_choices"].split(self.Unprompted.Config.syntax_delimiter),interactive=True)
|
||||
elif (block_name == "slider"):
|
||||
gr.Slider(label=this_label,value=int(content),minimum=kwargs["_minimum"],maximum=kwargs["_maximum"],step=kwargs["_step"])
|
||||
obj = gr.Slider(label=this_label,value=int(content),minimum=kwargs["_minimum"],maximum=kwargs["_maximum"],step=kwargs["_step"])
|
||||
|
||||
setattr(obj,"do_not_save_to_config",True)
|
||||
return("")
|
||||
wizard_shortcode_parser.register(handler,"set",f"{Unprompted.Config.syntax.tag_close}set")
|
||||
|
||||
|
|
@ -311,11 +318,15 @@ class Scripts(scripts.Script):
|
|||
guide = gr.Markdown(value=get_markdown("docs/GUIDE.md"))
|
||||
|
||||
|
||||
return [is_enabled]
|
||||
return [is_enabled,unprompted_seed]
|
||||
|
||||
def process(self, p, is_enabled):
|
||||
def process(self, p, is_enabled, unprompted_seed):
|
||||
if not is_enabled:
|
||||
return p
|
||||
|
||||
if unprompted_seed != -1:
|
||||
import random
|
||||
random.seed(unprompted_seed)
|
||||
|
||||
def apply_prompt_template(string,template):
|
||||
return template.replace("*",string)
|
||||
|
|
@ -348,7 +359,7 @@ class Scripts(scripts.Script):
|
|||
|
||||
# Set up system var support - copy relevant p attributes into shortcode var object
|
||||
for att in dir(p):
|
||||
if not att.startswith("__") and att != "sd_model": # Workaround for sd_model var, will look into adding proper support soon
|
||||
if not att.startswith("__") and att != "sd_model":
|
||||
Unprompted.shortcode_user_vars[att] = getattr(p,att)
|
||||
|
||||
Unprompted.shortcode_user_vars["prompt"] = Unprompted.process_string(apply_prompt_template(original_prompt,Unprompted.Config.templates.default))
|
||||
|
|
@ -356,9 +367,16 @@ class Scripts(scripts.Script):
|
|||
|
||||
# Apply any updates to system vars
|
||||
for att in dir(p):
|
||||
if not att.startswith("__") and att != "sd_model": # Workaround for sd_model var, will look into adding proper support soon
|
||||
if not att.startswith("__") and att != "sd_model":
|
||||
setattr(p,att,Unprompted.shortcode_user_vars[att])
|
||||
|
||||
# Support loading a new checkpoint by name
|
||||
if "sd_model" in Unprompted.shortcode_user_vars:
|
||||
info = sd_models.get_closet_checkpoint_match(Unprompted.shortcode_user_vars["sd_model"])
|
||||
print(info)
|
||||
if (info): sd_models.reload_model_weights(None,info)
|
||||
|
||||
|
||||
if p.seed is not None and p.seed != -1.0:
|
||||
if (Unprompted.is_int(p.seed)): p.seed = int(p.seed)
|
||||
p.all_seeds[0] = p.seed
|
||||
|
|
@ -392,7 +410,7 @@ class Scripts(scripts.Script):
|
|||
Unprompted.shortcode_objects[i].cleanup()
|
||||
|
||||
# After routines
|
||||
def postprocess(self, p, processed, is_enabled):
|
||||
def postprocess(self, p, processed, is_enabled, unprompted_seed):
|
||||
Unprompted.log("Entering After routine...")
|
||||
for i in Unprompted.after_routines:
|
||||
Unprompted.shortcode_objects[i].after(p,processed)
|
||||
|
|
@ -0,0 +1,146 @@
|
|||
from re import sub
|
||||
from modules.processing import StableDiffusionProcessingImg2Img, Processed, process_images
|
||||
from modules import images
|
||||
from torchvision.transforms.functional import to_pil_image, pil_to_tensor
|
||||
import torch
|
||||
from modules.shared import opts, state
|
||||
|
||||
class Shortcode():
|
||||
def __init__(self,Unprompted):
|
||||
self.Unprompted = Unprompted
|
||||
self.init_images = []
|
||||
self.image_masks = []
|
||||
self.processing = False
|
||||
self.orginal_n_iter = None
|
||||
self.description = "Allows to use multiple init_images or multiple masks"
|
||||
|
||||
def run_atomic(self, pargs, kwargs, context):
|
||||
if self.processing:
|
||||
return ""
|
||||
|
||||
had_init_image = False
|
||||
if "init_images" in self.Unprompted.shortcode_user_vars:
|
||||
self.init_images += self.Unprompted.shortcode_user_vars["init_images"]
|
||||
had_init_image = True
|
||||
|
||||
if "image_masks" in self.Unprompted.shortcode_user_vars:
|
||||
self.image_masks += [self.Unprompted.shortcode_user_vars["image_masks"]]
|
||||
elif "image_mask" in self.Unprompted.shortcode_user_vars:
|
||||
self.image_masks += [[self.Unprompted.shortcode_user_vars["image_mask"]]]
|
||||
elif had_init_image:
|
||||
# each init_image has at least an empty mask
|
||||
self.image_masks += [[]]
|
||||
|
||||
if "n_iter" in self.Unprompted.shortcode_user_vars:
|
||||
self.orginal_n_iter = self.Unprompted.shortcode_user_vars["n_iter"]
|
||||
self.Unprompted.shortcode_user_vars["n_iter"] = 0
|
||||
|
||||
return ""
|
||||
|
||||
def after(self, p:StableDiffusionProcessingImg2Img, processed: Processed):
|
||||
if not self.processing and self.orginal_n_iter is not None:
|
||||
self.processing = True
|
||||
|
||||
try:
|
||||
mask_count = sum([len(masks) for masks in self.image_masks])
|
||||
if mask_count == 0:
|
||||
state.job_count = self.orginal_n_iter
|
||||
else:
|
||||
if len(self.init_images) == 1:
|
||||
state.job_count = mask_count * self.orginal_n_iter
|
||||
else:
|
||||
state.job_count = mask_count
|
||||
|
||||
batched_init_imgs = [self.init_images[idx:idx+p.batch_size] for idx in range(0, len(self.init_images), p.batch_size)]
|
||||
batched_prompts = [p.all_prompts[idx:idx+p.batch_size] for idx in range(0, len(p.all_prompts), p.batch_size)]
|
||||
batched_neg_prompts = [p.all_negative_prompts[idx:idx+p.batch_size] for idx in range(0, len(p.all_negative_prompts), p.batch_size)]
|
||||
batched_masks = [self.image_masks[idx:idx+p.batch_size] for idx in range(0, len(self.image_masks), p.batch_size)]
|
||||
batched_seeds = [p.all_seeds[idx:idx+p.batch_size] for idx in range(0, len(p.all_seeds), p.batch_size)]
|
||||
|
||||
create_grid = not p.do_not_save_grid
|
||||
save_imgs = not p.do_not_save_samples
|
||||
|
||||
p.do_not_save_grid = True
|
||||
p.do_not_save_samples = True
|
||||
|
||||
p.n_iter = 1
|
||||
if len(self.init_images) == 1:
|
||||
batched_init_imgs = [[self.init_images[0]] * p.batch_size] * self.orginal_n_iter
|
||||
batched_masks = [[self.image_masks[0]] * p.batch_size] * self.orginal_n_iter
|
||||
|
||||
for init_imgs, prompts, neg_prompts, seeds, maskss in zip(batched_init_imgs, batched_prompts, batched_neg_prompts, batched_seeds, batched_masks):
|
||||
if sum([len(masks) for masks in maskss]) == 0:
|
||||
p.init_images = init_imgs
|
||||
p.all_prompts = batched_prompts
|
||||
p.all_negative_prompts = batched_neg_prompts
|
||||
p.all_seeds = seeds
|
||||
p.mask = None
|
||||
sub_processed = process_images(p)
|
||||
processed.images += sub_processed.images
|
||||
else:
|
||||
output_resolution = (init_imgs[0].width, init_imgs[0].height) if p.inpaint_full_res else (p.width, p.height)
|
||||
|
||||
if len(self.init_images) == 1:
|
||||
imgs = torch.stack([pil_to_tensor(init_imgs[0].resize(output_resolution))] * p.batch_size).clone()
|
||||
|
||||
for idx, mask in enumerate(maskss[0]):
|
||||
p.init_images = [to_pil_image(img) for img in imgs]
|
||||
p.image_mask = mask
|
||||
p.all_prompts = prompts
|
||||
p.all_negative_prompts = neg_prompts
|
||||
p.all_seeds = [seed + idx + 800 for seed in seeds]
|
||||
|
||||
sub_processed = process_images(p)
|
||||
|
||||
mask = mask.resize(output_resolution)
|
||||
mask = pil_to_tensor(mask) > 0
|
||||
mask = mask.broadcast_to(imgs.shape)
|
||||
|
||||
imgs[mask] = torch.stack([pil_to_tensor(img) for img in sub_processed.images[:len(imgs)]])[mask]
|
||||
|
||||
processed.images += [to_pil_image(img) for img in imgs]
|
||||
else:
|
||||
for init_img, prompt, neg_prompt, seed, masks in zip(init_imgs, prompts, neg_prompts, seeds, maskss):
|
||||
img = pil_to_tensor(init_img.resize(output_resolution))
|
||||
|
||||
for idx, mask in enumerate(masks):
|
||||
p.batch_size = 1
|
||||
p.init_images = [to_pil_image(img)]
|
||||
p.image_mask = mask
|
||||
p.all_prompts = [prompt]
|
||||
p.all_negative_prompts = [neg_prompt]
|
||||
p.all_seeds = [seed + idx + 800]
|
||||
|
||||
sub_processed = process_images(p)
|
||||
|
||||
mask = mask.resize(output_resolution)
|
||||
mask = pil_to_tensor(mask) > 0
|
||||
mask = mask.broadcast_to(img.shape)
|
||||
|
||||
img[mask] = pil_to_tensor(sub_processed.images[0])[mask]
|
||||
|
||||
processed.images.append(to_pil_image(img))
|
||||
|
||||
if opts.samples_save and save_imgs:
|
||||
for img, prompt, neg_prompt, seed in zip(processed.images, p.all_prompts, p.all_negative_prompts, p.all_seeds):
|
||||
images.save_image(img, p.outpath_samples, "", seed, prompt, opts.samples_format)
|
||||
|
||||
if create_grid and len(processed.images) > 1:
|
||||
grid = images.image_grid(processed.images, p.batch_size * len(batched_init_imgs))
|
||||
if opts.return_grid:
|
||||
processed.images.insert(0, grid)
|
||||
processed.index_of_first_image = 1
|
||||
if opts.grid_save:
|
||||
images.save_image(grid, p.outpath_grids, "grid", p.all_seeds[0], p.all_prompts[0], opts.grid_format, short_filename=not opts.grid_extended_filename, p=p, grid=True)
|
||||
|
||||
finally:
|
||||
self.processing = False
|
||||
self.init_images = []
|
||||
self.image_masks = []
|
||||
self.orginal_n_iter = None
|
||||
|
||||
|
||||
|
||||
|
||||
def ui(self,gr):
|
||||
pass
|
||||
|
|
@ -18,17 +18,18 @@ class Shortcode():
|
|||
break
|
||||
|
||||
img2img_result = modules.img2img.img2img(
|
||||
self.Unprompted.shortcode_user_vars["mode"] if "mode" in self.Unprompted.shortcode_user_vars else 0, #p.mode
|
||||
"unprompted_img2img",
|
||||
self.Unprompted.shortcode_user_vars["img2img_mode"] if "img2img_mode" in self.Unprompted.shortcode_user_vars else 0, #p.mode
|
||||
self.Unprompted.shortcode_user_vars["prompt"],
|
||||
self.Unprompted.shortcode_user_vars["negative_prompt"],
|
||||
"None", #prompt_style1
|
||||
"None", #prompt_style2
|
||||
"None", # prompt_styles
|
||||
self.Unprompted.shortcode_user_vars["init_images"][len(self.Unprompted.after_processed.images) - 1],
|
||||
None, # sketch
|
||||
None, # p.init_img_with_mask
|
||||
None, # p.init_img_with_mask_orig
|
||||
None, # inpaint_color_sketch
|
||||
None, # inpaint_color_sketch_orig
|
||||
self.Unprompted.shortcode_user_vars["init_images"][len(self.Unprompted.after_processed.images) - 1], # p.init_img_inpaint
|
||||
init_mask, # p.init_mask_inpaint
|
||||
self.Unprompted.shortcode_user_vars["mask_mode"],
|
||||
self.Unprompted.shortcode_user_vars["steps"],
|
||||
sampler_index,
|
||||
self.Unprompted.shortcode_user_vars["mask_blur"] if "mask_blur" in self.Unprompted.shortcode_user_vars else 0, # p.mask_blur
|
||||
|
|
|
|||
|
|
@ -1,5 +1,8 @@
|
|||
<<<<<<< Updated upstream
|
||||
from torchvision.utils import draw_segmentation_masks
|
||||
from torchvision.transforms.functional import pil_to_tensor, to_pil_image
|
||||
=======
|
||||
>>>>>>> Stashed changes
|
||||
|
||||
class Shortcode():
|
||||
def __init__(self,Unprompted):
|
||||
|
|
@ -10,7 +13,6 @@ class Shortcode():
|
|||
|
||||
def run_block(self, pargs, kwargs, context, content):
|
||||
from lib_unprompted.stable_diffusion.clipseg.models.clipseg import CLIPDensePredT
|
||||
|
||||
from PIL import ImageChops, Image, ImageOps
|
||||
import os.path
|
||||
import torch
|
||||
|
|
@ -99,7 +101,11 @@ class Shortcode():
|
|||
def get_mask():
|
||||
# load model
|
||||
model = CLIPDensePredT(version='ViT-B/16', reduce_dim=64, complex_trans_conv=not self.legacy_weights)
|
||||
<<<<<<< Updated upstream
|
||||
model_dir = f"{self.Unprompted.base_dir}/lib/stable_diffusion/clipseg/weights"
|
||||
=======
|
||||
model_dir = f"{self.Unprompted.base_dir}/lib_unprompted/stable_diffusion/clipseg/weights"
|
||||
>>>>>>> Stashed changes
|
||||
os.makedirs(model_dir, exist_ok=True)
|
||||
|
||||
d64_filename = "rd64-uni.pth" if self.legacy_weights else "rd64-uni-refined.pth"
|
||||
|
|
@ -161,7 +167,7 @@ class Shortcode():
|
|||
|
||||
# Set up processor parameters correctly
|
||||
self.image_mask = get_mask().resize((self.Unprompted.shortcode_user_vars["init_images"][0].width,self.Unprompted.shortcode_user_vars["init_images"][0].height))
|
||||
self.Unprompted.shortcode_user_vars["mode"] = 1
|
||||
self.Unprompted.shortcode_user_vars["mode"] = 0
|
||||
self.Unprompted.shortcode_user_vars["mask_mode"] = 1
|
||||
self.Unprompted.shortcode_user_vars["image_mask"] =self.image_mask
|
||||
self.Unprompted.shortcode_user_vars["mask_for_overlay"] = self.image_mask
|
||||
|
|
@ -172,6 +178,9 @@ class Shortcode():
|
|||
return ""
|
||||
|
||||
def after(self,p=None,processed=None):
|
||||
from torchvision.utils import draw_segmentation_masks
|
||||
from torchvision.transforms.functional import pil_to_tensor, to_pil_image
|
||||
|
||||
if self.image_mask and self.show:
|
||||
processed.images.append(self.image_mask)
|
||||
|
||||
|
|
@ -192,4 +201,7 @@ class Shortcode():
|
|||
gr.Number(label="Smoothing radius in pixels 🡢 smoothing",value=20,interactive=True)
|
||||
gr.Number(label="Smoothing radius in pixels 🡢 neg_smoothing",value=20,interactive=True)
|
||||
gr.Textbox(label="Negative mask prompt 🡢 negative_mask",max_lines=1)
|
||||
gr.Number(label="Negative mask precision of selected area 🡢 neg_precision",value=100,interactive=True)
|
||||
gr.Number(label="Negative mask padding radius in pixels 🡢 neg_padding",value=0,interactive=True)
|
||||
gr.Number(label="Negative mask smoothing radius in pixels 🡢 neg_smoothing",value=20,interactive=True)
|
||||
gr.Textbox(label="Save the mask size to the following variable 🡢 size_var",max_lines=1)
|
||||
|
|
@ -8,7 +8,7 @@ Value of my_var: [get my_var]
|
|||
|
||||
|
||||
[##]
|
||||
Old method:
|
||||
Old method (should still work):
|
||||
|
||||
You can add or subtract from an existing variable with 'set'.
|
||||
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
# https://patreon.com/thereforegames
|
||||
# https://github.com/ThereforeGames/unprompted
|
||||
|
||||
from lib.shared import Unprompted
|
||||
from lib_unprompted.shared import Unprompted
|
||||
|
||||
# Main object
|
||||
Unprompted = Unprompted()
|
||||
|
|
|
|||
Loading…
Reference in New Issue