update installer and add sd_model_dict

This commit is contained in:
Vladimir Mandic
2023-06-07 13:26:19 -04:00
parent 8e3a8fb474
commit aaa0d46286
15 changed files with 110 additions and 103 deletions
+3 -2
View File
@@ -256,9 +256,11 @@
{"id":"","label":"random","localized":"","hint":""}
],
"settings": [
{"id":"","label":"Stable Diffusion checkpoint","localized":"","hint":"Select model checkpoint to use"},
{"id":"","label":"Stable Diffusion checkpoint dict","localized":"","hint":"Select model from which to extract dictionary only"},
{"id":"","label":"Number of cached model checkpoints","localized":"","hint":""},
{"id":"","label":"Number of cached VAE checkpoints","localized":"","hint":""},
{"id":"","label":"Select VAE","localized":"","hint":""},
{"id":"","label":"Select VAE","localized":"","hint":"Select variable auto-encoder to work with model when rendering images"},
{"id":"","label":"Enable splitting of hires batch processing","localized":"","hint":""},
{"id":"","label":"When loading models attempt stream loading optimized for slow or network storage","localized":"","hint":""},
{"id":"","label":"When loading models attempt to reuse previous model dictionary","localized":"","hint":""},
@@ -513,7 +515,6 @@
{"id":"","label":"Resize to ","localized":"","hint":""},
{"id":"","label":"Resize by ","localized":"","hint":""},
{"id":"","label":"Use via API ","localized":"","hint":""},
{"id":"","label":"Stable Diffusion checkpoint","localized":"","hint":""},
{"id":"","label":"Styles","localized":"","hint":""},
{"id":"","label":"Put variable parts at start of prompt","localized":"","hint":""},
{"id":"","label":"Use different seed for each picture","localized":"","hint":""},
+26 -51
View File
@@ -12,10 +12,6 @@ import cProfile
import argparse
import pkg_resources
try:
from modules.cmd_args import parser
except:
parser = argparse.ArgumentParser(description="SD.Next", conflict_handler='resolve', formatter_class=lambda prog: argparse.HelpFormatter(prog, max_help_position=55, indent_increment=2, width=200))
class Dot(dict): # dot notation access to dictionary attributes
__getattr__ = dict.get
@@ -69,8 +65,6 @@ def setup_logging(clean=False):
"traceback.border.syntax_error": "black",
"inspect.value.border": "black",
}))
# logging.getLogger("urllib3").setLevel(logging.ERROR)
# logging.getLogger("httpx").setLevel(logging.ERROR)
level = logging.DEBUG if args.debug else logging.INFO
logging.basicConfig(level=logging.ERROR, format='%(asctime)s | %(name)s | %(levelname)s | %(module)s | %(message)s', filename=log_file, filemode='a', encoding='utf-8', force=True)
log.setLevel(logging.DEBUG) # log to file is always at level debug for facility `sd`
@@ -81,6 +75,9 @@ def setup_logging(clean=False):
while log.hasHandlers() and len(log.handlers) > 0:
log.removeHandler(log.handlers[0])
log.addHandler(rh)
logging.getLogger("urllib3").setLevel(logging.ERROR)
logging.getLogger("httpx").setLevel(logging.ERROR)
logging.getLogger("ControlNet").handlers = log.handlers
def print_profile(profile: cProfile.Profile, msg: str):
@@ -351,7 +348,7 @@ def install_packages():
if args.profile:
pr = cProfile.Profile()
pr.enable()
log.info('Installing packages')
log.info('Verifying packages')
# gfpgan_package = os.environ.get('GFPGAN_PACKAGE', "git+https://github.com/TencentARC/GFPGAN.git@8d2447a2d918f8eba5a4a01463fd48e45126a379")
# openclip_package = os.environ.get('OPENCLIP_PACKAGE', "git+https://github.com/mlfoundations/open_clip.git@bb6e834e9c70d9c27d0dc3ecedeebeaeb1ffad6b")
# install(gfpgan_package, 'gfpgan')
@@ -593,6 +590,8 @@ def check_version(offline=False, reset=True): # pylint: disable=unused-argument
log.info(f'Version: {ver}')
if args.version:
return
if args.skip_git:
return
commit = git('rev-parse HEAD')
global git_commit # pylint: disable=global-statement
git_commit = commit[:7]
@@ -673,7 +672,7 @@ def check_timestamp():
return ok
def add_args():
def add_args(parser):
group = parser.add_argument_group('Setup options')
group.add_argument('--debug', default = False, action='store_true', help = "Run installer with debug logging, default: %(default)s")
group.add_argument('--reset', default = False, action='store_true', help = "Reset main repository to latest version, default: %(default)s")
@@ -696,44 +695,36 @@ def add_args():
group.add_argument('--base', default = False, action='store_true', help = argparse.SUPPRESS)
def parse_args():
def parse_args(parser):
# command line args
global args # pylint: disable=global-statement
args = parser.parse_args()
return args
def extensions_preload(force = False):
def extensions_preload(parser):
if args.profile:
pr = cProfile.Profile()
pr.enable()
setup_time = 0
if not force:
if os.path.isfile(log_file):
with open(log_file, 'r', encoding='utf8') as f:
lines = f.readlines()
for line in lines:
if 'Setup complete without errors' in line:
setup_time = int(line.split(' ')[-1])
if setup_time > 0 or force:
# log.info('Running extension preloading')
if args.safe:
log.info('Running in safe mode without user extensions')
try:
from modules.script_loading import preload_extensions
from modules.paths_internal import extensions_builtin_dir, extensions_dir
extension_folders = [extensions_builtin_dir] if args.safe else [extensions_builtin_dir, extensions_dir]
if args.base:
extension_folders = []
for ext_dir in extension_folders:
t0 = time.time()
preload_extensions(ext_dir, parser)
t1 = time.time()
log.info(f'Extension preload: {round(t1 - t0, 1)}s {ext_dir}')
except:
log.error('Error running extension preloading')
if args.safe:
log.info('Running in safe mode without user extensions')
try:
from modules.script_loading import preload_extensions
from modules.paths_internal import extensions_builtin_dir, extensions_dir
extension_folders = [extensions_builtin_dir] if args.safe else [extensions_builtin_dir, extensions_dir]
if args.base:
extension_folders = []
for ext_dir in extension_folders:
t0 = time.time()
preload_extensions(ext_dir, parser)
t1 = time.time()
log.info(f'Extension preload: {round(t1 - t0, 1)}s {ext_dir}')
except:
log.error('Error running extension preloading')
if args.profile:
print_profile(pr, 'Preload')
def git_reset():
log.warning('Running GIT reset')
global quick_allowed # pylint: disable=global-statement
@@ -752,22 +743,13 @@ def read_options():
opts = json.load(file)
# entry method when used as module
def run_setup():
# setup_logging(args.upgrade)
log.info('Starting SD.Next')
check_python()
if args.reset:
git_reset()
if args.skip_git:
log.info('Skipping GIT operations')
check_version()
set_environment()
if args.reinstall:
log.info('Forcing reinstall of all packages')
check_torch()
install_requirements()
install_packages()
if check_timestamp():
log.info('No changes detected: Quick launch active')
return
@@ -782,10 +764,3 @@ def run_setup():
else:
log.warning(f'Setup complete with errors: {errors}')
log.warning(f'See log file for more details: {log_file}')
if __name__ == "__main__":
add_args()
ensure_base_requirements()
parse_args()
run_setup()
+31 -23
View File
@@ -4,23 +4,15 @@ import time
import shlex
import logging
import subprocess
import installer
commandline_args = os.environ.get('COMMANDLINE_ARGS', "")
sys.argv += shlex.split(commandline_args)
import installer
installer.ensure_base_requirements()
installer.add_args()
installer.parse_args()
installer.setup_logging(False)
installer.read_options()
installer.extensions_preload(force=False)
import modules.cmd_args
args, _ = modules.cmd_args.parser.parse_known_args()
import modules.paths_internal
script_path = modules.paths_internal.script_path
extensions_dir = modules.paths_internal.extensions_dir
args = None
parser = None
script_path = None
extensions_dir = None
git = os.environ.get('GIT', "git")
index_url = os.environ.get('INDEX_URL', "")
stored_commit_hash = None
@@ -29,6 +21,17 @@ python = sys.executable # used by some extensions to run python
skip_install = False # parsed by some extensions
def init_modules():
global parser, args, script_path, extensions_dir # pylint: disable=global-statement
import modules.cmd_args
parser = modules.cmd_args.parser
installer.add_args(parser)
args, _ = parser.parse_known_args()
import modules.paths_internal
script_path = modules.paths_internal.script_path
extensions_dir = modules.paths_internal.extensions_dir
def commit_hash(): # compatbility function
global stored_commit_hash # pylint: disable=global-statement
if stored_commit_hash is not None:
@@ -134,17 +137,22 @@ def start_server(immediate=True, server=None):
if __name__ == "__main__":
if args.version:
installer.add_args()
installer.log.info('SD.Next version information')
installer.check_python()
installer.check_version()
installer.check_torch()
exit(0)
installer.ensure_base_requirements()
init_modules() # setup argparser and default folders
installer.args = args
installer.setup_logging(False)
installer.log.info('Starting SD.Next')
installer.check_python()
installer.check_version()
installer.set_environment()
installer.check_torch()
installer.install_requirements()
installer.install_packages()
installer.extensions_preload(parser) # adds additional args from extensions
args = installer.parse_args(parser)
installer.read_options()
installer.run_setup()
installer.extensions_preload(force=True)
installer.log.info(f"Server arguments: {sys.argv[1:]}")
installer.log.debug('Starting WebUI')
logging.disable(logging.NOTSET if args.debug else logging.DEBUG)
instance = start_server(immediate=True, server=None)
+1 -1
View File
@@ -139,7 +139,7 @@ def list_extensions():
shared.log.info(f'Skipping conflicting extension: {path}')
continue
extension_names.append(extension_dirname)
extension_paths.append((extension_dirname, path, dirname == dirname))
extension_paths.append((extension_dirname, path, dirname == extensions_builtin_dir))
for dirname, path, is_builtin in extension_paths:
extension = Extension(name=dirname, path=path, enabled=dirname not in shared.opts.disabled_extensions, is_builtin=is_builtin)
extensions.append(extension)
+2 -2
View File
@@ -933,7 +933,7 @@ class StableDiffusionProcessingTxt2Img(StableDiffusionProcessing):
image_conditioning = self.img2img_image_conditioning(decoded_samples, samples)
shared.state.nextjob()
img2img_sampler_name = self.sampler_name
force_latent_upscaler = shared.opts.data.get('xyz_fallback_sampler')
force_latent_upscaler = shared.opts.data.get('force_latent_sampler')
if force_latent_upscaler != 'None' and force_latent_upscaler != 'PLMS':
img2img_sampler_name = force_latent_upscaler
if img2img_sampler_name == 'PLMS':
@@ -981,7 +981,7 @@ class StableDiffusionProcessingImg2Img(StableDiffusionProcessing):
self.image_conditioning = None
def init(self, all_prompts, all_seeds, all_subseeds):
force_latent_upscaler = shared.opts.data.get('xyz_fallback_sampler')
force_latent_upscaler = shared.opts.data.get('force_latent_sampler')
if self.sampler_name in ['PLMS']:
self.sampler_name = force_latent_upscaler if force_latent_upscaler != 'None' else shared.opts.fallback_sampler # PLMS does not support img2img, use fallback instead
self.sampler = sd_samplers.create_sampler(self.sampler_name, self.sd_model)
+22 -10
View File
@@ -190,8 +190,8 @@ def model_hash(filename):
return 'NOHASH'
def select_checkpoint():
model_checkpoint = shared.opts.sd_model_checkpoint
def select_checkpoint(model=True):
model_checkpoint = shared.opts.sd_model_checkpoint if model else shared.opts.sd_model_dict
checkpoint_info = checkpoint_aliases.get(model_checkpoint, None)
if checkpoint_info is not None:
shared.log.debug(f'Select checkpoint: {checkpoint_info.title if checkpoint_info is not None else None}')
@@ -300,7 +300,8 @@ def load_model_weights(model: torch.nn.Module, checkpoint_info: CheckpointInfo,
shared.log.debug(f'Model weights loading: {memory_stats()}')
sd_model_hash = checkpoint_info.calculate_shorthash()
timer.record("hash")
shared.opts.data["sd_model_checkpoint"] = checkpoint_info.title
if model_data.sd_dict == 'None':
shared.opts.data["sd_model_checkpoint"] = checkpoint_info.title
if state_dict is None:
state_dict = get_checkpoint_state_dict(checkpoint_info, timer)
model.load_state_dict(state_dict, strict=False)
@@ -398,6 +399,7 @@ sd2_clip_weight = 'cond_stage_model.model.transformer.resblocks.0.attn.in_proj_w
class SdModelData:
def __init__(self):
self.sd_model = None
self.sd_dict = 'None'
self.initial = True
self.lock = threading.Lock()
@@ -406,7 +408,7 @@ class SdModelData:
with self.lock:
try:
if shared.backend == shared.Backend.ORIGINAL:
load_model()
reload_model_weights()
elif shared.backend == shared.Backend.DIFFUSERS:
load_diffuser()
else:
@@ -552,15 +554,21 @@ def load_model(checkpoint_info=None, already_loaded_state_dict=None, timer=None)
shared.log.info(f'Model load finished: {memory_stats()}')
def reload_model_weights(sd_model=None, info=None):
def reload_model_weights(sd_model=None, info=None, reuse_dict=False):
load_dict = shared.opts.sd_model_dict != model_data.sd_dict
global skip_next_load # pylint: disable=global-statement
if skip_next_load:
shared.log.debug('Reload model weights skip')
skip_next_load = False
return
shared.log.debug(f'Reload model weights: {sd_model is not None} {info}')
from modules import lowvram, sd_hijack
checkpoint_info = info or select_checkpoint()
checkpoint_info = info or select_checkpoint(model=not load_dict) # are we selecting model or dictionary
next_checkpoint_info = info or select_checkpoint(model=load_dict) if load_dict else None
if load_dict:
shared.log.debug(f'Model dict: existing={sd_model is not None} target={checkpoint_info.filename} info={info}')
else:
model_data.sd_dict = 'None'
shared.log.debug(f'Reload model weights: existing={sd_model is not None} target={checkpoint_info.filename} info={info}')
if not sd_model:
sd_model = model_data.sd_model
if sd_model is None: # previous model load failed
@@ -573,7 +581,7 @@ def reload_model_weights(sd_model=None, info=None):
lowvram.send_everything_to_cpu()
else:
sd_model.to(devices.cpu)
if shared.opts.model_reuse_dict and sd_model is not None:
if reuse_dict or (shared.opts.model_reuse_dict and sd_model is not None):
shared.log.info('Reusing previous model dictionary')
sd_hijack.model_hijack.undo_hijack(sd_model)
else:
@@ -590,6 +598,10 @@ def reload_model_weights(sd_model=None, info=None):
load_model(checkpoint_info, already_loaded_state_dict=state_dict, timer=timer)
else:
load_diffuser(checkpoint_info, already_loaded_state_dict=state_dict, timer=timer)
if load_dict and next_checkpoint_info is not None:
model_data.sd_dict = shared.opts.sd_model_dict
shared.opts.data["sd_model_checkpoint"] = next_checkpoint_info.title
reload_model_weights(reuse_dict=True) # ok we loaded dict now lets redo and load model on top of it
return model_data.sd_model
try:
load_model_weights(sd_model, checkpoint_info, state_dict, timer)
@@ -615,8 +627,8 @@ def unload_model_weights(sd_model=None, _info=None):
sd_hijack.model_hijack.undo_hijack(model_data.sd_model)
model_data.sd_model = None
sd_model = None
devices.torch_gc(force=True)
shared.log.debug(f'Model weights unloaded: {memory_stats()}')
devices.torch_gc(force=True)
shared.log.debug(f'Model weights unloaded: {memory_stats()}')
return sd_model
+3 -2
View File
@@ -291,6 +291,7 @@ options_templates.update(options_section(('sd', "Stable Diffusion"), {
"sd_checkpoint_cache": OptionInfo(0, "Number of cached model checkpoints", gr.Slider, {"minimum": 0, "maximum": 10, "step": 1}),
"sd_vae_checkpoint_cache": OptionInfo(0, "Number of cached VAE checkpoints", gr.Slider, {"minimum": 0, "maximum": 10, "step": 1}),
"sd_vae": OptionInfo("Automatic", "Select VAE", gr.Dropdown, lambda: {"choices": shared_items.sd_vae_items()}, refresh=shared_items.refresh_vae_list),
"sd_model_dict": OptionInfo('None', "Stable Diffusion checkpoint dict", gr.Dropdown, lambda: {"choices": ['None'] + list_checkpoint_tiles()}, refresh=refresh_checkpoints),
"sd_vae_sliced_encode": OptionInfo(False, "Enable splitting of hires batch processing"),
"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"),
@@ -440,7 +441,7 @@ options_templates.update(options_section(('ui', "Live previews"), {
options_templates.update(options_section(('sampler-params', "Sampler Settings"), {
"show_samplers": OptionInfo(["Euler a", "UniPC", "DDIM", "DPM++ 2M SDE", "DPM++ 2M SDE Karras", "DPM2 Karras", "DPM++ 2M Karras"], "Show samplers in user interface", gr.CheckboxGroup, lambda: {"choices": [x.name for x in list_samplers() if x.name != "PLMS"]}),
"fallback_sampler": OptionInfo("Euler a", "Secondary sampler", gr.Dropdown, lambda: {"choices": ["None"] + [x.name for x in list_samplers()]}),
"xyz_fallback_sampler": OptionInfo("None", "Force latent upscaler sampler", gr.Dropdown, lambda: {"choices": ["None"] + [x.name for x in list_samplers()]}),
"force_latent_sampler": OptionInfo("None", "Force latent upscaler sampler", gr.Dropdown, lambda: {"choices": ["None"] + [x.name for x in list_samplers()]}),
"eta_ancestral": OptionInfo(1.0, "Noise multiplier for ancestral samplers (eta)", gr.Slider, {"minimum": 0.0, "maximum": 1.0, "step": 0.01}),
"eta_ddim": OptionInfo(0.0, "Noise multiplier for DDIM (eta)", gr.Slider, {"minimum": 0.0, "maximum": 1.0, "step": 0.01}),
"ddim_discretize": OptionInfo('uniform', "DDIM discretize img2img", gr.Radio, {"choices": ['uniform', 'quad']}),
@@ -504,7 +505,7 @@ options_templates.update(options_section(('upscaling', "Upscaling"), {
}))
options_templates.update(options_section(('lora', "Lora"), {
"lyco_patch_lora": OptionInfo(False, "Use LyCoris handler for all Lora types", gr.Checkbox, { "visible": True }), # TODO: lyco-patch-lora
"lyco_patch_lora": OptionInfo(False, "Use LyCoris handler for all Lora types", gr.Checkbox, { "visible": True }),
"lora_disable": OptionInfo(False, "Disable built-in Lora handler", gr.Checkbox, { "visible": True }, onchange=lora_disable),
"lora_functional": OptionInfo(False, "Use Kohya method for handling multiple Loras", gr.Checkbox, { "visible": True }),
}))
@@ -243,7 +243,7 @@ class EmbeddingDatabase:
self.previously_displayed_embeddings = displayed_embeddings
shared.log.info(f"Embeddings loaded: {len(self.word_embeddings)} {[k for k in self.word_embeddings.keys()]}")
if len(self.skipped_embeddings) > 0:
shared.log.info(f"Textual inversion embeddings skipped({len(self.skipped_embeddings)}): {', '.join(self.skipped_embeddings.keys())}")
shared.log.info(f"Embeddings skipped: {len(self.skipped_embeddings)} {[k for k in self.skipped_embeddings.keys()]}")
def find_embedding_at_position(self, tokens, offset):
token = tokens[offset]
+2 -2
View File
@@ -1638,7 +1638,7 @@ def html_head():
head += f'<script type="module" src="{webpath(script.path)}"></script>\n'
added.append(script.path)
added = [a.replace(script_path, '').replace('\\', '/') for a in added]
modules.shared.log.debug(f'Adding JS scripts: {added}')
# modules.shared.log.debug(f'Adding JS scripts: {added}')
return head
@@ -1671,7 +1671,7 @@ def html_css():
if os.path.exists(os.path.join(data_path, "user.css")):
head += stylesheet(os.path.join(data_path, "user.css"))
added = [a.replace(script_path, '').replace('\\', '/') for a in added]
modules.shared.log.debug(f'Adding CSS stylesheets: {added}')
# modules.shared.log.debug(f'Adding CSS stylesheets: {added}')
return head
+1 -1
View File
@@ -261,7 +261,7 @@ def search_extensions(search_text, sort_column):
def refresh_extensions_list_from_data(search_text, sort_column):
shared.log.debug(f'Extensions manager: refresh list search="{search_text}" sort="{sort_column}"')
# shared.log.debug(f'Extensions manager: refresh list search="{search_text}" sort="{sort_column}"')
code = """
<table id="extensions">
<colgroup>
+7 -4
View File
@@ -121,7 +121,7 @@ def apply_fallback(p, x, xs):
if sampler_name is None:
shared.log.warning(f"XYZ grid: unknown sampler: {x}")
else:
shared.opts.data["xyz_fallback_sampler"] = sampler_name
shared.opts.data["force_latent_sampler"] = sampler_name
def apply_uni_pc_order(p, x, xs):
@@ -209,6 +209,7 @@ axis_options = [
AxisOption("Nothing", str, do_nothing, fmt=format_nothing),
AxisOption("Checkpoint name", str, apply_checkpoint, fmt=format_value, confirm=confirm_checkpoints, cost=1.0, choices=lambda: list(sd_models.checkpoints_list)),
AxisOption("VAE", str, apply_vae, cost=0.7, choices=lambda: ['None'] + list(sd_vae.vae_dict)),
AxisOption("Dict name", str, apply_checkpoint, fmt=format_value, confirm=confirm_checkpoints, cost=1.0, choices=lambda: ['None'] + list(sd_models.checkpoints_list)),
AxisOption("Prompt S/R", str, apply_prompt, fmt=format_value),
AxisOption("Styles", str, apply_styles, choices=lambda: list(shared.prompt_styles.styles)),
AxisOptionTxt2Img("Sampler", str, apply_sampler, fmt=format_value, confirm=confirm_samplers, choices=lambda: [x.name for x in sd_samplers.samplers]),
@@ -351,8 +352,9 @@ class SharedSettingsStackHelper(object):
self.token_merging_ratio = shared.opts.token_merging_ratio
self.token_merging_random = shared.opts.token_merging_random
self.sd_model_checkpoint = shared.opts.sd_model_checkpoint
self.sd_model_dict = shared.opts.sd_model_dict
self.sd_vae_checkpoint = shared.opts.sd_vae
self.xyz_fallback_sampler = shared.opts.xyz_fallback_sampler
self.force_latent_sampler = shared.opts.force_latent_sampler
def __exit__(self, exc_type, exc_value, tb):
#Restore overriden settings after plot generation.
@@ -361,8 +363,9 @@ class SharedSettingsStackHelper(object):
shared.opts.data["token_merging_ratio_hr"] = self.token_merging_ratio_hr
shared.opts.data["token_merging_ratio"] = self.token_merging_ratio
shared.opts.data["token_merging_random"] = self.token_merging_random
shared.opts.data["xyz_fallback_sampler"] = self.xyz_fallback_sampler
if self.sd_model_checkpoint != shared.opts.sd_model_checkpoint:
shared.opts.data["force_latent_sampler"] = self.force_latent_sampler
if (self.sd_model_checkpoint != shared.opts.sd_model_checkpoint) or (self.sd_model_dict != shared.opts.sd_model_dict):
shared.opts.data["sd_model_dict"] = self.sd_model_dict
shared.opts.data["sd_model_checkpoint"] = self.sd_model_checkpoint
sd_models.reload_model_weights()
if self.sd_vae_checkpoint != shared.opts.sd_vae:
+8 -1
View File
@@ -85,7 +85,7 @@ def check_rollback_vae():
def initialize():
log.debug('Entering Initialize')
log.debug('Entering initialize')
check_rollback_vae()
modules.sd_vae.refresh_vae_list()
@@ -104,6 +104,7 @@ def initialize():
gfpgan.setup_model(opts.gfpgan_models_path)
startup_timer.record("gfpgan")
log.debug('Loading scripts')
modules.scripts.load_scripts()
startup_timer.record("scripts")
@@ -157,6 +158,7 @@ def load_model():
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.opts.onchange("sd_model_dict", wrap_queued_call(lambda: modules.sd_models.reload_model_weights()), call=False)
shared.state.end()
startup_timer.record("checkpoint")
@@ -282,6 +284,11 @@ def webui():
start_ui()
load_model()
log.info(f"Startup time: {startup_timer.summary()}")
# override all loggers to use the same handlers as the main logger
for logger in [logging.getLogger(name) for name in logging.root.manager.loggerDict]: # pylint: disable=no-member
logger.handlers = log.handlers
if cmd_opts.autolaunch and local_url is not None:
cmd_opts.autolaunch = False
shared.log.info('Launching browser')
+1 -1
Submodule wiki updated: d420606fc4...d54b7fd3be