diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 000000000..87fa94dbb --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1,11 @@ +github: [vladmandic] +patreon: # Replace with a single Patreon username +open_collective: # Replace with a single Open Collective username +ko_fi: # Replace with a single Ko-fi username +tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel +community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry +liberapay: # Replace with a single Liberapay username +issuehunt: # Replace with a single IssueHunt username +otechie: # Replace with a single Otechie username +lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry +custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index 7d435297a..f0b02904a 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -1,100 +1,46 @@ -name: Bug Report -description: You think somethings is broken in the UI -title: "[Bug]: " -labels: ["bug-report"] +name: Issue Report +description: Something is broken +title: "[Issue]: " +labels: ["issue"] body: - - type: checkboxes + - type: textarea + id: description attributes: - label: Is there an existing issue for this? - description: Please search to see if an issue already exists for the bug you encountered, and that it hasn't been fixed in a recent build/commit. - options: - - label: I have searched the existing issues and checked the recent builds/commits - required: true + label: Issue Description + description: Tell us what happened in a very clear and simple way + value: Please fill this form with as much information as possible + - type: textarea + id: platform + attributes: + label: Version Platform Description + description: Describe your platform (program version, OS, browser) + value: - type: markdown attributes: value: | - *Please fill this form with as much information as possible, don't forget to fill "What OS..." and "What browsers" and *provide screenshots if possible** - - type: textarea - id: what-did + Any issues without version information will be closed + Look at console log and copy the version string from there + For example: `Version: f256fb8b Fri Apr 14 17:41:30 2023 -0400` + + Additionally provide any relevant platorm information (OS, browser, versions) + - type: markdown attributes: - label: What happened? - description: Tell us what happened in a very clear and simple way - validations: - required: true - - type: textarea - id: steps - attributes: - label: Steps to reproduce the problem - description: Please provide us with precise step by step information on how to reproduce the bug value: | - 1. Go to .... - 2. Press .... - 3. ... - validations: - required: true - - type: textarea - id: what-should + If issue is setup, installation or startup related, please check `setup.log` before reporting + And when posting console logs, please use code blocks ( \`\`\` ) to format them insead of uploading screenshots + - type: markdown attributes: - label: What should have happened? - description: Tell what you think the normal behavior should be - validations: - required: true - - type: input - id: commit + value: | + Verify that issue persists after restarting server from command line + Restarting from UI or reloading browser is insufficient to create reproducible environment + - type: markdown attributes: - label: Commit where the problem happens - description: Which commit are you running ? (Do not write *Latest version/repo/commit*, as this means nothing and will have changed by the time we read your issue. Rather, copy the **Commit** link at the bottom of the UI, or from the cmd/terminal if you can't launch it.) - validations: - required: true - - type: dropdown - id: platforms + value: | + If you have additional extensions installed, try to reproduce the issue with user extensions disabled + And if the issue is with compatibility with specific extension, mark it as such when creating the issue + - type: markdown attributes: - label: What platforms do you use to access the UI ? - multiple: true - options: - - Windows - - Linux - - MacOS - - iOS - - Android - - Other/Cloud - - type: dropdown - id: browsers - attributes: - label: What browsers do you use to access the UI ? - multiple: true - options: - - Mozilla Firefox - - Google Chrome - - Brave - - Apple Safari - - Microsoft Edge - - type: textarea - id: cmdargs - attributes: - label: Command Line Arguments - description: Are you using any launching parameters/command line arguments (modified webui-user .bat/.sh) ? If yes, please write them below. Write "No" otherwise. - render: Shell - validations: - required: true - - type: textarea - id: extensions - attributes: - label: List of extensions - description: Are you using any extensions other than built-ins? If yes, provide a list, you can copy it at "Extensions" tab. Write "No" otherwise. - validations: - required: true - - type: textarea - id: logs - attributes: - label: Console logs - description: Please provide **full** cmd/terminal logs from the moment you started UI to the end of it, after your bug happened. If it's very long, provide a link to pastebin or similar service. - render: Shell - validations: - required: true - - type: textarea - id: misc - attributes: - label: Additional information - description: Please provide us with any relevant additional info or context. + value: | + If possible update to latest version before reporting the issue as older versions cannot be properly supported + And search existing **issues** and **discussions** before creating a new one diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index f58c94a9b..afdb9109a 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -1,5 +1,5 @@ blank_issues_enabled: false contact_links: - name: WebUI Community Support - url: https://github.com/AUTOMATIC1111/stable-diffusion-webui/discussions + url: https://github.com/vladmandic/automatic/discussions about: Please ask and answer questions here. diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml index 35a887408..4c21a785d 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.yml +++ b/.github/ISSUE_TEMPLATE/feature_request.yml @@ -1,40 +1,18 @@ name: Feature request description: Suggest an idea for this project -title: "[Feature Request]: " +title: "[Feature]: " labels: ["enhancement"] body: - - type: checkboxes - attributes: - label: Is there an existing issue for this? - description: Please search to see if an issue already exists for the feature you want, and that it's not implemented in a recent build/commit. - options: - - label: I have searched the existing issues and checked the recent builds/commits - required: true - - type: markdown - attributes: - value: | - *Please fill this form with as much information as possible, provide screenshots and/or illustrations of the feature if possible* - type: textarea - id: feature + id: description attributes: - label: What would your feature do ? - description: Tell us about your feature in a very clear and simple way, and what problem it would solve - validations: - required: true + label: Feature description + description: Describe the feature in a clear and simple way + value: - type: textarea - id: workflow + id: platform attributes: - label: Proposed workflow - description: Please provide us with step by step information on how you'd like the feature to be accessed and used - value: | - 1. Go to .... - 2. Press .... - 3. ... - validations: - required: true - - type: textarea - id: misc - attributes: - label: Additional information - description: Add any other context or screenshots about the feature request here. + label: Version Platform Description + description: Describe your platform (program version, OS, browser) + value: diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 69056331b..fdb4c0516 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -1,28 +1,11 @@ -# Please read the [contributing wiki page](https://github.com/AUTOMATIC1111/stable-diffusion-webui/wiki/Contributing) before submitting a pull request! +## Description -If you have a large change, pay special attention to this paragraph: +A clear and concise description of what you're trying to accomplish with this, so your intent doesn't have to be extracted from your code -> Before making changes, if you think that your feature will result in more than 100 lines changing, find me and talk to me about the feature you are proposing. It pains me to reject the hard work someone else did, but I won't add everything to the repo, and it's better if the rejection happens before you have to waste time working on the feature. +## Notes -Otherwise, after making sure you're following the rules described in wiki page, remove this section and continue on. +More technical discussion about your changes go here, plus anything that a maintainer might have to specifically take a look at, or be wary of -**Describe what this pull request is trying to achieve.** +## Environment and Testing -A clear and concise description of what you're trying to accomplish with this, so your intent doesn't have to be extracted from your code. - -**Additional notes and description of your changes** - -More technical discussion about your changes go here, plus anything that a maintainer might have to specifically take a look at, or be wary of. - -**Environment this was tested in** - -List the environment you have developed / tested this on. As per the contributing page, changes should be able to work on Windows out of the box. - - OS: [e.g. Windows, Linux] - - Browser: [e.g. chrome, safari] - - Graphics card: [e.g. NVIDIA RTX 2080 8GB, AMD RX 6600 8GB] - -**Screenshots or videos of your changes** - -If applicable, screenshots or a video showing off your changes. If it edits an existing UI, it should ideally contain a comparison of what used to be there, before your changes were made. - -This is **required** for anything that touches the user interface. \ No newline at end of file +List the environment you have developed / tested this on diff --git a/.github/workflows/on_pull_request.yaml b/.github/workflows/on_pull_request.yaml index a168be5b8..011fe9b2d 100644 --- a/.github/workflows/on_pull_request.yaml +++ b/.github/workflows/on_pull_request.yaml @@ -18,13 +18,12 @@ jobs: steps: - name: Checkout Code uses: actions/checkout@v3 - - name: Set up Python 3.10 + - name: Set up Python uses: actions/setup-python@v4 with: python-version: 3.10.6 cache: pip - cache-dependency-path: | - **/requirements*txt + cache-dependency-path: requirements.txt - name: Install PyLint run: | python -m pip install --upgrade pip diff --git a/.github/workflows/run_tests.yaml b/.github/workflows/run_tests.yaml index 9a0b8d22b..18b90660a 100644 --- a/.github/workflows/run_tests.yaml +++ b/.github/workflows/run_tests.yaml @@ -10,20 +10,11 @@ jobs: steps: - name: Checkout Code uses: actions/checkout@v3 - - name: Set up Python 3.10 + - name: Set up Python uses: actions/setup-python@v4 with: python-version: 3.10.6 cache: pip - cache-dependency-path: | - **/requirements*txt + cache-dependency-path: requirements.txt - name: Run tests - run: python launch.py --tests test --no-half --disable-opt-split-attention --use-cpu all --skip-torch-cuda-test - - name: Upload main app stdout-stderr - uses: actions/upload-artifact@v3 - if: always() - with: - name: stdout-stderr - path: | - test/stdout.txt - test/stderr.txt + run: python launch.py diff --git a/.gitignore b/.gitignore index 0b1d17ca3..fa8769047 100644 --- a/.gitignore +++ b/.gitignore @@ -1,35 +1,43 @@ +# defaults __pycache__ +/params.txt +/cache.json +/config.json +/ui-config.json +/setup.log +/styles.csv +/user.css +/webui-user.bat +/javascript/themes.json +venv + +# all models and temp files +*.bak *.ckpt *.safetensors *.pth -/ESRGAN/* -/SwinIR/* -/repositories -/venv -/tmp -/model.ckpt +*.pt +*.bin +*.optim +*.lock +*.zip +*.rar +*.pyc + +# all dynamic stuff +/repositories/**/* +/extensions/**/* +/outputs/**/* +/embeddings/**/* /models/**/* -/GFPGANv1.3.pth -/gfpgan/weights/*.pth -/ui-config.json -/outputs -/config.json +/interrogate/**/* +/train/log/**/* +/tmp /log -/webui.settings.bat -/embeddings -/styles.csv -/params.txt -/styles.csv.bak -/webui-user.bat -/webui-user.sh -/interrogate -/user.css -/.idea -notification.mp3 -/SwinIR -/textual_inversion -.vscode -/extensions -/test/stdout.txt -/test/stderr.txt -/cache.json +/cert +.vscode/ + +# unexcluded so folders get created +!/repositories/.placeholder +!/models/VAE-approx +!/models/VAE-approx/model.pt diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 000000000..ab36c3699 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,50 @@ +[submodule "wiki"] + path = wiki + url = https://github.com/vladmandic/automatic.wiki +[submodule "extensions-builtin/sd-extension-system-info"] + path = extensions-builtin/sd-extension-system-info + url = https://github.com/vladmandic/sd-extension-system-info +[submodule "extensions-builtin/sd-extension-aesthetic-scorer"] + path = extensions-builtin/sd-extension-aesthetic-scorer + url = https://github.com/vladmandic/sd-extension-aesthetic-scorer +[submodule "extensions-builtin/sd-extension-steps-animation"] + path = extensions-builtin/sd-extension-steps-animation + url = https://github.com/vladmandic/sd-extension-steps-animation +[submodule "extensions-builtin/stable-diffusion-webui-images-browser"] + path = extensions-builtin/stable-diffusion-webui-images-browser + url = https://github.com/AlUlkesh/stable-diffusion-webui-images-browser + ignore = dirty +[submodule "extensions-builtin/seed_travel"] + path = extensions-builtin/seed_travel + url = https://github.com/yownas/seed_travel + ignore = dirty +[submodule "extensions-builtin/sd-webui-model-converter"] + path = extensions-builtin/sd-webui-model-converter + url = https://github.com/Akegarasu/sd-webui-model-converter + ignore = dirty +[submodule "extensions-builtin/sd-dynamic-thresholding"] + path = extensions-builtin/sd-dynamic-thresholding + url = https://github.com/mcmonkeyprojects/sd-dynamic-thresholding + ignore = dirty +[submodule "modules/lora"] + path = modules/lora + url = https://github.com/kohya-ss/sd-scripts + ignore = dirty +[submodule "extensions-builtin/clip-interrogator-ext"] + path = extensions-builtin/clip-interrogator-ext + url = https://github.com/pharmapsychotic/clip-interrogator-ext.git +[submodule "extensions-builtin/sd-webui-controlnet"] + path = extensions-builtin/sd-webui-controlnet + url = https://github.com/Mikubill/sd-webui-controlnet +[submodule "modules/lycoris"] + path = modules/lycoris + url = https://github.com/KohakuBlueleaf/LyCORIS +[submodule "extensions-builtin/stable-diffusion-webui-rembg"] + path = extensions-builtin/stable-diffusion-webui-rembg + url = https://github.com/AUTOMATIC1111/stable-diffusion-webui-rembg +[submodule "extensions-builtin/a1111-sd-webui-lycoris"] + path = extensions-builtin/a1111-sd-webui-lycoris + url = https://github.com/KohakuBlueleaf/a1111-sd-webui-lycoris +[submodule "extensions-builtin/multidiffusion-upscaler-for-automatic1111"] + path = extensions-builtin/multidiffusion-upscaler-for-automatic1111 + url = https://github.com/pkuliyi2015/multidiffusion-upscaler-for-automatic1111 diff --git a/.markdownlint.json b/.markdownlint.json new file mode 100644 index 000000000..c9179cd2f --- /dev/null +++ b/.markdownlint.json @@ -0,0 +1,7 @@ +{ + "MD012": false, + "MD013": false, + "MD033": false, + "MD036": false, + "MD041": false +} \ No newline at end of file diff --git a/.pylintrc b/.pylintrc index 53254e5dc..72e1224e8 100644 --- a/.pylintrc +++ b/.pylintrc @@ -1,3 +1,209 @@ -# See https://pylint.pycqa.org/en/latest/user_guide/messages/message_control.html +[MAIN] +analyse-fallback-blocks=no +clear-cache-post-run=no +#enable-all-extensions= +#errors-only= +#exit-zero= +extension-pkg-allow-list= +extension-pkg-whitelist= +fail-on= +fail-under=10 +ignore=CVS +ignore-paths=^repositories/.*$, + ^extensions/.*$, + /usr/lib/.*$, +ignore-patterns= +ignored-modules= +jobs=0 +limit-inference-results=100 +load-plugins= +persistent=yes +py-version=3.10 +recursive=no +source-roots= +suggestion-mode=yes +unsafe-load-any-extension=no +#verbose= + +[BASIC] +argument-naming-style=snake_case +#argument-rgx= +attr-naming-style=snake_case +#attr-rgx= +bad-names=foo, bar, baz, toto, tutu, tata +bad-names-rgxs= +class-attribute-naming-style=any +class-const-naming-style=UPPER_CASE +#class-const-rgx= +class-naming-style=PascalCase +#class-rgx= +const-naming-style=snake_case +#const-rgx= +docstring-min-length=-1 +function-naming-style=snake_case +#function-rgx= +# Good variable names which should always be accepted, separated by a comma. +good-names=i,j,k,e,ex,ok,p +good-names-rgxs= +include-naming-hint=no +inlinevar-naming-style=any +#inlinevar-rgx= +method-naming-style=snake_case +#method-rgx= +module-naming-style=snake_case +#module-rgx= +name-group= +no-docstring-rgx=^_ +property-classes=abc.abstractproperty +#typealias-rgx= +#typevar-rgx= +variable-naming-style=snake_case +#variable-rgx= + +[CLASSES] +check-protected-access-in-special-methods=no +defining-attr-methods=__init__, + __new__, + setUp, + asyncSetUp, + __post_init__ +exclude-protected=_asdict,_fields,_replace,_source,_make,os._exit +valid-classmethod-first-arg=cls +valid-metaclass-classmethod-first-arg=mcs + +[DESIGN] +exclude-too-few-public-methods= +ignored-parents= +max-args=5 +max-attributes=7 +max-bool-expr=5 +max-branches=12 +max-locals=15 +max-parents=7 +max-public-methods=20 +max-returns=6 +max-statements=50 +min-public-methods=2 + +[EXCEPTIONS] +overgeneral-exceptions=builtins.BaseException,builtins.Exception + +[FORMAT] +expected-line-ending-format= +ignore-long-lines=^\s*(# )??$ +indent-after-paren=4 +indent-string=' ' +max-line-length=200 +max-module-lines=9999 +single-line-class-stmt=no +single-line-if-stmt=no + +[IMPORTS] +allow-any-import-level= +allow-reexport-from-package=no +allow-wildcard-with-all=no +deprecated-modules= +ext-import-graph= +import-graph= +int-import-graph= +known-standard-library= +known-third-party=enchant +preferred-modules= + +[LOGGING] +logging-format-style=new +logging-modules=logging + [MESSAGES CONTROL] -disable=C,R,W,E,I +confidence=HIGH, + CONTROL_FLOW, + INFERENCE, + INFERENCE_FAILURE, + UNDEFINED +# disable=C,R,W +disable=raw-checker-failed, + bad-inline-option, + locally-disabled, + file-ignored, + suppressed-message, + useless-suppression, + deprecated-pragma, + use-symbolic-message-instead, + line-too-long, + missing-function-docstring, + missing-module-docstring, + missing-class-docstring, + logging-fstring-interpolation, + import-outside-toplevel, + consider-iterating-dictionary, + wrong-import-position, + unnecessary-lambda, + consider-using-dict-items, + dangerous-default-value, + unnecessary-dunder-call, +enable=c-extension-no-member + +[METHOD_ARGS] +timeout-methods=requests.api.delete,requests.api.get,requests.api.head,requests.api.options,requests.api.patch,requests.api.post,requests.api.put,requests.api.request + +[MISCELLANEOUS] +notes=FIXME, + XXX, + TODO +notes-rgx= + +[REFACTORING] +max-nested-blocks=5 +never-returning-functions=sys.exit,argparse.parse_error + +[REPORTS] +evaluation=max(0, 0 if fatal else 10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10)) +msg-template= +#output-format= +reports=no +score=no + +[SIMILARITIES] +ignore-comments=yes +ignore-docstrings=yes +ignore-imports=yes +ignore-signatures=yes +min-similarity-lines=4 + +[SPELLING] +max-spelling-suggestions=4 +spelling-dict= +spelling-ignore-comment-directives=fmt: on,fmt: off,noqa:,noqa,nosec,isort:skip,mypy: +spelling-ignore-words= +spelling-private-dict-file= +spelling-store-unknown-words=no + +[STRING] +check-quote-consistency=no +check-str-concat-over-line-jumps=no + +[TYPECHECK] +contextmanager-decorators=contextlib.contextmanager +generated-members=numpy.*,torch.*,cv2.* +ignore-none=yes +ignore-on-opaque-inference=yes +ignored-checks-for-mixins=no-member, + not-async-context-manager, + not-context-manager, + attribute-defined-outside-init +ignored-classes=optparse.Values,thread._local,_thread._local,argparse.Namespace +missing-member-hint=yes +missing-member-hint-distance=1 +missing-member-max-choices=1 +mixin-class-rgx=.*[Mm]ixin +signature-mutators= + +[VARIABLES] +additional-builtins= +allow-global-unused-variables=yes +allowed-redefined-builtins= +callbacks=cb_, +dummy-variables-rgx=_+$|(_[a-zA-Z0-9_]*[a-zA-Z0-9]+?$)|dummy|^ignored_|^unused_ +ignored-argument-names=_.*|^ignored_|^unused_ +init-import=no +redefining-builtins-modules=six.moves,past.builtins,future.builtins,builtins,io diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 000000000..d5e8da26c --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,14 @@ +{ + "python.analysis.extraPaths": [ + ".", + "./modules", + "./modules/lora", + "./repositories/BLIP", + "./repositories/CodeFormer", + "./repositories/k-diffusion", + "./repositories/taming-transformers", + "./repositories/stable-diffusion-stability-ai", + "./repositories/stable-diffusion-stability-ai/ldm" + ], + "python.analysis.typeCheckingMode": "off" +} diff --git a/CODEOWNERS b/CODEOWNERS deleted file mode 100644 index 7438c9bc6..000000000 --- a/CODEOWNERS +++ /dev/null @@ -1,12 +0,0 @@ -* @AUTOMATIC1111 - -# if you were managing a localization and were removed from this file, this is because -# the intended way to do localizations now is via extensions. See: -# https://github.com/AUTOMATIC1111/stable-diffusion-webui/wiki/Developing-extensions -# Make a repo with your localization and since you are still listed as a collaborator -# you can add it to the wiki page yourself. This change is because some people complained -# the git commit log is cluttered with things unrelated to almost everyone and -# because I believe this is the best overall for the project to handle localizations almost -# entirely without my oversight. - - diff --git a/README.md b/README.md index b67e2296a..5b98cde34 100644 --- a/README.md +++ b/README.md @@ -1,161 +1,165 @@ -# Stable Diffusion web UI -A browser interface based on Gradio library for Stable Diffusion. +[![](https://img.shields.io/static/v1?label=Sponsor&message=%E2%9D%A4&logo=GitHub&color=%23fe8e86)](https://github.com/sponsors/vladmandic) +![Last Commit](https://img.shields.io/github/last-commit/vladmandic/human?style=flat-square&svg=true) +![License](https://img.shields.io/github/license/vladmandic/human?style=flat-square&svg=true) +![GitHub Status Checks](https://img.shields.io/github/checks-status/vladmandic/human/main?style=flat-square&svg=true) -![](screenshot.png) +# Stable Diffusion - Automatic -## Features -[Detailed feature showcase with images](https://github.com/AUTOMATIC1111/stable-diffusion-webui/wiki/Features): -- Original txt2img and img2img modes -- One click install and run script (but you still must install python and git) -- Outpainting -- Inpainting -- Color Sketch -- Prompt Matrix -- Stable Diffusion Upscale -- Attention, specify parts of text that the model should pay more attention to - - a man in a `((tuxedo))` - will pay more attention to tuxedo - - a man in a `(tuxedo:1.21)` - alternative syntax - - select text and press `Ctrl+Up` or `Ctrl+Down` to automatically adjust attention to selected text (code contributed by anonymous user) -- Loopback, run img2img processing multiple times -- X/Y/Z plot, a way to draw a 3 dimensional plot of images with different parameters -- Textual Inversion - - have as many embeddings as you want and use any names you like for them - - use multiple embeddings with different numbers of vectors per token - - works with half precision floating point numbers - - train embeddings on 8GB (also reports of 6GB working) -- Extras tab with: - - GFPGAN, neural network that fixes faces - - CodeFormer, face restoration tool as an alternative to GFPGAN - - RealESRGAN, neural network upscaler - - ESRGAN, neural network upscaler with a lot of third party models - - SwinIR and Swin2SR ([see here](https://github.com/AUTOMATIC1111/stable-diffusion-webui/pull/2092)), neural network upscalers - - LDSR, Latent diffusion super resolution upscaling -- Resizing aspect ratio options -- Sampling method selection - - Adjust sampler eta values (noise multiplier) - - More advanced noise setting options -- Interrupt processing at any time -- 4GB video card support (also reports of 2GB working) -- Correct seeds for batches -- Live prompt token length validation -- Generation parameters - - parameters you used to generate images are saved with that image - - in PNG chunks for PNG, in EXIF for JPEG - - can drag the image to PNG info tab to restore generation parameters and automatically copy them into UI - - can be disabled in settings - - drag and drop an image/text-parameters to promptbox -- Read Generation Parameters Button, loads parameters in promptbox to UI -- Settings page -- Running arbitrary python code from UI (must run with `--allow-code` to enable) -- Mouseover hints for most UI elements -- Possible to change defaults/mix/max/step values for UI elements via text config -- Tiling support, a checkbox to create images that can be tiled like textures -- Progress bar and live image generation preview - - Can use a separate neural network to produce previews with almost none VRAM or compute requirement -- Negative prompt, an extra text field that allows you to list what you don't want to see in generated image -- Styles, a way to save part of prompt and easily apply them via dropdown later -- Variations, a way to generate same image but with tiny differences -- Seed resizing, a way to generate same image but at slightly different resolution -- CLIP interrogator, a button that tries to guess prompt from an image -- Prompt Editing, a way to change prompt mid-generation, say to start making a watermelon and switch to anime girl midway -- Batch Processing, process a group of files using img2img -- Img2img Alternative, reverse Euler method of cross attention control -- Highres Fix, a convenience option to produce high resolution pictures in one click without usual distortions -- Reloading checkpoints on the fly -- Checkpoint Merger, a tab that allows you to merge up to 3 checkpoints into one -- [Custom scripts](https://github.com/AUTOMATIC1111/stable-diffusion-webui/wiki/Custom-Scripts) with many extensions from community -- [Composable-Diffusion](https://energy-based-model.github.io/Compositional-Visual-Generation-with-Composable-Diffusion-Models/), a way to use multiple prompts at once - - separate prompts using uppercase `AND` - - also supports weights for prompts: `a cat :1.2 AND a dog AND a penguin :2.2` -- No token limit for prompts (original stable diffusion lets you use up to 75 tokens) -- DeepDanbooru integration, creates danbooru style tags for anime prompts -- [xformers](https://github.com/AUTOMATIC1111/stable-diffusion-webui/wiki/Xformers), major speed increase for select cards: (add `--xformers` to commandline args) -- via extension: [History tab](https://github.com/yfszzx/stable-diffusion-webui-images-browser): view, direct and delete images conveniently within the UI -- Generate forever option -- Training tab - - hypernetworks and embeddings options - - Preprocessing images: cropping, mirroring, autotagging using BLIP or deepdanbooru (for anime) -- Clip skip -- Hypernetworks -- Loras (same as Hypernetworks but more pretty) -- A sparate UI where you can choose, with preview, which embeddings, hypernetworks or Loras to add to your prompt -- Can select to load a different VAE from settings screen -- Estimated completion time in progress bar -- API -- Support for dedicated [inpainting model](https://github.com/runwayml/stable-diffusion#inpainting-with-stable-diffusion) by RunwayML -- via extension: [Aesthetic Gradients](https://github.com/AUTOMATIC1111/stable-diffusion-webui-aesthetic-gradients), a way to generate images with a specific aesthetic by using clip images embeds (implementation of [https://github.com/vicgalle/stable-diffusion-aesthetic-gradients](https://github.com/vicgalle/stable-diffusion-aesthetic-gradients)) -- [Stable Diffusion 2.0](https://github.com/Stability-AI/stablediffusion) support - see [wiki](https://github.com/AUTOMATIC1111/stable-diffusion-webui/wiki/Features#stable-diffusion-20) for instructions -- [Alt-Diffusion](https://arxiv.org/abs/2211.06679) support - see [wiki](https://github.com/AUTOMATIC1111/stable-diffusion-webui/wiki/Features#alt-diffusion) for instructions -- Now without any bad letters! -- Load checkpoints in safetensors format -- Eased resolution restriction: generated image's domension must be a multiple of 8 rather than 64 -- Now with a license! -- Reorder elements in the UI from settings screen +*Heavily opinionated custom fork of* -## Installation and Running -Make sure the required [dependencies](https://github.com/AUTOMATIC1111/stable-diffusion-webui/wiki/Dependencies) are met and follow the instructions available for both [NVidia](https://github.com/AUTOMATIC1111/stable-diffusion-webui/wiki/Install-and-Run-on-NVidia-GPUs) (recommended) and [AMD](https://github.com/AUTOMATIC1111/stable-diffusion-webui/wiki/Install-and-Run-on-AMD-GPUs) GPUs. +Fork is as close as up-to-date with origin as time allows +All code changes are merged upstream whenever possible -Alternatively, use online services (like Google Colab): +The idea behind the fork is to enable latest technologies and advances in text-to-image generation +*Sometimes this is not the same as "as simple as possible to use"* +If you are looking an amazing simple-to-use Stable Diffusion tool, I'd suggest [InvokeAI](https://invoke-ai.github.io/InvokeAI/) specifically due to its automated installer and ease of use -- [List of Online Services](https://github.com/AUTOMATIC1111/stable-diffusion-webui/wiki/Online-Services) +
-### Automatic Installation on Windows -1. Install [Python 3.10.6](https://www.python.org/downloads/windows/), checking "Add Python to PATH". -2. Install [git](https://git-scm.com/download/win). -3. Download the stable-diffusion-webui repository, for example by running `git clone https://github.com/AUTOMATIC1111/stable-diffusion-webui.git`. -4. Run `webui-user.bat` from Windows Explorer as normal, non-administrator, user. +### Follow [Development updates](https://github.com/vladmandic/automatic/discussions/99) for daily updates on new features/fixes -### Automatic Installation on Linux -1. Install the dependencies: -```bash -# Debian-based: -sudo apt install wget git python3 python3-venv -# Red Hat-based: -sudo dnf install wget git python3 -# Arch-based: -sudo pacman -S wget git python3 -``` -2. To install in `/home/$(whoami)/stable-diffusion-webui/`, run: -```bash -bash <(wget -qO- https://raw.githubusercontent.com/AUTOMATIC1111/stable-diffusion-webui/master/webui.sh) -``` -3. Run `webui.sh`. -### Installation on Apple Silicon +
-Find the instructions [here](https://github.com/AUTOMATIC1111/stable-diffusion-webui/wiki/Installation-on-Apple-Silicon). +![screenshot](javascript/black-orange.jpg) -## Contributing -Here's how to add code to this repo: [Contributing](https://github.com/AUTOMATIC1111/stable-diffusion-webui/wiki/Contributing) +
-## Documentation -The documentation was moved from this README over to the project's [wiki](https://github.com/AUTOMATIC1111/stable-diffusion-webui/wiki). +## Notes -## Credits -Licenses for borrowed code can be found in `Settings -> Licenses` screen, and also in `html/licenses.html` file. +### Fork does differ in few things -- Stable Diffusion - https://github.com/CompVis/stable-diffusion, https://github.com/CompVis/taming-transformers -- k-diffusion - https://github.com/crowsonkb/k-diffusion.git -- GFPGAN - https://github.com/TencentARC/GFPGAN.git -- CodeFormer - https://github.com/sczhou/CodeFormer -- ESRGAN - https://github.com/xinntao/ESRGAN -- SwinIR - https://github.com/JingyunLiang/SwinIR -- Swin2SR - https://github.com/mv-lab/swin2sr -- LDSR - https://github.com/Hafiidz/latent-diffusion -- MiDaS - https://github.com/isl-org/MiDaS -- Ideas for optimizations - https://github.com/basujindal/stable-diffusion -- Cross Attention layer optimization - Doggettx - https://github.com/Doggettx/stable-diffusion, original idea for prompt editing. -- Cross Attention layer optimization - InvokeAI, lstein - https://github.com/invoke-ai/InvokeAI (originally http://github.com/lstein/stable-diffusion) -- Sub-quadratic Cross Attention layer optimization - Alex Birch (https://github.com/Birch-san/diffusers/pull/1), Amin Rezaei (https://github.com/AminRezaei0x443/memory-efficient-attention) -- Textual Inversion - Rinon Gal - https://github.com/rinongal/textual_inversion (we're not using his code, but we are using his ideas). -- Idea for SD upscale - https://github.com/jquesnelle/txt2imghd -- Noise generation for outpainting mk2 - https://github.com/parlance-zz/g-diffuser-bot -- CLIP interrogator idea and borrowing some code - https://github.com/pharmapsychotic/clip-interrogator -- Idea for Composable Diffusion - https://github.com/energy-based-model/Compositional-Visual-Generation-with-Composable-Diffusion-Models-PyTorch -- xformers - https://github.com/facebookresearch/xformers -- DeepDanbooru - interrogator for anime diffusers https://github.com/KichangKim/DeepDanbooru -- Sampling in float32 precision from a float16 UNet - marunine for the idea, Birch-san for the example Diffusers implementation (https://github.com/Birch-san/diffusers-play/tree/92feee6) -- Instruct pix2pix - Tim Brooks (star), Aleksander Holynski (star), Alexei A. Efros (no star) - https://github.com/timothybrooks/instruct-pix2pix -- Security advice - RyotaK -- UniPC sampler - Wenliang Zhao - https://github.com/wl-zhao/UniPC -- Initial Gradio script - posted on 4chan by an Anonymous user. Thank you Anonymous user. -- (You) \ No newline at end of file +- New installer +- Advanced CUDA tuning + Available in UI Settings +- Advanced environment tuning +- Optimized startup and models lazy-loading +- Built-in performance profiler +- Updated libraries to latest known compatible versions +- Includes opinionated **System** and **Options** configuration +- Does not rely on `Accelerate` as it only affects distributed systems + Gradio web server will be initialized much earlier which model load is done in the background + Faster model loading plus ability to fallback on corrupt models +- Uses simplified folder structure + e.g. `/train`, `/outputs/*`, `/models/*`, etc. +- Enhanced training templates +- Built-in `LoRA`, `LyCORIS`, `Custom Diffusion`, `Dreambooth` training +- Majority of settings configurable via UI without the need for command line flags + e.g, cross-optimization methods, system folders, etc. +- New logger +- New error and exception handlers + +### Optimizations + +- Optimized for `Torch` 2.0 +- Runs with `SDP` memory attention enabled by default if supported by system + *Note*: `xFormers` and other cross-optimization methods are still available +- Auto-adjust parameters when running on **CPU** or **CUDA** + *Note:* AMD and M1 platforms are supported, but without out-of-the-box optimizations + +### Integrated Extensions + +Hand-picked list of extensions that are deeply integrated into core workflows: + +- [System Info](https://github.com/vladmandic/sd-extension-system-info) +- [ControlNet](https://github.com/Mikubill/sd-webui-controlnet) +- [Image Browser](https://github.com/AlUlkesh/stable-diffusion-webui-images-browser) +- [LORA](https://github.com/kohya-ss/sd-scripts) *(both training and inference)* +- [LyCORIS](https://github.com/KohakuBlueleaf/LyCORIS) *(both training and inference)* +- [Model Converter](https://github.com/Akegarasu/sd-webui-model-converter) +- [CLiP Interrogator](https://github.com/pharmapsychotic/clip-interrogator-ext) +- [Dynamic Thresholding](https://github.com/mcmonkeyprojects/sd-dynamic-thresholding) +- [Steps Animation](https://github.com/vladmandic/sd-extension-steps-animation) +- [Seed Travel](https://github.com/yownas/seed_travel) +- [Multi-Diffusion Upscaler](https://github.com/pkuliyi2015/multidiffusion-upscaler-for-automatic1111) + +### User Interface + +- Includes updated **UI**: reskinned and reorganized + Black and orange dark theme with fixed width options panels and larger previews +- Includes support for **Gradio themes** + *Settings* -> *User interface* -> *UI theme* + Link to themes list & previews: + +### Removed + +- Drops compatibility with older versions of `python` and requires **3.9** or **3.10** +- Drops localizations + +### Integrated CLI/API tools + +Fork adds extra functionality: + +- New skin and UI layout +- Ships with set of **CLI** tools that rely on *SD API* for execution: + e.g. `generate`, `train`, `bench`, etc. + [Full list]() + +
+ +## Install + +1. Install first: +**Python** & **Git** +2. If you have nVidia GPU, install nVidia CUDA toolkit: + +3. Clone repository +`git clone https://github.com/vladmandic/automatic` + +## Run + +Run desired startup script to install dependencies and extensions and start server: + +- `webui.bat` and `webui.sh`: + Platform specific wrapper scripts For Windows, Linux and OSX + Starts `launch.py` in a Python virtual environment (venv) + *Note*: Server can run without virtual environment, but it is recommended to use it to avoid library version conflicts with other applications + **If you're unsure which launcher to use, this is the one you want** +- `launch.py`: + Main startup script + Can be used directly to start server in a manually activated `venv` or to run server without `venv` +- `setup.py`: + Main installer, used by `launch.py` + Can also be used directly to update repository or extensions + If running manually, make sure to activate `venv` first (if used) +- `webui.py`: + Main server script + +Any of the above scripts can be used with `--help` to display detailed usage information and available parameters +For example: +> webui.bat --help + +Full startup sequence is logged in `setup.log`, so if you encounter any issues, please check it first + +## Update + +The launcher can perform automatic update of main repository, requirements, extensions and submodules: + +- **Main repository**: + Update is *not* performed by default, enable with `--upgrade` flag +- **Requirements**: + Check is performed on each startup and missing requirements are auto-installed + Can be skipped with `--skip-requirements` flag +- **Extensions and submodules**: + Update is performed on each startup and installer for each extension is started + Can be skipped with `--skip-extensions` flag +- **Quick mode**: Automatically enabled if timestamp of last sucessful setup is newer than actual repository version or version of newest extension + +
+ +## Other + +### Scripts + +This repository comes with a large collection of scripts that can be used to process inputs, train, generate, and benchmark models +As well as number of auxiliary scripts that do not rely on **WebUI**, but can be used for end-to-end solutions such as extract frames from videos, etc. +For full details see [Docs](cli/README.md) + +
+ +### Docs + +- Scripts are in [Scripts](cli/README.md) +- Everything else is in [Wiki](https://github.com/vladmandic/automatic/wiki) +- Except my current [TODO](TODO.md) + +
diff --git a/TODO.md b/TODO.md new file mode 100644 index 000000000..6c58525e1 --- /dev/null +++ b/TODO.md @@ -0,0 +1,68 @@ +# TODO + +## Issues + +Stuff to be fixed... + +- ClipSkip not updated on read gen info +- Usage of `sd_vae` in quick settings +- Run VAE with hires at 1280 +- Make TensorFlow optional + + +## Features + +Stuff to be added... + +- Add Gradio theme maker +- Create new GitHub hooks/actions for CI/CD +- Move Restart Server from WebUI to Launch and reload modules +- Redo Extensions tab: see +- Stream-load models as option for slow storage +- Autodetect nVidia and AMD: `nvidia-smi` vs `rocm-smi` + +## Investigate + +Stuff to be investigated... + +- Torch Compile +- `Torch-DirectML` +- `TensorRT` + +## Merge PRs + +Pick & merge PRs from main repo... + +- Merge backlog: + +## Models + +StabilityAI is working on new stuff... + +- SD XL +- SD ReImagined + +## Integration + +Tech that can be integrated as part of the core workflow... + +- [Merge without distortion](https://github.com/ogkalu2/Merge-Stable-Diffusion-models-without-distortion) +- [Weighted merges](https://github.com/bbc-mc/sdweb-merge-block-weighted-gui/tree/master) +- [Null-text inversion](https://github.com/ouhenio/null-text-inversion-colab) +- [Custom diffusion](https://github.com/guaneec/custom-diffusion-webui), [Custom diffusion](https://www.cs.cmu.edu/~custom-diffusion/) +- [Dream artist](https://github.com/7eu7d7/DreamArtist-sd-webui-extension) + +## Random + +- Bunch of stuff: + +### Pending Code Updates + +- fix VAE dtype + should fix most issues with NaN or black images +- add built-in Gradio themes +- fix setup race conditions +- reduce requirements +- more AMD specific work +- initial work on Apple platform support +- additional PR merges diff --git a/automatic.ico b/automatic.ico new file mode 100644 index 000000000..72054a0fb Binary files /dev/null and b/automatic.ico differ diff --git a/automatic.png b/automatic.png new file mode 100644 index 000000000..228af4b0e Binary files /dev/null and b/automatic.png differ diff --git a/automatic.svg b/automatic.svg new file mode 100644 index 000000000..ac6e5431d --- /dev/null +++ b/automatic.svg @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/cli/.pylintrc b/cli/.pylintrc new file mode 100644 index 000000000..1231dff7a --- /dev/null +++ b/cli/.pylintrc @@ -0,0 +1,3 @@ +# See https://pylint.pycqa.org/en/latest/user_guide/messages/message_control.html +[MESSAGES CONTROL] +enable=C,R,W,E,I diff --git a/cli/README.md b/cli/README.md new file mode 100644 index 000000000..1081e3215 --- /dev/null +++ b/cli/README.md @@ -0,0 +1,163 @@ +# Stable-Diffusion Productivity Scripts + +*Notes*: +- Offline scripts can be used with or without **Automatic WebUI** +- Online scripts rely on **Automatic WebUI** API which should be started with `--api` parameter +- All scripts have built-in `--help` parameter that can be used to get more information + +
+ +## Main Scripts + +### Generate + +Text-to-image with all of the possible parameters +Supports upsampling, face restoration and grid creation +> python generate.py + +By default uses parameters from `generate.json` + +Parameters that are not specified will be randomized: +- Prompt will be dynamically created from template of random samples: `random.json` +- Sampler/Scheduler will be randomly picked from available ones +- CFG Scale set to 5-10 + +### Train + +Textual inversion embedding training +> python train-ti.py + +Combined pipeline: +1. Creates embedding +2. Extracts images if input is movie +3. Preprocesses images +4. Runs training + +LoRA training +> python train-lora.py + +Combined pipeline: +1. Preprocesses images +2. Runs training + +[Detailed documentation](https://github.com/vladmandic/automatic/wiki/Process.md) + +LoRA extract from model +> python moidules/lora-extract.py + +
+ +## Auxiliary Scripts + +### Benchmark + +Benchmark your **Automatic WebUI** +Note: Requires SD API + +> python modules/bench.py + +### Embedding Previews + +Create previews of embeddings using preview templates +Note: Requires SD API + +> python modules/preview-embeddings.py + +## Grid + +Create flexible image grids from any number of images +Note: Offline tool + +> python modiles/grid.py + +### Image Watermark + +Create invisible image watermark and remove existing EXIF tags +Note: Offline tool + +> python modules/image-watermark.py + +### Interrogate + +Runs CLiP and Booru image interrogation +Note: Requires SD API + +> python modules/interrogate.py + +### Interrogate-Offline + +Standalone implementation of GiT, CLiP and ViT image interrogation +Note: Offline tool + +> python modules/interrogate-offline.py + +### Models Previews + +Create previews of models using built-in templates +Note: Requires SD API + +> python modules/preview-models.py + +### Palette Extract + +Extract color palette from image(s) +Note: Offline tool + +> python modules/palette-extract.py + +### Image Process + +Run image processing to extract face/body segments and run resolution/blur/dynamic-range checks +Note: Offline except for interrogate to generate caption files which requires SD API + +> python modules/process.py + +[Detailed documentation](https://github.com/vladmandic/automatic/wiki/Process.md) + +### Prompt Ideas + +Generate complex prompt ideas +Note: Offline tool + +> python modules/prompt-ideas.py + +### Prompt Promptist + +Attempts to beautify the provided prompt +Note: Offline tool + +> python modules/promptist.py + +### Training Loss-Chart + +Create loss-chart from training log +Note: Offline tool, may require adjustment to train paths if used with other repos + +> python modules/train-losschart.py + +### Training Loss-Rate + +Create customizable loss rate to be used in training +Note: Offline tool + +> python modules/train-lossrate.py + +### Video Extract + +Extract frames from video files +Note: Offline tool + +> python modules/video-extract.py + +
+ +## Utility Scripts +### SDAPI + +Utility module that handles async communication to Automatic API endpoints +Note: Requires SD API + +Can be used to manually execute specific commands: +> python sdapi.py progress +> python sdapi.py interrupt +> python sdapi.py shutdown diff --git a/cli/generate.json b/cli/generate.json new file mode 100644 index 000000000..0bbcb1439 --- /dev/null +++ b/cli/generate.json @@ -0,0 +1,38 @@ +{ + "paths": + { + "root": "/mnt/c/Users/mandi/OneDrive/Generative/Generate", + "generate": "image", + "upscale": "upscale", + "grid": "grid" + }, + "generate": + { + "restore_faces": true, + "prompt": "dynamic", + "negative_prompt": "foggy, blurry, blurred, duplicate, ugly, mutilated, mutation, mutated, out of frame, bad anatomy, disfigured, deformed, censored, low res, watermark, text, poorly drawn face, signature", + "steps": 30, + "batch_size": 2, + "n_iter": 1, + "seed": -1, + "sampler_name": "DPM2 Karras", + "cfg_scale": 6, + "width": 512, + "height": 512 + }, + "upscale": + { + "upscaler_1": "SwinIR_4x", + "upscaler_2": "None", + "upscale_first": false, + "upscaling_resize": 0, + "gfpgan_visibility": 0, + "codeformer_visibility": 0, + "codeformer_weight": 0.5 + }, + "options": + { + "sd_model_checkpoint": "sd-v15-runwayml", + "sd_vae": "vae-ft-mse-840000-ema-pruned.ckpt" + } +} diff --git a/cli/generate.py b/cli/generate.py new file mode 100755 index 000000000..85860acb3 --- /dev/null +++ b/cli/generate.py @@ -0,0 +1,378 @@ +#!/bin/env python +# pylint: disable=no-member +"""generate batches of images from prompts and upscale them + +params: run with `--help` + +default workflow runs infinite loop and prints stats when interrupted: +1. choose random scheduler lookup all available and pick one +2. generate dynamic prompt based on styles, embeddings, places, artists, suffixes +3. beautify prompt +4. generate 3x3 images +5. create image grid +6. upscale images with face restoration +""" + +import argparse +import asyncio +import base64 +import io +import json +import logging +import math +import os +import pathlib +import secrets +import time +import sys +import importlib + +from random import randrange +from PIL import Image +from PIL.ExifTags import TAGS +from PIL.TiffImagePlugin import ImageFileDirectory_v2 + +sys.path.append(os.path.join(os.path.dirname(__file__), 'modules')) +from modules.sdapi import close, get, interrupt, post, session +from modules.util import Map, log, safestring + + +sd = {} +random = {} +stats = Map({ 'images': 0, 'wall': 0, 'generate': 0, 'upscale': 0 }) +avg = {} + + +def grid(data): + if len(data.image) > 1: + w, h = data.image[0].size + rows = round(math.sqrt(len(data.image))) + cols = math.ceil(len(data.image) / rows) + image = Image.new('RGB', size = (cols * w, rows * h), color = 'black') + for i, img in enumerate(data.image): + image.paste(img, box=(i % cols * w, i // cols * h)) + short = data.info.prompt[:min(len(data.info.prompt), 96)] # limit prompt part of filename to 96 chars + name = '{seed:0>9} {short}'.format(short = short, seed = data.info.all_seeds[0]) # pylint: disable=consider-using-f-string + name = safestring(name) + '.jpg' + f = os.path.join(sd.paths.root, sd.paths.grid, name) + log.info({ 'grid': { 'name': f, 'size': image.size, 'images': len(data.image) } }) + image.save(f, 'JPEG', exif = exif(data.info, None, 'grid'), optimize = True, quality = 70) + return image + + +def exif(info, i = None, op = 'generate'): + seed = [info.all_seeds[i]] if len(info.all_seeds) > 0 and i is not None else info.all_seeds # always returns list + seed = ', '.join([str(x) for x in seed]) # int list to str list to single str + template = '{prompt} | negative {negative_prompt} | seed {s} | steps {steps} | cfgscale {cfg_scale} | sampler {sampler_name} | batch {batch_size} | timestamp {job_timestamp} | model {model} | vae {vae}'.format(s = seed, model = sd.options['sd_model_checkpoint'], vae = sd.options['sd_vae'], **info) # pylint: disable=consider-using-f-string + if op == 'upscale': + template += ' | faces gfpgan' if sd.upscale.gfpgan_visibility > 0 else '' + template += ' | faces codeformer' if sd.upscale.codeformer_visibility > 0 else '' + template += ' | upscale {resize}x {upscaler}'.format(resize = sd.upscale.upscaling_resize, upscaler = sd.upscale.upscaler_1) if sd.upscale.upscaler_1 != 'None' else '' # pylint: disable=consider-using-f-string + template += ' | upscale {resize}x {upscaler}'.format(resize = sd.upscale.upscaling_resize, upscaler = sd.upscale.upscaler_2) if sd.upscale.upscaler_2 != 'None' else '' # pylint: disable=consider-using-f-string + if op == 'grid': + template += ' | grid {num}'.format(num = sd.generate.batch_size * sd.generate.n_iter) # pylint: disable=consider-using-f-string + ifd = ImageFileDirectory_v2() + exif_stream = io.BytesIO() + _TAGS = dict(((v, k) for k, v in TAGS.items())) # enumerate possible exif tags + ifd[_TAGS['ImageDescription']] = template + ifd.save(exif_stream) + val = b'Exif\x00\x00' + exif_stream.getvalue() + return val + + +def randomize(lst): + if len(lst) > 0: + return secrets.choice(lst) + else: + return '' + + +def prompt(params): # generate dynamic prompt or use one if provided + sd.generate.prompt = params.prompt if params.prompt != 'dynamic' else randomize(random.prompts) + sd.generate.negative_prompt = params.negative if params.negative != 'dynamic' else randomize(random.negative) + embedding = params.embedding if params.embedding != 'random' else randomize(random.embeddings) + sd.generate.prompt = sd.generate.prompt.replace('', embedding) + artist = params.artist if params.artist != 'random' else randomize(random.artists) + sd.generate.prompt = sd.generate.prompt.replace('', artist) + style = params.style if params.style != 'random' else randomize(random.styles) + sd.generate.prompt = sd.generate.prompt.replace('