diff --git a/README.md b/README.md
index c07d782c4..62d46b3b8 100644
--- a/README.md
+++ b/README.md
@@ -23,8 +23,8 @@ Fork adds extra functionality:
- [System Info](https://github.com/vladmandic/sd-extension-system-info)
- [ControlNet](https://github.com/Mikubill/sd-webui-controlnet)
- [Image Browser](https://github.com/AlUlkesh/stable-diffusion-webui-images-browser)
-- [LORA](https://github.com/kohya-ss/sd-scripts) (both training and inference)
-- [LyCORIS](https://github.com/KohakuBlueleaf/LyCORIS) (both training and inference)
+- [LORA](https://github.com/kohya-ss/sd-scripts) *(both training and inference)*
+- [LyCORIS](https://github.com/KohakuBlueleaf/LyCORIS) *(both training and inference)*
- [Model Converter](https://github.com/Akegarasu/sd-webui-model-converter)
- [CLiP Interrogator](https://github.com/pharmapsychotic/clip-interrogator-ext)
- [Dynamic Thresholding](https://github.com/mcmonkeyprojects/sd-dynamic-thresholding)
@@ -95,7 +95,7 @@ Start with listen on public IP with authentication enabled
## Install
1. Install `Python`, `Git`
-2. Install `PyTorch` and `Xformers`
+2. Install `PyTorch`
See [Wiki](wiki/Torch%20Optimizations.md) for details or TL;DR below
3. Clone and initialize repository
@@ -116,6 +116,11 @@ Start with listen on public IP with authentication enabled
Detached repos
Local changes
+*Note*: If you're not using `automatic.sh` launcher, install dependencies manually:
+
+> pip -r requirements.txt
+> pip -r requirements_versions.txt
+
## Differences
@@ -142,11 +147,12 @@ Fork does differ in few things:
User Interface:
-- Includes reskinned **UI**
+- Includes updated **UI**: reskinned and reorganized
Black and orange dark theme with fixed width options panels and larger previews
Optimizations:
+- Optimized for `Torch` 2.0
- Runs with `SDP` memory attention enabled by default if supported by system
- Fallback to `XFormers` if SDP is not supported
- If either `SDP` or `XFormers` are not supported, falls back to usual cmd line arguments
diff --git a/cli/modules/preview-models.py b/cli/modules/preview-models.py
index eac43e3b0..6786d46aa 100755
--- a/cli/modules/preview-models.py
+++ b/cli/modules/preview-models.py
@@ -33,8 +33,8 @@ prompts = [
('wlop', 'a stunning portrait of sexy teen girl in a wet t-shirt, vivid color palette, digital painting, octane render, highly detailed, particles, light effect, volumetric lighting, art by wlop'),
('greg rutkowski', 'beautiful woman, high detailed, sharp focus, depth of field, 4k, art by greg rutkowski'),
- ('carne griggiths', 'beautiful woman taylor swift, high detailed, sharp focus, depth of field, art by carne griffiths '),
- ('carne griggiths', 'man vlado, high detailed, sharp focus, depth of field, art by carne griffiths '),
+ ('carne griffiths', 'beautiful woman taylor swift, high detailed, sharp focus, depth of field, art by carne griffiths '),
+ ('carne griffiths', 'man vlado, high detailed, sharp focus, depth of field, art by carne griffiths '),
]
options = Map({
diff --git a/extensions-builtin/sd-extension-system-info b/extensions-builtin/sd-extension-system-info
index c7a5c647e..a42e9e364 160000
--- a/extensions-builtin/sd-extension-system-info
+++ b/extensions-builtin/sd-extension-system-info
@@ -1 +1 @@
-Subproject commit c7a5c647e0a10483a68abe1b0897141ca011b596
+Subproject commit a42e9e3648d5a51237dab6de6b57a47a6b38ca6e
diff --git a/launch.py b/launch.py
index 431f6173f..784dc2eed 100644
--- a/launch.py
+++ b/launch.py
@@ -209,7 +209,7 @@ def run_extensions_installers(settings_file):
def prepare_environment():
global skip_install
- torch_command = os.environ.get('TORCH_COMMAND', "pip install torch torchaudio torchvision triton --force --extra-index-url https://download.pytorch.org/whl/cu118")
+ torch_command = os.environ.get('TORCH_COMMAND', "pip install torch torchaudio torchvision --force --extra-index-url https://download.pytorch.org/whl/cu118")
requirements_file = os.environ.get('REQS_FILE', "requirements_versions.txt")
xformers_package = os.environ.get('XFORMERS_PACKAGE', 'xformers==0.0.16')
@@ -290,37 +290,6 @@ def prepare_environment():
print("Exiting because of --exit argument")
exit(0)
- if args.tests and not args.no_tests:
- exitcode = tests(args.tests)
- exit(exitcode)
-
-
-def tests(test_dir):
- if "--api" not in sys.argv:
- sys.argv.append("--api")
- if "--ckpt" not in sys.argv:
- sys.argv.append("--ckpt")
- sys.argv.append(os.path.join(script_path, "test/test_files/empty.pt"))
- if "--skip-torch-cuda-test" not in sys.argv:
- sys.argv.append("--skip-torch-cuda-test")
- if "--disable-nan-check" not in sys.argv:
- sys.argv.append("--disable-nan-check")
- if "--no-tests" not in sys.argv:
- sys.argv.append("--no-tests")
-
- print(f"Launching Web UI in another process for testing with arguments: {' '.join(sys.argv[1:])}")
-
- os.environ['COMMANDLINE_ARGS'] = ""
- with open(os.path.join(script_path, 'test/stdout.txt'), "w", encoding="utf8") as stdout, open(os.path.join(script_path, 'test/stderr.txt'), "w", encoding="utf8") as stderr:
- proc = subprocess.Popen([sys.executable, *sys.argv], stdout=stdout, stderr=stderr)
-
- import test.server_poll
- exitcode = test.server_poll.run_tests(proc, test_dir)
-
- print(f"Stopping Web UI process with id {proc.pid}")
- proc.kill()
- return exitcode
-
def start():
print(f"Launching {'API server' if '--nowebui' in sys.argv else 'Web UI'} with arguments: {' '.join(sys.argv[1:])}")
diff --git a/modules/errors.py b/modules/errors.py
index f6b80dbbd..017269174 100644
--- a/modules/errors.py
+++ b/modules/errors.py
@@ -1,11 +1,13 @@
import sys
import traceback
+from rich.console import Console
+
+already_displayed = {}
def print_error_explanation(message):
lines = message.strip().split("\n")
max_len = max([len(x) for x in lines])
-
print('=' * max_len, file=sys.stderr)
for line in lines:
print(line, file=sys.stderr)
@@ -14,25 +16,14 @@ def print_error_explanation(message):
def display(e: Exception, task):
print(f"{task or 'error'}: {type(e).__name__}", file=sys.stderr)
- print(traceback.format_exc(), file=sys.stderr)
-
- message = str(e)
- if "copying a param with shape torch.Size([640, 1024]) from checkpoint, the shape in current model is torch.Size([640, 768])" in message:
- print_error_explanation("""
-The most likely cause of this is you are trying to load Stable Diffusion 2.0 model without specifying its config file.
-See https://github.com/AUTOMATIC1111/stable-diffusion-webui/wiki/Features#stable-diffusion-20 for how to solve this.
- """)
-
-
-already_displayed = {}
+ console = Console()
+ console.print_exception(show_locals=False, max_frames=2, extra_lines=1, suppress=[], word_wrap=False, width=min([console.width, 200]))
def display_once(e: Exception, task):
if task in already_displayed:
return
-
display(e, task)
-
already_displayed[task] = 1
diff --git a/modules/sd_models.py b/modules/sd_models.py
index c19eff46e..e4c3f5689 100644
--- a/modules/sd_models.py
+++ b/modules/sd_models.py
@@ -238,28 +238,31 @@ def read_metadata_from_safetensors(filename):
def read_state_dict(checkpoint_file):
- with progress.open(checkpoint_file, 'rb', description=f'Loading weights: [cyan]{checkpoint_file}', auto_refresh=True) as f:
- _, extension = os.path.splitext(checkpoint_file)
- if 'v1-5-pruned-emaonly.safetensors' or 'vae-ft-mse-840000-ema-pruned.ckpt' in checkpoint_file:
- if extension.lower() == ".safetensors":
- pl_sd = safetensors.torch.load_file(checkpoint_file, device='cpu')
+ try:
+ with progress.open(checkpoint_file, 'rb', description=f'Loading weights: [cyan]{checkpoint_file}', auto_refresh=True) as f:
+ _, extension = os.path.splitext(checkpoint_file)
+ if 'v1-5-pruned-emaonly.safetensors' or 'vae-ft-mse-840000-ema-pruned.ckpt' in checkpoint_file:
+ if extension.lower() == ".safetensors":
+ pl_sd = safetensors.torch.load_file(checkpoint_file, device='cpu')
+ else:
+ pl_sd = torch.load(checkpoint_file, map_location='cpu')
else:
- pl_sd = torch.load(checkpoint_file, map_location='cpu')
- else:
- if extension.lower() == ".safetensors":
- buffer = f.read()
- pl_sd = safetensors.torch.load(buffer)
- else:
- buffer = io.BytesIO(f.read())
- pl_sd = torch.load(buffer, map_location='cpu')
- sd = get_state_dict_from_checkpoint(pl_sd)
+ if extension.lower() == ".safetensors":
+ buffer = f.read()
+ pl_sd = safetensors.torch.load(buffer)
+ else:
+ buffer = io.BytesIO(f.read())
+ pl_sd = torch.load(buffer, map_location='cpu')
+ sd = get_state_dict_from_checkpoint(pl_sd)
+ except Exception as e:
+ from rich.console import Console
+ console = Console()
+ console.print_exception(show_locals=False, max_frames=2, extra_lines=1, suppress=[], word_wrap=False, width=min([console.width, 200]))
+ sd = None
return sd
def get_checkpoint_state_dict(checkpoint_info: CheckpointInfo, timer):
- sd_model_hash = checkpoint_info.calculate_shorthash()
- timer.record("calculate hash")
-
if checkpoint_info in checkpoints_loaded:
# use checkpoint cache
print(f"Loading weights from cache")
@@ -394,22 +397,31 @@ def load_model(checkpoint_info=None, already_loaded_state_dict=None):
from modules import lowvram, sd_hijack
checkpoint_info = checkpoint_info or select_checkpoint()
+ do_inpainting_hijack()
+
+ timer = Timer()
+
+ current_checkpoint_info = None
if shared.sd_model:
+ current_checkpoint_info = shared.sd_model.sd_checkpoint_info
sd_hijack.model_hijack.undo_hijack(shared.sd_model)
shared.sd_model = None
gc.collect()
devices.torch_gc()
- do_inpainting_hijack()
-
- timer = Timer()
-
if already_loaded_state_dict is not None:
state_dict = already_loaded_state_dict
else:
state_dict = get_checkpoint_state_dict(checkpoint_info, timer)
checkpoint_config = sd_models_config.find_checkpoint_config(state_dict, checkpoint_info)
+ if state_dict is None or checkpoint_config is None:
+ print(f"Failed to load checkpooint: {checkpoint_info.filename}")
+ if current_checkpoint_info is not None:
+ print(f"Restoring previous checkpoint: {current_checkpoint_info.filename}")
+ load_model(current_checkpoint_info, None)
+ return
+
clip_is_included_into_sd = sd1_clip_weight in state_dict or sd2_clip_weight in state_dict
timer.record("find config")
@@ -426,10 +438,6 @@ def load_model(checkpoint_info=None, already_loaded_state_dict=None):
with sd_disable_initialization.DisableInitialization(disable_clip=clip_is_included_into_sd):
sd_model = instantiate_from_config(sd_config.model)
except Exception as e:
- pass
-
- if sd_model is None:
- print('Failed to create model quickly; will retry using slow method.', file=sys.stderr)
sd_model = instantiate_from_config(sd_config.model)
sd_model.used_config = checkpoint_config
diff --git a/modules/sd_models_config.py b/modules/sd_models_config.py
index 91c217004..a25263938 100644
--- a/modules/sd_models_config.py
+++ b/modules/sd_models_config.py
@@ -63,6 +63,8 @@ def is_using_v_parameterization_for_sd2(state_dict):
def guess_model_config_from_state_dict(sd, filename):
+ if sd is None:
+ return None
sd2_cond_proj_weight = sd.get('cond_stage_model.model.transformer.resblocks.0.attn.in_proj_weight', None)
diffusion_model_input = sd.get('model.diffusion_model.input_blocks.0.0.weight', None)
diff --git a/user.css b/user.css
index c48a91b02..fd11140a4 100644
--- a/user.css
+++ b/user.css
@@ -38,8 +38,8 @@ div.gradio-container.dark > div.w-full.flex.flex-col.min-h-screen > div { backgr
.dark fieldset span.text-gray-500, .dark .gr-block.gr-box span.text-gray-500, .dark label.block span { border-radius: 0;}
.eta-bar { display: none !important }
.extra-network-cards .card .actions .name { font-weight: 400; font-size: 1.2rem; }
-.extra-network-cards .card { width: 10em; height: 10em; box-shadow: none; }
-.extra-network-cards .card:hover { transform: scale(1.3); transition: all 0.3s ease; z-index: 99; box-shadow: none; }
+.extra-network-cards .card { width: 18em; height: 12em; box-shadow: none; }
+.extra-network-cards .card:hover { transform: scale(1.5); transition: all 0.3s ease; z-index: 99; box-shadow: none; }
.feather .feather-image { display: none }
.gap-2 { padding-top: 8px; }
.gr-box > div > div > input.gr-text-input { right: 0; width: 4em; padding: 0; top: -12px; border: none; max-height: 20px; }
diff --git a/webui.py b/webui.py
index af7a65e63..1452291b5 100644
--- a/webui.py
+++ b/webui.py
@@ -157,9 +157,11 @@ def load_model():
modules.sd_models.load_model()
except Exception as e:
errors.display(e, "loading stable diffusion model")
- print("", file=sys.stderr)
print("Stable diffusion model failed to load, exiting", file=sys.stderr)
exit(1)
+ if shared.sd_model is None:
+ print("No stable diffusion model loaded, exiting", file=sys.stderr)
+ exit(1)
shared.opts.data["sd_model_checkpoint"] = shared.sd_model.sd_checkpoint_info.title
shared.opts.onchange("sd_model_checkpoint", wrap_queued_call(lambda: modules.sd_models.reload_model_weights()))
shared.state.end()