From f64864969b1d8efa0b747f23e7fbf381e47ec309 Mon Sep 17 00:00:00 2001 From: vladmandic Date: Wed, 18 Oct 2023 13:17:38 +0000 Subject: [PATCH 01/15] =?UTF-8?q?Deploying=20to=20master=20from=20@=20vlad?= =?UTF-8?q?mandic/automatic@379fe1f305853058d0157c45463f5f60d30ac410=20?= =?UTF-8?q?=F0=9F=9A=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index bb3b34e94..13e53421a 100644 --- a/README.md +++ b/README.md @@ -175,7 +175,7 @@ General goals: ### **Sponsors**
-Allan GrantMichael HarrisBrent OzarToniXMatthew RunoHELLO WORLD SASSalad TechnologiesGym Dreams • GymDreams8 +Allan GrantMichael HarrisBrent OzarToniXMatthew RunoHELLO WORLD SASSalad TechnologiesGym Dreams • GymDreams8

From 231ca1ac7e7ceb1655b4a0c0251198556fb1351c Mon Sep 17 00:00:00 2001 From: Vladimir Mandic Date: Wed, 18 Oct 2023 11:37:30 -0400 Subject: [PATCH 02/15] fixes for zero-day issues --- CHANGELOG.md | 22 +++++ extensions-builtin/Lora/networks.py | 9 +- html/locale_en.json | 2 +- installer.py | 2 +- javascript/base.css | 125 +++++++++++++++++++++++++++ javascript/{style.css => sdnext.css} | 2 +- modules/cmd_args.py | 2 +- modules/sd_hijack_freeu.py | 32 +++---- modules/sd_models.py | 30 +++---- modules/shared.py | 90 +------------------ modules/styles.py | 2 +- modules/theme.py | 88 +++++++++++++++++++ modules/ui.py | 15 ++-- requirements.txt | 4 +- scripts/xyz_grid.py | 43 +++++---- webui.py | 2 +- wiki | 2 +- 17 files changed, 319 insertions(+), 153 deletions(-) create mode 100644 javascript/base.css rename javascript/{style.css => sdnext.css} (98%) create mode 100644 modules/theme.py diff --git a/CHANGELOG.md b/CHANGELOG.md index 8e5765563..74d998f15 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,27 @@ # Change Log for SD.Next +## Update for 2023-10-18 + +Service release addressing all zero-day issues reported so far... + +**Fixes** +- complete lyco removal +- fix freeu for backend original and add it to xyz grid +- fix loading diffuser models in huggingface format from non-standard location +- fix default styles looking in wrong location +- update `typing-extensions` + +**Themes** +- all built-in themes are fully supported: + - *black-teal (default), light-teal, black-orange, invoked, amethyst-nightfall, midnight-barbie* +- if you're using any **gradio default** themes or a **3rd party** theme or that are not optimized for SD.Next, you may experience issues + default minimal style has been updated for compatibility, but actual styling is completely outside of SD.Next control + +**Cannot reproduce** +- diffusers: img2img: batch count 2 => black images for higher batches +- diffusers deis sampler reporting sde-dpmsolver++ is not implemented + + ## Update for 2023-10-17 This is a major release, with many changes and new functionality... diff --git a/extensions-builtin/Lora/networks.py b/extensions-builtin/Lora/networks.py index 4edcf986b..2132c8ed5 100644 --- a/extensions-builtin/Lora/networks.py +++ b/extensions-builtin/Lora/networks.py @@ -374,8 +374,13 @@ def list_available_networks(): available_network_hash_lookup.clear() forbidden_network_aliases.update({"none": 1, "Addams": 1}) os.makedirs(shared.cmd_opts.lora_dir, exist_ok=True) - candidates = list(shared.walk_files(shared.cmd_opts.lora_dir, allowed_extensions=[".pt", ".ckpt", ".safetensors"])) - candidates += list(shared.walk_files(shared.cmd_opts.lyco_dir, allowed_extensions=[".pt", ".ckpt", ".safetensors"])) + candidates = [] + if os.path.exists(shared.cmd_opts.lora_dir): + candidates += list(shared.walk_files(shared.cmd_opts.lora_dir, allowed_extensions=[".pt", ".ckpt", ".safetensors"])) + else: + shared.log.warning('LoRA directory not found: path={shared.cmd_opts.lora_dir}') + if os.path.exists(shared.cmd_opts.lyco_dir): + candidates += list(shared.walk_files(shared.cmd_opts.lyco_dir, allowed_extensions=[".pt", ".ckpt", ".safetensors"])) for filename in candidates: if os.path.isdir(filename): continue diff --git a/html/locale_en.json b/html/locale_en.json index 92b41bf39..e1a6cc93c 100644 --- a/html/locale_en.json +++ b/html/locale_en.json @@ -59,7 +59,7 @@ {"id":"","label":"Skip","localized":"","hint":"Stop processing current job and continue processing"}, {"id":"","label":"Interrupt","localized":"","hint":"Interrupt current processing job"}, {"id":"","label":"Pause","localized":"","hint":"Pause processing"}, - {"id":"","label":"Apply","localized":"","hint":"Apply parameters from last known generated image"}, + {"id":"","label":"Restore","localized":"","hint":"Restore parameters from last known generated image"}, {"id":"","label":"Clear","localized":"","hint":"Clear prompts"}, {"id":"","label":"Networks","localized":"","hint":"Open extra network interface"}, {"id":"","label":"Interrogate\nCLIP","localized":"","hint":"Run interrogate using CLIP model"}, diff --git a/installer.py b/installer.py index 36121cdba..83221fc7a 100644 --- a/installer.py +++ b/installer.py @@ -447,7 +447,7 @@ def check_torch(): log.info('Using CPU-only Torch') torch_command = os.environ.get('TORCH_COMMAND', 'torch torchvision') if 'torch' in torch_command and not args.version: - log.info('Installing torch - this may take a while') + # log.info('Installing torch - this may take a while') install(torch_command, 'torch torchvision') else: try: diff --git a/javascript/base.css b/javascript/base.css new file mode 100644 index 000000000..86ef0f2a7 --- /dev/null +++ b/javascript/base.css @@ -0,0 +1,125 @@ +/* toolbutton */ +.gradio-button.tool { max-width: min-content; min-width: min-content !important; align-self: end; font-size: 1.4em; color: var(--body-text-color) !important; margin-bottom: var(--spacing-md); } + +/* token counters */ +.block.token-counter{ position: absolute; display: inline-block; right: 0; min-width: 0 !important; width: auto; z-index: 100; top: 0; } +.block.token-counter span{ background: var(--input-background-fill) !important; box-shadow: 0 0 0.0 0.3em rgba(192,192,192,0.15), inset 0 0 0.6em rgba(192,192,192,0.075); border: 2px solid rgba(192,192,192,0.4) !important; } +.block.token-counter.error span{ box-shadow: 0 0 0.0 0.3em rgba(255,0,0,0.15), inset 0 0 0.6em rgba(255,0,0,0.075); border: 2px solid rgba(255,0,0,0.4) !important; } +.block.token-counter div{ display: inline; } +.block.token-counter span{ padding: 0.1em 0.75em; } + +/* live preview */ +.progressDiv{ position: relative; height: 20px; background: #b4c0cc; margin-bottom: -3px; } +.dark .progressDiv{ background: #424c5b; } +.progressDiv .progress{ width: 0%; height: 20px; background: #0060df; color: white; font-weight: bold; line-height: 20px; padding: 0 8px 0 0; text-align: right; overflow: visible; white-space: nowrap; padding: 0 0.5em; } +.livePreview { position: absolute; z-index: 50; background-color: transparent; width: -moz-available; width: -webkit-fill-available; } +.livePreview img { position: absolute; object-fit: contain; width: 100%; height: 100%; } +.dark .livePreview { background-color: rgb(17 24 39 / var(--tw-bg-opacity)); } +.popup-metadata { color: white; background: #0000; display: inline-block; white-space: pre-wrap; font-size: 0.75em; } +.global-popup{ display: flex; position: fixed; z-index: 10001; left: 0; top: 0; width: 100%; height: 100%; overflow: auto; background-color: rgba(20, 20, 20, 0.95);} +.global-popup-close:before { content: "×"; } +.global-popup-close{ position: fixed; right: 0.5em; top: 0; cursor: pointer; color: white; font-size: 32pt; } +.global-popup-inner{ display: inline-block; margin: auto; padding: 2em; } + +/* fullpage image viewer */ +#lightboxModal{ display: none; position: fixed; z-index: 1001; left: 0; top: 0; width: 100%; height: 100%; overflow: auto; background-color: rgba(20, 20, 20, 0.75); backdrop-filter: blur(6px); + user-select: none; -webkit-user-select: none; flex-direction: row; } +.modalControls { display: flex; justify-content: space-evenly; background-color: transparent; position: absolute; width: 99%; z-index: 1; } +.modalControls:hover { background-color: #50505050; } +.modalControls span { color: white; font-size: 2em; font-weight: bold; cursor: pointer; filter: grayscale(100%); } +.modalControls span:hover, .modalControls span:focus { color: var(--highlight-color); filter: none; } +.lightboxModalPreviewZone { display: flex; width: 100%; height: 100%; } +.lightboxModalPreviewZone:focus-visible { outline: none; } +.lightboxModalPreviewZone > img { display: block; margin: auto; width: auto; } +.lightboxModalPreviewZone > img.modalImageFullscreen{ object-fit: contain; height: 100%; width: 100%; min-height: 0; background: transparent; } +table.settings-value-table { background: white; border-collapse: collapse; margin: 1em; border: var(--spacing-sm) solid white; } +table.settings-value-table td { padding: 0.4em; border: 1px solid #ccc; max-width: 36em; } +.modalPrev, .modalNext { cursor: pointer; position: relative; z-index: 1; top: 0; width: auto; height: 100vh; line-height: 100vh; text-align: center; padding: 16px; + margin-top: -50px; color: white; font-weight: bold; font-size: 20px; transition: 0.6s ease; user-select: none; -webkit-user-select: none; } +.modalNext { right: 0; } +.modalPrev:hover, .modalNext:hover { background-color: rgba(0, 0, 0, 0.8); } +#imageARPreview { position: absolute; top: 0px; left: 0px; border: 2px solid red; background: rgba(255, 0, 0, 0.3); z-index: 900; pointer-events: none; display: none; } + +/* context menu (ie for the generate button) */ +#context-menu { z-index: 9999; position: absolute; display: block; padding: var(--spacing-md); border: 2px solid var(--highlight-color); background: var(--background-fill-primary); color: var(--body-text-color); } +.context-menu-items { list-style: none; margin: 0; padding: 0; } +.context-menu-items a { display: block; padding: var(--spacing-md); cursor: pointer; font-weight: normal; } +.context-menu-items a:hover { background: var(--highlight-color) } + +/* log monitor */ +.log-monitor { display: none; justify-content: unset !important; overflow: hidden; padding: 0; margin-top: auto; font-family: monospace; font-size: 0.85em; } +.log-monitor td, .log-monitor th { padding-left: 1em; } + +/* changelog */ +.md h2 { background-color: var(--background-fill-primary); padding: 0.5em; } +.md ul { list-style-type: square !important; text-indent: 1em; margin-left: 4em; } +.md li { list-style-position: outside !important; text-indent: 0; } +.md p { margin-left: 2em; } + +/* extensions */ +#tab_extensions table, #tab_config table{ border-collapse: collapse; } +#tab_extensions table td, #tab_extensions table th, #tab_config table td, #tab_config table th { border: 1px solid #ccc; padding: 0.25em 0.5em; } +#tab_extensions table input[type="checkbox"] { margin-right: 0.5em; appearance: checkbox; } +#tab_extensions button{ max-width: 16em; } +#tab_extensions input[disabled="disabled"]{ opacity: 0.5; } +.extension-tag{ font-weight: bold; font-size: 95%; } +.extension-button { font-size: 95% !important; width: 6em; } +#extensions .name{ font-size: 1.1rem } +#extensions .type{ opacity: 0.5; font-size: 90%; text-align: center; } +#extensions .version{ opacity: 0.7; } +#extensions .info{ margin: 0; } +#extensions .date{ opacity: 0.85; font-size: 90%; } + +/* extra networks */ +.extra-networks > div { margin: 0; gap: 0.2em; border-bottom: none !important; } +.extra-networks .second-line { display: flex; width: -moz-available; width: -webkit-fill-available; gap: 0.3em; box-shadow: var(--input-shadow); } +.extra-networks .search { flex: 1; } +.extra-networks .description { flex: 3; } +.extra-networks .tab-nav > button { margin-right: 0; height: 24px; padding: 2px 4px 2px 4px; } +.extra-networks .buttons { position: absolute; right: 0; margin: -4px; background: var(--background-color); } +.extra-networks .buttons>button { height: 1.2em; margin-top: var(--spacing-md); } +.extra-networks .custom-button { width: 120px; width: 100%; background: none; justify-content: left; text-align: left; padding: 2px 8px 2px 16px; text-indent: -8px; box-shadow: none; line-break: auto; } +.extra-networks .custom-button:hover { background: var(--button-primary-background-fill) } +.extra-networks-tab { padding: 0 !important; } +.extra-network-subdirs { background: var(--input-background-fill); overflow-x: hidden; overflow-y: auto; min-width: max(15%, 120px); padding-top: 0.5em; margin-top: -4px !important; } +.extra-networks-page { display: flex } +.extra-network-cards { display: flex; flex-wrap: wrap; overflow-y: auto; overflow-x: hidden; align-content: flex-start; width: -moz-available; width: -webkit-fill-available; } +.extra-network-cards .card { height: fit-content; margin: 0 0 0.5em 0.5em; position: relative; scroll-snap-align: start; scroll-margin-top: 0; } +.extra-network-cards .card .overlay { position: absolute; bottom: 0; padding: 0.2em; z-index: 10; width: 100%; background: none; } +.extra-network-cards .card .overlay .name { font-size: 1.1em; font-weight: bold; text-shadow: 1px 1px black; color: white; overflow-wrap: break-word; } +.extra-network-cards .card .preview { box-shadow: var(--button-shadow); min-height: 30px; } +.extra-network-cards .card:hover .overlay { background: rgba(0, 0, 0, 0.40); } +.extra-network-cards .card:hover .preview { box-shadow: none; filter: grayscale(100%); } +.extra-network-cards .card:hover .overlay { background: rgba(0, 0, 0, 0.40); } +.extra-network-cards .card .overlay .tags { margin: 4px; display: none; overflow-wrap: break-word; } +.extra-network-cards .card .overlay .tag { padding: 2px; margin: 2px; background: var(--neutral-700); cursor: pointer; display: inline-block; } +.extra-network-cards .card .actions > span { padding: 4px; } +.extra-network-cards .card:hover .actions { display: block; } +.extra-network-cards .card:hover .overlay .tags { display: block; } +.extra-network-cards .card .actions { font-size: 3em; display: none; text-align-last: right; cursor: pointer; font-variant: unicase; position: absolute; z-index: 100; right: 0; height: 0.7em; width: 100%; background: rgba(0, 0, 0, 0.40); } +#txt2img_description, #img2img_description { max-height: 63px; overflow-y: auto !important; } +#txt2img_description > label > textarea, #img2img_description > label > textarea { font-size: 0.9em } + +#txt2img_extra_details > div, #img2img_extra_details > div { overflow-y: auto; min-height: 40vh; max-height: 80vh; align-self: flex-start; } +#txt2img_extra_details, #img2img_extra_details { position: fixed; bottom: 50%; left: 50%; transform: translate(-50%, 50%); padding: 0.8em; border: var(--block-border-width) solid var(--highlight-color) !important; + z-index: 100; box-shadow: var(--button-shadow); } +#txt2img_extra_details td:first-child, #img2img_extra_details td:first-child { font-weight: bold; vertical-align: top; } +#txt2img_extra_details .gradio-image, #img2img_extra_details .gradio-image { max-height: 70vh; } + +/* custom component */ +.folder-selector textarea { height: 2em !important; padding: 6px !important; } +.nvml { position: fixed; bottom: 10px; right: 10px; background: var(--background-fill-primary); border: 1px solid var(--button-primary-border-color); padding: 6px; color: var(--button-primary-text-color); + font-size: 0.7em; z-index: 50; font-family: monospace; display: none; } + +/* loader */ +.splash { position: fixed; top: 0; left: 0; width: 100vw; height: 100vh; z-index: 1000; display: block; text-align: center; } +.motd { margin-top: 2em; color: var(--body-text-color-subdued); font-family: monospace; font-variant: all-petite-caps; } +.splash-img { margin: 10% auto 0 auto; width: 512px; background-repeat: no-repeat; height: 512px; animation: color 10s infinite alternate; } +.loading { color: white; position: absolute; top: 20%; left: 50%; transform: translateX(-50%); } +.loader { width: 300px; height: 300px; border: var(--spacing-md) solid transparent; border-radius: 50%; border-top: var(--spacing-md) solid var(--primary-600); animation: spin 4s linear infinite; position: relative; } +.loader::before, .loader::after { content: ""; position: absolute; top: 6px; bottom: 6px; left: 6px; right: 6px; border-radius: 50%; border: var(--spacing-md) solid transparent; } +.loader::before { border-top-color: var(--primary-900); animation: 3s spin linear infinite; } +.loader::after { border-top-color: var(--primary-300); animation: spin 1.5s linear infinite; } +@keyframes move { from { background-position-x: 0, -40px; } to { background-position-x: 0, 40px; } } +@keyframes spin { from { transform: rotate(0deg); } to { transform: rotate(360deg); } } +@keyframes color { from { filter: hue-rotate(0deg) } to { filter: hue-rotate(360deg) } } diff --git a/javascript/style.css b/javascript/sdnext.css similarity index 98% rename from javascript/style.css rename to javascript/sdnext.css index 217796950..fb6a198f3 100644 --- a/javascript/style.css +++ b/javascript/sdnext.css @@ -1,4 +1,4 @@ -:root { --checkbox-label-gap: 0.25em 0.1em; --section-header-text-size: 12pt; --block-background-fill: transparent;} +:root { --left-column: 490px; } a { font-weight: bold; cursor: pointer; } h2 { margin-top: 1em !important; font-size: 1.4em !important; } footer { display: none; } diff --git a/modules/cmd_args.py b/modules/cmd_args.py index 6459204d1..5570bd02a 100644 --- a/modules/cmd_args.py +++ b/modules/cmd_args.py @@ -94,7 +94,7 @@ def compatibility_args(opts, args): group.add_argument("--lyco-dir", help=argparse.SUPPRESS, default=opts.lyco_dir) group.add_argument("--embeddings-dir", help=argparse.SUPPRESS, default=opts.embeddings_dir) group.add_argument("--hypernetwork-dir", help=argparse.SUPPRESS, default=opts.hypernetwork_dir) - group.add_argument("--lyco-patch-lora", help=argparse.SUPPRESS, default=opts.lyco_patch_lora) + group.add_argument("--lyco-patch-lora", help=argparse.SUPPRESS, default=False) group.add_argument("--lyco-debug", help=argparse.SUPPRESS, action='store_true', default=False) group.add_argument("--enable-console-prompts", help=argparse.SUPPRESS, action='store_true', default=False) group.add_argument("--safe", help=argparse.SUPPRESS, action='store_true', default=False) diff --git a/modules/sd_hijack_freeu.py b/modules/sd_hijack_freeu.py index 4d21601d4..ef893d2f3 100644 --- a/modules/sd_hijack_freeu.py +++ b/modules/sd_hijack_freeu.py @@ -1,7 +1,7 @@ import math import functools import torch -from modules.shared import state, log, opts +from modules import shared from modules.sd_hijack_unet import th # based on @@ -23,7 +23,7 @@ cat_original = None def to_denoising_step(number, steps=None) -> int: if steps is None: - steps = state.sampling_steps + steps = shared.state.sampling_steps if isinstance(number, float): return int(number * steps) return number @@ -34,11 +34,11 @@ def get_schedule_ratio(): stop_step = to_denoising_step(stop_ratio) if start_step == stop_step: smooth_schedule_ratio = 0.0 - elif state.sampling_step < start_step: - smooth_schedule_ratio = min(1.0, max(0.0, state.sampling_step / start_step)) + elif shared.state.sampling_step < start_step: + smooth_schedule_ratio = min(1.0, max(0.0, shared.state.sampling_step / start_step)) else: - smooth_schedule_ratio = min(1.0, max(0.0, 1 + (state.sampling_step - start_step) / (start_step - stop_step))) - flat_schedule_ratio = 1.0 if start_step <= state.sampling_step < stop_step else 0.0 + smooth_schedule_ratio = min(1.0, max(0.0, 1 + (shared.state.sampling_step - start_step) / (start_step - stop_step))) + flat_schedule_ratio = 1.0 if start_step <= shared.state.sampling_step < stop_step else 0.0 return lerp(flat_schedule_ratio, smooth_schedule_ratio, transition_smoothness) @@ -47,7 +47,7 @@ def lerp(a, b, r): def free_u_cat_hijack(hs, *args, original_function, **kwargs): - if not opts.freeu_enabled: + if not shared.opts.freeu_enabled: return original_function(hs, *args, **kwargs) schedule_ratio = get_schedule_ratio() if schedule_ratio == 0: @@ -67,8 +67,8 @@ def free_u_cat_hijack(hs, *args, original_function, **kwargs): mask = (region_begin <= mask) & (mask <= region_end) if region_inverted: mask = ~mask - backbone_factor = opts.freeu_b1 if index == 0 else opts.freeu_b2 - skip_factor = opts.freeu_s1 if index == 0 else opts.freeu_s2 + backbone_factor = shared.opts.freeu_b1 if index == 0 else shared.opts.freeu_b2 + skip_factor = shared.opts.freeu_s1 if index == 0 else shared.opts.freeu_s2 h[:, mask] *= lerp(1, backbone_factor, schedule_ratio) h_skip = filter_skip(h_skip, threshold=skip_cutoff, scale=lerp(1, skip_factor, schedule_ratio), scale_high=lerp(1, skip_high_end_factor, schedule_ratio)) return original_function([h, h_skip], *args, **kwargs) @@ -130,8 +130,8 @@ def apply_freeu(p, backend_original): global state_enabled # pylint: disable=global-statement global cat_original # pylint: disable=global-statement if backend_original: - if opts.freeu_enabled: - p.extra_generation_params['FreeU'] = f'b1={opts.freeu_b1} b2={opts.freeu_b2} s1={opts.freeu_s1} s2={opts.freeu_s2}' + if shared.opts.freeu_enabled: + p.extra_generation_params['FreeU'] = f'b1={shared.opts.freeu_b1} b2={shared.opts.freeu_b2} s1={shared.opts.freeu_s1} s2={shared.opts.freeu_s2}' if not state_enabled: # otherwise already patched cat_original = th.cat th.cat = functools.partial(free_u_cat_hijack, original_function=th.cat) @@ -141,12 +141,12 @@ def apply_freeu(p, backend_original): th.cat = cat_original state_enabled = False elif hasattr(p.sd_model, 'enable_freeu'): - if opts.freeu_enabled: - p.extra_generation_params['FreeU'] = f'b1={opts.freeu_b1} b2={opts.freeu_b2} s1={opts.freeu_s1} s2={opts.freeu_s2}' - p.sd_model.enable_freeu(s1=opts.freeu_s1, s2=opts.freeu_s2, b1=opts.freeu_b1, b2=opts.freeu_b2) + if shared.opts.freeu_enabled: + p.extra_generation_params['FreeU'] = f'b1={shared.opts.freeu_b1} b2={shared.opts.freeu_b2} s1={shared.opts.freeu_s1} s2={shared.opts.freeu_s2}' + p.sd_model.enable_freeu(s1=shared.opts.freeu_s1, s2=shared.opts.freeu_s2, b1=shared.opts.freeu_b1, b2=shared.opts.freeu_b2) state_enabled = True elif state_enabled: p.sd_model.disable_freeu() state_enabled = False - if opts.freeu_enabled: - log.info(f'Applying free-u: b1={opts.freeu_b1} b2={opts.freeu_b2} s1={opts.freeu_s1} s2={opts.freeu_s2}') + if shared.opts.freeu_enabled: + shared.log.info(f'Applying free-u: b1={shared.opts.freeu_b1} b2={shared.opts.freeu_b2} s1={shared.opts.freeu_s1} s2={shared.opts.freeu_s2}') diff --git a/modules/sd_models.py b/modules/sd_models.py index 6aad35ea0..3b94ed70c 100644 --- a/modules/sd_models.py +++ b/modules/sd_models.py @@ -50,21 +50,24 @@ class CheckpointInfo: self.hash = None self.filename = filename self.type = '' - filename = os.path.abspath(filename) relname = filename - if relname.startswith(script_path): + + def rel(fn, path): try: - relname = os.path.relpath(filename, script_path) + return os.path.relpath(fn, path) except: - pass - try: - relname = os.path.relpath(filename, model_path) - except: - pass - try: - relname = os.path.relpath(filename, shared.cmd_opts.ckpt_dir) - except: - pass + return fn + + if relname.startswith(shared.opts.ckpt_dir): + relname = rel(filename, shared.opts.ckpt_dir) + elif relname.startswith(shared.opts.diffusers_dir): + relname = rel(filename, shared.opts.diffusers_dir) + elif relname.startswith(model_path): + relname = rel(filename, model_path) + elif relname.startswith(script_path): + relname = rel(filename, script_path) + else: + relname = os.path.abspath(relname) relname, ext = os.path.splitext(relname) ext = ext.lower()[1:] @@ -87,9 +90,6 @@ class CheckpointInfo: self.sha256 = repo[0]['hash'] self.type = 'diffusers' - # info = shared.readfile(self.filename, silent=True) - # if 'tags' in info: - # self.tags = info['tags'] self.shorthash = self.sha256[0:10] if self.sha256 else None self.title = self.name if self.shorthash is None else f'{self.name} [{self.shorthash}]' self.path = self.filename diff --git a/modules/shared.py b/modules/shared.py index 0b2d3f41c..fff70fa2b 100644 --- a/modules/shared.py +++ b/modules/shared.py @@ -4,7 +4,6 @@ import sys import time import json import contextlib -import urllib.request from types import SimpleNamespace from urllib.parse import urlparse from enum import Enum @@ -12,7 +11,7 @@ import requests import gradio as gr import fasteners from rich.console import Console -from modules import errors, shared_items, shared_state, cmd_args, ui_components +from modules import errors, shared_items, shared_state, cmd_args, ui_components, theme from modules.paths_internal import models_path, script_path, data_path, sd_configs_path, sd_default_config, sd_model_file, default_sd_model_file, extensions_dir, extensions_builtin_dir # pylint: disable=W0611 from modules.dml import memory_providers, default_memory_provider, directml_do_hijack import modules.interrogate @@ -42,7 +41,6 @@ extra_networks = [] options_templates = {} hypernetworks = {} loaded_hypernetworks = [] -gradio_theme = gr.themes.Base() settings_components = None latent_upscale_default_mode = "None" latent_upscale_modes = { @@ -171,50 +169,10 @@ def temp_disable_extensions(): if ext not in opts.disabled_extensions: disabled.append(ext) log.info(f'Diffusers disabling uncompatible extensions: {disabled}') - if opts.lyco_patch_lora and backend != Backend.DIFFUSERS: - cmd_opts.lyco_dir = opts.lora_dir - if 'Lora' not in opts.disabled_extensions: - disabled.append('Lora') cmd_opts.controlnet_loglevel = 'WARNING' return disabled -def list_builtin_themes(): - files = [os.path.splitext(f)[0] for f in os.listdir('javascript') if f.endswith('.css')] - return files - - -def list_themes(): - fn = os.path.join('html', 'themes.json') - if not os.path.exists(fn): - refresh_themes() - if os.path.exists(fn): - with open(fn, mode='r', encoding='utf=8') as f: - res = json.loads(f.read()) - else: - res = [] - builtin = list_builtin_themes() - default = ["gradio/default", "gradio/base", "gradio/glass", "gradio/monochrome", "gradio/soft"] - external = {x['id'] for x in res if x['status'] == 'RUNNING' and 'test' not in x['id'].lower()} - log.debug(f'Themes: builtin={len(builtin)} default={len(default)} external={len(external)}') - themes = sorted(builtin) + sorted(default) + sorted(external, key=str.casefold) - return themes - - -def refresh_themes(): - try: - r = req('https://huggingface.co/datasets/freddyaboulton/gradio-theme-subdomains/resolve/main/subdomains.json') - if r.status_code == 200: - res = r.json() - fn = os.path.join('html', 'themes.json') - writefile(res, fn) - list_themes() - else: - log.error('Error refreshing UI themes') - except Exception: - log.error('Exception refreshing UI themes') - - def readfile(filename, silent=False): data = {} try: @@ -388,9 +346,9 @@ options_templates.update(options_section(('system-paths', "System Paths"), { "ckpt_dir": OptionInfo(os.path.join(paths.models_path, 'Stable-diffusion'), "Folder with stable diffusion models", folder=True), "diffusers_dir": OptionInfo(os.path.join(paths.models_path, 'Diffusers'), "Folder with Hugggingface models", folder=True), "vae_dir": OptionInfo(os.path.join(paths.models_path, 'VAE'), "Folder with VAE files", folder=True), - # "sd_lora": OptionInfo("", "Add LoRA to prompt", gr.Textbox, {"visible": False}), + "sd_lora": OptionInfo("", "Add LoRA to prompt", gr.Textbox, {"visible": False}), "lora_dir": OptionInfo(os.path.join(paths.models_path, 'Lora'), "Folder with LoRA network(s)", folder=True), - "lyco_dir": OptionInfo(os.path.join(paths.models_path, 'LyCORIS'), "Folder with LyCORIS network(s)", folder=True), + "lyco_dir": OptionInfo(os.path.join(paths.models_path, 'LyCORIS'), "Folder with LyCORIS network(s)", gr.Text, {"visible": False}), "styles_dir": OptionInfo(os.path.join(paths.data_path, 'styles.csv'), "File or Folder with user-defined styles", folder=True), "embeddings_dir": OptionInfo(os.path.join(paths.models_path, 'embeddings'), "Folder with textual inversion embeddings", folder=True), "hypernetwork_dir": OptionInfo(os.path.join(paths.models_path, 'hypernetworks'), "Folder with Hypernetwork models", folder=True), @@ -464,7 +422,7 @@ options_templates.update(options_section(('saving-paths', "Image Naming & Paths" options_templates.update(options_section(('ui', "User Interface"), { "motd": OptionInfo(True, "Show MOTD"), - "gradio_theme": OptionInfo("black-teal", "UI theme", gr.Dropdown, lambda: {"choices": list_themes()}, refresh=refresh_themes), + "gradio_theme": OptionInfo("black-teal", "UI theme", gr.Dropdown, lambda: {"choices": theme.list_themes()}, refresh=theme.refresh_themes), "theme_style": OptionInfo("Auto", "Theme mode", gr.Radio, {"choices": ["Auto", "Dark", "Light"]}), "tooltips": OptionInfo("UI Tooltips", "UI tooltips", gr.Radio, {"choices": ["None", "Browser default", "UI tooltips"], "visible": False}), "compact_view": OptionInfo(False, "Compact view"), @@ -611,7 +569,6 @@ options_templates.update(options_section(('extra_networks', "Extra Networks"), { "lora_preferred_name": OptionInfo("filename", "LoRA preffered name", gr.Radio, {"choices": ["filename", "alias"]}), "lora_add_hashes_to_infotext": OptionInfo(True, "LoRA add hash info"), "lora_in_memory_limit": OptionInfo(0, "LoRA memory cache", gr.Slider, {"minimum": 0, "maximum": 10, "step": 1}), - "lyco_patch_lora": OptionInfo(False, "Use LyCoris handler for all LoRA types", gr.Checkbox, { "visible": False }), "lora_functional": OptionInfo(False, "Use Kohya method for handling multiple LoRA", gr.Checkbox, { "visible": False }), "sd_hypernetwork": OptionInfo("None", "Add hypernetwork to prompt", gr.Dropdown, { "choices": ["None"], "visible": False }), @@ -809,45 +766,6 @@ if devices.backend == "directml": directml_do_hijack() -def reload_gradio_theme(theme_name=None): - global gradio_theme # pylint: disable=global-statement - if not theme_name: - theme_name = opts.gradio_theme - default_font_params = {} - res = 0 - try: - request = urllib.request.Request("https://fonts.googleapis.com/css2?family=IBM+Plex+Mono", method="HEAD") - res = urllib.request.urlopen(request, timeout=3.0).status # pylint: disable=consider-using-with - except Exception: - res = 0 - if res != 200: - log.info('No internet access detected, using default fonts') - default_font_params = { - 'font':['Helvetica', 'ui-sans-serif', 'system-ui', 'sans-serif'], - 'font_mono':['IBM Plex Mono', 'ui-monospace', 'Consolas', 'monospace'] - } - if theme_name in list_builtin_themes(): - gradio_theme = gr.themes.Base(**default_font_params) - elif theme_name.startswith("gradio/"): - if theme_name == "gradio/default": - gradio_theme = gr.themes.Default(**default_font_params) - if theme_name == "gradio/base": - gradio_theme = gr.themes.Base(**default_font_params) - if theme_name == "gradio/glass": - gradio_theme = gr.themes.Glass(**default_font_params) - if theme_name == "gradio/monochrome": - gradio_theme = gr.themes.Monochrome(**default_font_params) - if theme_name == "gradio/soft": - gradio_theme = gr.themes.Soft(**default_font_params) - else: - try: - gradio_theme = gr.themes.ThemeClass.from_hub(theme_name) - except Exception: - log.error("Theme download error accessing HuggingFace") - gradio_theme = gr.themes.Default(**default_font_params) - log.info(f'Loading UI theme: name={theme_name} style={opts.theme_style}') - - class TotalTQDM: # compatibility with previous global-tqdm # import tqdm def __init__(self): diff --git a/modules/styles.py b/modules/styles.py index 2b637800a..ea7c2dc7b 100644 --- a/modules/styles.py +++ b/modules/styles.py @@ -124,7 +124,7 @@ class StyleDatabase: list_folder(self.path) self.styles = dict(sorted(self.styles.items(), key=lambda style: style[1].filename)) if self.built_in: - self.load_style(os.path.join(paths.data_path, 'html', 'art-styles.json'), 'built-in') + self.load_style(os.path.join('html', 'art-styles.json'), 'built-in') log.debug(f'Loaded styles: folder={self.path} items={len(self.styles.keys())}') diff --git a/modules/theme.py b/modules/theme.py new file mode 100644 index 000000000..293a174fb --- /dev/null +++ b/modules/theme.py @@ -0,0 +1,88 @@ +import os +import json +import urllib.request +import gradio as gr +import modules.shared +# from modules.shared import log, opts, req, writefile + + +gradio_theme = gr.themes.Base() + + +def list_builtin_themes(): + files = [os.path.splitext(f)[0] for f in os.listdir('javascript') if f.endswith('.css')] + return files + + +def list_themes(): + fn = os.path.join('html', 'themes.json') + if not os.path.exists(fn): + refresh_themes() + if os.path.exists(fn): + with open(fn, mode='r', encoding='utf=8') as f: + res = json.loads(f.read()) + else: + res = [] + builtin = list_builtin_themes() + default = ["gradio/default", "gradio/base", "gradio/glass", "gradio/monochrome", "gradio/soft"] + external = {x['id'] for x in res if x['status'] == 'RUNNING' and 'test' not in x['id'].lower()} + modules.shared.log.debug(f'Themes: builtin={len(builtin)} default={len(default)} external={len(external)}') + themes = sorted(builtin) + sorted(default) + sorted(external, key=str.casefold) + return themes + + +def refresh_themes(): + try: + r = modules.shared.req('https://huggingface.co/datasets/freddyaboulton/gradio-theme-subdomains/resolve/main/subdomains.json') + if r.status_code == 200: + res = r.json() + fn = os.path.join('html', 'themes.json') + modules.shared.writefile(res, fn) + list_themes() + else: + modules.shared.log.error('Error refreshing UI themes') + except Exception: + modules.shared.log.error('Exception refreshing UI themes') + + +def reload_gradio_theme(theme_name=None): + global gradio_theme # pylint: disable=global-statement + if not theme_name: + theme_name = modules.shared.opts.gradio_theme + default_font_params = {} + res = 0 + try: + request = urllib.request.Request("https://fonts.googleapis.com/css2?family=IBM+Plex+Mono", method="HEAD") + res = urllib.request.urlopen(request, timeout=3.0).status # pylint: disable=consider-using-with + except Exception: + res = 0 + if res != 200: + modules.shared.log.info('No internet access detected, using default fonts') + default_font_params = { + 'font':['Helvetica', 'ui-sans-serif', 'system-ui', 'sans-serif'], + 'font_mono':['IBM Plex Mono', 'ui-monospace', 'Consolas', 'monospace'] + } + is_builtin = theme_name in list_builtin_themes() + modules.shared.log.info(f'Loading UI theme: name={theme_name} style={modules.shared.opts.theme_style} base={"style.css" if is_builtin else "base.css"}') + if is_builtin: + gradio_theme = gr.themes.Base(**default_font_params) + elif theme_name.startswith("gradio/"): + modules.shared.log.warning('Using Gradio default theme which is not optimized for SD.Next') + if theme_name == "gradio/default": + gradio_theme = gr.themes.Default(**default_font_params) + if theme_name == "gradio/base": + gradio_theme = gr.themes.Base(**default_font_params) + if theme_name == "gradio/glass": + gradio_theme = gr.themes.Glass(**default_font_params) + if theme_name == "gradio/monochrome": + gradio_theme = gr.themes.Monochrome(**default_font_params) + if theme_name == "gradio/soft": + gradio_theme = gr.themes.Soft(**default_font_params) + else: + try: + modules.shared.log.warning('Using 3rd party theme which is not optimized for SD.Next') + gradio_theme = gr.themes.ThemeClass.from_hub(theme_name) + except Exception: + modules.shared.log.error("Theme download error accessing HuggingFace") + gradio_theme = gr.themes.Default(**default_font_params) + return is_builtin diff --git a/modules/ui.py b/modules/ui.py index 5a7573be8..b7edcdaac 100644 --- a/modules/ui.py +++ b/modules/ui.py @@ -25,6 +25,7 @@ import modules.shared import modules.errors import modules.styles import modules.extras +import modules.theme import modules.textual_inversion.ui import modules.sd_samplers @@ -250,7 +251,7 @@ def create_toprow(is_img2img): pause = gr.Button('Pause', elem_id=f"{id_part}_pause") pause.click(fn=lambda: modules.shared.state.pause(), _js='checkPaused', inputs=[], outputs=[]) with gr.Row(elem_id=f"{id_part}_tools"): - button_paste = gr.Button(value='Apply', variant='secondary', elem_id="paste") # symbols.paste + button_paste = gr.Button(value='Restore', variant='secondary', elem_id="paste") # symbols.paste button_clear = gr.Button(value='Clear', variant='secondary', elem_id=f"{id_part}_clear_prompt_btn") # symbols.clear button_extra = gr.Button(value='Networks', variant='secondary', elem_id=f"{id_part}_extra_networks_btn") # symbols.networks button_clear.click(fn=lambda *x: ['', ''], inputs=[prompt, negative_prompt], outputs=[prompt, negative_prompt], show_progress=False) @@ -1103,7 +1104,7 @@ def create_ui(startup_timer = None): for _interface, label, _ifid in interfaces: modules.shared.tab_names.append(label) - with gr.Blocks(theme=modules.shared.gradio_theme, analytics_enabled=False, title="SD.Next") as demo: + with gr.Blocks(theme=modules.theme.gradio_theme, analytics_enabled=False, title="SD.Next") as demo: with gr.Row(elem_id="quicksettings", variant="compact"): for _i, k, _item in sorted(quicksettings_list, key=lambda x: quicksettings_names.get(x[1], x[0])): component = create_setting_component(k, is_quicksettings=True) @@ -1226,19 +1227,20 @@ def html_body(): return body -def html_css(): +def html_css(is_builtin: bool): added = [] def stylesheet(fn): added.append(fn) return f'' - head = stylesheet(os.path.join(script_path, 'javascript/style.css')) + css = 'sdnext.css' if is_builtin else 'base.css' + head = stylesheet(os.path.join(script_path, 'javascript', css)) for cssfile in modules.scripts.list_files_with_name("style.css"): if not os.path.isfile(cssfile): continue head += stylesheet(cssfile) - if opts.gradio_theme in modules.shared.list_builtin_themes(): + if opts.gradio_theme in modules.theme.list_builtin_themes(): head += stylesheet(os.path.join(script_path, "javascript", f"{opts.gradio_theme}.css")) if os.path.exists(os.path.join(data_path, "user.css")): head += stylesheet(os.path.join(data_path, "user.css")) @@ -1248,8 +1250,9 @@ def html_css(): def reload_javascript(): + is_builtin = modules.theme.reload_gradio_theme() head = html_head() - css = html_css() + css = html_css(is_builtin) body = html_body() def template_response(*args, **kwargs): diff --git a/requirements.txt b/requirements.txt index 7d5e41aef..0f716d03e 100644 --- a/requirements.txt +++ b/requirements.txt @@ -43,7 +43,7 @@ fasteners dctorch compel==2.0.2 torchsde==0.2.6 -typing-extensions==4.7.1 +typing-extensions==4.8.0 antlr4-python3-runtime==4.9.3 requests==2.31.0 tqdm==4.66.1 @@ -64,4 +64,4 @@ tomesd==0.1.3 urllib3==1.26.15 Pillow==9.5.0 timm==0.9.7 -pydantic==1.10.11 +pydantic==1.10.13 diff --git a/scripts/xyz_grid.py b/scripts/xyz_grid.py index 3a251e668..81ef716d1 100644 --- a/scripts/xyz_grid.py +++ b/scripts/xyz_grid.py @@ -225,27 +225,32 @@ axis_options = [ AxisOption("Clip skip", int, apply_clip_skip), AxisOption("Denoising strength", float, apply_field("denoising_strength")), AxisOption("Prompt order", str_permutations, apply_order, fmt=format_value_join_list), - AxisOption("Upscaler", str, apply_upscaler, choices=lambda: [x.name for x in shared.sd_upscalers][1:]), - AxisOption("Face restore", str, apply_face_restore, fmt=format_value), - AxisOption("Token merging ratio (txt2img)", float, apply_override('token_merging_ratio')), - AxisOption("Token merging ratio (hires)", float, apply_override('token_merging_ratio_hr')), + AxisOption("[Postprocess] Upscaler", str, apply_upscaler, choices=lambda: [x.name for x in shared.sd_upscalers][1:]), + AxisOption("[Postprocess] Face restore", str, apply_face_restore, fmt=format_value), AxisOptionImg2Img("Image mask weight", float, apply_field("inpainting_mask_weight")), AxisOption("Model dictionary", str, apply_dict, fmt=format_value, cost=1.0, choices=lambda: ['None'] + list(sd_models.checkpoints_list)), - AxisOption("Sampler sigma min", float, apply_field("s_min")), - AxisOption("Sampler sigma max", float, apply_field("s_max")), - AxisOption("Sampler sigma tmin", float, apply_field("s_tmin")), - AxisOption("Sampler sigma tmax", float, apply_field("s_tmax")), - AxisOption("Sampler sigma Churn", float, apply_field("s_churn")), - AxisOption("Sampler sigma noise", float, apply_field("s_noise")), - AxisOption("Sampler eta", float, apply_field("eta")), - AxisOption("Sampler solver order", int, apply_setting("schedulers_solver_order")), - AxisOption("SecondPass upscaler", str, apply_field("hr_upscaler"), choices=lambda: [*shared.latent_upscale_modes, *[x.name for x in shared.sd_upscalers]]), - AxisOption("SecondPass sampler", str, apply_latent_sampler, fmt=format_value, confirm=confirm_samplers, choices=lambda: [x.name for x in sd_samplers.samplers]), - AxisOption("SecondPass denoising Strength", float, apply_field("denoising_strength")), - AxisOption("SecondPass steps", int, apply_field("hr_second_pass_steps")), - AxisOption("SecondPass CFG scale", float, apply_field("image_cfg_scale")), - AxisOption("SecondPass guidance rescale", float, apply_field("diffusers_guidance_rescale")), - AxisOption("SecondPass refiner start", float, apply_field("refiner_start")), + AxisOption("[Sampler] sigma min", float, apply_field("s_min")), + AxisOption("[Sampler] sigma max", float, apply_field("s_max")), + AxisOption("[Sampler] sigma tmin", float, apply_field("s_tmin")), + AxisOption("[Sampler] sigma tmax", float, apply_field("s_tmax")), + AxisOption("[Sampler] sigma Churn", float, apply_field("s_churn")), + AxisOption("[Sampler] sigma noise", float, apply_field("s_noise")), + AxisOption("[Sampler] eta", float, apply_field("eta")), + AxisOption("[Sampler] solver order", int, apply_setting("schedulers_solver_order")), + AxisOption("[Second pass] upscaler", str, apply_field("hr_upscaler"), choices=lambda: [*shared.latent_upscale_modes, *[x.name for x in shared.sd_upscalers]]), + AxisOption("[Second pass] sampler", str, apply_latent_sampler, fmt=format_value, confirm=confirm_samplers, choices=lambda: [x.name for x in sd_samplers.samplers]), + AxisOption("[Second pass] denoising Strength", float, apply_field("denoising_strength")), + AxisOption("[Second pass] steps", int, apply_field("hr_second_pass_steps")), + AxisOption("[Second pass] CFG scale", float, apply_field("image_cfg_scale")), + AxisOption("[Second pass] guidance rescale", float, apply_field("diffusers_guidance_rescale")), + AxisOption("[Second pass] refiner start", float, apply_field("refiner_start")), + AxisOption("[Second pass] refiner start", float, apply_field("refiner_start")), + AxisOption("[TOME] Token merging ratio (txt2img)", float, apply_override('token_merging_ratio')), + AxisOption("[TOME] Token merging ratio (hires)", float, apply_override('token_merging_ratio_hr')), + AxisOption("[FreeU] 1st stage backbone factor", float, apply_setting('freeu_b1')), + AxisOption("[FreeU] 2nd stage backbone factor", float, apply_setting('freeu_b2')), + AxisOption("[FreeU] 1st stage skip factor", float, apply_setting('freeu_s1')), + AxisOption("[FreeU] 2nd stage skip factor", float, apply_setting('freeu_s2')), ] diff --git a/webui.py b/webui.py index fafa3aca8..1974cd89e 100644 --- a/webui.py +++ b/webui.py @@ -115,7 +115,7 @@ def initialize(): shared.opts.onchange("sd_vae", wrap_queued_call(lambda: modules.sd_vae.reload_vae_weights()), call=False) shared.opts.onchange("temp_dir", ui_tempdir.on_tmpdir_changed) - shared.opts.onchange("gradio_theme", shared.reload_gradio_theme) + # shared.opts.onchange("gradio_theme", shared.reload_gradio_theme) timer.startup.record("onchange") modules.textual_inversion.textual_inversion.list_textual_inversion_templates() diff --git a/wiki b/wiki index 128faf8d7..3b4fb16cb 160000 --- a/wiki +++ b/wiki @@ -1 +1 @@ -Subproject commit 128faf8d7fc9e8f94376fb211b0e44f30d15638f +Subproject commit 3b4fb16cb127069f76dc2ae049603f8a951864d8 From 079f5c9f2ad4f65dc0811e49fba7c0d7a9627dc3 Mon Sep 17 00:00:00 2001 From: Vladimir Mandic Date: Wed, 18 Oct 2023 13:01:26 -0400 Subject: [PATCH 03/15] add compatibility reexport for codeformers --- CHANGELOG.md | 2 ++ modules/api/api.py | 3 ++- modules/postprocess/codeformer_model.py | 5 +---- modules/upscaler.py | 2 ++ webui.py | 1 + 5 files changed, 8 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 74d998f15..e09c0e9ca 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,8 @@ Service release addressing all zero-day issues reported so far... - fix freeu for backend original and add it to xyz grid - fix loading diffuser models in huggingface format from non-standard location - fix default styles looking in wrong location +- fix missing upscaler folder on initial startup +- enhance extension compatibility for exensions directly importing codeformers - update `typing-extensions` **Themes** diff --git a/modules/api/api.py b/modules/api/api.py index 163e11881..6cdb362d5 100644 --- a/modules/api/api.py +++ b/modules/api/api.py @@ -182,7 +182,8 @@ class Api: if shared.opts.motd: res = requests.get('https://vladmandic.github.io/automatic/motd', timeout=10) if res.status_code == 200: - shared.log.info(f'MOTD: {res.text}') + msg = (res.text or '').strip() + shared.log.info(f'MOTD: {msg if len(msg) > 0 else "N/A"}') motd += res.text return motd diff --git a/modules/postprocess/codeformer_model.py b/modules/postprocess/codeformer_model.py index e11747018..3f959b6b8 100644 --- a/modules/postprocess/codeformer_model.py +++ b/modules/postprocess/codeformer_model.py @@ -1,9 +1,6 @@ import os -import sys - import cv2 import torch - import modules.face_restoration from modules import shared, devices, modelloader, errors from modules.paths import models_path @@ -88,7 +85,7 @@ def setup_model(dirname): cropped_face_t = cropped_face_t.unsqueeze(0).to(devices.device_codeformer) try: with devices.inference_context(): - output = self.net(cropped_face_t, w=w if w is not None else shared.opts.code_former_weight, adain=True)[0] + output = self.net(cropped_face_t, w=w if w is not None else shared.opts.code_former_weight, adain=True)[0] # pylint: disable=not-callable restored_face = tensor2img(output, rgb2bgr=True, min_max=(-1, 1)) del output devices.torch_gc() diff --git a/modules/upscaler.py b/modules/upscaler.py index 45cdef63a..b05862f78 100644 --- a/modules/upscaler.py +++ b/modules/upscaler.py @@ -64,6 +64,8 @@ class Upscaler: scalers.append(scaler) loaded.append(model_path) # modules.shared.log.debug(f'Upscaler type={self.name} folder="{self.user_path}" model="{model[0]}" path="{model_path}"') + if not os.path.exists(self.user_path): + return scalers for fn in os.listdir(self.user_path): # from folder if not fn.endswith('.pth') and not fn.endswith('.pt'): continue diff --git a/webui.py b/webui.py index 1974cd89e..f8e750888 100644 --- a/webui.py +++ b/webui.py @@ -100,6 +100,7 @@ def initialize(): import modules.postprocess.codeformer_model as codeformer codeformer.setup_model(opts.codeformer_models_path) + sys.modules["modules.codeformer_model"] = codeformer import modules.postprocess.gfpgan_model as gfpgan gfpgan.setup_model(opts.gfpgan_models_path) timer.startup.record("face-restore") From ea0e479a703e7d7a5df86958287e74026414b4a8 Mon Sep 17 00:00:00 2001 From: Vladimir Mandic Date: Wed, 18 Oct 2023 13:10:36 -0400 Subject: [PATCH 04/15] update changelog --- CHANGELOG.md | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e09c0e9ca..f329bbaea 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,11 +5,11 @@ Service release addressing all zero-day issues reported so far... **Fixes** -- complete lyco removal - fix freeu for backend original and add it to xyz grid - fix loading diffuser models in huggingface format from non-standard location - fix default styles looking in wrong location - fix missing upscaler folder on initial startup +- complete lyco removal - enhance extension compatibility for exensions directly importing codeformers - update `typing-extensions` @@ -19,11 +19,6 @@ Service release addressing all zero-day issues reported so far... - if you're using any **gradio default** themes or a **3rd party** theme or that are not optimized for SD.Next, you may experience issues default minimal style has been updated for compatibility, but actual styling is completely outside of SD.Next control -**Cannot reproduce** -- diffusers: img2img: batch count 2 => black images for higher batches -- diffusers deis sampler reporting sde-dpmsolver++ is not implemented - - ## Update for 2023-10-17 This is a major release, with many changes and new functionality... From 76d262f1d14b787b640342316997a0fa42cbe2a2 Mon Sep 17 00:00:00 2001 From: Vladimir Mandic Date: Wed, 18 Oct 2023 13:25:12 -0400 Subject: [PATCH 05/15] lint fix --- modules/sd_models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/sd_models.py b/modules/sd_models.py index 3b94ed70c..d35eb4955 100644 --- a/modules/sd_models.py +++ b/modules/sd_models.py @@ -55,7 +55,7 @@ class CheckpointInfo: def rel(fn, path): try: return os.path.relpath(fn, path) - except: + except Exception: return fn if relname.startswith(shared.opts.ckpt_dir): From fbe3fcb9fd08f275bf4308639457511e4afee907 Mon Sep 17 00:00:00 2001 From: Cody Wyatt Neiman Date: Wed, 18 Oct 2023 15:54:22 -0400 Subject: [PATCH 06/15] fix(installer): rocm TORCH_COMMAND fallback missing fstring --- installer.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/installer.py b/installer.py index 83221fc7a..f8bb39c2c 100644 --- a/installer.py +++ b/installer.py @@ -410,9 +410,9 @@ def check_torch(): rocm_ver = None if rocm_ver in {"5.7"}: # install torch nightly via torchvision to avoid wasting bandwidth when torchvision depends on torch from yesterday - torch_command = os.environ.get('TORCH_COMMAND', 'torch torchvision --pre --index-url https://download.pytorch.org/whl/nightly/rocm{rocm_ver}') + torch_command = os.environ.get('TORCH_COMMAND', f'torch torchvision --pre --index-url https://download.pytorch.org/whl/nightly/rocm{rocm_ver}') elif rocm_ver in {"5.5", "5.6"}: - torch_command = os.environ.get('TORCH_COMMAND', 'torch torchvision --index-url https://download.pytorch.org/whl/nightly/rocm{rocm_ver}') + torch_command = os.environ.get('TORCH_COMMAND', f'torch torchvision --index-url https://download.pytorch.org/whl/nightly/rocm{rocm_ver}') else: # ROCm 5.5 is oldest for PyTorch 2.1 torch_command = os.environ.get('TORCH_COMMAND', 'torch torchvision --index-url https://download.pytorch.org/whl/rocm5.5') From 96f14e48fac0dc7ea7697b9c20e06bd3d838eb95 Mon Sep 17 00:00:00 2001 From: Disty0 Date: Thu, 19 Oct 2023 10:52:03 +0300 Subject: [PATCH 07/15] Temp fix for OpenVINO PyTorch --- installer.py | 29 ++++++++++++++++++++++++++--- modules/intel/openvino/__init__.py | 11 ++++++----- 2 files changed, 32 insertions(+), 8 deletions(-) diff --git a/installer.py b/installer.py index f8bb39c2c..421ec3d3a 100644 --- a/installer.py +++ b/installer.py @@ -431,9 +431,32 @@ def check_torch(): ipex_pip = 'https://github.com/Nuullll/intel-extension-for-pytorch/releases/download/v2.0.110%2Bxpu-master%2Bdll-bundle/intel_extension_for_pytorch-2.0.110+gitc6ea20b-cp310-cp310-win_amd64.whl' torch_command = os.environ.get('TORCH_COMMAND', f'{pytorch_pip} {torchvision_pip} {ipex_pip}') elif allow_openvino and args.use_openvino: - #Remove this after 2.1.0 releases log.info('Using OpenVINO') - torch_command = os.environ.get('TORCH_COMMAND', '--pre torch==2.1.0.dev20230820+cpu torchvision==0.16.0.dev20230820+cpu -f https://download.pytorch.org/whl/nightly/cpu/torch_nightly.html') + if "linux" in sys.platform: + if sys.version_info[1] == 11: + pytorch_pip = 'https://github.com/Disty0/automatic/releases/download/openvino_pre_release_pytorch/torch-2.1.0.dev20230820+cpu-cp311-cp311-linux_x86_64.whl' + torchvision_pip = 'https://github.com/Disty0/automatic/releases/download/openvino_pre_release_pytorch/torchvision-0.16.0.dev20230820+cpu-cp311-cp311-linux_x86_64.whl' + elif sys.version_info[1] == 10: + pytorch_pip = 'https://github.com/Disty0/automatic/releases/download/openvino_pre_release_pytorch/torch-2.1.0.dev20230820+cpu-cp310-cp310-linux_x86_64.whl' + torchvision_pip = 'https://github.com/Disty0/automatic/releases/download/openvino_pre_release_pytorch/torchvision-0.16.0.dev20230820+cpu-cp310-cp310-linux_x86_64.whl' + elif sys.version_info[1] == 8: + pytorch_pip = 'https://github.com/Disty0/automatic/releases/download/openvino_pre_release_pytorch/torch-2.1.0.dev20230820+cpu-cp38-cp38-linux_x86_64.whl' + torchvision_pip = 'https://github.com/Disty0/automatic/releases/download/openvino_pre_release_pytorch/torchvision-0.16.0.dev20230820+cpu-cp38-cp38-linux_x86_64.whl' + else: + log.error('Unsupported Pyhton version') + else: + if sys.version_info[1] == 11: + pytorch_pip = 'https://github.com/Disty0/automatic/releases/download/openvino_pre_release_pytorch/torch-2.1.0.dev20230820+cpu-cp311-cp311-win_amd64.whl' + torchvision_pip = 'https://github.com/Disty0/automatic/releases/download/openvino_pre_release_pytorch/torchvision-0.16.0.dev20230820+cpu-cp311-cp311-win_amd64.whl' + elif sys.version_info[1] == 10: + pytorch_pip = 'https://github.com/Disty0/automatic/releases/download/openvino_pre_release_pytorch/torch-2.1.0.dev20230820+cpu-cp310-cp310-win_amd64.whl' + torchvision_pip = 'https://github.com/Disty0/automatic/releases/download/openvino_pre_release_pytorch/torchvision-0.16.0.dev20230820+cpu-cp310-cp310-win_amd64.whl' + elif sys.version_info[1] == 8: + pytorch_pip = 'https://github.com/Disty0/automatic/releases/download/openvino_pre_release_pytorch/torch-2.1.0.dev20230820+cpu-cp38-cp38-win_amd64.whl' + torchvision_pip = 'https://github.com/Disty0/automatic/releases/download/openvino_pre_release_pytorch/torchvision-0.16.0.dev20230820+cpu-cp38-cp38-win_amd64.whl' + else: + log.error('Unsupported Pyhton version') + torch_command = os.environ.get('TORCH_COMMAND', f'{pytorch_pip} {torchvision_pip}') else: machine = platform.machine() if sys.platform == 'darwin': @@ -505,7 +528,7 @@ def check_torch(): if opts.get('cuda_compile_backend', '') == 'hidet': install('hidet', 'hidet') if args.use_openvino or opts.get('cuda_compile_backend', '') == 'openvino_fx': - install('openvino==2023.1.0', 'openvino') + install('openvino==2023.2.0.dev20230922', 'openvino') os.environ.setdefault('PYTORCH_TRACING_MODE', 'TORCHFX') os.environ.setdefault('NEOReadDebugKeys', '1') os.environ.setdefault('ClDeviceGlobalMemSizeAvailablePercent', '100') diff --git a/modules/intel/openvino/__init__.py b/modules/intel/openvino/__init__.py index 61bb32921..b4294f9ee 100644 --- a/modules/intel/openvino/__init__.py +++ b/modules/intel/openvino/__init__.py @@ -8,6 +8,7 @@ from openvino.runtime import Core, Type, PartialShape, serialize from torch._dynamo.backends.common import fake_tensor_unsupported from torch._dynamo.backends.registry import register_backend from torch.fx.experimental.proxy_tensor import make_fx +from torch.fx import GraphModule from torch.utils._pytree import tree_flatten from types import MappingProxyType from hashlib import sha256 @@ -132,7 +133,7 @@ def cached_model_name(model_hash_str, device, args, cache_root, reversed = False return file_name -def check_fully_supported(self, graph_module): +def check_fully_supported(self, graph_module: GraphModule) -> bool: num_fused = 0 for node in graph_module.graph.nodes: if node.op == "call_module" and "fused_" in node.name: @@ -178,7 +179,7 @@ def openvino_clear_caches(): compiled_cache.clear() partitioned_modules.clear() -def openvino_compile(gm, *args, model_hash_str: str = None, file_name=""): +def openvino_compile(gm: GraphModule, *args, model_hash_str: str = None, file_name=""): core = Core() device = get_device() @@ -259,7 +260,7 @@ def openvino_compile_cached_model(cached_model_path, *example_inputs): return compiled_model -def openvino_execute(gm, *args, executor_parameters=None, partition_id, file_name=""): +def openvino_execute(gm: GraphModule, *args, executor_parameters=None, partition_id, file_name=""): executor_parameters = executor_parameters or DEFAULT_OPENVINO_PYTHON_CONFIG use_cache = executor_parameters.get( @@ -292,7 +293,7 @@ def openvino_execute(gm, *args, executor_parameters=None, partition_id, file_nam return results1[0] return results1 -def openvino_execute_partitioned(gm, *args, executor_parameters=None, file_name=""): +def openvino_execute_partitioned(gm: GraphModule, *args, executor_parameters=None, file_name=""): executor_parameters = executor_parameters or DEFAULT_OPENVINO_PYTHON_CONFIG global partitioned_modules @@ -316,7 +317,7 @@ def openvino_execute_partitioned(gm, *args, executor_parameters=None, file_name= return partitioned_modules[signature](*args) -def partition_graph(gm, use_python_fusion_cache: bool, model_hash_str: str = None, file_name=""): +def partition_graph(gm: GraphModule, use_python_fusion_cache: bool, model_hash_str: str = None, file_name=""): global max_openvino_partitions for node in gm.graph.nodes: if node.op == "call_module" and "fused_" in node.name: From 632fab3052b84420683fb313ea4ac18e6afb979a Mon Sep 17 00:00:00 2001 From: Disty0 Date: Thu, 19 Oct 2023 10:56:20 +0300 Subject: [PATCH 08/15] Cleanup --- installer.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/installer.py b/installer.py index 421ec3d3a..71ac51a28 100644 --- a/installer.py +++ b/installer.py @@ -443,7 +443,10 @@ def check_torch(): pytorch_pip = 'https://github.com/Disty0/automatic/releases/download/openvino_pre_release_pytorch/torch-2.1.0.dev20230820+cpu-cp38-cp38-linux_x86_64.whl' torchvision_pip = 'https://github.com/Disty0/automatic/releases/download/openvino_pre_release_pytorch/torchvision-0.16.0.dev20230820+cpu-cp38-cp38-linux_x86_64.whl' else: - log.error('Unsupported Pyhton version') + log.error('Unsupported Python version') + #Will error when generating an image: + pytorch_pip = 'torch==2.1.0' + torchvision_pip = 'torchvision==0.16.0 --index-url https://download.pytorch.org/whl/cpu' else: if sys.version_info[1] == 11: pytorch_pip = 'https://github.com/Disty0/automatic/releases/download/openvino_pre_release_pytorch/torch-2.1.0.dev20230820+cpu-cp311-cp311-win_amd64.whl' @@ -455,7 +458,10 @@ def check_torch(): pytorch_pip = 'https://github.com/Disty0/automatic/releases/download/openvino_pre_release_pytorch/torch-2.1.0.dev20230820+cpu-cp38-cp38-win_amd64.whl' torchvision_pip = 'https://github.com/Disty0/automatic/releases/download/openvino_pre_release_pytorch/torchvision-0.16.0.dev20230820+cpu-cp38-cp38-win_amd64.whl' else: - log.error('Unsupported Pyhton version') + log.error('Unsupported Python version') + #Will error when generating an image: + pytorch_pip = 'torch==2.1.0' + torchvision_pip = 'torchvision==0.16.0 --index-url https://download.pytorch.org/whl/cpu' torch_command = os.environ.get('TORCH_COMMAND', f'{pytorch_pip} {torchvision_pip}') else: machine = platform.machine() From 505f36df8707ee0b2faa12799bc1477d0e4a2e7a Mon Sep 17 00:00:00 2001 From: Vladimir Mandic Date: Thu, 19 Oct 2023 09:36:10 -0400 Subject: [PATCH 09/15] multiple fixes --- CHANGELOG.md | 9 +++++++-- installer.py | 1 + launch.py | 2 +- modules/cmd_args.py | 2 +- modules/loader.py | 10 +++++++--- modules/processing.py | 10 +++++++--- modules/sd_models.py | 8 ++++++++ modules/sd_vae_approx.py | 35 ++++++++++++++++------------------- requirements.txt | 2 +- 9 files changed, 49 insertions(+), 30 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f329bbaea..75ac65794 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,8 +9,13 @@ Service release addressing all zero-day issues reported so far... - fix loading diffuser models in huggingface format from non-standard location - fix default styles looking in wrong location - fix missing upscaler folder on initial startup -- complete lyco removal -- enhance extension compatibility for exensions directly importing codeformers +- fix handling of relative path for models +- fix simple live preview device mismatch +- fix batch img2img +- force second requirements check on startup +- remove lyco, multiple_tqdm +- enhance extension compatibility for exensions directly importing codeformers +- enhance extension compatibility for exensions directly accessing processing params - update `typing-extensions` **Themes** diff --git a/installer.py b/installer.py index 71ac51a28..e93ae9b01 100644 --- a/installer.py +++ b/installer.py @@ -786,6 +786,7 @@ def set_environment(): os.environ.setdefault('HF_HUB_DISABLE_EXPERIMENTAL_WARNING', '1') os.environ.setdefault('UVICORN_TIMEOUT_KEEP_ALIVE', '60') os.environ.setdefault('K_DIFFUSION_USE_COMPILE', '0') + os.environ.setdefault('TF_ENABLE_ONEDNN_OPTS', '0') if sys.platform == 'darwin': os.environ.setdefault('PYTORCH_ENABLE_MPS_FALLBACK', '1') diff --git a/launch.py b/launch.py index d5fe9a7d1..b725961f9 100644 --- a/launch.py +++ b/launch.py @@ -199,7 +199,7 @@ if __name__ == "__main__": installer.install_repositories() installer.install_submodules() installer.install_extensions() - installer.install_packages() # redo packages since extensions may change them + installer.install_requirements() # redo requirements since extensions may change them installer.update_wiki() if installer.errors == 0: installer.log.debug(f'Setup complete without errors: {round(time.time())}') diff --git a/modules/cmd_args.py b/modules/cmd_args.py index 5570bd02a..ef2074f1e 100644 --- a/modules/cmd_args.py +++ b/modules/cmd_args.py @@ -114,7 +114,7 @@ def compatibility_args(opts, args): opts.sd_vae_as_default = True opts.enable_emphasis = True opts.enable_batch_seeds = True - opts.multiple_tqdm = False + # opts.multiple_tqdm = False opts.print_hypernet_extra = False opts.dimensions_and_batch_together = True opts.enable_pnginfo = True diff --git a/modules/loader.py b/modules/loader.py index c0cc8dea3..6353ee1bb 100644 --- a/modules/loader.py +++ b/modules/loader.py @@ -9,7 +9,11 @@ initialized = False logging.getLogger("DeepSpeed").disabled = True # os.environ.setdefault('OMP_NUM_THREADS', 1) # os.environ.setdefault('MKL_NUM_THREADS', 1) + +# import tensorflow as tf # pylint: disable=C0411 + import torch # pylint: disable=C0411 + # torch.set_num_threads(1) try: import intel_extension_for_pytorch as ipex # pylint: disable=import-error, unused-import @@ -19,14 +23,14 @@ except Exception: urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) import torchvision # pylint: disable=W0611,C0411 import pytorch_lightning # pytorch_lightning should be imported after torch, but it re-enables warnings on import so import once to disable them # pylint: disable=W0611,C0411 -if ".dev" in torch.__version__ or "+git" in torch.__version__: - torch.__long_version__ = torch.__version__ - torch.__version__ = re.search(r'[\d.]+[\d]', torch.__version__).group(0) logging.getLogger("xformers").addFilter(lambda record: 'A matching Triton is not available' not in record.getMessage()) logging.getLogger("pytorch_lightning").disabled = True warnings.filterwarnings(action="ignore", category=DeprecationWarning) warnings.filterwarnings(action="ignore", category=FutureWarning) warnings.filterwarnings(action="ignore", category=UserWarning, module="torchvision") +if ".dev" in torch.__version__ or "+git" in torch.__version__: + torch.__long_version__ = torch.__version__ + torch.__version__ = re.search(r'[\d.]+[\d]', torch.__version__).group(0) timer.startup.record("torch") from fastapi import FastAPI # pylint: disable=W0611,C0411 diff --git a/modules/processing.py b/modules/processing.py index aa0bfafc8..2c6deb0b1 100644 --- a/modules/processing.py +++ b/modules/processing.py @@ -163,6 +163,7 @@ class StableDiffusionProcessing: self.refiner_steps = 5 self.refiner_start = 0 self.ops = [] + self.resize_mode: int = 0 self.ddim_discretize = shared.opts.ddim_discretize self.s_min_uncond = shared.opts.s_min_uncond self.s_churn = shared.opts.s_churn @@ -172,9 +173,10 @@ class StableDiffusionProcessing: self.s_tmin = shared.opts.s_tmin self.s_tmax = float('inf') # not representable as a standard ui option self.refiner_switch_at = 0 # a1111 compatibility item - self.comments = {} - self.is_api = False - self.resize_mode: int = 0 + self.all_hr_prompts = [] # a1111 compatibility item + self.hr_prompt = '' # a1111 compatibility item + self.comments = {} # a1111 compatibility item + self.is_api = False # a1111 compatibility item shared.opts.data['clip_skip'] = clip_skip @property @@ -1180,6 +1182,8 @@ class StableDiffusionProcessingImg2Img(StableDiffusionProcessing): crop_region = None image_mask = self.image_mask if image_mask is not None: + if type(image_mask) == list: + image_mask = image_mask[0] image_mask = image_mask.convert('L') if self.inpainting_mask_invert: image_mask = ImageOps.invert(image_mask) diff --git a/modules/sd_models.py b/modules/sd_models.py index d35eb4955..a6ab5656a 100644 --- a/modules/sd_models.py +++ b/modules/sd_models.py @@ -51,6 +51,7 @@ class CheckpointInfo: self.filename = filename self.type = '' relname = filename + app_path = os.path.abspath(script_path) def rel(fn, path): try: @@ -58,6 +59,8 @@ class CheckpointInfo: except Exception: return fn + if relname.startswith('..'): + relname = os.path.abspath(relname) if relname.startswith(shared.opts.ckpt_dir): relname = rel(filename, shared.opts.ckpt_dir) elif relname.startswith(shared.opts.diffusers_dir): @@ -66,6 +69,8 @@ class CheckpointInfo: relname = rel(filename, model_path) elif relname.startswith(script_path): relname = rel(filename, script_path) + elif relname.startswith(app_path): + relname = rel(filename, app_path) else: relname = os.path.abspath(relname) relname, ext = os.path.splitext(relname) @@ -705,6 +710,9 @@ def compile_diffusers(sd_model): def set_diffuser_options(sd_model, vae, op: str): + if sd_model is None: + shared.log.warning(f'{op} is not loaded') + return if (shared.opts.diffusers_model_cpu_offload or shared.cmd_opts.medvram) and (shared.opts.diffusers_seq_cpu_offload or shared.cmd_opts.lowvram): shared.log.warning(f'Setting {op}: Model CPU offload and Sequential CPU offload are not compatible') shared.log.debug(f'Setting {op}: disabling model CPU offload') diff --git a/modules/sd_vae_approx.py b/modules/sd_vae_approx.py index f5c577458..6c48d977a 100644 --- a/modules/sd_vae_approx.py +++ b/modules/sd_vae_approx.py @@ -5,8 +5,6 @@ from modules import devices, paths, shared sd_vae_approx_model = None -simple_weights = None -simple_bias = None class VAEApprox(nn.Module): @@ -58,24 +56,23 @@ def nn_approximation(sample): # Approximate NN def cheap_approximation(sample): # Approximate simple # https://discuss.huggingface.co/t/decoding-latents-to-rgb-without-upscaling/23204/2 - global simple_weights, simple_bias # pylint: disable=global-statement - if simple_weights is None or simple_bias is None: - if shared.sd_model_type == "sdxl": - simple_weights = torch.tensor([ - [0.4543,-0.2868, 0.1566,-0.4748], - [0.5008, 0.0952, 0.2155,-0.3268], - [0.5294, 0.1625,-0.0624,-0.3793] - ]).reshape(3, 4, 1, 1).to(sample.device) - simple_bias = torch.tensor([0.1375, 0.0144, -0.0675]).to(sample.device) - else: - simple_weights = torch.tensor([ - [0.298, 0.187,-0.158,-0.184], - [0.207, 0.286, 0.189,-0.271], - [0.208, 0.173, 0.264,-0.473], - ]).reshape(3, 4, 1, 1).to(sample.device) - simple_bias = None + if shared.sd_model_type == "sdxl": + simple_weights = torch.tensor([ + [0.4543,-0.2868, 0.1566,-0.4748], + [0.5008, 0.0952, 0.2155,-0.3268], + [0.5294, 0.1625,-0.0624,-0.3793] + ]).reshape(3, 4, 1, 1) + simple_bias = torch.tensor([0.1375, 0.0144, -0.0675]) + else: + simple_weights = torch.tensor([ + [0.298, 0.187,-0.158,-0.184], + [0.207, 0.286, 0.189,-0.271], + [0.208, 0.173, 0.264,-0.473], + ]).reshape(3, 4, 1, 1) + simple_bias = None try: - x_sample = nn.functional.conv2d(sample, simple_weights, simple_bias) # pylint: disable=not-callable + print('HERE', sample.dtype, sample.device) + x_sample = nn.functional.conv2d(sample, simple_weights.to(sample.device, sample.dtype), simple_bias.to(sample.device, sample.dtype)) # pylint: disable=not-callable return x_sample except Exception as e: shared.log.error(f'Decode simple: {e}') diff --git a/requirements.txt b/requirements.txt index 0f716d03e..ffb5dacc3 100644 --- a/requirements.txt +++ b/requirements.txt @@ -43,7 +43,6 @@ fasteners dctorch compel==2.0.2 torchsde==0.2.6 -typing-extensions==4.8.0 antlr4-python3-runtime==4.9.3 requests==2.31.0 tqdm==4.66.1 @@ -65,3 +64,4 @@ urllib3==1.26.15 Pillow==9.5.0 timm==0.9.7 pydantic==1.10.13 +typing-extensions==4.8.0 From e0c92b108548003da54e898ecaa71c1d0cfc76e8 Mon Sep 17 00:00:00 2001 From: Vladimir Mandic Date: Thu, 19 Oct 2023 10:19:46 -0400 Subject: [PATCH 10/15] fix samplers --- CHANGELOG.md | 1 + modules/sd_samplers_diffusers.py | 8 +++++--- modules/ui_extra_networks.py | 10 +++++++++- 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 75ac65794..a405af01d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ Service release addressing all zero-day issues reported so far... - fix handling of relative path for models - fix simple live preview device mismatch - fix batch img2img +- fix diffusers dpm++ 2m and 1s samplers - force second requirements check on startup - remove lyco, multiple_tqdm - enhance extension compatibility for exensions directly importing codeformers diff --git a/modules/sd_samplers_diffusers.py b/modules/sd_samplers_diffusers.py index 6dfd2c73c..58a16c9b3 100644 --- a/modules/sd_samplers_diffusers.py +++ b/modules/sd_samplers_diffusers.py @@ -29,8 +29,8 @@ config = { 'DDIM': { 'clip_sample': True, 'set_alpha_to_one': True, 'steps_offset': 0, 'clip_sample_range': 1.0, 'sample_max_value': 1.0, 'timestep_spacing': 'linspace', 'rescale_betas_zero_snr': False }, 'DDPM': { 'variance_type': "fixed_small", 'clip_sample': True, 'thresholding': False, 'clip_sample_range': 1.0, 'sample_max_value': 1.0, 'timestep_spacing': 'linspace'}, 'DEIS': { 'solver_order': 2, 'thresholding': False, 'sample_max_value': 1.0, 'algorithm_type': "deis", 'solver_type': "logrho", 'lower_order_final': True }, - 'DPM 1S++': { 'solver_order': 2, 'thresholding': False, 'sample_max_value': 1.0, 'algorithm_type': "dpmsolver++", 'solver_type': "midpoint", 'lower_order_final': True, 'use_karras_sigmas': False }, - 'DPM 2M++': { 'thresholding': False, 'sample_max_value': 1.0, 'algorithm_type': "dpmsolver++", 'solver_type': "midpoint", 'lower_order_final': True, 'use_karras_sigmas': False }, + 'DPM++ 1S': { 'solver_order': 2, 'thresholding': False, 'sample_max_value': 1.0, 'algorithm_type': "dpmsolver++", 'solver_type': "midpoint", 'lower_order_final': True, 'use_karras_sigmas': False }, + 'DPM++ 2M': { 'thresholding': False, 'sample_max_value': 1.0, 'algorithm_type': "dpmsolver++", 'solver_type': "midpoint", 'lower_order_final': True, 'use_karras_sigmas': False }, 'DPM SDE': { 'use_karras_sigmas': False }, 'Euler a': { }, 'Euler': { 'interpolation_type': "linear", 'use_karras_sigmas': False }, @@ -66,9 +66,10 @@ class DiffusionSampler: return self.name = name self.config = {} - self.config = config['All'].copy() # apply global defaults if not hasattr(model, 'scheduler'): return + for key, value in config.get('All', {}).items(): # apply global defaults + self.config[key] = value for key, value in config.get(name, {}).items(): # apply diffusers per-scheduler defaults self.config[key] = value if hasattr(model.scheduler, 'scheduler_config'): # find model defaults @@ -102,5 +103,6 @@ class DiffusionSampler: self.config['beta_start'] = shared.opts.schedulers_beta_start if 'beta_end' in self.config and shared.opts.schedulers_beta_end > 0: self.config['beta_end'] = shared.opts.schedulers_beta_end + print('HERE9', self.config) self.sampler = constructor(**self.config) self.sampler.name = name diff --git a/modules/ui_extra_networks.py b/modules/ui_extra_networks.py index cc5101931..97cdd7390 100644 --- a/modules/ui_extra_networks.py +++ b/modules/ui_extra_networks.py @@ -23,9 +23,11 @@ allowed_dirs = [] dir_cache = {} # key=path, value=(mtime, listdir(path)) refresh_time = 0 extra_pages = shared.extra_networks +debug = shared.log.info if os.environ.get('SD_EN_DEBUG', None) is not None else lambda *args, **kwargs: None def listdir(path): + debug(f'EN list-dir: {path}') if not os.path.exists(path): return [] if path in dir_cache and os.path.getmtime(path) == dir_cache[path][0]: @@ -37,6 +39,7 @@ def listdir(path): def register_page(page): # registers extra networks page for the UI; recommend doing it in on_before_ui() callback for extensions + debug(f'EN register-page: {page}') shared.extra_networks.append(page) allowed_dirs.clear() for pg in shared.extra_networks: @@ -165,6 +168,7 @@ class ExtraNetworksPage: return True def create_thumb(self): + debug(f'EN create-thumb: {self.name}') created = 0 for f in self.missing_thumbs: if not os.path.exists(f): @@ -197,6 +201,7 @@ class ExtraNetworksPage: self.missing_thumbs.clear() def create_items(self, tabname): + debug(f'EN create-items: {self.name}') if self.refresh_time is not None and self.refresh_time > refresh_time: # cached results return t0 = time.time() @@ -213,6 +218,7 @@ class ExtraNetworksPage: def create_page(self, tabname, skip = False): + debug(f'EN create-page: {self.name}') if self.page_time > refresh_time: # cached page return self.html self_name_id = self.name.replace(" ", "_") @@ -249,7 +255,8 @@ class ExtraNetworksPage: else: return '' shared.log.debug(f"Extra networks: page='{self.name}' items={len(self.items)} subdirs={len(subdirs)} tab={tabname} dirs={self.allowed_directories_for_previews()} time={self.list_time}s") - threading.Thread(target=self.create_thumb).start() + if len(self.missing_thumbs) > 0: + threading.Thread(target=self.create_thumb).start() return self.html def list_items(self): @@ -394,6 +401,7 @@ class ExtraNetworksUi: def create_ui(container, button_parent, tabname, skip_indexing = False): + debug(f'EN create-ui: {tabname}') ui = ExtraNetworksUi() ui.tabname = tabname ui.pages = [] From 11c073a3caf3933d7a506ee23252f90610379810 Mon Sep 17 00:00:00 2001 From: Vladimir Mandic Date: Thu, 19 Oct 2023 10:37:03 -0400 Subject: [PATCH 11/15] fix create style filename template --- CHANGELOG.md | 1 + modules/images.py | 2 +- modules/ui_extra_networks_styles.py | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a405af01d..0099be32a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ Service release addressing all zero-day issues reported so far... - fix simple live preview device mismatch - fix batch img2img - fix diffusers dpm++ 2m and 1s samplers +- fix new style filename template - force second requirements check on startup - remove lyco, multiple_tqdm - enhance extension compatibility for exensions directly importing codeformers diff --git a/modules/images.py b/modules/images.py index 299eaa4d9..b84d44eee 100644 --- a/modules/images.py +++ b/modules/images.py @@ -351,7 +351,7 @@ class FilenameGenerator: return shorthash def prompt_words(self): - if self.p is None or self.prompt is None: + if self.prompt is None: return '' no_attention = re_attention.sub(r'\1', self.prompt) no_network = re_network.sub(r'\1', no_attention) diff --git a/modules/ui_extra_networks_styles.py b/modules/ui_extra_networks_styles.py index 96a584e8d..96b68c3bb 100644 --- a/modules/ui_extra_networks_styles.py +++ b/modules/ui_extra_networks_styles.py @@ -44,6 +44,7 @@ class ExtraNetworksPageStyles(ui_extra_networks.ExtraNetworksPage): from modules.images import FilenameGenerator from hashlib import sha256 namegen = FilenameGenerator(p=None, seed=None, prompt=params.get('Prompt', ''), image=None, grid=False) + print('HERE', params) name = namegen.prompt_words() sha = sha256(json.dumps(name).encode()).hexdigest()[0:8] fn = os.path.join(shared.opts.styles_dir, sha + '.json') From 6bda4fbc7103510da7ea4a2aaea9d5b305e943e3 Mon Sep 17 00:00:00 2001 From: Vladimir Mandic Date: Thu, 19 Oct 2023 11:43:29 -0400 Subject: [PATCH 12/15] use short model name and update hints --- CHANGELOG.md | 1 + html/locale_en.json | 42 +++++++++++++++++------------------------- javascript/setHints.js | 21 ++++++++------------- modules/images.py | 4 ++-- modules/processing.py | 13 ++++++++----- modules/shared.py | 4 ++-- modules/ui_models.py | 2 +- wiki | 2 +- 8 files changed, 40 insertions(+), 49 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0099be32a..97677921d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ Service release addressing all zero-day issues reported so far... - fix batch img2img - fix diffusers dpm++ 2m and 1s samplers - fix new style filename template +- fix image name template using model name - force second requirements check on startup - remove lyco, multiple_tqdm - enhance extension compatibility for exensions directly importing codeformers diff --git a/html/locale_en.json b/html/locale_en.json index e1a6cc93c..de35d33ec 100644 --- a/html/locale_en.json +++ b/html/locale_en.json @@ -79,26 +79,23 @@ {"id":"","label":"Do not automatically build extra network pages","localized":"","hint":""}, {"id":"","label":"Use LyCoris handler for all Lora types","localized":"","hint":""}, {"id":"","label":"Use Kohya method for handling multiple LoRA","localized":"","hint":""}, - {"id":"","label":"Multiplier for extra networks","localized":"","hint":"When adding extra network such as Hypernetwork or Lora to prompt, use this multiplier for it"}, + {"id":"","label":"Default multiplier for extra networks","localized":"","hint":"When adding extra network such as Lora to prompt, use this multiplier for it"}, {"id":"","label":"Add hypernetwork to prompt","localized":"","hint":""}, {"id":"","label":"Add Lora to prompt","localized":"","hint":""}, {"id":"","label":"shuffle tags by ',' when creating prompts.","localized":"","hint":""}, {"id":"","label":"When adding to prompt, refer to Lora by","localized":"","hint":""}, {"id":"","label":"add lora hashes to infotext","localized":"","hint":""}, - {"id":"","label":"Checkpoints","localized":"","hint":"Trained model checkpoints"}, + {"id":"","label":"Model","localized":"","hint":"Trained model checkpoints"}, + {"id":"","label":"Style","localized":"","hint":"Additional styles to be applied on selected generation paramters"}, {"id":"","label":"Styles","localized":"","hint":"Additional styles to be applied on selected generation paramters"}, {"id":"","label":"Lora","localized":"","hint":"LoRA: Low-Rank Adaptation. Fine-tuned model that is applied on top of a loaded model"}, {"id":"","label":"LyCORIS","localized":"","hint":"LyCORIS: Lora beYond Conventional methods. Fine-tuned model that is applied on top of a loaded model"}, - {"id":"","label":"Textual Inversion","localized":"","hint":"Textual inversion embedding is a trained embedded information about the subject"}, - {"id":"","label":"Hypernetworks","localized":"","hint":"Small trained neural network that modifies behavior of the loaded model"}, - {"id":"","label":"Save preview","localized":"","hint":"Save current image as extra network preview"}, - {"id":"","label":"Save description","localized":"","hint":"Save current text as extra network description"}, - {"id":"","label":"Read description","localized":"","hint":"Read stored extra network description"} + {"id":"","label":"Embedding","localized":"","hint":"Textual inversion embedding is a trained embedded information about the subject"}, + {"id":"","label":"Hypernetwork","localized":"","hint":"Small trained neural network that modifies behavior of the loaded model"} ], "gallery buttons": [ {"id":"","label":"show","localized":"","hint":"Show image location"}, {"id":"","label":"save","localized":"","hint":"Save image"}, - {"id":"","label":"zip","localized":"","hint":"Create zip archive from images"}, {"id":"","label":"delete","localized":"","hint":"Delete image"}, {"id":"","label":"replace","localized":"","hint":"Replace image"}, {"id":"","label":"➠ text","localized":"","hint":"Transfer image to text interface"}, @@ -118,8 +115,8 @@ {"id":"","label":"Specific branch name","localized":"","hint":"Specify extension branch name, leave blank for default"}, {"id":"","label":"Local directory name","localized":"","hint":"Directory where to install extension, leave blank for default"}, {"id":"","label":"Refresh extension list","localized":"","hint":"Refresh list of available extensions"}, - {"id":"","label":"Update installed extensions","localized":"","hint":"Update installed extensions to their latest available version"}, - {"id":"","label":"Apply changes & restart server","localized":"","hint":"Apply all changes and restart server"}, + {"id":"","label":"Update all installed","localized":"","hint":"Update installed extensions to their latest available version"}, + {"id":"","label":"Apply changes","localized":"","hint":"Apply all changes and restart server"}, {"id":"","label":"install","localized":"","hint":"install this extension"}, {"id":"","label":"uninstall","localized":"","hint":"uninstall this extension"}, {"id":"","label":"User interface","localized":"","hint":"Review and set current values as default values for the user interface"}, @@ -135,13 +132,15 @@ {"id":"","label":"Advanced","localized":"","hint":"Additional advanced options"}, {"id":"","label":"Sampling method","localized":"","hint":"Which algorithm to use to produce the image"}, {"id":"","label":"Sampling steps","localized":"","hint":"How many times to improve the generated image iteratively; higher values take longer; very low values can produce bad results"}, + {"id":"","label":"Sampler options","localized":"","hint":"Advanced sampler options"}, + {"id":"","label":"Sigma algorithm","localized":"","hint":"Algorithm to progress noise resolution on each sampler step"}, {"id":"","label":"Restore faces","localized":"","hint":"Use a pre-trained model to correct the generated faces. See GFPGAN or Codeformer."}, {"id":"","label":"Tiling","localized":"","hint":"Produce an image that can be tiled"}, {"id":"","label":"full quality","localized":"","hint":"Use full quality VAE to decode latent samples"}, {"id":"","label":"face restore","localized":"","hint":"Run processed image through additional face restoration model"}, {"id":"","label":"denoise","localized":"","hint":"Denoising details for img2img"}, {"id":"","label":"remove background","localized":"","hint":"Run processed image through additional background removal model"}, - {"id":"","label":"Second pass","localized":"","hint":"Use a similar process as image to image to upscale and/or add detail to the final image. Optionally uses refiner model to enhance image details."}, + {"id":"","label":"Enable second pass","localized":"","hint":"Use a similar process as image to image to upscale and/or add detail to the final image. Optionally uses refiner model to enhance image details."}, {"id":"","label":"Denoising strength","localized":"","hint":"Determines how little respect the algorithm should have for image's content. At 0, nothing will change, and at 1 you'll get an unrelated image. With values below 1.0, processing will take less steps than the Sampling Steps slider specifies"}, {"id":"","label":"Denoise start","localized":"","hint":"Override denoise strength by stating how early base model should finish and when refiner should start. Only applicable to refiner usage. If set to 0 or 1, denoising strength will be used"}, {"id":"","label":"Hires steps","localized":"","hint":"Number of sampling steps for upscaled picture. If 0, uses same as for original"}, @@ -163,7 +162,7 @@ {"id":"","label":"Batch size","localized":"","hint":"How many image to create in a single batch (increases generation performance at cost of higher VRAM usage)"}, {"id":"","label":"cfg scale","localized":"","hint":"Classifier Free Guidance scale: how strongly the image should conform to prompt. Lower values produce more creative results, higher values make it follow the prompt more strictly; recommended values between 5-10"}, {"id":"","label":"CLIP skip","localized":"","hint":"Clip skip is a feature that allows users to control the level of specificity of the prompt, the higher the CLIP skip value, the less deep the prompt will be interpreted. CLIP Skip 1 is typical while some anime models produce better results at CLIP skip 2"}, - {"id":"","label":"Seed","localized":"","hint":"A value that determines the output of random number generator - if you create an image with same parameters and seed as another image, you'll get the same result"}, + {"id":"","label":"Initial seed","localized":"","hint":"A value that determines the output of random number generator - if you create an image with same parameters and seed as another image, you'll get the same result"}, {"id":"","label":"Extra","localized":"","hint":"Show additional options"}, {"id":"","label":"Variation seed","localized":"","hint":"Seed of a different picture to be mixed into the generation"}, {"id":"","label":"Variation strength","localized":"","hint":"How strong of a variation to produce. At 0, there will be no effect. At 1, you will get the complete picture with variation seed (except for ancestral samplers, where you will just get something)"}, @@ -183,10 +182,7 @@ {"id":"","label":"Resize","localized":"","hint":"Resizing details. Higher resolutions require additional processing memory."}, {"id":"","label":"Crop to fit","localized":"","hint":"If the dimensions of your source image (e.g. 512x510) deviate from your target dimensions (e.g. 1024x768) this function will fit your upscaled image into your target size image. Excess will be cropped"}, {"id":"","label":"Secondary Upscaler","localized":"","hint":"Select secondary upscaler to run after initial upscaler"}, - {"id":"","label":"Upscaler 2 visibility","localized":"","hint":"Strength of the secondary upscaler"}, - {"id":"","label":"GFPGAN visibility","localized":"","hint":"Strength of GFPGAN face restore network, 0=disabled"}, - {"id":"","label":"CodeFormer visibility","localized":"","hint":"Strength of CodeFormer face restore network, 0=disabled"}, - {"id":"","label":"CodeFormer weight","localized":"","hint":"0=maximum strength, 1=minimum strength"} + {"id":"","label":"Upscaler 2 visibility","localized":"","hint":"Strength of the secondary upscaler"} ], "settings menu": [ {"id":"settings_submit","label":"Apply settings","localized":"","hint":"Save current settings, server restart is recommended"}, @@ -251,7 +247,7 @@ {"id":"","label":"Merge","localized":"","hint":""}, {"id":"","label":"Validate","localized":"","hint":""}, {"id":"","label":"List model details","localized":"","hint":""}, - {"id":"","label":"Calculate hash for all models (may take a long time)","localized":"","hint":""}, + {"id":"","label":"Calculate hash for all models","localized":"","hint":"Calculates hash for all available models which may take a very long time"}, {"id":"","label":"search models","localized":"","hint":""}, {"id":"","label":"select model","localized":"","hint":""}, {"id":"","label":"specify model variant","localized":"","hint":""}, @@ -492,8 +488,8 @@ {"id":"","label":"Path to notification sound","localized":"","hint":""}, {"id":"","label":"Live preview display period","localized":"","hint":""}, {"id":"","label":"Full VAE","localized":"","hint":""}, - {"id":"","label":"Approximate NN","localized":"","hint":"Cheap neural network approximation. Very fast compared to VAE, but produces pictures with 4 times smaller horizontal/vertical resolution and lower quality"}, - {"id":"","label":"Approximate simple","localized":"","hint":"Very cheap approximation. Very fast compared to VAE, but produces pictures with 8 times smaller horizontal/vertical resolution and extremely low quality"}, + {"id":"","label":"Approximate","localized":"","hint":"Cheap neural network approximation. Very fast compared to VAE, but produces pictures with 4 times smaller horizontal/vertical resolution and lower quality"}, + {"id":"","label":"Simple","localized":"","hint":"Very cheap approximation. Very fast compared to VAE, but produces pictures with 8 times smaller horizontal/vertical resolution and extremely low quality"}, {"id":"","label":"TAESD","localized":"","hint":""}, {"id":"","label":"Combined","localized":"","hint":""}, {"id":"","label":"Progress update period","localized":"","hint":"Update period for UI progress bar and preview checks, in miliseconds"}, @@ -546,8 +542,6 @@ {"id":"","label":"Filename word regex","localized":"","hint":"This regular expression will be used extract words from filename, and they will be joined using the option below into label text used for training. Leave empty to keep filename text as it is"}, {"id":"","label":"Filename join string","localized":"","hint":"This string will be used to join split words into a single line if the option above is enabled"}, {"id":"","label":"Embeddings train templates directory","localized":"","hint":""}, - {"id":"","label":"Number of repeats for a single input image per epoch","localized":"","hint":"Used only for displaying epoch number"}, - {"id":"","label":"Save CSV file containing the loss to log directory","localized":"","hint":"Save CSV file containing the loss to log directory every N steps, 0 to disable"}, {"id":"","label":"Enable tensorboard logging","localized":"","hint":""}, {"id":"","label":"Save generated images within tensorboard","localized":"","hint":""}, {"id":"","label":"Tensorboard flush period","localized":"","hint":"How often, in seconds, to flush the pending Tensorboard events and summaries to disk"}, @@ -567,10 +561,8 @@ {"id":"","label":"Escape brackets in deepbooru","localized":"","hint":"Escape (\\) brackets in deepbooru so they are used as literal brackets and not for emphasis"}, {"id":"","label":"Filter out tags from deepbooru output","localized":"","hint":"Filter out those tags from deepbooru output (separated by comma)"}, {"id":"","label":"Default upscaler for image resize operations","localized":"","hint":""}, - {"id":"","label":"Tile size for ESRGAN upscalers","localized":"","hint":"0 = no tiling"}, - {"id":"","label":"Tile overlap in pixels for ESRGAN upscalers","localized":"","hint":"Low values = visible seam"}, - {"id":"","label":"Tile size for SCUNET upscalers","localized":"","hint":"0 = no tiling"}, - {"id":"","label":"Tile overlap for SCUNET upscalers","localized":"","hint":" Low values = visible seam"}, + {"id":"","label":"Upscaler tile size","localized":"","hint":"0 = no tiling"}, + {"id":"","label":"Upscaler tile overlap","localized":"","hint":"Low values = visible seam"}, {"id":"","label":"Do not fix prompt schedule for second order samplers","localized":"","hint":""}, {"id":"","label":"CodeFormer","localized":"","hint":""}, {"id":"","label":"GFPGAN","localized":"","hint":"Restore low quality faces using GFPGAN neural network"}, diff --git a/javascript/setHints.js b/javascript/setHints.js index 1ce221723..726d83dfa 100644 --- a/javascript/setHints.js +++ b/javascript/setHints.js @@ -30,20 +30,15 @@ async function tooltipHide(e) { async function validateHints(elements, data) { let original = elements.map((e) => e.textContent.toLowerCase().trim()).sort((a, b) => a > b); - original = [...new Set(original)]; - log('all hints:', original); - log('hints-differences', { elements: original.length, hints: data.length }); + original = [...new Set(original)]; // remove duplicates const current = data.map((e) => e.label.toLowerCase().trim()).sort((a, b) => a > b); - let missing = []; - for (let i = 0; i < original.length; i++) { - if (!current.includes(original[i])) missing.push(original[i]); - } - log('missing in locale:', missing); - missing = []; - for (let i = 0; i < current.length; i++) { - if (!original.includes(current[i])) missing.push(current[i]); - } - log('in locale but not ui:', missing); + log('all elements:', original); + log('all hints:', current); + log('hints-differences', { elements: original.length, hints: current.length }); + const missingLocale = original.filter((e) => !current.includes(e)); + log('missing in locale:', missingLocale); + const missingUI = current.filter((e) => !original.includes(e)); + log('in locale but not ui:', missingUI); } async function setHints() { diff --git a/modules/images.py b/modules/images.py index b84d44eee..4b0d198a2 100644 --- a/modules/images.py +++ b/modules/images.py @@ -294,8 +294,8 @@ class FilenameGenerator: 'job_timestamp': lambda self: getattr(self.p, "job_timestamp", shared.state.job_timestamp), 'model': lambda self: shared.sd_model.sd_checkpoint_info.title, - 'model_shortname': lambda self: shared.sd_model.sd_checkpoint_info.name, - 'model_name': lambda self: shared.sd_model.sd_checkpoint_info.name, + 'model_shortname': lambda self: shared.sd_model.sd_checkpoint_info.model_name, + 'model_name': lambda self: shared.sd_model.sd_checkpoint_info.model_name, 'model_hash': lambda self: shared.sd_model.sd_checkpoint_info.shorthash, 'prompt': lambda self: self.prompt, diff --git a/modules/processing.py b/modules/processing.py index 2c6deb0b1..0b3e461da 100644 --- a/modules/processing.py +++ b/modules/processing.py @@ -172,12 +172,15 @@ class StableDiffusionProcessing: self.s_max = shared.opts.s_max self.s_tmin = shared.opts.s_tmin self.s_tmax = float('inf') # not representable as a standard ui option - self.refiner_switch_at = 0 # a1111 compatibility item - self.all_hr_prompts = [] # a1111 compatibility item - self.hr_prompt = '' # a1111 compatibility item - self.comments = {} # a1111 compatibility item - self.is_api = False # a1111 compatibility item shared.opts.data['clip_skip'] = clip_skip + # TODO a1111 compatibility items + self.refiner_switch_at = 0 + self.hr_prompt = '' + self.all_hr_prompts = [] + self.hr_negative_prompt = '' + self.all_hr_negative_prompts = [] + self.comments = {} + self.is_api = False @property def sd_model(self): diff --git a/modules/shared.py b/modules/shared.py index fff70fa2b..9c0b8058e 100644 --- a/modules/shared.py +++ b/modules/shared.py @@ -160,7 +160,7 @@ def list_samplers(): def temp_disable_extensions(): disabled = [] if cmd_opts.safe: - for ext in ['sd-webui-controlnet', 'multidiffusion-upscaler-for-automatic1111', 'a1111-sd-webui-lycoris', 'sd-webui-agent-scheduler', 'clip-interrogator-ext', 'stable-diffusion-webui-rembg', 'sd-extension-chainner']: + for ext in ['sd-webui-controlnet', 'multidiffusion-upscaler-for-automatic1111', 'a1111-sd-webui-lycoris', 'sd-webui-agent-scheduler', 'clip-interrogator-ext', 'stable-diffusion-webui-rembg', 'sd-extension-chainner', 'stable-diffusion-webui-images-browser']: if ext not in opts.disabled_extensions: disabled.append(ext) log.info(f'Safe mode disabling extensions: {disabled}') @@ -297,7 +297,7 @@ options_templates.update(options_section(('advanced', "Inference Settings"), { "token_merging_sep": OptionInfo("

Token merging

", "", gr.HTML), "token_merging_ratio": OptionInfo(0.0, "Token merging ratio (txt2img)", gr.Slider, {"minimum": 0.0, "maximum": 0.9, "step": 0.1}), "token_merging_ratio_img2img": OptionInfo(0.0, "Token merging ratio (img2img)", gr.Slider, {"minimum": 0.0, "maximum": 0.9, "step": 0.1}), - "token_merging_ratio_hr": OptionInfo(0.0, "Token merging ratio for (hires)", gr.Slider, {"minimum": 0.0, "maximum": 0.9, "step": 0.1}), + "token_merging_ratio_hr": OptionInfo(0.0, "Token merging ratio (hires)", gr.Slider, {"minimum": 0.0, "maximum": 0.9, "step": 0.1}), "freeu_sep": OptionInfo("

FreeU

", "", gr.HTML), "freeu_enabled": OptionInfo(False, "FreeU enabled"), diff --git a/modules/ui_models.py b/modules/ui_models.py index 817ec607d..717fe15d8 100644 --- a/modules/ui_models.py +++ b/modules/ui_models.py @@ -143,7 +143,7 @@ def create_ui(): with gr.Row(): model_list_btn = gr.Button(value="List model details", variant='primary') - model_checkhash_btn = gr.Button(value="Calculate hash for all models (may take a long time)", variant='primary') + model_checkhash_btn = gr.Button(value="Calculate hash for all models", variant='primary') model_checkhash_btn.click(fn=sd_models.update_model_hashes, inputs=[], outputs=[models_outcome]) with gr.Row(): model_table = gr.DataFrame( diff --git a/wiki b/wiki index 3b4fb16cb..58e8d11f9 160000 --- a/wiki +++ b/wiki @@ -1 +1 @@ -Subproject commit 3b4fb16cb127069f76dc2ae049603f8a951864d8 +Subproject commit 58e8d11f94503d86f0b9b3f73046c5996a2fc000 From d173821116608ddd70faefcad1a88aaf82020851 Mon Sep 17 00:00:00 2001 From: Vladimir Mandic Date: Thu, 19 Oct 2023 11:55:27 -0400 Subject: [PATCH 13/15] force convert relative paths --- modules/paths.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/modules/paths.py b/modules/paths.py index 6baed946c..c364085c8 100644 --- a/modules/paths.py +++ b/modules/paths.py @@ -70,6 +70,8 @@ def create_paths(opts, log=None): return tgt else: tgt = os.path.join(data_path, tgt) + if tgt.startswith('..'): + tgt = os.path.abspath(tgt) if os.path.isabs(tgt): return tgt tgt = os.path.relpath(tgt, script_path) From 441ca2f648ac2a44b489abb86fe840f739d1e7bf Mon Sep 17 00:00:00 2001 From: Vladimir Mandic Date: Thu, 19 Oct 2023 13:22:34 -0400 Subject: [PATCH 14/15] fix model paths --- CHANGELOG.md | 1 + modules/paths.py | 56 ++++++++++++++++++++------------------------ modules/sd_models.py | 3 ++- webui.py | 2 +- 4 files changed, 30 insertions(+), 32 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 97677921d..fade0f679 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ Service release addressing all zero-day issues reported so far... - fix diffusers dpm++ 2m and 1s samplers - fix new style filename template - fix image name template using model name +- fix model path using relative path - force second requirements check on startup - remove lyco, multiple_tqdm - enhance extension compatibility for exensions directly importing codeformers diff --git a/modules/paths.py b/modules/paths.py index c364085c8..0fd7b87b5 100644 --- a/modules/paths.py +++ b/modules/paths.py @@ -1,17 +1,18 @@ import os import sys -import modules.paths_internal +from modules import paths_internal, errors -data_path = modules.paths_internal.data_path -script_path = modules.paths_internal.script_path -models_path = modules.paths_internal.models_path -sd_configs_path = modules.paths_internal.sd_configs_path -sd_default_config = modules.paths_internal.sd_default_config -sd_model_file = modules.paths_internal.sd_model_file -default_sd_model_file = modules.paths_internal.default_sd_model_file -extensions_dir = modules.paths_internal.extensions_dir -extensions_builtin_dir = modules.paths_internal.extensions_builtin_dir +debug = errors.log.info if os.environ.get('SD_PATH_DEBUG', None) is not None else lambda *args, **kwargs: None +data_path = paths_internal.data_path +script_path = paths_internal.script_path +models_path = paths_internal.models_path +sd_configs_path = paths_internal.sd_configs_path +sd_default_config = paths_internal.sd_default_config +sd_model_file = paths_internal.sd_model_file +default_sd_model_file = paths_internal.default_sd_model_file +extensions_dir = paths_internal.extensions_dir +extensions_builtin_dir = paths_internal.extensions_builtin_dir # data_path = cmd_opts_pre.data sys.path.insert(0, script_path) @@ -39,14 +40,14 @@ paths = {} for d, must_exist, what, _options in path_dirs: must_exist_path = os.path.abspath(os.path.join(script_path, d, must_exist)) if not os.path.exists(must_exist_path): - print(f"Warning: {what} not found at path {must_exist_path}", file=sys.stderr) + errors.log.error(f'Required path not found: path={must_exist_path} item={what}') else: d = os.path.abspath(d) sys.path.append(d) paths[what] = d -def create_paths(opts, log=None): +def create_paths(opts): def create_path(folder): if folder is None or folder == '': return @@ -54,28 +55,22 @@ def create_paths(opts, log=None): return try: os.makedirs(folder, exist_ok=True) - if log is not None: - log.debug(f'Create folder={folder}') + errors.log.info(f'Create folder={folder}') except Exception as e: - if log is not None: - log.error(f'Create Failed folder={folder} {e}') + errors.log.error(f'Create Failed folder={folder} {e}') def fix_path(folder): tgt = opts.data.get(folder, None) or opts.data_labels[folder].default if tgt is None or tgt == '': return tgt - if os.path.isabs(tgt): - return tgt - if len(data_path) > 0 and tgt.startswith(data_path): # path is already relative to data_path - return tgt - else: - tgt = os.path.join(data_path, tgt) - if tgt.startswith('..'): - tgt = os.path.abspath(tgt) - if os.path.isabs(tgt): - return tgt - tgt = os.path.relpath(tgt, script_path) - opts.data[folder] = tgt + fix = tgt + if not os.path.isabs(tgt) and len(data_path) > 0 and not tgt.startswith(data_path): # path is already relative to data_path + fix = os.path.join(data_path, fix) + if fix.startswith('..'): + fix = os.path.abspath(fix) + fix = fix if os.path.isabs(fix) else os.path.relpath(fix, script_path) + opts.data[folder] = fix + debug(f'Paths: folder={folder} original="{tgt}" target="{fix}"') return opts.data[folder] create_path(data_path) @@ -85,11 +80,12 @@ def create_paths(opts, log=None): create_path(extensions_dir) create_path(extensions_builtin_dir) create_path(fix_path('temp_dir')) - create_path(fix_path('hypernetwork_dir')) create_path(fix_path('ckpt_dir')) - create_path(fix_path('vae_dir')) create_path(fix_path('diffusers_dir')) + create_path(fix_path('vae_dir')) + create_path(fix_path('lora_dir')) create_path(fix_path('embeddings_dir')) + create_path(fix_path('hypernetwork_dir')) create_path(fix_path('outdir_samples')) create_path(fix_path('outdir_txt2img_samples')) create_path(fix_path('outdir_img2img_samples')) diff --git a/modules/sd_models.py b/modules/sd_models.py index a6ab5656a..ff95ee7a8 100644 --- a/modules/sd_models.py +++ b/modules/sd_models.py @@ -269,7 +269,8 @@ def select_checkpoint(op='model'): return checkpoint_info if len(checkpoints_list) == 0 and not shared.cmd_opts.no_download: shared.log.error("Cannot generate without a checkpoint") - shared.log.error("Use --ckpt to force using existing checkpoint") + shared.log.info("Set system paths to use existing folders in a different location") + shared.log.info("Or use --ckpt to force using existing checkpoint") return None checkpoint_info = next(iter(checkpoints_list.values())) if model_checkpoint is not None: diff --git a/webui.py b/webui.py index f8e750888..daab8d82b 100644 --- a/webui.py +++ b/webui.py @@ -216,7 +216,7 @@ def start_common(): log.info(f'Using data path: {shared.cmd_opts.data_dir}') if shared.cmd_opts.models_dir is not None and len(shared.cmd_opts.models_dir) > 0 and shared.cmd_opts.models_dir != 'models': log.info(f'Using models path: {shared.cmd_opts.models_dir}') - create_paths(opts, log) + create_paths(opts) async_policy() initialize() if shared.opts.clean_temp_dir_at_start: From 53d0cb35b8b550b8c33091051570c25bfd1def33 Mon Sep 17 00:00:00 2001 From: Vladimir Mandic Date: Thu, 19 Oct 2023 13:43:41 -0400 Subject: [PATCH 15/15] cleanup --- CHANGELOG.md | 2 ++ beautiful girl sitting on an edge of a.jpg | Bin 0 -> 23511 bytes modules/sd_samplers_diffusers.py | 1 - modules/sd_vae_approx.py | 1 - modules/ui_extra_networks.py | 7 +++++-- modules/ui_extra_networks_styles.py | 1 - 6 files changed, 7 insertions(+), 5 deletions(-) create mode 100644 beautiful girl sitting on an edge of a.jpg diff --git a/CHANGELOG.md b/CHANGELOG.md index fade0f679..47ffc4781 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,10 +16,12 @@ Service release addressing all zero-day issues reported so far... - fix new style filename template - fix image name template using model name - fix model path using relative path +- fix torch-rocm version detection (thanks @xangelix) - force second requirements check on startup - remove lyco, multiple_tqdm - enhance extension compatibility for exensions directly importing codeformers - enhance extension compatibility for exensions directly accessing processing params +- update `openvino` (thanks @disty0) - update `typing-extensions` **Themes** diff --git a/beautiful girl sitting on an edge of a.jpg b/beautiful girl sitting on an edge of a.jpg new file mode 100644 index 0000000000000000000000000000000000000000..1c5e7382fe5e0f7176a74970746a909864ea9014 GIT binary patch literal 23511 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 0: self.config['beta_end'] = shared.opts.schedulers_beta_end - print('HERE9', self.config) self.sampler = constructor(**self.config) self.sampler.name = name diff --git a/modules/sd_vae_approx.py b/modules/sd_vae_approx.py index 6c48d977a..3e4b93ddd 100644 --- a/modules/sd_vae_approx.py +++ b/modules/sd_vae_approx.py @@ -71,7 +71,6 @@ def cheap_approximation(sample): # Approximate simple ]).reshape(3, 4, 1, 1) simple_bias = None try: - print('HERE', sample.dtype, sample.device) x_sample = nn.functional.conv2d(sample, simple_weights.to(sample.device, sample.dtype), simple_bias.to(sample.device, sample.dtype)) # pylint: disable=not-callable return x_sample except Exception as e: diff --git a/modules/ui_extra_networks.py b/modules/ui_extra_networks.py index 97cdd7390..0fff0776f 100644 --- a/modules/ui_extra_networks.py +++ b/modules/ui_extra_networks.py @@ -525,8 +525,11 @@ def create_ui(container, button_parent, tabname, skip_indexing = False): if image.width > 512 or image.height > 512: image = image.convert('RGB') image.thumbnail((512, 512), Image.HAMMING) - image.save(ui.last_item.local_preview, quality=50) - shared.log.debug(f'Extra network save image: item={ui.last_item.name} filename={ui.last_item.local_preview}') + try: + image.save(ui.last_item.local_preview, quality=50) + shared.log.debug(f'Extra network save image: item={ui.last_item.name} filename={ui.last_item.local_preview}') + except Exception as e: + shared.log.error(f'Extra network save image: item={ui.last_item.name} filename={ui.last_item.local_preview} {e}') return image def fn_delete_img(): diff --git a/modules/ui_extra_networks_styles.py b/modules/ui_extra_networks_styles.py index 96b68c3bb..96a584e8d 100644 --- a/modules/ui_extra_networks_styles.py +++ b/modules/ui_extra_networks_styles.py @@ -44,7 +44,6 @@ class ExtraNetworksPageStyles(ui_extra_networks.ExtraNetworksPage): from modules.images import FilenameGenerator from hashlib import sha256 namegen = FilenameGenerator(p=None, seed=None, prompt=params.get('Prompt', ''), image=None, grid=False) - print('HERE', params) name = namegen.prompt_words() sha = sha256(json.dumps(name).encode()).hexdigest()[0:8] fn = os.path.join(shared.opts.styles_dir, sha + '.json')