From 397e6f9b2b3e25854f1e2581a04893bc3fd2a3e2 Mon Sep 17 00:00:00 2001 From: Aarni Koskela Date: Thu, 21 Mar 2024 09:46:08 +0200 Subject: [PATCH] Improve docs a bit (#125) * Enable and run Prettier lint * Make changelog a Markdown list so it's formatted nicely on GitHub * Regenerate TOCs with markdown-toc * Document wrap command --- .github/workflows/ci.yml | 4 +- .pre-commit-config.yaml | 4 + CHANGELOG.md | 110 +++++------ README.md | 100 ++++++---- docs/SYNTAX.md | 186 ++++++++++-------- docs/tutorial.md | 9 +- tests/test_data/wildcards/drink.yaml | 6 +- tests/test_data/wildcards/flavors/pantry.json | 5 +- tests/test_data/wildcards/pantry.yaml | 8 +- 9 files changed, 240 insertions(+), 192 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f4d72e46..8efdc8e5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -5,7 +5,7 @@ on: branches: - main tags: - - 'v*' + - "v*" pull_request: branches: - main @@ -36,7 +36,7 @@ jobs: fail-fast: false matrix: os: [ubuntu-latest, windows-latest] - python-version: ["3.8"] # minimum supported version + python-version: ["3.8"] # minimum supported version steps: - uses: actions/checkout@v4 - name: Set up Python ${{ matrix.python-version }} diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 86afbe5d..bbb50a6a 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -11,3 +11,7 @@ repos: hooks: - id: end-of-file-fixer - id: trailing-whitespace + - repo: https://github.com/pre-commit/mirrors-prettier + rev: v3.1.0 + hooks: + - id: prettier diff --git a/CHANGELOG.md b/CHANGELOG.md index 96da1997..1bdf6d0e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,55 +1,55 @@ -0.30.4 - Fix corner case regression introduced in 0.30.0 (#107) -0.30.3 - Fix spurious warnings introduced by #103 (#105) -0.30.2 - No code changes. -0.30.1 - Made weighted wildcard shorthand parsing a little more robust (#103) -0.30.0 - Removed support for python 3.7 ([#98](https://github.com/adieyal/dynamicprompts/pull/98)), wildcard files now support weights ([#97](https://github.com/adieyal/dynamicprompts/pull/97)). Also added infrastructure to return additional metadata gatherered during sampling ([#100](https://github.com/adieyal/dynamicprompts/pull/100)). -0.29.0 - Added an option to shuffle the output of the wildcard manager -0.28.0 - WildcardManager no longer deduplicates wildcards. Return a list instead of a set -0.27.1 - Late-import of jinja2 Jinja2 to work around issues with incompatible versions of Jinja2 being installed in some downstream users' environments. See [#476](https://github.com/adieyal/sd-dynamic-prompts/issues/476) -0.27.0 - Added sort and dedup properties to wildcardcard manager. Also fixed device selection for magic prompt -0.26.1 - Fixed cyclical sampling when using the RandomPromptGenerator - see [#84](https://github.com/adieyal/dynamicprompts/issues/84) -0.26.0 - Added fall-back sentence chunker when spacy is not installed -0.25.1 - Added kwargs argument to promptgenerator.generate methods -0.25.0 - Added the ability to pass random seeds into the random prompt generator for finer control over random prompt sampling. See the documentation for details. -0.24.0 - The wildcard manager now has a fallback mode that searches the entire wildcard hierarchy if it can't find a wildcard. Addresses issues like this one - [#377](https://github.com/adieyal/sd-dynamic-prompts/issues/377) -0.23.0 - Parser performance improvements - see [#77](https://github.com/adieyal/dynamicprompts/pull/77#event-8976756671). Deprecated Legacy Parser and ActionBuilder APIs have now been removed. See [#78](https://github.com/adieyal/dynamicprompts/pull/78) -0.22.0 - Make WildcardManager trees easily composable - [#74](https://github.com/adieyal/dynamicprompts/pull/74) -0.21.2 - Added missing parser config -0.21.1 - Another fix for wildcard variants, see [#358](https://github.com/adieyal/sd-dynamic-prompts/issues/358) -0.21.0 - Introduced setting variables and parameterised templates. -0.20.2 - Fixed [#354](https://github.com/adieyal/sd-dynamic-prompts/issues/354) - No values found for wildcards on Windows -0.20.1 - Fixed parsing bug #28 -0.20.0 - Backward incompatible rework of the wildcard machinery, with support for JSON/YAML structured wildcard files. -0.10.6 - Fixed a bug in the parser that didn't accept whitespace before or after a variant option - see https://github.com/adieyal/sd-dynamic-prompts/issues/324 -0.10.5 - Bug fix that cause RandomPromptGenerator to incorrectly handle wildcards in variants -0.10.4 - Fixed wildcard in variant syntax `{2$$__wildcard__}` -0.10.3 - Enabled batch processing for magic prompts. Higher batch size can dramatically improve prompt generation time at the expense of slightly higher memory usage. -0.10.2 - Fixed a bug where the JinjaGenerator was not ignoring whitespace -0.10.1 - Added limit_prompts to JinjaGenerator. When set to True, `.generate(..., num_images=X)` will produced at most X prompts -0.10.0 - Added added the ability to combine random and combinatorial prompts. Also added a cyclical sampler - see documentation for details -0.9.1 - WildcardManager now uses the current working directory by default if a path is not provided -0.9.0 - Configurable wildcard symbols - it's possible to change from the default __ to any arbitrary string -0.8.0 - Added syntax for changing samplers within prompt sub-trees. -0.7.1 - Fixed missing parser_config argument in CombinatorialPromptGenerator -0.7.0 - Configurable variant braces -0.6.0 - Support symlinks for the wildcards directory -0.5.0 - A major re-organisation of the parsing machinary. -0.4.3 - Allow zero repetitions in sequence commands, e.g. `{0-3$$A|B|C}` -0.4.2 - Added type information -0.4.1 - Variant separator can now be most printables e.g. `{2$$|$$A|B|C}`. This addresses [#211](https://github.com/adieyal/sd-dynamic-prompts/issues/211). -0.4.0 - Added block regex for magicprompts to remove unwanted modifiers. Many other small improvements, thanks to @akx -0.3.2 - Added LICENCE, many code improvements,security fix that prevents wildcard searches outside the wildcard directory - thanks to @akx -0.3.1 - Clean-up with thanks to @akx -0.3.0 - Added additional models to Magic Prompt -0.2.6 - Wildcards caching for speeding up complex prompts - with thanks to @RossM - see [#pr1](https://github.com/adieyal/dynamicprompts/pull/1) -0.2.5 - Fixed decimal weights in variants -0.2.4 - Fixed missing whitespace between two wildcards -0.2.3 - Fixed unlink seed from prompt which allows for a custom random number generator to be passed to the RandomGenerator -0.2.2 - Minor bug fixes -0.2.1 - Fixed a bug that cause the CombinatorialPromptGenerator to run very slowly when many wildcards were used. -0.2.0 - The parser now treats whitespace as significant in order to not ensure that the original prompt is left unaltered -0.1.19 - Added the Jinja2 generator from the SD Dynamic Prompts extension. Also fixed the Jinja2 interface to match the other generators -0.1.18 - Removed explicit dependency on pytorch, added default arguments for number of prompts produced by DummyGenerator and RandomPromptGenerator -0.1.17 - Fixed alternating words syntax [cat|dog] - pipes are only reserved inside variants. Also standardised MagicPrompt, AttentionGenerator, and FeelingLucky to use a DummyGenerator by default so that users are not forced to provide an alternative generator if one isn't needed. -0.1.16 - Changed type annotations to use classes from the typing package instead of native type in order to support python 3.7 -0.1.15 - First public release +- 0.30.4 - Fix corner case regression introduced in 0.30.0 (#107) +- 0.30.3 - Fix spurious warnings introduced by #103 (#105) +- 0.30.2 - No code changes. +- 0.30.1 - Made weighted wildcard shorthand parsing a little more robust (#103) +- 0.30.0 - Removed support for python 3.7 ([#98](https://github.com/adieyal/dynamicprompts/pull/98)), wildcard files now support weights ([#97](https://github.com/adieyal/dynamicprompts/pull/97)). Also added infrastructure to return additional metadata gatherered during sampling ([#100](https://github.com/adieyal/dynamicprompts/pull/100)). +- 0.29.0 - Added an option to shuffle the output of the wildcard manager +- 0.28.0 - WildcardManager no longer deduplicates wildcards. Return a list instead of a set +- 0.27.1 - Late-import of jinja2 Jinja2 to work around issues with incompatible versions of Jinja2 being installed in some downstream users' environments. See [#476](https://github.com/adieyal/sd-dynamic-prompts/issues/476) +- 0.27.0 - Added sort and dedup properties to wildcardcard manager. Also fixed device selection for magic prompt +- 0.26.1 - Fixed cyclical sampling when using the RandomPromptGenerator - see [#84](https://github.com/adieyal/dynamicprompts/issues/84) +- 0.26.0 - Added fall-back sentence chunker when spacy is not installed +- 0.25.1 - Added kwargs argument to promptgenerator.generate methods +- 0.25.0 - Added the ability to pass random seeds into the random prompt generator for finer control over random prompt sampling. See the documentation for details. +- 0.24.0 - The wildcard manager now has a fallback mode that searches the entire wildcard hierarchy if it can't find a wildcard. Addresses issues like this one - [#377](https://github.com/adieyal/sd-dynamic-prompts/issues/377) +- 0.23.0 - Parser performance improvements - see [#77](https://github.com/adieyal/dynamicprompts/pull/77#event-8976756671). Deprecated Legacy Parser and ActionBuilder APIs have now been removed. See [#78](https://github.com/adieyal/dynamicprompts/pull/78) +- 0.22.0 - Make WildcardManager trees easily composable - [#74](https://github.com/adieyal/dynamicprompts/pull/74) +- 0.21.2 - Added missing parser config +- 0.21.1 - Another fix for wildcard variants, see [#358](https://github.com/adieyal/sd-dynamic-prompts/issues/358) +- 0.21.0 - Introduced setting variables and parameterised templates. +- 0.20.2 - Fixed [#354](https://github.com/adieyal/sd-dynamic-prompts/issues/354) - No values found for wildcards on Windows +- 0.20.1 - Fixed parsing bug #28 +- 0.20.0 - Backward incompatible rework of the wildcard machinery, with support for JSON/YAML structured wildcard files. +- 0.10.6 - Fixed a bug in the parser that didn't accept whitespace before or after a variant option - see https://github.com/adieyal/sd-dynamic-prompts/issues/324 +- 0.10.5 - Bug fix that cause RandomPromptGenerator to incorrectly handle wildcards in variants +- 0.10.4 - Fixed wildcard in variant syntax `{2$$__wildcard__}` +- 0.10.3 - Enabled batch processing for magic prompts. Higher batch size can dramatically improve prompt generation time at the expense of slightly higher memory usage. +- 0.10.2 - Fixed a bug where the JinjaGenerator was not ignoring whitespace +- 0.10.1 - Added limit_prompts to JinjaGenerator. When set to True, `.generate(..., num_images=X)` will produced at most X prompts +- 0.10.0 - Added added the ability to combine random and combinatorial prompts. Also added a cyclical sampler - see documentation for details +- 0.9.1 - WildcardManager now uses the current working directory by default if a path is not provided +- 0.9.0 - Configurable wildcard symbols - it's possible to change from the default `__` to any arbitrary string +- 0.8.0 - Added syntax for changing samplers within prompt sub-trees. +- 0.7.1 - Fixed missing parser_config argument in CombinatorialPromptGenerator +- 0.7.0 - Configurable variant braces +- 0.6.0 - Support symlinks for the wildcards directory +- 0.5.0 - A major re-organisation of the parsing machinary. +- 0.4.3 - Allow zero repetitions in sequence commands, e.g. `{0-3$$A|B|C}` +- 0.4.2 - Added type information +- 0.4.1 - Variant separator can now be most printables e.g. `{2$$|$$A|B|C}`. This addresses [#211](https://github.com/adieyal/sd-dynamic-prompts/issues/211). +- 0.4.0 - Added block regex for magicprompts to remove unwanted modifiers. Many other small improvements, thanks to @akx +- 0.3.2 - Added LICENCE, many code improvements,security fix that prevents wildcard searches outside the wildcard directory - thanks to @akx +- 0.3.1 - Clean-up with thanks to @akx +- 0.3.0 - Added additional models to Magic Prompt +- 0.2.6 - Wildcards caching for speeding up complex prompts - with thanks to @RossM - see [#pr1](https://github.com/adieyal/dynamicprompts/pull/1) +- 0.2.5 - Fixed decimal weights in variants +- 0.2.4 - Fixed missing whitespace between two wildcards +- 0.2.3 - Fixed unlink seed from prompt which allows for a custom random number generator to be passed to the RandomGenerator +- 0.2.2 - Minor bug fixes +- 0.2.1 - Fixed a bug that cause the CombinatorialPromptGenerator to run very slowly when many wildcards were used. +- 0.2.0 - The parser now treats whitespace as significant in order to not ensure that the original prompt is left unaltered +- 0.1.19 - Added the Jinja2 generator from the SD Dynamic Prompts extension. Also fixed the Jinja2 interface to match the other generators +- 0.1.18 - Removed explicit dependency on pytorch, added default arguments for number of prompts produced by DummyGenerator and RandomPromptGenerator +- 0.1.17 - Fixed alternating words syntax [cat|dog] - pipes are only reserved inside variants. Also standardised MagicPrompt, AttentionGenerator, and FeelingLucky to use a DummyGenerator by default so that users are not forced to provide an alternative generator if one isn't needed. +- 0.1.16 - Changed type annotations to use classes from the typing package instead of native type in order to support python 3.7 +- 0.1.15 - First public release diff --git a/README.md b/README.md index 77052be8..192fd640 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,5 @@ # Dynamic Prompts - ![MIT](https://img.shields.io/github/license/adieyal/dynamicprompts)  -  ![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/adieyal/dynamicprompts/test.yml) @@ -14,46 +13,59 @@ Dynamic prompts is a Python library that provides developers with a **flexible a It includes: -* An easy-to-learn templating language that lets you create a number of unique prompts from a single template. -* Support for wildcard files as placeholders in templates. -* A mechanism for creating a wildcard library. Text, JSON, and YAML files are supported. -* Exhaustive generation of all prompts from a template. -* Variable assignment enabling re-usable prompt snippets. -* Supports Magic Prompt which automatically spices up your prompt with modifiers -* Provides an I'm Feeling Lucky feature which uses the semantic search on Lexica.art to find similar prompts. -* For systems that support attention syntax, Attention Grabber will emphasis random phrases in your prompt. -* Jinja-powered templating for advanced prompt creation. + +- An easy-to-learn templating language that lets you create a number of unique prompts from a single template. +- Support for wildcard files as placeholders in templates. +- A mechanism for creating a wildcard library. Text, JSON, and YAML files are supported. +- Exhaustive generation of all prompts from a template. +- Variable assignment enabling re-usable prompt snippets. +- Supports Magic Prompt which automatically spices up your prompt with modifiers +- Provides an I'm Feeling Lucky feature which uses the semantic search on Lexica.art to find similar prompts. +- For systems that support attention syntax, Attention Grabber will emphasis random phrases in your prompt. +- Jinja-powered templating for advanced prompt creation. The dynamic prompts library powers the [Dynamic Prompts](https://github.com/adieyal/sd-dynamic-prompts) extension for Automatic1111. ## Table of contents -* [Dynamic Prompts](#dynamic-prompts) - * [Quick overview of the templating language:](#quick-overview-of-the-templating-language) - * [Variants](#variants) - * [Choosing multiple variants](#choosing-multiple-variants) - * [Wildcards](#wildcards) - * [Let's try a real-world prompt](#lets-try-a-real-world-prompt) - * [Use whitespace for readability](#use-whitespace-for-readability) - * [Installation](#installation) - * [Quick Start](#quick-start) - * [Combinatorial Generation](#combinatorial-generation) - * [Magic Prompt](#magic-prompt) - * [I'm feeling lucky](#im-feeling-lucky) - * [Attention Generator](#attention-generator) - * [Jinja2 templates](#jinja2-templates) - * [Template syntax](#template-syntax) - * [Syntax customisation](#syntax-customisation) - * [Wildcard Collections](#wildcard-collections) - * [Dynamic Prompts in the wild.](#dynamic-prompts-in-the-wild) + + +- [Quick overview of the templating language:](#quick-overview-of-the-templating-language) + - [Variants](#variants) + - [Choosing multiple variants](#choosing-multiple-variants) + - [Wildcards](#wildcards) + - [Let's try a real-world prompt](#lets-try-a-real-world-prompt) + - [Use whitespace for readability](#use-whitespace-for-readability) +- [Installation](#installation) +- [Quick Start](#quick-start) + - [Random seeds](#random-seeds) + - [Combinatorial Generation](#combinatorial-generation) + - [Usage](#usage) + - [Magic Prompt](#magic-prompt) + - [Usage](#usage-1) + - [Other models](#other-models) + - [I'm feeling lucky](#im-feeling-lucky) + - [Usage](#usage-2) + - [Attention Generator](#attention-generator) + - [Usage](#usage-3) +- [Jinja2 templates](#jinja2-templates) +- [Template syntax](#template-syntax) + - [Syntax customisation](#syntax-customisation) +- [Wildcard Collections](#wildcard-collections) +- [Dynamic Prompts in the wild.](#dynamic-prompts-in-the-wild) + + ## Quick overview of the templating language: ### Variants + ``` {summer|autumn|winter|spring} is coming ``` + Randomly generate one of: + ``` summer is coming autumn is coming @@ -62,7 +74,9 @@ spring is coming ``` ### Choosing multiple variants + This syntax `{2$$ and $$A|B|C}` will choose two values from the list: + ``` A and B A and C @@ -73,13 +87,15 @@ C and B ``` ### Wildcards + ``` __season__ is coming ``` -Randomly selects a value from season.txt in your wildcard directory. +Randomly selects a value from season.txt in your wildcard directory. ### Let's try a real-world prompt + One prompt template can generate a family of prompts: ``` @@ -90,7 +106,6 @@ Funko pop {yoda|darth vader|jabba the hutt|princess leia|chewbacca|luke skywalke
- Now, how about two characters at the same time: ``` @@ -99,10 +114,10 @@ Funko pop {2$$ and $$yoda|darth vader|jabba the hutt|princess leia|chewbacca|luk -
### Use whitespace for readability + ``` # Add comments like this Funko pop @@ -123,7 +138,6 @@ Funko pop }, product studio shot, on a white background, diffused lighting, centered ``` - Use wildcards for re-usable lists: ``` @@ -150,21 +164,21 @@ product studio shot, on a white background, diffused lighting, centered ``` Now compose your prompt like this: + ``` Funko pop __starwars__ figurine, made of __material__, __studio-shot__ ``` and easily change it to: + ``` Funko pop __celebrities__ figurine, made of __material__, __studio-shot__ ``` - Hat tip to [publicprompts](https://publicprompts.art/) for the funko pop prompt. The complete syntax can be found [here](docs/SYNTAX.md). - ## Installation `pip install dynamicprompts` @@ -218,6 +232,7 @@ generator.generate("I love __colours__ roses", num_prompts) ### Random seeds You can pass a random seed in the constructor for predictable outputs + ``` generator = RandomPromptGenerator(wildcard_manager=wm, seed=999) ``` @@ -227,6 +242,7 @@ A list of seeds can also be provided in the `generate` method. ``` generator.generate("I love __colours__ roses", num_prompts, seeds=[1,2,3]) ``` + In this example, a seed is provided for each prompt generated. The number of seeds must equal the number of prompts, i.e. `len(seeds) == num_prompts`. If `len(seeds) == 1` then the same seed is used for every image. As a convenience, `seeds` may also be an int value. @@ -236,16 +252,19 @@ generator.generate("I love __colours__ roses", num_prompts=3, seeds=5) ``` is equivalent to: + ``` generator.generate("I love __colours__ roses", num_prompts=3, seeds=[5, 5, 5]) ``` ### Combinatorial Generation + Instead of generating random prompts from a template, combinatorial generation produces every possible prompt from the given string. For example: `I {love|hate} {New York|Chicago} in {June|July|August}` will produce: + > I love New York in June
> I love New York in July
> I love New York in August
@@ -264,6 +283,7 @@ If a `__wildcard__` is provided, then a new prompt will be produced for every va `My favourite season is __seasons__` will produce: + > My favourite season is Summer
> My favourite season is August
> My favourite season is Winter
@@ -295,8 +315,8 @@ If colours.txt contains 10 different colours, a combinatorial enumeration of tha > My favourite colours are red, blue, and purple
> ...
- ### Magic Prompt + Using [Gustavosta](https://huggingface.co/Gustavosta/MagicPrompt-Stable-Diffusion)'s MagicPrompt model, automatically generate new prompts from the input. Trained on 80,000 prompts from [Lexica.art](lexica.art), it can help give you interesting new prompts on a given subject. Here are some automatically generated variations for "dogs playing football": > dogs playing football, in the streets of a japanese town at night, with people watching in wonder, in the style of studio ghibli and makoto shinkai, highly detailed digital art, trending on artstation
@@ -331,6 +351,7 @@ Magic Prompt is not available by default, you need to install it as follows: `pip install "dynamicprompts[magicprompt]"` #### Other models + There a few alternatives to Gustavosta's model available. You can try: ``` @@ -343,6 +364,7 @@ You can find a longer list [here](https://github.com/adieyal/sd-dynamic-prompts/ Note that each model requires a download of large model files. ### I'm feeling lucky + Use the [lexica.art](https://lexica.art) API to create random prompts. Useful if you're looking for inspiration, or are simply too lazy to think of your own prompts. When this option is selected, the template is used as a search string. For example, prompt "Mech warrior" might return: > A large robot stone statue in the middle of a forest by Greg Rutkowski, Sung Choi, Mitchell Mohrhauser, Maciej Kuciara, Johnson Ting, Maxim Verehin, Peter Konig, final fantasy , 8k photorealistic, cinematic lighting, HD, high details, atmospheric, @@ -370,6 +392,7 @@ lucky_generator.generate("I love {red|green|blue} roses", num_prompts) ``` ### Attention Generator + If you are using [Automatic1111](https://github.com/AUTOMATIC1111/stable-diffusion-webui/) or a similar frontend to Stable Diffusion that uses attention syntax, e.g. `(some text:1.4)`, AttentionGenerator will randomly add attention to various phrases in your prompt. This injects a small amount of randomness into your prompt. #### Usage @@ -397,6 +420,7 @@ You may get better results with AttentionGenerator by installing the `spacy` NLP When Spacy is available, an NLP model will automatically be downloaded on first use. ## Jinja2 templates + If the standard template language is not sufficient for your needs, you can try the Jinja2 generator. Jinja2 templates have familiar programming constructs such as looping, conditionals, variables, etc. Youcan find a guide on using Jinja2 templates with Dynamic Prompts, [here](https://github.com/adieyal/sd-dynamic-prompts/blob/main/jinja2.md). Here is the minimal code you need to instantiate Jinja2 generator. ```python @@ -421,7 +445,9 @@ generator.generate(template) You can find the complete syntax guide [here](docs/SYNTAX.md) ### Syntax customisation + To address potential syntax clashes with other tools it is possible to change various tokens. Instead of `{red|green|blue}` you can configure the library to use the `<` `>` pair instead, e.g. ``. You can also change the `__` used in wildcards. So instead of `__colours__`, you can configure wildcards to use `**`, e.g. `**colours**` + ```python from dynamicprompts.generators import RandomPromptGenerator @@ -431,11 +457,15 @@ parser_config = ParserConfig(variant_start="<", variant_end=">", wildcard_wrap=" generator = RandomPromptGenerator(parser_config=parser_config) ``` + ## Wildcard Collections + You can bootstrap your wildcard library by using our [pre-existing collections](https://github.com/adieyal/sd-dynamic-prompts/tree/main/collections). You'll find just under 80,000 wildcards divided into 1900 files. Feel free to pick and choose or take them in their entirety. ## Dynamic Prompts in the wild. + Dynamic Prompts has been used in: + 1. [SD Dynamic Prompts](https://github.com/adieyal/sd-dynamic-prompts/edit/main/README.md) Auto1111 extension 2. Deforum 0.7 [colab](https://colab.research.google.com/drive/1qtYHUwFl9ocLyzDRL1_MlpQluV32ndoT?usp=sharing) 3. [ComfyUI Nodes](https://github.com/adieyal/comfyui-dynamicprompts) diff --git a/docs/SYNTAX.md b/docs/SYNTAX.md index db29cc72..5ffd4c05 100644 --- a/docs/SYNTAX.md +++ b/docs/SYNTAX.md @@ -3,43 +3,46 @@ This guide will walk you through the template language used to generate dynamic prompts. It covers various features such as variants, wildcards, variables, and parameterized templates. ## Table of contents -- [Syntax Guide](#syntax-guide) - - [Table of contents](#table-of-contents) - - [Variants](#variants) - - [Basic Syntax](#basic-syntax) - - [Weighting Options](#weighting-options) - - [Choosing Multiple Values](#choosing-multiple-values) - - [Custom Separator](#custom-separator) - - [Range of Options](#range-of-options) - - [Omitting Bounds](#omitting-bounds) - - [Limitations](#limitations) - - [Wildcards](#wildcards) - - [Basic Syntax](#basic-syntax-1) - - [Wildcards in Variants](#wildcards-in-variants) - - [Variants in Wildcards](#variants-in-wildcards) - - [Nested Wildcards](#nested-wildcards) - - [Resolving Wildcards with Globbing](#resolving-wildcards-with-globbing) - - [Basic Syntax](#basic-syntax-2) - - [Example](#example) - - [Recursive globbing](#recursive-globbing) - - [File formats](#file-formats) - - [Text files](#text-files) - - [YAML files](#yaml-files) - - [Weighted options in YAML](#weighted-options-in-yaml) - - [JSON files](#json-files) - - [Variables](#variables) - - [Immediate Evaluation](#immediate-evaluation) - - [Non-immediate Evaluation](#non-immediate-evaluation) - - [Parameterized Templates](#parameterized-templates) - - [Basic Syntax](#basic-syntax-3) - - [Default values](#default-values) - - [Preserving Existing Values](#preserving-existing-values) - - [Whitespace and comments](#whitespace-and-comments) - - [Samplers](#samplers) - - [Random Sampler](#random-sampler) - - [Combinatorial Sampler](#combinatorial-sampler) - - [Cyclical Sampler](#cyclical-sampler) + + +- [Variants](#variants) + - [Basic Syntax](#basic-syntax) + - [Weighting Options](#weighting-options) + - [Choosing Multiple Values](#choosing-multiple-values) + - [Custom Separator](#custom-separator) + - [Range of Options](#range-of-options) + - [Omitting Bounds](#omitting-bounds) + - [Limitations](#limitations) +- [Wildcards](#wildcards) + - [Basic Syntax](#basic-syntax-1) + - [Wildcards in Variants](#wildcards-in-variants) + - [Variants in Wildcards](#variants-in-wildcards) + - [Nested Wildcards](#nested-wildcards) + - [Resolving Wildcards with Globbing](#resolving-wildcards-with-globbing) + - [Basic Syntax](#basic-syntax-2) + - [Example](#example) + - [Recursive globbing](#recursive-globbing) + - [File formats](#file-formats) + - [Text files](#text-files) + - [YAML files](#yaml-files) + - [Weighted options in YAML](#weighted-options-in-yaml) + - [JSON files](#json-files) +- [Variables](#variables) + - [Immediate Evaluation](#immediate-evaluation) + - [Non-immediate Evaluation](#non-immediate-evaluation) +- [Parameterized Templates](#parameterized-templates) + - [Basic Syntax](#basic-syntax-3) + - [Default values](#default-values) + - [Preserving Existing Values](#preserving-existing-values) +- [Whitespace and comments](#whitespace-and-comments) +- [Wrap command](#wrap-command) +- [Samplers](#samplers) + - [Random Sampler](#random-sampler) + - [Combinatorial Sampler](#combinatorial-sampler) + - [Cyclical Sampler](#cyclical-sampler) + + ## Variants @@ -55,10 +58,10 @@ To create a variant, wrap your options in curly brackets {} and separate them wi This will randomly generate one of the following: -* summer is coming -* autumn is coming -* winter is coming -* spring is coming +- summer is coming +- autumn is coming +- winter is coming +- spring is coming ### Weighting Options @@ -82,11 +85,11 @@ My favourite ice-cream flavours are {2$$chocolate|vanilla|strawberry} This will generate one of the following: -* My favourite ice-cream flavours are chocolate, vanilla -* My favourite ice-cream flavours are chocolate, strawberry -* My favourite ice-cream flavours are vanilla, chocolate -* ... -etc +- My favourite ice-cream flavours are chocolate, vanilla +- My favourite ice-cream flavours are chocolate, strawberry +- My favourite ice-cream flavours are vanilla, chocolate +- ... + etc Values are chosen without replacement, so you won't get repeats. @@ -100,10 +103,10 @@ My favourite ice-cream flavours are {2$$ and $$chocolate|vanilla|strawberry} This will generate one of the following: -* My favourite ice-cream flavours are chocolate and vanilla -* My favourite ice-cream flavours are chocolate and strawberry -* My favourite ice-cream flavours are vanilla and chocolate -* ... +- My favourite ice-cream flavours are chocolate and vanilla +- My favourite ice-cream flavours are chocolate and strawberry +- My favourite ice-cream flavours are vanilla and chocolate +- ... ### Range of Options @@ -115,13 +118,13 @@ My favourite ice-cream flavours are {1-2$$ and $$chocolate|vanilla|strawberry} This will generate: -* My favourite ice-cream flavours are chocolate -* My favourite ice-cream flavours are strawberry -* My favourite ice-cream flavours are vanilla -* My favourite ice-cream flavours are chocolate and vanilla -* My favourite ice-cream flavours are chocolate and strawberry -* My favourite ice-cream flavours are vanilla and chocolate -* ... +- My favourite ice-cream flavours are chocolate +- My favourite ice-cream flavours are strawberry +- My favourite ice-cream flavours are vanilla +- My favourite ice-cream flavours are chocolate and vanilla +- My favourite ice-cream flavours are chocolate and strawberry +- My favourite ice-cream flavours are vanilla and chocolate +- ... #### Omitting Bounds @@ -163,10 +166,10 @@ spring This prompt will randomly generate one of the following: -* summer is coming -* autumn is coming -* winter is coming -* spring is coming +- summer is coming +- autumn is coming +- winter is coming +- spring is coming ### Wildcards in Variants @@ -198,11 +201,11 @@ spring The possible outputs are: -* summer is coming -* autumn is coming -* fall is coming -* winter is coming -* spring is coming +- summer is coming +- autumn is coming +- fall is coming +- winter is coming +- spring is coming ### Nested Wildcards @@ -284,10 +287,10 @@ The colour of my shirt is __colours*__ Possible outputs are: -* The colour of my shirt is blue -* The colour of my shirt is green -* The colour of my shirt is red -* The colour of my shirt is yellow +- The colour of my shirt is blue +- The colour of my shirt is green +- The colour of my shirt is red +- The colour of my shirt is yellow #### Recursive globbing @@ -337,11 +340,10 @@ The last two entries are ignore since they don't store arrays. A handy feature of YAML files is that they provide an easy way to add weights to wildcards, something which isn't possible using standard text files. Here is an example: ```yaml -{ - 2::red - | 3::blue - | 1:: green -} +{ ? 2::red + | 3::blue + | 1: + : green } ``` #### JSON files @@ -400,11 +402,10 @@ In ${season}, I wear ${season} shirts and ${season} trousers This will generate: -* In summer, I wear summer shirts and summer trousers -* In autumn, I wear autumn shirts and autumn trousers -* In winter, I wear winter shirts and winter trousers -* In spring, I wear spring shirts and spring trousers - +- In summer, I wear summer shirts and summer trousers +- In autumn, I wear autumn shirts and autumn trousers +- In winter, I wear winter shirts and winter trousers +- In spring, I wear spring shirts and spring trousers ### Non-immediate Evaluation @@ -467,19 +468,19 @@ Now if you forget to create the season variable, the prompt will be `In summer, ### Preserving Existing Values -Within a parameterized template, there may be cases where you want to assign a variable instead of providing a default value in order to achieve better consistency across nested parameterized templates. When assigning a variable a value, you can indicate that you do not want to overwrite an existing value by placing a `?` before the `=` in the assignment. +Within a parameterized template, there may be cases where you want to assign a variable instead of providing a default value in order to achieve better consistency across nested parameterized templates. When assigning a variable a value, you can indicate that you do not want to overwrite an existing value by placing a `?` before the `=` in the assignment. For instance, given the following example parameterized templates with variables: ```yaml examples: prompt: - - '${subject?=!{man|woman}} ${weather?=!{sun|rain}} ${drink?=!{__examples/drink__}} a ${subject} standing in the ${weather} drinking ${drink}' + - "${subject?=!{man|woman}} ${weather?=!{sun|rain}} ${drink?=!{__examples/drink__}} a ${subject} standing in the ${weather} drinking ${drink}" drink: - coffee - tea winter: - - '${weather=snow} ${drink=hot chocolate} __examples/prompt__' + - "${weather=snow} ${drink=hot chocolate} __examples/prompt__" ``` Then the following prompts would produce results similar to the following: @@ -537,6 +538,27 @@ public-prompts: square image ``` +## Wrap command + +The wrap command lets you use a template, e.g. from a wildcard file, and wrap it around another prompt, +as an alternative approach to parametrized templates. + +This is similar to the [Styles feature in A1111](https://github.com/AUTOMATIC1111/stable-diffusion-webui/wiki/Features#styles). +This is useful if you want to use a template to generate a complex structure and then use that structure in a prompt. + +The syntax for wraps is + +``` +%{something wrapping ..., very cool, neat$$this internal prompt} +``` + +This would result in the prompt `something wrapping this internal prompt, very cool, neat`. + +Both sides of the wrap command are evaluated before the wrap itself is, so this can be combined with other features like wildcards and variables. + +Various ellipsis characters are supported for the `...` placeholder, but `...` (3 ASCII periods) +might be the easiest to use. + ## Samplers Samplers are an advanced topic although understanding how they work will help you understand how the dynamic prompts engine works. diff --git a/docs/tutorial.md b/docs/tutorial.md index 5a84afae..c3580838 100644 --- a/docs/tutorial.md +++ b/docs/tutorial.md @@ -18,7 +18,6 @@ What if we wanted an image of a platinum ring as well? We can use the Dynamic Pr Dynamic Prompts would then generate one of: - A diamond ring set on a gold band and @@ -31,7 +30,6 @@ Gold comes in various varieties, let's add those as well: A diamond ring set on a {{rose|yellow|white} gold|platinum} band. - Notice how we nested a variant for the type of gold, i.e. `{rose|yellow|white}` inside the main variant. So now, when generating an image, one of the following prompts is created: @@ -62,7 +60,6 @@ This template could produce any of these prompts: A emerald ring set on a thin platinum band etc. - That second prompt isn't grammatically correct, it doesn't matter to Stable Diffusion, but if you prefer correct grammar, you can write something like: {A diamond|A ruby|An emerald} ring set on a {classic|thin|thick} @@ -73,6 +70,7 @@ That second prompt isn't grammatically correct, it doesn't matter to Stable Diff band ## Wildcards + What if we had many gems that we would like to use in our rings? You can certainly add them as variants along with rubies and emeralds, but this may become cumbersome with many variants. In this case, we can use a wildcard. First, we create a file called `gems.txt` inside the wildcards folder. The location depends on the frontend you're using for Dynamic Prompts. @@ -151,7 +149,6 @@ Some examples of prompts that are generated: surfer in space, intricate detail, airbrush painting, illustration, by Fritz Wegner,Dawu Yu - The default separator is a `,` - if you prefer to use `and` then change the prompt like this: surfer in space, intricate detail, airbrush painting, illustration, by {2$$ and $$__artists/illustrations/childrens_books__} @@ -194,14 +191,12 @@ Here are some example prompts that I get when using Magic Prompt: A mech-warrior in a post-apocalyptic setting. realistic shaded lighting poster by Ilya Kuvshinov katsuhiro, magali villeneuve, artgerm, Jeremy Lipkin and Michael Garmash, Rob Rey and Kentar� Miura style, trending on art station - When I have a subject in mind but I'm not yet sure about how I want the final image to look, I usually play around with magic prompt until I find something I like. I then use the generated prompt and tune from there. ## I'm feeling lucky Another way of getting inspiration is through the I'm feeling lucky function. Instead of using a neural network, I'm feeling lucky uses the search engine on [Lexica.art](http://lexica.art) to find prompts that match your input. Quality may vary, but it is also a fun way to explore the latent space. - Using `mech-warrior` as my prompt, I get the following: giant oversized battle robot mech in battle pose is giant baby on a village, wooden fence and tree remains in far background, hero pose, Cinematic focus, Polaroid photo, vintage, neutral colors, soft lights, foggy, natural mysterous intricate detailed grainy photo, by Steve Hanks, by Serov Valentin, by lisa yuskavage, by Andrei Tarkovsky @@ -234,8 +229,8 @@ We add randomly add emphasis. For these images, I kept the seed constant so that a detailed manga illustration character full body portrait of a dark haired cyborg anime man who has a red mechanical eye, trending on artstation, digital art, 4 k resolution, detailed, high quality, sharp focus, hq artwork, insane detail, concept art, character concept, (character illustration:1.26), full body illustration, cinematic, dramatic lighting - These changes are far more subtle and can be helpful if you want to explore slight changes to your image. + # Conclusion This tutorial has covered the basics. There are additional features to try out once you feel comfortable using the tool. diff --git a/tests/test_data/wildcards/drink.yaml b/tests/test_data/wildcards/drink.yaml index ef0d32b6..b8fb26ce 100644 --- a/tests/test_data/wildcards/drink.yaml +++ b/tests/test_data/wildcards/drink.yaml @@ -1,9 +1,9 @@ drink: beverage: - - '${season?=!{winter|summer}} ${temp?=!{hot|cold}} ${location?=!{north|south}} a __drink/container/${temp}__ of __drink/temp/${temp}__ __drink/${season}/${location}__' + - "${season?=!{winter|summer}} ${temp?=!{hot|cold}} ${location?=!{north|south}} a __drink/container/${temp}__ of __drink/temp/${temp}__ __drink/${season}/${location}__" winter: beverage: - - '${temp=hot} ${season=winter} ${location?=north} __drink/beverage__' + - "${temp=hot} ${season=winter} ${location?=north} __drink/beverage__" north: - tea @@ -12,7 +12,7 @@ drink: summer: beverage: - - '${temp=cold} ${season=summer} ${location?=south} __drink/beverage__' + - "${temp=cold} ${season=summer} ${location?=south} __drink/beverage__" north: - tea - pop diff --git a/tests/test_data/wildcards/flavors/pantry.json b/tests/test_data/wildcards/flavors/pantry.json index 43616f29..3756ed92 100644 --- a/tests/test_data/wildcards/flavors/pantry.json +++ b/tests/test_data/wildcards/flavors/pantry.json @@ -1,6 +1,3 @@ { - "bitter": [ - "coffee", - "dark chocolate" - ] + "bitter": ["coffee", "dark chocolate"] } diff --git a/tests/test_data/wildcards/pantry.yaml b/tests/test_data/wildcards/pantry.yaml index b8f9be23..e2d98acb 100644 --- a/tests/test_data/wildcards/pantry.yaml +++ b/tests/test_data/wildcards/pantry.yaml @@ -11,7 +11,7 @@ artists: - Piet Mondrian - Rembrandt van Rijn - Vincent van Gogh - moonbase: john madden # interpreted as a single john madden - 1234: 5678 # this is ignored - flurp: 12345 # this too - flem: "" # and this + moonbase: john madden # interpreted as a single john madden + 1234: 5678 # this is ignored + flurp: 12345 # this too + flem: "" # and this