Skip to content

Commit

Permalink
Merge branch 'master' into weighted-learning
Browse files Browse the repository at this point in the history
  • Loading branch information
AUTOMATIC1111 authored Feb 19, 2023
2 parents edb1009 + 4313777 commit dfb3b8f
Show file tree
Hide file tree
Showing 25 changed files with 159 additions and 59 deletions.
5 changes: 2 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,8 +104,7 @@ Alternatively, use online services (like Google Colab):
1. Install [Python 3.10.6](https://www.python.org/downloads/windows/), checking "Add Python to PATH"
2. Install [git](https://git-scm.com/download/win).
3. Download the stable-diffusion-webui repository, for example by running `git clone https://github.com/AUTOMATIC1111/stable-diffusion-webui.git`.
4. Place stable diffusion checkpoint (`model.ckpt`) in the `models/Stable-diffusion` directory (see [dependencies](https://github.com/AUTOMATIC1111/stable-diffusion-webui/wiki/Dependencies) for where to get it).
5. Run `webui-user.bat` from Windows Explorer as normal, non-administrator, user.
4. Run `webui-user.bat` from Windows Explorer as normal, non-administrator, user.

### Automatic Installation on Linux
1. Install the dependencies:
Expand All @@ -121,7 +120,7 @@ sudo pacman -S wget git python3
```bash
bash <(wget -qO- https://raw.githubusercontent.com/AUTOMATIC1111/stable-diffusion-webui/master/webui.sh)
```

3. Run `webui.sh`.
### Installation on Apple Silicon

Find the instructions [here](https://github.com/AUTOMATIC1111/stable-diffusion-webui/wiki/Installation-on-Apple-Silicon).
Expand Down
4 changes: 2 additions & 2 deletions javascript/hints.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ titles = {
"DDIM": "Denoising Diffusion Implicit Models - best at inpainting",
"DPM adaptive": "Ignores step count - uses a number of steps determined by the CFG and resolution",

"Batch count": "How many batches of images to create",
"Batch size": "How many image to create in a single batch",
"Batch count": "How many batches of images to create (has no impact on generation performance or VRAM usage)",
"Batch size": "How many image to create in a single batch (increases generation performance at cost of higher VRAM usage)",
"CFG Scale": "Classifier Free Guidance Scale - how strongly the image should conform to prompt - lower values produce more creative results",
"Seed": "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",
"\u{1f3b2}\ufe0f": "Set seed to -1, which will cause a new random number to be used every time",
Expand Down
2 changes: 1 addition & 1 deletion launch.py
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,7 @@ def prepare_environment():

sys.argv += shlex.split(commandline_args)

parser = argparse.ArgumentParser()
parser = argparse.ArgumentParser(add_help=False)
parser.add_argument("--ui-settings-file", type=str, help="filename to use for ui settings", default='config.json')
args, _ = parser.parse_known_args(sys.argv)

Expand Down
2 changes: 1 addition & 1 deletion modules/api/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -498,7 +498,7 @@ def train_hypernetwork(self, args: dict):
if not apply_optimizations:
sd_hijack.undo_optimizations()
try:
hypernetwork, filename = train_hypernetwork(*args)
hypernetwork, filename = train_hypernetwork(**args)
except Exception as e:
error = e
finally:
Expand Down
1 change: 1 addition & 0 deletions modules/esrgan_model_arch.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# this file is adapted from https://github.com/victorca25/iNNfer

from collections import OrderedDict
import math
import functools
import torch
Expand Down
6 changes: 6 additions & 0 deletions modules/extensions.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import sys
import traceback

import time
import git

from modules import paths, shared
Expand All @@ -25,6 +26,7 @@ def __init__(self, name, path, enabled=True, is_builtin=False):
self.status = ''
self.can_update = False
self.is_builtin = is_builtin
self.version = ''

repo = None
try:
Expand All @@ -40,6 +42,10 @@ def __init__(self, name, path, enabled=True, is_builtin=False):
try:
self.remote = next(repo.remote().urls, None)
self.status = 'unknown'
head = repo.head.commit
ts = time.asctime(time.gmtime(repo.head.commit.committed_date))
self.version = f'{head.hexsha[:8]} ({ts})'

except Exception:
self.remote = None

Expand Down
7 changes: 4 additions & 3 deletions modules/generation_parameters_copypaste.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,8 @@ def image_from_url_text(filedata):
return image


def add_paste_fields(tabname, init_img, fields):
paste_fields[tabname] = {"init_img": init_img, "fields": fields}
def add_paste_fields(tabname, init_img, fields, override_settings_component=None):
paste_fields[tabname] = {"init_img": init_img, "fields": fields, "override_settings_component": override_settings_component}

# backwards compatibility for existing extensions
import modules.ui
Expand Down Expand Up @@ -110,6 +110,7 @@ def connect_paste_params_buttons():
for binding in registered_param_bindings:
destination_image_component = paste_fields[binding.tabname]["init_img"]
fields = paste_fields[binding.tabname]["fields"]
override_settings_component = binding.override_settings_component or paste_fields[binding.tabname]["override_settings_component"]

destination_width_component = next(iter([field for field, name in fields if name == "Size-1"] if fields else []), None)
destination_height_component = next(iter([field for field, name in fields if name == "Size-2"] if fields else []), None)
Expand All @@ -130,7 +131,7 @@ def connect_paste_params_buttons():
)

if binding.source_text_component is not None and fields is not None:
connect_paste(binding.paste_button, fields, binding.source_text_component, binding.override_settings_component, binding.tabname)
connect_paste(binding.paste_button, fields, binding.source_text_component, override_settings_component, binding.tabname)

if binding.source_tabname is not None and fields is not None:
paste_field_names = ['Prompt', 'Negative prompt', 'Steps', 'Face restoration'] + (["Seed"] if shared.opts.send_seed else [])
Expand Down
4 changes: 2 additions & 2 deletions modules/hypernetworks/hypernetwork.py
Original file line number Diff line number Diff line change
Expand Up @@ -380,8 +380,8 @@ def apply_single_hypernetwork(hypernetwork, context_k, context_v, layer=None):
layer.hyper_k = hypernetwork_layers[0]
layer.hyper_v = hypernetwork_layers[1]

context_k = hypernetwork_layers[0](context_k)
context_v = hypernetwork_layers[1](context_v)
context_k = devices.cond_cast_unet(hypernetwork_layers[0](devices.cond_cast_float(context_k)))
context_v = devices.cond_cast_unet(hypernetwork_layers[1](devices.cond_cast_float(context_v)))
return context_k, context_v


Expand Down
18 changes: 11 additions & 7 deletions modules/images.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
import json
import hashlib

from modules import sd_samplers, shared, script_callbacks
from modules import sd_samplers, shared, script_callbacks, errors
from modules.shared import opts, cmd_opts

LANCZOS = (Image.Resampling.LANCZOS if hasattr(Image, 'Resampling') else Image.LANCZOS)
Expand Down Expand Up @@ -553,6 +553,8 @@ def _atomically_save_image(image_to_save, filename_without_extension, extension)
elif extension.lower() in (".jpg", ".jpeg", ".webp"):
if image_to_save.mode == 'RGBA':
image_to_save = image_to_save.convert("RGB")
elif image_to_save.mode == 'I;16':
image_to_save = image_to_save.point(lambda p: p * 0.0038910505836576).convert("RGB" if extension.lower() == ".webp" else "L")

image_to_save.save(temp_file_path, format=image_format, quality=opts.jpeg_quality)

Expand All @@ -575,17 +577,19 @@ def _atomically_save_image(image_to_save, filename_without_extension, extension)

image.already_saved_as = fullfn

target_side_length = 4000
oversize = image.width > target_side_length or image.height > target_side_length
if opts.export_for_4chan and (oversize or os.stat(fullfn).st_size > 4 * 1024 * 1024):
oversize = image.width > opts.target_side_length or image.height > opts.target_side_length
if opts.export_for_4chan and (oversize or os.stat(fullfn).st_size > opts.img_downscale_threshold * 1024 * 1024):
ratio = image.width / image.height

if oversize and ratio > 1:
image = image.resize((target_side_length, image.height * target_side_length // image.width), LANCZOS)
image = image.resize((opts.target_side_length, image.height * opts.target_side_length // image.width), LANCZOS)
elif oversize:
image = image.resize((image.width * target_side_length // image.height, target_side_length), LANCZOS)
image = image.resize((image.width * opts.target_side_length // image.height, opts.target_side_length), LANCZOS)

_atomically_save_image(image, fullfn_without_extension, ".jpg")
try:
_atomically_save_image(image, fullfn_without_extension, ".jpg")
except Exception as e:
errors.display(e, "saving image as downscaled JPG")

if opts.save_txt and info is not None:
txt_fullfn = f"{fullfn_without_extension}.txt"
Expand Down
2 changes: 2 additions & 0 deletions modules/img2img.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,8 @@ def process_batch(p, input_dir, output_dir, inpaint_mask_dir, args):

if not save_normally:
os.makedirs(output_dir, exist_ok=True)
if processed_image.mode == 'RGBA':
processed_image = processed_image.convert("RGB")
processed_image.save(os.path.join(output_dir, filename))


Expand Down
24 changes: 14 additions & 10 deletions modules/processing.py
Original file line number Diff line number Diff line change
Expand Up @@ -543,8 +543,6 @@ def infotext(iteration=0, position_in_batch=0):
if os.path.exists(cmd_opts.embeddings_dir) and not p.do_not_reload_embeddings:
model_hijack.embedding_db.load_textual_inversion_embeddings()

_, extra_network_data = extra_networks.parse_prompts(p.all_prompts[0:1])

if p.scripts is not None:
p.scripts.process(p)

Expand Down Expand Up @@ -582,13 +580,6 @@ def get_conds_with_caching(function, required_prompts, steps, cache):
if shared.opts.live_previews_enable and opts.show_progress_type == "Approx NN":
sd_vae_approx.model()

if not p.disable_extra_networks:
extra_networks.activate(p, extra_network_data)

with open(os.path.join(paths.data_path, "params.txt"), "w", encoding="utf8") as file:
processed = Processed(p, [], p.seed, "")
file.write(processed.infotext(p, 0))

if state.job_count == -1:
state.job_count = p.n_iter

Expand All @@ -609,11 +600,24 @@ def get_conds_with_caching(function, required_prompts, steps, cache):
if len(prompts) == 0:
break

prompts, _ = extra_networks.parse_prompts(prompts)
prompts, extra_network_data = extra_networks.parse_prompts(prompts)

if not p.disable_extra_networks:
with devices.autocast():
extra_networks.activate(p, extra_network_data)

if p.scripts is not None:
p.scripts.process_batch(p, batch_number=n, prompts=prompts, seeds=seeds, subseeds=subseeds)

# params.txt should be saved after scripts.process_batch, since the
# infotext could be modified by that callback
# Example: a wildcard processed by process_batch sets an extra model
# strength, which is saved as "Model Strength: 1.0" in the infotext
if n == 0:
with open(os.path.join(paths.data_path, "params.txt"), "w", encoding="utf8") as file:
processed = Processed(p, [], p.seed, "")
file.write(processed.infotext(p, 0))

uc = get_conds_with_caching(prompt_parser.get_learned_conditioning, negative_prompts, p.steps, cached_uc)
c = get_conds_with_caching(prompt_parser.get_multicond_learned_conditioning, prompts, p.steps, cached_c)

Expand Down
29 changes: 29 additions & 0 deletions modules/script_callbacks.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,18 @@ def __init__(self, x, image_cond, sigma, sampling_step, total_sampling_steps):
"""Total number of sampling steps planned"""


class CFGDenoisedParams:
def __init__(self, x, sampling_step, total_sampling_steps):
self.x = x
"""Latent image representation in the process of being denoised"""

self.sampling_step = sampling_step
"""Current Sampling step number"""

self.total_sampling_steps = total_sampling_steps
"""Total number of sampling steps planned"""


class UiTrainTabParams:
def __init__(self, txt2img_preview_params):
self.txt2img_preview_params = txt2img_preview_params
Expand All @@ -68,6 +80,7 @@ def __init__(self, imgs, cols, rows):
callbacks_before_image_saved=[],
callbacks_image_saved=[],
callbacks_cfg_denoiser=[],
callbacks_cfg_denoised=[],
callbacks_before_component=[],
callbacks_after_component=[],
callbacks_image_grid=[],
Expand Down Expand Up @@ -150,6 +163,14 @@ def cfg_denoiser_callback(params: CFGDenoiserParams):
report_exception(c, 'cfg_denoiser_callback')


def cfg_denoised_callback(params: CFGDenoisedParams):
for c in callback_map['callbacks_cfg_denoised']:
try:
c.callback(params)
except Exception:
report_exception(c, 'cfg_denoised_callback')


def before_component_callback(component, **kwargs):
for c in callback_map['callbacks_before_component']:
try:
Expand Down Expand Up @@ -283,6 +304,14 @@ def on_cfg_denoiser(callback):
add_callback(callback_map['callbacks_cfg_denoiser'], callback)


def on_cfg_denoised(callback):
"""register a function to be called in the kdiffussion cfg_denoiser method after building the inner model inputs.
The callback is called with one argument:
- params: CFGDenoisedParams - parameters to be passed to the inner model and sampling state details.
"""
add_callback(callback_map['callbacks_cfg_denoised'], callback)


def on_before_component(callback):
"""register a function to be called before a component is created.
The callback is called with arguments:
Expand Down
2 changes: 2 additions & 0 deletions modules/sd_hijack.py
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,8 @@ def hijack(self, m):
m.cond_stage_model = sd_hijack_open_clip.FrozenOpenCLIPEmbedderWithCustomWords(m.cond_stage_model, self)

apply_weighted_forward(m)
if m.cond_stage_key == "edit":
sd_hijack_unet.hijack_ddpm_edit()

self.optimization_method = apply_optimizations()

Expand Down
1 change: 1 addition & 0 deletions modules/sd_hijack_inpainting.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
from ldm.models.diffusion.ddpm import LatentDiffusion
from ldm.models.diffusion.plms import PLMSSampler
from ldm.models.diffusion.ddim import DDIMSampler, noise_like
from ldm.models.diffusion.sampling_util import norm_thresholding


@torch.no_grad()
Expand Down
11 changes: 11 additions & 0 deletions modules/sd_hijack_unet.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ def apply_model(orig_func, self, x_noisy, t, cond, **kwargs):
with devices.autocast():
return orig_func(self, x_noisy.to(devices.dtype_unet), t.to(devices.dtype_unet), cond, **kwargs).float()


class GELUHijack(torch.nn.GELU, torch.nn.Module):
def __init__(self, *args, **kwargs):
torch.nn.GELU.__init__(self, *args, **kwargs)
Expand All @@ -53,6 +54,16 @@ def forward(self, x):
else:
return torch.nn.GELU.forward(self, x)


ddpm_edit_hijack = None
def hijack_ddpm_edit():
global ddpm_edit_hijack
if not ddpm_edit_hijack:
CondFunc('modules.models.diffusion.ddpm_edit.LatentDiffusion.decode_first_stage', first_stage_sub, first_stage_cond)
CondFunc('modules.models.diffusion.ddpm_edit.LatentDiffusion.encode_first_stage', first_stage_sub, first_stage_cond)
ddpm_edit_hijack = CondFunc('modules.models.diffusion.ddpm_edit.LatentDiffusion.apply_model', apply_model, unet_needs_upcast)


unet_needs_upcast = lambda *args, **kwargs: devices.unet_needs_upcast
CondFunc('ldm.models.diffusion.ddpm.LatentDiffusion.apply_model', apply_model, unet_needs_upcast)
CondFunc('ldm.modules.diffusionmodules.openaimodel.timestep_embedding', lambda orig_func, timesteps, *args, **kwargs: orig_func(timesteps, *args, **kwargs).to(torch.float32 if timesteps.dtype == torch.int64 else devices.dtype_unet), unet_needs_upcast)
Expand Down
2 changes: 1 addition & 1 deletion modules/sd_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ def alphanumeric_key(key):
def list_models():
checkpoints_list.clear()
checkpoint_alisases.clear()
model_list = modelloader.load_models(model_path=model_path, command_path=shared.cmd_opts.ckpt_dir, ext_filter=[".ckpt", ".safetensors"], ext_blacklist=[".vae.safetensors"])
model_list = modelloader.load_models(model_path=model_path, model_url="https://huggingface.co/runwayml/stable-diffusion-v1-5/resolve/main/v1-5-pruned-emaonly.safetensors", command_path=shared.cmd_opts.ckpt_dir, ext_filter=[".ckpt", ".safetensors"], download_name="v1-5-pruned-emaonly.safetensors", ext_blacklist=[".vae.ckpt", ".vae.safetensors"])

cmd_ckpt = shared.cmd_opts.ckpt
if os.path.exists(cmd_ckpt):
Expand Down
Loading

0 comments on commit dfb3b8f

Please sign in to comment.