mirror of
https://github.com/vladmandic/automatic
synced 2026-09-18 16:54:33 +02:00
diffusers merge
This commit is contained in:
Submodule extensions-builtin/sd-webui-controlnet updated: a83a260605...0d1c252cad
Submodule extensions-builtin/stable-diffusion-webui-images-browser updated: 7da8aec62b...c61fae964a
@@ -1,6 +1,7 @@
|
||||
/* global gradioApp, onUiUpdate, opts */
|
||||
|
||||
window.opts = {};
|
||||
window.localization = {};
|
||||
let tabSelected = '';
|
||||
|
||||
function set_theme(theme) {
|
||||
@@ -192,6 +193,22 @@ function recalculate_prompts_inpaint(...args) {
|
||||
return args_to_array(args);
|
||||
}
|
||||
|
||||
function register_drag_drop() {
|
||||
const qs = gradioApp().getElementById('quicksettings');
|
||||
if (!qs) return;
|
||||
qs.addEventListener('dragover', (evt) => {
|
||||
evt.preventDefault();
|
||||
evt.dataTransfer.dropEffect = 'copy';
|
||||
});
|
||||
qs.addEventListener('drop', (evt) => {
|
||||
evt.preventDefault();
|
||||
evt.dataTransfer.dropEffect = 'copy';
|
||||
for (const f of evt.dataTransfer.files) {
|
||||
console.log('QuickSettingsDrop', f);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
onUiUpdate(() => {
|
||||
sort_ui_elements();
|
||||
if (Object.keys(opts).length !== 0) return;
|
||||
@@ -202,6 +219,7 @@ onUiUpdate(() => {
|
||||
const jsdata = textarea.value;
|
||||
opts = JSON.parse(jsdata);
|
||||
executeCallbacks(optionsChangedCallbacks);
|
||||
register_drag_drop();
|
||||
|
||||
Object.defineProperty(textarea, 'value', {
|
||||
set(newValue) {
|
||||
|
||||
@@ -65,10 +65,7 @@ def wrap_gradio_call(func, extra_outputs=None, add_stats=False):
|
||||
if shared.cmd_opts.profile:
|
||||
pr.disable()
|
||||
s = io.StringIO()
|
||||
ps = pstats.Stats(pr, stream=s)
|
||||
ps.sort_stats(pstats.SortKey.CUMULATIVE)
|
||||
# ps.strip_dirs()
|
||||
ps.print_stats(15)
|
||||
pstats.Stats(pr, stream=s).sort_stats(pstats.SortKey.CUMULATIVE).print_stats(15)
|
||||
print('Profile Exec:', s.getvalue())
|
||||
except Exception as e:
|
||||
errors.display(e, 'gradio call')
|
||||
|
||||
+1
-1
@@ -34,7 +34,7 @@ def print_error_explanation(message):
|
||||
|
||||
def display(e: Exception, task, suppress=[]):
|
||||
log.error(f"{task or 'error'}: {type(e).__name__}")
|
||||
console.print_exception(show_locals=False, max_frames=2, extra_lines=1, suppress=suppress, theme="ansi_dark", word_wrap=False, width=min([console.width, 200]))
|
||||
console.print_exception(show_locals=False, max_frames=5, extra_lines=1, suppress=suppress, theme="ansi_dark", word_wrap=False, width=min([console.width, 200]))
|
||||
|
||||
|
||||
def display_once(e: Exception, task):
|
||||
|
||||
+14
-5
@@ -642,18 +642,27 @@ Steps: {json_info["steps"]}, Sampler: {sampler}, CFG scale: {json_info["scale"]}
|
||||
|
||||
def image_data(data):
|
||||
import gradio as gr
|
||||
if data is None:
|
||||
return gr.update(), None
|
||||
err1 = None
|
||||
err2 = None
|
||||
try:
|
||||
image = Image.open(io.BytesIO(data))
|
||||
errors.log.debug(f'Decoded object: image={image}')
|
||||
textinfo, _ = read_info_from_image(image)
|
||||
return textinfo, None
|
||||
except Exception:
|
||||
pass
|
||||
except Exception as e:
|
||||
err1 = e
|
||||
try:
|
||||
if len(data) > 1024 * 10:
|
||||
errors.log.warning(f'Error decoding object: data too long: {len(data)}')
|
||||
return gr.update(), None
|
||||
text = data.decode('utf8')
|
||||
assert len(text) < 10000
|
||||
errors.log.debug(f'Decoded object: size={len(text)}')
|
||||
return text, None
|
||||
except Exception:
|
||||
pass
|
||||
except Exception as e:
|
||||
err2 = e
|
||||
errors.log.error(f'Error decoding object: {err1 or err2}')
|
||||
return gr.update(), None
|
||||
|
||||
|
||||
|
||||
@@ -70,6 +70,9 @@ def img2img(id_task: str, mode: int, prompt: str, negative_prompt: str, prompt_s
|
||||
if shared.sd_model is None:
|
||||
shared.log.warning('Model not loaded')
|
||||
return
|
||||
if init_img is None:
|
||||
shared.log.warning('Init image not set')
|
||||
return
|
||||
shared.log.debug(f'img2img: id_task={id_task}|mode={mode}|prompt={prompt}|negative_prompt={negative_prompt}|prompt_styles={prompt_styles}|init_img={init_img}|sketch={sketch}|init_img_with_mask={init_img_with_mask}|inpaint_color_sketch={inpaint_color_sketch}|inpaint_color_sketch_orig={inpaint_color_sketch_orig}|init_img_inpaint={init_img_inpaint}|init_mask_inpaint={init_mask_inpaint}|steps={steps}|sampler_index={sampler_index}|mask_blur={mask_blur}|mask_alpha={mask_alpha}|inpainting_fill={inpainting_fill}|restore_faces={restore_faces}|tiling={tiling}|n_iter={n_iter}|batch_size={batch_size}|cfg_scale={cfg_scale}|image_cfg_scale={image_cfg_scale}|clip_skip={clip_skip}|denoising_strength={denoising_strength}|seed={seed}|subseed{subseed}|subseed_strength={subseed_strength}|seed_resize_from_h={seed_resize_from_h}|seed_resize_from_w={seed_resize_from_w}|seed_enable_extras={seed_enable_extras}|selected_scale_tab={selected_scale_tab}|height={height}|width={width}|scale_by={scale_by}|resize_mode={resize_mode}|inpaint_full_res={inpaint_full_res}|inpaint_full_res_padding={inpaint_full_res_padding}|inpainting_mask_invert={inpainting_mask_invert}|img2img_batch_input_dir={img2img_batch_input_dir}|img2img_batch_output_dir={img2img_batch_output_dir}|img2img_batch_inpaint_mask_dir={img2img_batch_inpaint_mask_dir}|override_settings_texts={override_settings_texts}|args={args}')
|
||||
|
||||
if sampler_index is None:
|
||||
|
||||
+39
-26
@@ -8,7 +8,7 @@ from modules.upscaler import Upscaler, UpscalerLanczos, UpscalerNearest, Upscale
|
||||
from modules.paths import script_path, models_path
|
||||
|
||||
|
||||
def load_models(model_path: str, model_url: str = None, command_path: str = None, ext_filter=None, download_name=None, ext_blacklist=None) -> list:
|
||||
def load_models(model_path: str, model_url: str = None, command_path: str = None, ext_filter=None, download_name=None, ext_blacklist=None, diffusors=False) -> list:
|
||||
"""
|
||||
A one-and done loader to try finding the desired models in specified directories.
|
||||
|
||||
@@ -19,32 +19,45 @@ def load_models(model_path: str, model_url: str = None, command_path: str = None
|
||||
@param ext_filter: An optional list of filename extensions to filter by
|
||||
@return: A list of paths containing the desired model(s)
|
||||
"""
|
||||
output = []
|
||||
try:
|
||||
places = []
|
||||
places.append(model_path)
|
||||
if command_path is not None and command_path != model_path and os.path.isdir(command_path):
|
||||
places.append(command_path)
|
||||
for place in places:
|
||||
for full_path in shared.walk_files(place, allowed_extensions=ext_filter):
|
||||
if os.path.islink(full_path) and not os.path.exists(full_path):
|
||||
print(f"Skipping broken symlink: {full_path}")
|
||||
continue
|
||||
if ext_blacklist is not None and any([full_path.endswith(x) for x in ext_blacklist]):
|
||||
continue
|
||||
if full_path not in output:
|
||||
output.append(full_path)
|
||||
if model_url is not None and len(output) == 0:
|
||||
if download_name is not None:
|
||||
from basicsr.utils.download_util import load_file_from_url
|
||||
dl = load_file_from_url(model_url, model_path, True, download_name)
|
||||
output.append(dl)
|
||||
else:
|
||||
output.append(model_url)
|
||||
except Exception:
|
||||
pass
|
||||
places = []
|
||||
places.append(model_path)
|
||||
if command_path is not None and command_path != model_path and os.path.isdir(command_path):
|
||||
places.append(command_path)
|
||||
|
||||
return output
|
||||
def get_checkpoints():
|
||||
output = []
|
||||
try:
|
||||
for place in places:
|
||||
for full_path in shared.walk_files(place, allowed_extensions=ext_filter):
|
||||
if os.path.islink(full_path) and not os.path.exists(full_path):
|
||||
print(f"Skipping broken symlink: {full_path}")
|
||||
continue
|
||||
if ext_blacklist is not None and any([full_path.endswith(x) for x in ext_blacklist]):
|
||||
continue
|
||||
if full_path not in output:
|
||||
output.append(full_path)
|
||||
if model_url is not None and len(output) == 0:
|
||||
if download_name is not None:
|
||||
from basicsr.utils.download_util import load_file_from_url
|
||||
dl = load_file_from_url(model_url, model_path, True, download_name)
|
||||
output.append(dl)
|
||||
else:
|
||||
output.append(model_url)
|
||||
except Exception:
|
||||
pass
|
||||
return output
|
||||
|
||||
def get_diffusors():
|
||||
output = []
|
||||
for place in places:
|
||||
output = os.listdir(place)
|
||||
output = [os.path.join(place, x) for x in output]
|
||||
return output
|
||||
|
||||
if not diffusors:
|
||||
return get_checkpoints()
|
||||
else:
|
||||
return get_diffusors()
|
||||
|
||||
|
||||
def friendly_name(file: str):
|
||||
|
||||
+88
-52
@@ -3,11 +3,13 @@ import math
|
||||
import os
|
||||
import hashlib
|
||||
import random
|
||||
from contextlib import nullcontext
|
||||
from typing import Any, Dict, List
|
||||
import torch
|
||||
import numpy as np
|
||||
from PIL import Image, ImageFilter, ImageOps
|
||||
import cv2
|
||||
import tomesd
|
||||
from skimage import exposure
|
||||
from ldm.data.util import AddMiDaS
|
||||
from ldm.models.diffusion.ddpm import LatentDepth2ImageDiffusion
|
||||
@@ -25,7 +27,7 @@ import modules.images as images
|
||||
import modules.styles
|
||||
import modules.sd_models as sd_models
|
||||
import modules.sd_vae as sd_vae
|
||||
import tomesd # pylint: disable=wrong-import-order
|
||||
|
||||
|
||||
opt_C = 4
|
||||
opt_f = 8
|
||||
@@ -218,6 +220,8 @@ class StableDiffusionProcessing:
|
||||
source_image = devices.cond_cast_float(source_image)
|
||||
# HACK: Using introspection as the Depth2Image model doesn't appear to uniquely
|
||||
# identify itself with a field common to all models. The conditioning_key is also hybrid.
|
||||
if opts.sd_backend == 'Diffusers': # TODO: img2img_image_conditioning
|
||||
return latent_image.new_zeros(latent_image.shape[0], 5, 1, 1)
|
||||
if isinstance(self.sd_model, LatentDepth2ImageDiffusion):
|
||||
return self.depth2img_image_conditioning(source_image)
|
||||
if self.sd_model.cond_stage_key == "edit":
|
||||
@@ -456,9 +460,19 @@ def create_infotext(p: StableDiffusionProcessing, all_prompts, all_seeds, all_su
|
||||
return f"{all_prompts[index]}{negative_prompt_text}\n{generation_params_text}".strip()
|
||||
|
||||
|
||||
def print_profile(profile, msg: str):
|
||||
try:
|
||||
from rich import print # pylint: disable=redefined-builtin
|
||||
except:
|
||||
pass
|
||||
lines = profile.key_averages().table(sort_by="cuda_time_total", row_limit=20)
|
||||
lines = lines.split('\n')
|
||||
lines = [l for l in lines if '/profiler' not in l]
|
||||
print(f'Profile {msg}:', '\n'.join(lines))
|
||||
|
||||
|
||||
def process_images(p: StableDiffusionProcessing) -> Processed:
|
||||
stored_opts = {k: opts.data[k] for k in p.override_settings.keys()}
|
||||
|
||||
try:
|
||||
# if no checkpoint override or the override checkpoint can't be found, remove override entry and load opts checkpoint
|
||||
if p.override_settings.get('sd_model_checkpoint', None) is not None and sd_models.checkpoint_aliases.get(p.override_settings.get('sd_model_checkpoint')) is None:
|
||||
@@ -471,28 +485,24 @@ def process_images(p: StableDiffusionProcessing) -> Processed:
|
||||
if k == 'sd_vae':
|
||||
sd_vae.reload_vae_weights()
|
||||
|
||||
"""
|
||||
import torch.profiler
|
||||
with torch.profiler.profile(activities=[torch.profiler.ProfilerActivity.CPU, torch.profiler.ProfilerActivity.CUDA], record_shapes=True, with_modules=True) as prof:
|
||||
with torch.profiler.record_function("process_images"):
|
||||
res = process_images_inner(p)
|
||||
print(prof.key_averages().table(sort_by="cuda_time_total", row_limit=15))
|
||||
"""
|
||||
|
||||
if (opts.token_merging or cmd_opts.token_merging) and not opts.token_merging_hr_only:
|
||||
sd_models.apply_token_merging(sd_model=p.sd_model, hr=False)
|
||||
log.debug('Token merging applied')
|
||||
|
||||
res = process_images_inner(p)
|
||||
|
||||
if cmd_opts.profile:
|
||||
import torch.profiler # pylint: disable=redefined-outer-name
|
||||
# activities=[torch.profiler.ProfilerActivity.CPU, torch.profiler.ProfilerActivity.CUDA]
|
||||
with torch.profiler.profile(profile_memory=True, with_modules=True) as prof:
|
||||
with torch.profiler.record_function("process_images"):
|
||||
res = process_images_inner(p)
|
||||
print_profile(prof, 'process_images')
|
||||
else:
|
||||
res = process_images_inner(p)
|
||||
finally:
|
||||
# undo model optimizations made by tomesd
|
||||
if opts.token_merging or cmd_opts.token_merging:
|
||||
tomesd.remove_patch(p.sd_model)
|
||||
log.debug('Token merging model optimizations removed')
|
||||
|
||||
# restore opts to original state
|
||||
if p.override_settings_restore_afterwards:
|
||||
if p.override_settings_restore_afterwards: # restore opts to original state
|
||||
for k, v in stored_opts.items():
|
||||
setattr(opts, k, v)
|
||||
if k == 'sd_model_checkpoint':
|
||||
@@ -500,7 +510,6 @@ def process_images(p: StableDiffusionProcessing) -> Processed:
|
||||
|
||||
if k == 'sd_vae':
|
||||
sd_vae.reload_vae_weights()
|
||||
|
||||
return res
|
||||
|
||||
|
||||
@@ -513,8 +522,9 @@ def process_images_inner(p: StableDiffusionProcessing) -> Processed:
|
||||
assert p.prompt is not None
|
||||
seed = get_fixed_seed(p.seed)
|
||||
subseed = get_fixed_seed(p.subseed)
|
||||
modules.sd_hijack.model_hijack.apply_circular(p.tiling)
|
||||
modules.sd_hijack.model_hijack.clear_comments()
|
||||
if opts.sd_backend == 'Original':
|
||||
modules.sd_hijack.model_hijack.apply_circular(p.tiling)
|
||||
modules.sd_hijack.model_hijack.clear_comments()
|
||||
comments = {}
|
||||
if type(p.prompt) == list:
|
||||
p.all_prompts = [shared.prompt_styles.apply_styles_to_prompt(x, p.styles) for x in p.prompt]
|
||||
@@ -563,10 +573,11 @@ def process_images_inner(p: StableDiffusionProcessing) -> Processed:
|
||||
cache[0] = (required_prompts, steps)
|
||||
return cache[1]
|
||||
|
||||
with torch.no_grad(), p.sd_model.ema_scope():
|
||||
ema_scope_context = p.sd_model.ema_scope if opts.sd_backend == 'Original' else nullcontext
|
||||
with torch.no_grad(), ema_scope_context():
|
||||
with devices.autocast():
|
||||
p.init(p.all_prompts, p.all_seeds, p.all_subseeds)
|
||||
if shared.opts.live_previews_enable and opts.show_progress_type == "Approx NN":
|
||||
if shared.opts.live_previews_enable and opts.show_progress_type == "Approx NN" and opts.sd_backend == 'Original':
|
||||
sd_vae_approx.model()
|
||||
if state.job_count == -1:
|
||||
state.job_count = p.n_iter
|
||||
@@ -604,42 +615,67 @@ def process_images_inner(p: StableDiffusionProcessing) -> Processed:
|
||||
step_multiplier = 2 if sd_samplers.all_samplers_map.get(p.sampler_name).aliases[0] in ['k_dpmpp_2s_a', 'k_dpmpp_2s_a_ka', 'k_dpmpp_sde', 'k_dpmpp_sde_ka', 'k_dpm_2', 'k_dpm_2_a', 'k_heun'] else 1
|
||||
except:
|
||||
pass
|
||||
uc = get_conds_with_caching(prompt_parser.get_learned_conditioning, negative_prompts, p.steps * step_multiplier, cached_uc)
|
||||
c = get_conds_with_caching(prompt_parser.get_multicond_learned_conditioning, prompts, p.steps * step_multiplier, cached_c)
|
||||
if len(model_hijack.comments) > 0:
|
||||
for comment in model_hijack.comments:
|
||||
comments[comment] = 1
|
||||
if p.n_iter > 1:
|
||||
shared.state.job = f"Batch {n+1} out of {p.n_iter}"
|
||||
with devices.without_autocast() if devices.unet_needs_upcast else devices.autocast():
|
||||
samples_ddim = p.sample(conditioning=c, unconditional_conditioning=uc, seeds=seeds, subseeds=subseeds, subseed_strength=p.subseed_strength, prompts=prompts)
|
||||
x_samples_ddim = [decode_first_stage(p.sd_model, samples_ddim[i:i+1].to(dtype=devices.dtype_vae))[0].cpu() for i in range(samples_ddim.size(0))]
|
||||
try:
|
||||
for x in x_samples_ddim:
|
||||
devices.test_for_nans(x, "vae")
|
||||
except devices.NansException as e:
|
||||
if not shared.opts.no_half and not shared.opts.no_half_vae and shared.cmd_opts.rollback_vae:
|
||||
log.warning('Tensor with all NaNs was produced in VAE')
|
||||
devices.dtype_vae = torch.bfloat16
|
||||
vae_file, vae_source = sd_vae.resolve_vae(p.sd_model.sd_model_checkpoint)
|
||||
sd_vae.load_vae(p.sd_model, vae_file, vae_source)
|
||||
x_samples_ddim = [decode_first_stage(p.sd_model, samples_ddim[i:i+1].to(dtype=devices.dtype_vae))[0].cpu() for i in range(samples_ddim.size(0))]
|
||||
|
||||
if opts.sd_backend == 'Original':
|
||||
uc = get_conds_with_caching(prompt_parser.get_learned_conditioning, negative_prompts, p.steps * step_multiplier, cached_uc)
|
||||
c = get_conds_with_caching(prompt_parser.get_multicond_learned_conditioning, prompts, p.steps * step_multiplier, cached_c)
|
||||
if len(model_hijack.comments) > 0:
|
||||
for comment in model_hijack.comments:
|
||||
comments[comment] = 1
|
||||
with devices.without_autocast() if devices.unet_needs_upcast else devices.autocast():
|
||||
samples_ddim = p.sample(conditioning=c, unconditional_conditioning=uc, seeds=seeds, subseeds=subseeds, subseed_strength=p.subseed_strength, prompts=prompts)
|
||||
x_samples_ddim = [decode_first_stage(p.sd_model, samples_ddim[i:i+1].to(dtype=devices.dtype_vae))[0].cpu() for i in range(samples_ddim.size(0))]
|
||||
try:
|
||||
for x in x_samples_ddim:
|
||||
devices.test_for_nans(x, "vae")
|
||||
else:
|
||||
raise e
|
||||
x_samples_ddim = torch.stack(x_samples_ddim).float()
|
||||
x_samples_ddim = torch.clamp((x_samples_ddim + 1.0) / 2.0, min=0.0, max=1.0)
|
||||
del samples_ddim
|
||||
if shared.cmd_opts.lowvram or shared.cmd_opts.medvram:
|
||||
lowvram.send_everything_to_cpu()
|
||||
devices.torch_gc()
|
||||
if p.scripts is not None:
|
||||
p.scripts.postprocess_batch(p, x_samples_ddim, batch_number=n)
|
||||
except devices.NansException as e:
|
||||
if not shared.opts.no_half and not shared.opts.no_half_vae and shared.cmd_opts.rollback_vae:
|
||||
log.warning('Tensor with all NaNs was produced in VAE')
|
||||
devices.dtype_vae = torch.bfloat16
|
||||
vae_file, vae_source = sd_vae.resolve_vae(p.sd_model.sd_model_checkpoint)
|
||||
sd_vae.load_vae(p.sd_model, vae_file, vae_source)
|
||||
x_samples_ddim = [decode_first_stage(p.sd_model, samples_ddim[i:i+1].to(dtype=devices.dtype_vae))[0].cpu() for i in range(samples_ddim.size(0))]
|
||||
for x in x_samples_ddim:
|
||||
devices.test_for_nans(x, "vae")
|
||||
else:
|
||||
raise e
|
||||
x_samples_ddim = torch.stack(x_samples_ddim).float()
|
||||
x_samples_ddim = torch.clamp((x_samples_ddim + 1.0) / 2.0, min=0.0, max=1.0)
|
||||
del samples_ddim
|
||||
if shared.cmd_opts.lowvram or shared.cmd_opts.medvram:
|
||||
lowvram.send_everything_to_cpu()
|
||||
devices.torch_gc()
|
||||
if p.scripts is not None:
|
||||
p.scripts.postprocess_batch(p, x_samples_ddim, batch_number=n)
|
||||
else: # TODO Diffusers
|
||||
generator = [torch.Generator(device="cpu").manual_seed(s) for s in seeds]
|
||||
if shared.sd_model.scheduler.name != p.sampler_name:
|
||||
sampler = sd_samplers.all_samplers_map.get(p.sampler_name, None)
|
||||
if sampler is None:
|
||||
sampler = sd_samplers.all_samplers_map.get("UniPC")
|
||||
scheduler = sampler.constructor(shared.sd_model.sd_checkpoint_info.filename)
|
||||
shared.sd_model.scheduler = scheduler.sampler
|
||||
output = shared.sd_model(
|
||||
prompt=prompts,
|
||||
negative_prompt=negative_prompts,
|
||||
num_inference_steps=p.steps,
|
||||
guidance_scale=p.cfg_scale,
|
||||
height=p.height,
|
||||
width=p.width,
|
||||
generator=generator,
|
||||
output_type="np",
|
||||
)
|
||||
x_samples_ddim = output.images
|
||||
|
||||
for i, x_sample in enumerate(x_samples_ddim):
|
||||
p.batch_index = i
|
||||
x_sample = 255. * np.moveaxis(x_sample.cpu().numpy(), 0, 2)
|
||||
x_sample = x_sample.astype(np.uint8)
|
||||
if opts.sd_backend == 'Original':
|
||||
x_sample = 255. * np.moveaxis(x_sample.cpu().numpy(), 0, 2)
|
||||
x_sample = x_sample.astype(np.uint8)
|
||||
else:
|
||||
x_sample = (255. * x_sample).astype(np.uint8)
|
||||
if p.restore_faces:
|
||||
if opts.save and not p.do_not_save_samples and opts.save_images_before_face_restoration:
|
||||
orig = p.restore_faces
|
||||
@@ -891,7 +927,7 @@ class StableDiffusionProcessingImg2Img(StableDiffusionProcessing):
|
||||
self.init_images = init_images
|
||||
self.resize_mode: int = resize_mode
|
||||
self.denoising_strength: float = denoising_strength
|
||||
self.image_cfg_scale: float = image_cfg_scale if shared.sd_model.cond_stage_key == "edit" else None
|
||||
self.image_cfg_scale: float = image_cfg_scale if (shared.sd_model is not None) and hasattr(shared.sd_model, 'cond_stage_key') and (shared.sd_model.cond_stage_key == "edit") else None
|
||||
self.init_latent = None
|
||||
self.image_mask = mask
|
||||
self.latent_mask = None
|
||||
|
||||
@@ -12,10 +12,7 @@ def load_module(path, detailed=False):
|
||||
try:
|
||||
module_spec.loader.exec_module(module)
|
||||
except Exception as e:
|
||||
if detailed:
|
||||
errors.display(e, f'Module load: {path}')
|
||||
else:
|
||||
errors.log.error(f'Module load: {path}')
|
||||
errors.display(e, f'Module load: {path}')
|
||||
return module
|
||||
|
||||
|
||||
@@ -31,11 +28,8 @@ def preload_extensions(extensions_dir, parser, detailed=False):
|
||||
if not os.path.isfile(preload_script):
|
||||
continue
|
||||
try:
|
||||
module = load_module(preload_script)
|
||||
module = load_module(preload_script, detailed)
|
||||
if hasattr(module, 'preload'):
|
||||
module.preload(parser)
|
||||
except Exception as e:
|
||||
if detailed:
|
||||
errors.display(e, f'Extension preload: {preload_script}')
|
||||
else:
|
||||
errors.log.error(f'Extension preload: {preload_script}')
|
||||
errors.display(e, f'Extension preload: {preload_script}')
|
||||
|
||||
@@ -136,7 +136,6 @@ class FrozenCLIPEmbedderWithCustomWordsBase(torch.nn.Module):
|
||||
position += embedding_length_in_tokens
|
||||
if len(chunk.tokens) > 0 or len(chunks) == 0:
|
||||
next_chunk(is_last=True)
|
||||
# print('CHUNKS', [vars(c) for c in chunks]) # TODO
|
||||
return chunks, token_count
|
||||
|
||||
def process_texts(self, texts):
|
||||
|
||||
+52
-6
@@ -27,7 +27,7 @@ checkpoints_loaded = collections.OrderedDict()
|
||||
skip_next_load = False
|
||||
|
||||
|
||||
class CheckpointInfo:
|
||||
class CheckpointInfo: # TODO Diffusers
|
||||
def __init__(self, filename):
|
||||
self.filename = filename
|
||||
abspath = os.path.abspath(filename)
|
||||
@@ -42,8 +42,13 @@ class CheckpointInfo:
|
||||
self.name = name
|
||||
self.name_for_extra = os.path.splitext(os.path.basename(filename))[0]
|
||||
self.model_name = os.path.splitext(name.replace("/", "_").replace("\\", "_"))[0]
|
||||
self.hash = model_hash(filename)
|
||||
self.sha256 = hashes.sha256_from_cache(self.filename, f"checkpoint/{name}")
|
||||
if shared.opts.sd_backend == 'Original':
|
||||
self.hash = model_hash(self.filename)
|
||||
self.sha256 = hashes.sha256_from_cache(self.filename, f"checkpoint/{name}")
|
||||
else: # TODO Diffusers calculate hash
|
||||
# sd_model.unet.config._name_or_path.split("/")[-2]
|
||||
self.hash = 'ABCDEFGH'
|
||||
self.sha256 = 'ABCDEFGH'
|
||||
self.shorthash = self.sha256[0:10] if self.sha256 else None
|
||||
self.title = name if self.shorthash is None else f'{name} [{self.shorthash}]'
|
||||
self.ids = [self.hash, self.model_name, self.title, name, f'{name} [{self.hash}]'] + ([self.shorthash, self.sha256, f'{self.name} [{self.shorthash}]'] if self.shorthash else [])
|
||||
@@ -99,9 +104,12 @@ def checkpoint_tiles():
|
||||
def list_models():
|
||||
checkpoints_list.clear()
|
||||
checkpoint_aliases.clear()
|
||||
model_list = modelloader.load_models(model_path=os.path.join(models_path, 'Stable-diffusion'), model_url=None, command_path=shared.opts.ckpt_dir, ext_filter=[".ckpt", ".safetensors"], download_name=None, ext_blacklist=[".vae.ckpt", ".vae.safetensors"])
|
||||
if shared.opts.sd_backend == 'Original':
|
||||
model_list = modelloader.load_models(model_path=os.path.join(models_path, 'Stable-diffusion'), model_url=None, command_path=shared.opts.ckpt_dir, ext_filter=[".ckpt", ".safetensors"], download_name=None, ext_blacklist=[".vae.ckpt", ".vae.safetensors"])
|
||||
else:
|
||||
model_list = modelloader.load_models(model_path=os.path.join(models_path, 'Diffusers'), model_url=None, command_path=shared.opts.diffusers_dir, ext_filter=[".ckpt", ".safetensors"], download_name=None, ext_blacklist=[".vae.ckpt", ".vae.safetensors"])
|
||||
if shared.cmd_opts.ckpt is not None:
|
||||
if not os.path.exists(shared.cmd_opts.ckpt):
|
||||
if not os.path.exists(shared.cmd_opts.ckpt) and shared.opts.sd_backend == 'Original':
|
||||
if shared.cmd_opts.ckpt.lower() != "none":
|
||||
shared.log.warning(f"Requested checkpoint not found: {shared.cmd_opts.ckpt}")
|
||||
else:
|
||||
@@ -363,7 +371,12 @@ class SdModelData:
|
||||
if self.sd_model is None:
|
||||
with self.lock:
|
||||
try:
|
||||
load_model()
|
||||
if shared.opts.sd_backend == 'Original':
|
||||
load_model()
|
||||
elif shared.opts.sd_backend == 'Diffusers':
|
||||
load_diffusers()
|
||||
else:
|
||||
shared.log.error(f"Unknown Stable Diffusion backend: {shared.opts.sd_backend}")
|
||||
except Exception as e:
|
||||
shared.log.error("Failed to load stable diffusion model")
|
||||
errors.display(e, "loading stable diffusion model")
|
||||
@@ -377,6 +390,39 @@ class SdModelData:
|
||||
model_data = SdModelData()
|
||||
|
||||
|
||||
def load_diffusers(checkpoint_info=None, already_loaded_state_dict=None, timer=None):
|
||||
if timer is None:
|
||||
timer = Timer()
|
||||
import diffusers
|
||||
timer.record("diffusers")
|
||||
diffusor_config = {
|
||||
"force_download": False,
|
||||
"safety_checker": None,
|
||||
"resume_download": True,
|
||||
"low_cpu_mem_usage": True,
|
||||
"use_safetensors": True,
|
||||
"cache_dir": shared.opts.diffusers_dir,
|
||||
"torch_dtype": devices.dtype,
|
||||
}
|
||||
shared.log.warning("Using experimental Diffusers backend for Stable Diffusion")
|
||||
if shared.opts.data['sd_model_checkpoint'] == 'model.ckpt':
|
||||
shared.opts.data['sd_model_checkpoint'] = "runwayml/stable-diffusion-v1-5"
|
||||
sd_model = None
|
||||
try:
|
||||
checkpoint_info = checkpoint_info or select_checkpoint()
|
||||
scheduler = diffusers.UniPCMultistepScheduler.from_pretrained(checkpoint_info.filename, subfolder="scheduler")
|
||||
scheduler.name = 'UniPC'
|
||||
sd_model = diffusers.DiffusionPipeline.from_pretrained(checkpoint_info.filename, scheduler=scheduler, **diffusor_config)
|
||||
sd_model.to(devices.device)
|
||||
sd_model.sd_checkpoint_info = checkpoint_info
|
||||
sd_model.sd_model_hash = checkpoint_info.hash
|
||||
except Exception as e:
|
||||
shared.log.error("Failed to load diffusers model")
|
||||
errors.display(e, "loading Diffusers model")
|
||||
shared.sd_model = sd_model
|
||||
timer.record("load")
|
||||
|
||||
|
||||
def load_model(checkpoint_info=None, already_loaded_state_dict=None, timer=None):
|
||||
from modules import lowvram, sd_hijack
|
||||
checkpoint_info = checkpoint_info or select_checkpoint()
|
||||
|
||||
+19
-8
@@ -1,10 +1,16 @@
|
||||
from modules import sd_samplers_compvis, sd_samplers_kdiffusion, shared
|
||||
from modules import sd_samplers_compvis, sd_samplers_kdiffusion, sd_samplers_diffusors, shared
|
||||
from modules.sd_samplers_common import samples_to_image_grid, sample_to_image # pylint: disable=unused-import
|
||||
from modules.shared import opts
|
||||
|
||||
all_samplers = [
|
||||
*sd_samplers_kdiffusion.samplers_data_k_diffusion,
|
||||
*sd_samplers_compvis.samplers_data_compvis,
|
||||
]
|
||||
if opts.sd_backend == 'Original':
|
||||
all_samplers = [
|
||||
*sd_samplers_kdiffusion.samplers_data_k_diffusion,
|
||||
*sd_samplers_compvis.samplers_data_compvis,
|
||||
]
|
||||
else:
|
||||
all_samplers = [
|
||||
*sd_samplers_diffusors.samplers_data_diffusors,
|
||||
]
|
||||
all_samplers_map = {x.name: x for x in all_samplers}
|
||||
samplers = all_samplers
|
||||
samplers_for_img2img = all_samplers
|
||||
@@ -17,9 +23,14 @@ def create_sampler(name, model):
|
||||
else:
|
||||
config = all_samplers[0]
|
||||
assert config is not None, f'bad sampler name: {name}'
|
||||
sampler = config.constructor(model)
|
||||
sampler.config = config
|
||||
return sampler
|
||||
if opts.sd_backend == 'Original':
|
||||
sampler = config.constructor(model)
|
||||
sampler.config = config
|
||||
return sampler
|
||||
else:
|
||||
sampler = config.constructor(model.sd_checkpoint_info.filename)
|
||||
model.scheduler = sampler.sampler
|
||||
return sampler.sampler
|
||||
|
||||
|
||||
def set_samplers():
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
from diffusers import (
|
||||
DDIMScheduler,
|
||||
DDPMScheduler,
|
||||
DEISMultistepScheduler,
|
||||
DPMSolverMultistepScheduler,
|
||||
EulerAncestralDiscreteScheduler,
|
||||
EulerDiscreteScheduler,
|
||||
HeunDiscreteScheduler,
|
||||
IPNDMScheduler,
|
||||
KDPM2AncestralDiscreteScheduler,
|
||||
PNDMScheduler,
|
||||
UniPCMultistepScheduler,
|
||||
# KarrasVeScheduler,
|
||||
# RePaintScheduler,
|
||||
# ScoreSdeVeScheduler,
|
||||
# UnCLIPScheduler,
|
||||
# VQDiffusionScheduler,
|
||||
)
|
||||
from modules import sd_samplers_common
|
||||
# scheduler = diffusers.UniPCMultistepScheduler.from_pretrained(shared.cmd_opts.ckpt, subfolder="scheduler")
|
||||
|
||||
samplers_data_diffusors = [
|
||||
sd_samplers_common.SamplerData('UniPC', lambda model: DiffusionSampler('UniPC', UniPCMultistepScheduler, model), [], {}),
|
||||
sd_samplers_common.SamplerData('DDIM', lambda model: DiffusionSampler('DDIM', DDIMScheduler, model), [], {}),
|
||||
sd_samplers_common.SamplerData('DDPMS', lambda model: DiffusionSampler('DDPMS', DDPMScheduler, model), [], {}),
|
||||
sd_samplers_common.SamplerData('DEIS', lambda model: DiffusionSampler('DEIS', DEISMultistepScheduler, model), [], {}),
|
||||
sd_samplers_common.SamplerData('DPMSolver', lambda model: DiffusionSampler('DPMSolver', DPMSolverMultistepScheduler, model), [], {}),
|
||||
sd_samplers_common.SamplerData('Euler', lambda model: DiffusionSampler('Euler', EulerDiscreteScheduler, model), [], {}),
|
||||
sd_samplers_common.SamplerData('EulerAncestral', lambda model: DiffusionSampler('EulerAncestral', EulerAncestralDiscreteScheduler, model), [], {}),
|
||||
sd_samplers_common.SamplerData('Heun', lambda model: DiffusionSampler('Heun', HeunDiscreteScheduler, model), [], {}),
|
||||
sd_samplers_common.SamplerData('IPNDM', lambda model: DiffusionSampler('IPNDM', IPNDMScheduler, model), [], {}),
|
||||
sd_samplers_common.SamplerData('KDPM2Ancestral', lambda model: DiffusionSampler('KDPM2Ancestral', KDPM2AncestralDiscreteScheduler, model), [], {}),
|
||||
sd_samplers_common.SamplerData('PNDMS', lambda model: DiffusionSampler('PNDMS', PNDMScheduler, model), [], {}),
|
||||
# sd_samplers_common.SamplerData('KarrasVe', lambda model: DiffusionSampler('KarrasVe', KarrasVeScheduler, model), [], {}),
|
||||
# sd_samplers_common.SamplerData('RePaint', lambda model: DiffusionSampler('RePaint', RePaintScheduler, model), [], {}),
|
||||
# sd_samplers_common.SamplerData('ScoreSdeVe', lambda model: DiffusionSampler('ScoreSdeVe', ScoreSdeVeScheduler, model), [], {}),
|
||||
# sd_samplers_common.SamplerData('UnCLIP', lambda model: DiffusionSampler('UnCLIP', UnCLIPScheduler, model), [], {}),
|
||||
# sd_samplers_common.SamplerData('VQDiffusion', lambda model: DiffusionSampler('VQDiffusion', VQDiffusionScheduler, model), [], {}),
|
||||
]
|
||||
|
||||
|
||||
class DiffusionSampler:
|
||||
def __init__(self, name, constructor, sd_model):
|
||||
self.sampler = constructor.from_pretrained(sd_model, subfolder="scheduler")
|
||||
self.sampler.name = name
|
||||
@@ -82,7 +82,7 @@ class CFGDenoiser(torch.nn.Module):
|
||||
|
||||
# at self.image_cfg_scale == 1.0 produced results for edit model are the same as with normal sampling,
|
||||
# so is_edit_model is set to False to support AND composition.
|
||||
is_edit_model = shared.sd_model.cond_stage_key == "edit" and self.image_cfg_scale is not None and self.image_cfg_scale != 1.0
|
||||
is_edit_model = (shared.sd_model is not None) and hasattr(shared.sd_model, 'cond_stage_key') and (shared.sd_model.cond_stage_key == "edit") and (self.image_cfg_scale is not None) and (self.image_cfg_scale != 1.0)
|
||||
|
||||
conds_list, tensor = prompt_parser.reconstruct_multicond_batch(cond, self.step)
|
||||
uncond = prompt_parser.reconstruct_cond_batch(uncond, self.step)
|
||||
|
||||
+23
-18
@@ -192,6 +192,7 @@ def list_checkpoint_tiles():
|
||||
import modules.sd_models # pylint: disable=W0621
|
||||
return modules.sd_models.checkpoint_tiles()
|
||||
|
||||
|
||||
default_checkpoint = list_checkpoint_tiles()[0] if len(list_checkpoint_tiles()) > 0 else "model.ckpt"
|
||||
|
||||
|
||||
@@ -251,29 +252,24 @@ options_templates.update(options_section(('sd', "Stable Diffusion"), {
|
||||
"sd_vae": OptionInfo("Automatic", "Select VAE", gr.Dropdown, lambda: {"choices": shared_items.sd_vae_items()}, refresh=shared_items.refresh_vae_list),
|
||||
"stream_load": OptionInfo(False, "When loading models attempt stream loading optimized for slow or network storage"),
|
||||
"model_reuse_dict": OptionInfo(False, "When loading models attempt to reuse previous model dictionary"),
|
||||
"inpainting_mask_weight": OptionInfo(1.0, "Inpainting conditioning mask strength", gr.Slider, {"minimum": 0.0, "maximum": 1.0, "step": 0.01}),
|
||||
"initial_noise_multiplier": OptionInfo(1.0, "Noise multiplier for img2img", gr.Slider, {"minimum": 0.1, "maximum": 1.5, "step": 0.01}),
|
||||
"img2img_color_correction": OptionInfo(False, "Apply color correction to img2img results to match original colors"),
|
||||
"img2img_fix_steps": OptionInfo(False, "For image processing do exactly the amount of steps as specified"),
|
||||
"img2img_background_color": OptionInfo("#ffffff", "With img2img fill image's transparent parts with this color", ui_components.FormColorPicker, {}),
|
||||
"enable_quantization": OptionInfo(True, "Enable quantization in K samplers for sharper and cleaner results"),
|
||||
"comma_padding_backtrack": OptionInfo(20, "Increase coherency by padding from the last comma within n tokens when using more than 75 tokens", gr.Slider, {"minimum": 0, "maximum": 74, "step": 1 }),
|
||||
"CLIP_stop_at_last_layers": OptionInfo(1, "Clip skip", gr.Slider, {"minimum": 1, "maximum": 8, "step": 1, "visible": False}),
|
||||
"upcast_attn": OptionInfo(False, "Upcast cross attention layer to FP32"),
|
||||
"cross_attention_optimization": OptionInfo(cross_attention_optimization_default, "Cross-attention optimization method", gr.Radio, lambda: {"choices": shared_items.list_crossattention() }),
|
||||
"cross_attention_options": OptionInfo([], "Cross-attention advanced options", gr.CheckboxGroup, lambda: {"choices": ['xFormers enable flash Attention', 'SDP disable memory attention']}),
|
||||
"sub_quad_q_chunk_size": OptionInfo(512, "Sub-quadratic cross-attention query chunk size for the layer optimization to use", gr.Slider, {"minimum": 16, "maximum": 8192, "step": 8}),
|
||||
"sub_quad_kv_chunk_size": OptionInfo(512, "Sub-quadratic cross-attentionkv chunk size for the sub-quadratic cross-attention layer optimization to use", gr.Slider, {"minimum": 0, "maximum": 8192, "step": 8}),
|
||||
"sub_quad_chunk_threshold": OptionInfo(80, "Sub-quadratic cross-attention percentage of VRAM chunking threshold", gr.Slider, {"minimum": 0, "maximum": 100, "step": 1}),
|
||||
"always_batch_cond_uncond": OptionInfo(False, "Disables cond/uncond batching that is enabled to save memory with --medvram or --lowvram"),
|
||||
"prompt_attention": OptionInfo("Full parser", "Prompt attention parser", gr.Radio, lambda: {"choices": ["Full parser", "Compel parser", "A1111 parser", "Fixed attention"] }),
|
||||
"prompt_mean_norm": OptionInfo(True, "Prompt attention mean normalization"),
|
||||
"always_batch_cond_uncond": OptionInfo(False, "Disables cond/uncond batching that is enabled to save memory with --medvram or --lowvram"),
|
||||
"enable_quantization": OptionInfo(True, "Enable quantization in K samplers for sharper and cleaner results"),
|
||||
"comma_padding_backtrack": OptionInfo(20, "Increase coherency by padding from the last comma within n tokens when using more than 75 tokens", gr.Slider, {"minimum": 0, "maximum": 74, "step": 1 }),
|
||||
"sd_backend": OptionInfo("Original", "Stable Diffusion backend (experimental)", gr.Radio, lambda: {"choices": ["Original", "Diffusers"] }),
|
||||
}))
|
||||
|
||||
options_templates.update(options_section(('system-paths', "System Paths"), {
|
||||
"temp_dir": OptionInfo("", "Directory for temporary images; leave empty for default"),
|
||||
"temp_dir": OptionInfo("", "Directory for temporary images; leave empty for default"),
|
||||
"clean_temp_dir_at_start": OptionInfo(True, "Cleanup non-default temporary directory when starting webui"),
|
||||
"ckpt_dir": OptionInfo(os.path.join(paths.models_path, 'Stable-diffusion'), "Path to directory with stable diffusion checkpoints"),
|
||||
"diffusers_dir": OptionInfo(os.path.join(paths.models_path, 'Diffusers'), "Path to directory with stable diffusion diffusers"),
|
||||
"vae_dir": OptionInfo(os.path.join(paths.models_path, 'VAE'), "Path to directory with VAE files"),
|
||||
"embeddings_dir": OptionInfo(os.path.join(paths.models_path, 'embeddings'), "Embeddings directory for textual inversion"),
|
||||
"hypernetwork_dir": OptionInfo(os.path.join(paths.models_path, 'hypernetworks'), "Hypernetwork directory"),
|
||||
@@ -289,10 +285,9 @@ options_templates.update(options_section(('system-paths', "System Paths"), {
|
||||
"lora_dir": OptionInfo(os.path.join(paths.models_path, 'Lora'), "Path to directory with Lora network(s)"),
|
||||
"lyco_dir": OptionInfo(os.path.join(paths.models_path, 'LyCORIS'), "Path to directory with LyCORIS network(s)"),
|
||||
"styles_dir": OptionInfo(os.path.join(paths.data_path, 'styles.csv'), "Path to user-defined styles file"),
|
||||
# "gfpgan_model": OptionInfo("", "GFPGAN model file name"),
|
||||
}))
|
||||
|
||||
options_templates.update(options_section(('saving-images', "Image options"), {
|
||||
options_templates.update(options_section(('saving-images', "Image Options"), {
|
||||
"samples_save": OptionInfo(True, "Always save all generated images"),
|
||||
"samples_format": OptionInfo('jpg', 'File format for images'),
|
||||
"samples_filename_pattern": OptionInfo("[seed]-[prompt_spaces]", "Images filename pattern", component_args=hide_dirs),
|
||||
@@ -324,6 +319,16 @@ options_templates.update(options_section(('saving-images', "Image options"), {
|
||||
"directories_max_prompt_words": OptionInfo(8, "Max prompt words for [prompt_words] pattern", gr.Slider, {"minimum": 1, "maximum": 20, "step": 1, **hide_dirs}),
|
||||
}))
|
||||
|
||||
options_templates.update(options_section(('image-processing', "Image Processing"), {
|
||||
"img2img_color_correction": OptionInfo(False, "Apply color correction to img2img results to match original colors"),
|
||||
"img2img_fix_steps": OptionInfo(False, "For image processing do exactly the amount of steps as specified"),
|
||||
"img2img_background_color": OptionInfo("#ffffff", "With img2img fill image's transparent parts with this color", ui_components.FormColorPicker, {}),
|
||||
"inpainting_mask_weight": OptionInfo(1.0, "Inpainting conditioning mask strength", gr.Slider, {"minimum": 0.0, "maximum": 1.0, "step": 0.01}),
|
||||
"initial_noise_multiplier": OptionInfo(1.0, "Noise multiplier for img2img", gr.Slider, {"minimum": 0.1, "maximum": 1.5, "step": 0.01}),
|
||||
"CLIP_stop_at_last_layers": OptionInfo(1, "Clip skip", gr.Slider, {"minimum": 1, "maximum": 8, "step": 1, "visible": False}),
|
||||
}))
|
||||
|
||||
|
||||
options_templates.update(options_section(('saving-paths', "Image Paths"), {
|
||||
"outdir_samples": OptionInfo("", "Output directory for images; if empty, defaults to three directories below", component_args=hide_dirs),
|
||||
"outdir_txt2img_samples": OptionInfo("outputs/text", 'Output directory for txt2img images', component_args=hide_dirs),
|
||||
@@ -342,11 +347,12 @@ options_templates.update(options_section(('cuda', "Compute Settings"), {
|
||||
"cuda_dtype": OptionInfo("FP32" if sys.platform == "darwin" else "FP16", "Device precision type", gr.Radio, lambda: {"choices": ["FP32", "FP16", "BF16"]}),
|
||||
"no_half": OptionInfo(False, "Use full precision for model (--no-half)", None, None, None),
|
||||
"no_half_vae": OptionInfo(False, "Use full precision for VAE (--no-half-vae)"),
|
||||
"upcast_sampling": OptionInfo(True if sys.platform == "darwin" or cmd_opts.use_ipex else False, "Enable upcast sampling. Usually produces similar results to --no-half with better performance while using less memory"),
|
||||
"disable_nan_check": OptionInfo(True, "Do not check if produced images/latent spaces have NaN values"),
|
||||
"upcast_sampling": OptionInfo(True if sys.platform == "darwin" or cmd_opts.use_ipex else False, "Enable upcast sampling"),
|
||||
"upcast_attn": OptionInfo(False, "Enable upcast cross attention layer"),
|
||||
"disable_nan_check": OptionInfo(True, "Disable NaN check in produced images/latent spaces"),
|
||||
"rollback_vae": OptionInfo(False, "Attempt to roll back VAE when produced NaN values, requires NaN check (experimental)"),
|
||||
"opt_channelslast": OptionInfo(False, "Use channels last as torch memory format "),
|
||||
"cudnn_benchmark": OptionInfo(False, "Enable cuDNN benchmark feature"),
|
||||
"cudnn_benchmark": OptionInfo(False, "Enable full-depth cuDNN benchmark feature"),
|
||||
"cuda_allow_tf32": OptionInfo(True, "Allow TF32 math ops"),
|
||||
"cuda_allow_tf16_reduced": OptionInfo(True, "Allow TF16 reduced precision math ops"),
|
||||
"cuda_compile": OptionInfo(False, "Enable model compile (experimental)"),
|
||||
@@ -778,7 +784,7 @@ def get_version():
|
||||
try:
|
||||
import subprocess
|
||||
res = subprocess.run('git log --pretty=format:"%h %ad" -1 --date=short', stdout = subprocess.PIPE, stderr = subprocess.PIPE, shell=True, check=True)
|
||||
ver = res.stdout.decode(encoding = 'utf8', errors='ignore') if len(res.stdout) > 0 else ''
|
||||
ver = res.stdout.decode(encoding = 'utf8', errors='ignore') if len(res.stdout) > 0 else ' '
|
||||
githash, updated = ver.split(' ')
|
||||
res = subprocess.run('git remote get-url origin', stdout = subprocess.PIPE, stderr = subprocess.PIPE, shell=True, check=True)
|
||||
origin = res.stdout.decode(encoding = 'utf8', errors='ignore') if len(res.stdout) > 0 else ''
|
||||
@@ -792,7 +798,6 @@ def get_version():
|
||||
}
|
||||
except:
|
||||
version = { 'app': 'sd.next' }
|
||||
pass
|
||||
return version
|
||||
|
||||
|
||||
|
||||
@@ -207,6 +207,8 @@ class EmbeddingDatabase:
|
||||
continue
|
||||
|
||||
def load_textual_inversion_embeddings(self, force_reload=False):
|
||||
if shared.opts.sd_backend == 'Diffusers': # TODO Diffusers
|
||||
return
|
||||
if not force_reload:
|
||||
need_reload = False
|
||||
for _path, embdir in self.embedding_dirs.items():
|
||||
|
||||
+15
-9
@@ -28,6 +28,7 @@ import modules.textual_inversion.ui
|
||||
import modules.sd_samplers
|
||||
from modules.textual_inversion import textual_inversion
|
||||
|
||||
|
||||
modules.errors.install()
|
||||
mimetypes.init()
|
||||
mimetypes.add_type('application/javascript', '.js')
|
||||
@@ -203,7 +204,13 @@ def update_token_counter(text, steps):
|
||||
prompt_schedules = [[[steps, text]]]
|
||||
flat_prompts = reduce(lambda list1, list2: list1+list2, prompt_schedules)
|
||||
prompts = [prompt_text for step, prompt_text in flat_prompts]
|
||||
token_count, max_length = max([sd_hijack.model_hijack.get_prompt_lengths(prompt) for prompt in prompts], key=lambda args: args[0])
|
||||
if opts.sd_backend == 'Original':
|
||||
token_count, max_length = max([sd_hijack.model_hijack.get_prompt_lengths(prompt) for prompt in prompts], key=lambda args: args[0])
|
||||
else:
|
||||
tokenizer = modules.shared.sd_model.tokenizer
|
||||
has_bos_token, has_eos_token = tokenizer.bos_token_id is not None, tokenizer.eos_token_id is not None
|
||||
token_count = max([len(modules.shared.sd_model.tokenizer(prompt)) for prompt in prompts]) - int(has_bos_token) - int(has_eos_token)
|
||||
max_length = tokenizer.model_max_length - int(has_bos_token) - int(has_eos_token)
|
||||
return f"<span class='gr-box gr-text-input'>{token_count}/{max_length}</span>"
|
||||
|
||||
|
||||
@@ -299,13 +306,12 @@ def create_output_panel(tabname, outdir):
|
||||
def create_sampler_and_steps_selection(choices, tabname):
|
||||
with FormRow(elem_id=f"sampler_selection_{tabname}"):
|
||||
if 'UniPC' in [sampler.name for sampler in choices]:
|
||||
chosen_sampler_name = 'UniPC'
|
||||
default_sampler_name = 'UniPC'
|
||||
elif 'Euler a' in [sampler.name for sampler in choices]:
|
||||
chosen_sampler_name = 'Euler a'
|
||||
default_sampler_name = 'Euler a'
|
||||
else:
|
||||
chosen_sampler_name = modules.sd_samplers.samplers[0].name
|
||||
|
||||
sampler_index = gr.Dropdown(label='Sampling method', elem_id=f"{tabname}_sampling", choices=[x.name for x in choices], value=chosen_sampler_name if tabname == 'txt2img' else "Euler a", type="index")
|
||||
default_sampler_name = modules.sd_samplers.samplers[0].name
|
||||
sampler_index = gr.Dropdown(label='Sampling method', elem_id=f"{tabname}_sampling", choices=[x.name for x in choices], value=default_sampler_name, type="index")
|
||||
steps = gr.Slider(minimum=1, maximum=99, step=1, elem_id=f"{tabname}_steps", label="Sampling steps", value=20)
|
||||
return steps, sampler_index
|
||||
|
||||
@@ -1452,9 +1458,9 @@ def create_ui():
|
||||
show_progress=info.refresh is not None,
|
||||
)
|
||||
|
||||
update_image_cfg_scale_visibility = lambda: gr.update(visible=modules.shared.sd_model and modules.shared.sd_model.cond_stage_key == "edit") # pylint: disable=unnecessary-lambda-assignment
|
||||
text_settings.change(fn=update_image_cfg_scale_visibility, inputs=[], outputs=[image_cfg_scale])
|
||||
demo.load(fn=update_image_cfg_scale_visibility, inputs=[], outputs=[image_cfg_scale])
|
||||
image_cfg_scale_visibility = (modules.shared.sd_model is not None) and hasattr(modules.shared.sd_model, 'cond_stage_key') and (modules.shared.sd_model.cond_stage_key == "edit") # pix2pix
|
||||
text_settings.change(fn=lambda: gr.update(visible=image_cfg_scale_visibility), inputs=[], outputs=[image_cfg_scale])
|
||||
demo.load(fn=lambda: gr.update(visible=image_cfg_scale_visibility), inputs=[], outputs=[image_cfg_scale])
|
||||
|
||||
button_set_checkpoint = gr.Button('Change checkpoint', elem_id='change_checkpoint', visible=False)
|
||||
button_set_checkpoint.click(
|
||||
|
||||
@@ -79,29 +79,25 @@ class ScriptPostprocessingUpscale(scripts_postprocessing.ScriptPostprocessing):
|
||||
return image
|
||||
|
||||
def process(self, pp: scripts_postprocessing.PostprocessedImage, upscale_mode=1, upscale_by=2.0, upscale_to_width=None, upscale_to_height=None, upscale_crop=False, upscaler_1_name=None, upscaler_2_name=None, upscaler_2_visibility=0.0): # pylint: disable=arguments-differ
|
||||
|
||||
if upscaler_1_name == "None":
|
||||
upscaler_1_name = None
|
||||
|
||||
upscaler1 = next(iter([x for x in shared.sd_upscalers if x.name == upscaler_1_name]), None)
|
||||
if not upscaler1:
|
||||
shared.log.warning(f"Could not find upscaler: {upscaler_1_name or '<empty string>'}")
|
||||
if upscaler_1_name is not None:
|
||||
shared.log.warning(f"Could not find upscaler: {upscaler_1_name or '<empty string>'}")
|
||||
return
|
||||
|
||||
if upscaler_2_name == "None":
|
||||
upscaler_2_name = None
|
||||
|
||||
upscaler2 = next(iter([x for x in shared.sd_upscalers if x.name == upscaler_2_name and x.name != "None"]), None)
|
||||
if not upscaler2 and (upscaler_2_name is not None):
|
||||
shared.log.warning(f"Could not find upscaler: {upscaler_2_name or '<empty string>'}")
|
||||
return
|
||||
|
||||
upscaled_image = self.upscale(pp.image, pp.info, upscaler1, upscale_mode, upscale_by, upscale_to_width, upscale_to_height, upscale_crop)
|
||||
pp.info["Postprocess upscaler"] = upscaler1.name
|
||||
|
||||
if upscaler_2_name == "None":
|
||||
upscaler_2_name = None
|
||||
upscaler2 = next(iter([x for x in shared.sd_upscalers if x.name == upscaler_2_name and x.name != "None"]), None)
|
||||
if not upscaler2 and (upscaler_2_name is not None):
|
||||
shared.log.warning(f"Could not find upscaler: {upscaler_2_name or '<empty string>'}")
|
||||
if upscaler2 and upscaler_2_visibility > 0:
|
||||
second_upscale = self.upscale(pp.image, pp.info, upscaler2, upscale_mode, upscale_by, upscale_to_width, upscale_to_height, upscale_crop)
|
||||
upscaled_image = Image.blend(upscaled_image, second_upscale, upscaler_2_visibility)
|
||||
|
||||
pp.info["Postprocess upscaler 2"] = upscaler2.name
|
||||
|
||||
pp.image = upscaled_image
|
||||
@@ -130,7 +126,7 @@ class ScriptPostprocessingUpscaleSimple(ScriptPostprocessingUpscale):
|
||||
|
||||
upscaler1 = next(iter([x for x in shared.sd_upscalers if x.name == upscaler_name]), None)
|
||||
if upscaler1 is None:
|
||||
shared.log.warning(f"Could not find upscaler: {upscaler_name or '<empty string>'}")
|
||||
shared.log.debug(f"Upscaler not found: {upscaler_name}")
|
||||
|
||||
pp.image = self.upscale(pp.image, pp.info, upscaler1, 0, upscale_by, 0, 0, False)
|
||||
pp.info["Postprocess upscaler"] = upscaler1.name
|
||||
|
||||
@@ -150,25 +150,13 @@ def initialize():
|
||||
def load_model():
|
||||
shared.state.begin()
|
||||
shared.state.job = 'load model'
|
||||
|
||||
"""
|
||||
try:
|
||||
modules.sd_models.load_model()
|
||||
modules.sd_models.skip_next_load = True
|
||||
except Exception as e:
|
||||
errors.display(e, "loading stable diffusion model")
|
||||
log.error("Stable diffusion model failed to load")
|
||||
exit(1)
|
||||
"""
|
||||
Thread(target=lambda: shared.sd_model).start()
|
||||
|
||||
if shared.sd_model is None:
|
||||
log.warning("No stable diffusion model loaded")
|
||||
# exit(1)
|
||||
else:
|
||||
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()), call=False)
|
||||
|
||||
shared.state.end()
|
||||
startup_timer.record("checkpoint")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user