major refactor

This commit is contained in:
Vladimir Mandic
2023-09-04 11:31:29 -04:00
parent cb6731cec2
commit e9055c7cd8
23 changed files with 188 additions and 183 deletions
+1
View File
@@ -27,6 +27,7 @@
highly recommended for simple prompts
- general:
- `rembg` remove backgrounds support for **is-net** model
- **settings** now show markers for all items set to non-default values
- pre-create all system folders on startup
## Update for 2023-08-30
+4 -4
View File
@@ -2,11 +2,11 @@
{"id":"","label":"📘","localized":"","hint":"Read generation parameters from prompt or last generation if prompt is empty into user interface"},
{"id":"","label":"🚮","localized":"","hint":"Clear prompt"},
{"id":"","label":"🌐","localized":"","hint":"Show/hide extra networks"},
{"id":"","label":"🧳","localized":"","hint":"Apply selected styles to current prompt"},
{"id":"","label":"🛅","localized":"","hint":"Save current prompt as style template"},
{"id":"","label":"","localized":"","hint":"Apply selected styles to current prompt"},
{"id":"","label":"⬇️","localized":"","hint":"Save current prompt as style template"},
{"id":"","label":"🔄","localized":"","hint":"Refresh"},
{"id":"","label":"","localized":"","hint":"Close"},
{"id":"","label":"📒","localized":"","hint":"Fill"},
{"id":"","label":"🛗","localized":"","hint":"Close"},
{"id":"","label":"","localized":"","hint":"Fill"},
{"id":"","label":"🎲️","localized":"","hint":"Use random seed"},
{"id":"","label":"♻️","localized":"","hint":"Reuse previous seed"},
{"id":"","label":"⇅","localized":"","hint":"Swap values"}
+1 -1
View File
@@ -120,7 +120,7 @@ svg.feather.feather-image, .feather .feather-image { display: none }
#pnginfo_html2_info { margin-top: -18px; background-color: var(--input-background-fill); padding: var(--input-padding) }
#txt2img_tools > div > button, #img2img_tools > div > button { filter: hue-rotate(180deg) saturate(0.5); }
#txt2img_tools, #img2img_tools { margin-top: -4px; margin-bottom: -4px; }
#txt2img_styles_row { margin-top: -6px; }
#txt2img_styles_row, #img2img_styles_row { margin-top: -6px; }
/* custom elements overrides */
#steps-animation, #controlnet { border-width: 0; }
+1 -1
View File
@@ -115,7 +115,7 @@ svg.feather.feather-image, .feather .feather-image { display: none }
#pnginfo_html2_info { margin-top: -18px; background-color: var(--input-background-fill); padding: var(--input-padding) }
#txt2img_tools > div > button, #img2img_tools > div > button { filter: hue-rotate(180deg) saturate(0.5); }
#txt2img_tools, #img2img_tools { margin-top: -4px; margin-bottom: -4px; }
#txt2img_styles_row { margin-top: -6px; }
#txt2img_styles_row, #img2img_styles_row { margin-top: -6px; }
/* custom elements overrides */
#steps-animation, #controlnet { border-width: 0; }
+13 -14
View File
@@ -18,15 +18,13 @@
--highlight-color: var(--primary-200);
--inactive-color: var(--primary--800);
--background-color: #000000;
}
.light, .dark {
--input-padding: 4px;
--radius-lg: 2px;
--radius-sm: 1px;
--radius-lg: 4px;
--radius-sm: 2px;
--spacing-md: 4px;
--spacing-xxl: 12px;
--line-sm: 1.3em;
--line-md: 1.3em;
--spacing-xxl: 8px;
--line-sm: 1.2em;
--line-md: 1.4em;
}
html { font-size: var(--font-size); }
@@ -35,10 +33,10 @@ button { font-size: 1.2rem; max-width: 400px; }
img { background-color: var(--background-color); }
input[type=checkbox] { background-color: transparent !important; }
input[type=range] { height: var(--line-sm); appearance: none; margin-top: 0; min-width: 160px; background-color: var(--background-color); width: 100%; background: transparent; }
input[type=range]::-webkit-slider-runnable-track { width: 100%; height: 18px; cursor: pointer; box-shadow: 2px 2px 3px #111111; background: var(--input-background-fill); border-radius: var(--radius-lg); border: 0px solid #222222; }
input[type=range]::-moz-range-track { width: 100%; height: 18px; cursor: pointer; box-shadow: 2px 2px 3px #111111; background: var(--input-background-fill); border-radius: var(--radius-lg); border: 0px solid #222222; }
input[type=range]::-webkit-slider-thumb { box-shadow: 2px 2px 3px #111111; border: 0px solid #000000; height: 18px; width: 40px; border-radius: var(--radius-lg); background: var(--highlight-color); cursor: pointer; appearance: none; margin-top: 0px; }
input[type=range]::-moz-range-thumb { box-shadow: 2px 2px 3px #111111; border: 0px solid #000000; height: 18px; width: 40px; border-radius: var(--radius-lg); background: var(--highlight-color); cursor: pointer; appearance: none; margin-top: 0px; }
input[type=range]::-webkit-slider-runnable-track { width: 100%; height: var(--line-sm); cursor: pointer; box-shadow: 2px 2px 3px #111111; background: var(--input-background-fill); border-radius: var(--radius-lg); border: 0px solid #222222; }
input[type=range]::-moz-range-track { width: 100%; height: var(--line-sm); cursor: pointer; box-shadow: 2px 2px 3px #111111; background: var(--input-background-fill); border-radius: var(--radius-lg); border: 0px solid #222222; }
input[type=range]::-webkit-slider-thumb { box-shadow: 2px 2px 3px #111111; border: 0px solid #000000; height: var(--line-sm); width: var(--line-sm); border-radius: var(--radius-lg); background: var(--highlight-color); cursor: pointer; appearance: none; margin-top: 0px; }
input[type=range]::-moz-range-thumb { box-shadow: 2px 2px 3px #111111; border: 0px solid #000000; height: var(--line-sm); width: var(--line-sm); border-radius: var(--radius-lg); background: var(--highlight-color); cursor: pointer; appearance: none; margin-top: 0px; }
::-webkit-scrollbar { width: 12px; }
::-webkit-scrollbar-track { background: #333333; }
::-webkit-scrollbar-thumb { background-color: var(--highlight-color); border-radius: var(--radius-lg); border-width: 0; box-shadow: 2px 2px 3px #111111; }
@@ -74,7 +72,7 @@ svg.feather.feather-image, .feather .feather-image { display: none }
.tab-nav { zoom: 120%; margin-bottom: 10px; border-bottom: 2px solid var(--highlight-color) !important; padding-bottom: 2px; }
.label-wrap { margin: 16px 0px 8px 0px; }
.gradio-slider input[type="number"] { width: 4.5em; font-size: 0.8rem; height: 20px; }
.gradio-button.tool { border: none; background: none; box-shadow: none; }
.gradio-button.tool { border: none; background: none; box-shadow: none; filter: hue-rotate(340deg) saturate(0.5); }
#tab_extensions table td, #tab_extensions table th { border: none; padding: 0.5em; }
#tab_extensions table { width: 96vw }
#tab_extensions table thead { background-color: var(--neutral-700); }
@@ -85,7 +83,9 @@ svg.feather.feather-image, .feather .feather-image { display: none }
.gallery-item { box-shadow: none !important; }
.performance { color: #888; }
.extra-networks { border-left: 2px solid var(--highlight-color) !important; padding-left: 4px; }
.image-buttons { gap: 10px !important}
.image-buttons { gap: 10px !important; justify-content: center; }
.image-buttons > button { max-width: 160px; }
#system_row > button, #settings_row > button, #config_row > button { max-width: 190px; }
/* gradio elements overrides */
#div.gradio-container { overflow-x: hidden; }
@@ -113,7 +113,6 @@ svg.feather.feather-image, .feather .feather-image { display: none }
#txt2img_results, #img2img_results, #extras_results { background-color: var(--background-color); padding: 0; }
#txt2img_settings { min-width: var(--left-column); max-width: var(--left-column); background-color: #111111; padding-top: 16px; }
#pnginfo_html2_info { margin-top: -18px; background-color: var(--input-background-fill); padding: var(--input-padding) }
#txt2img_tools > div > button, #img2img_tools > div > button { filter: hue-rotate(340deg) saturate(0.5); }
#txt2img_tools, #img2img_tools { margin-top: -4px; margin-bottom: -4px; }
#txt2img_styles_row, #img2img_styles_row { margin-top: -6px; }
+1
View File
@@ -45,6 +45,7 @@ function markIfModified(setting_name, value) {
const changed_value = previous_value !== current_value;
if (changed_value) elem.title = `click to revert to previous value: ${previous_value}`;
const is_stored = opts_metadata[setting_name].is_stored;
if (is_stored) console.log('A', opts_metadata[setting_name]);
if (is_stored) elem.title = 'custom value';
elem.disabled = !changed_value && !is_stored;
elem.classList.toggle('changed', changed_value);
+1 -1
View File
@@ -239,7 +239,7 @@ table.settings-value-table td { padding: 0.4em; border: 1px solid #ccc; max-widt
.extra-network-cards .card { height: fit-content; margin: 0.5em; position: relative; scroll-snap-align: start; scroll-margin-top: 0; }
.extra-network-cards .card .overlay { position: absolute; bottom: 0; padding: 0.2em; z-index: 10; width: 100%; background: none; }
.extra-network-cards .card:hover .overlay { background: rgba(0, 0, 0, 0.40); }
.extra-network-cards .card .overlay .name { font-size: 1.2em; font-weight: bold; line-break: anywhere; text-shadow: 1px 1px black; color: white; }
.extra-network-cards .card .overlay .name { font-size: 1.1em; font-weight: bold; text-shadow: 1px 1px black; color: white; }
.extra-network-cards .card .overlay .tags { margin: 4px; display: none; overflow-wrap: break-word; }
.extra-network-cards .card .overlay .tag { padding: 2px; margin: 2px; background: var(--neutral-700); cursor: pointer; display: inline-block; }
.extra-network-cards .card .overlay .actions { font-size: 2.2em; display: none; text-align-last: center; cursor: pointer; font-variant: unicase; height: 0.8em }
+37
View File
@@ -0,0 +1,37 @@
from __future__ import annotations
import re
import logging
import warnings
import urllib3
from modules import timer, errors
initialized = False
logging.getLogger("DeepSpeed").disabled = True
import torch # pylint: disable=C0411
try:
import intel_extension_for_pytorch as ipex # pylint: disable=import-error, unused-import
except Exception:
pass
errors.log.debug(f'Loaded Torch=={torch.__version__}')
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
import torchvision # pylint: disable=W0611,C0411
import pytorch_lightning # pytorch_lightning should be imported after torch, but it re-enables warnings on import so import once to disable them # pylint: disable=W0611,C0411
if ".dev" in torch.__version__ or "+git" in torch.__version__:
torch.__long_version__ = torch.__version__
torch.__version__ = re.search(r'[\d.]+[\d]', torch.__version__).group(0)
logging.getLogger("xformers").addFilter(lambda record: 'A matching Triton is not available' not in record.getMessage())
logging.getLogger("pytorch_lightning").disabled = True
warnings.filterwarnings(action="ignore", category=DeprecationWarning)
warnings.filterwarnings(action="ignore", category=FutureWarning)
warnings.filterwarnings(action="ignore", category=UserWarning, module="torchvision")
timer.startup.record("torch")
from fastapi import FastAPI # pylint: disable=W0611,C0411
import gradio # pylint: disable=W0611,C0411
errors.log.debug(f'Loaded Gradio=={gradio.__version__}')
timer.startup.record("gradio")
errors.install([gradio])
import diffusers # pylint: disable=W0611,C0411
errors.log.debug(f'Loaded Diffusers=={diffusers.__version__}')
timer.startup.record("diffusers")
+3 -6
View File
@@ -244,12 +244,9 @@ def directory_has_changed(dir:str, *, recursive:bool=True) -> bool: # pylint: di
def directory_directories(dir:str, *, recursive:bool=True) -> dict[str,tuple[float,list[str]]]: # pylint: disable=redefined-builtin
dir = os.path.abspath(dir)
if directory_has_changed(dir, recursive=recursive):
for _dir in modelloader_directories:
try:
if (os.path.exists(_dir) and os.path.isdir(_dir)):
continue
except Exception:
pass
for _dir in list(modelloader_directories):
if os.path.exists(_dir) or os.path.isdir(_dir):
continue
del modelloader_directories[_dir]
for _dir, _files in walk(dir, lambda e, path: shared.log.debug(f"FS walk error: {e} {path}")):
try:
+4 -1
View File
@@ -27,6 +27,9 @@ import modules.sd_models as sd_models
import modules.sd_vae as sd_vae
opt_C = 4
opt_f = 8
def setup_color_correction(image):
shared.log.debug("Calibrating color correction.")
correction_target = cv2.cvtColor(np.asarray(image.copy()), cv2.COLOR_RGB2LAB)
@@ -933,8 +936,8 @@ class StableDiffusionProcessingTxt2Img(StableDiffusionProcessing):
self.extra_generation_params["Hires steps"] = self.hr_second_pass_steps
if self.hr_upscaler is not None:
self.extra_generation_params["Hires upscaler"] = self.hr_upscaler
shared.log.debug(f'Init hires: upscaler={self.hr_upscaler} sampler={self.latent_sampler} resize={self.hr_resize_x}x{self.hr_resize_y} upscale={self.hr_upscale_to_x}x{self.hr_upscale_to_y}')
self.extra_generation_params["Secondary sampler"] = self.latent_sampler
shared.log.debug(f'Init hires: upscaler={self.hr_upscaler} sampler={self.latent_sampler} resize={self.hr_resize_x}x{self.hr_resize_y} upscale={self.hr_upscale_to_x}x{self.hr_upscale_to_y}')
def sample(self, conditioning, unconditional_conditioning, seeds, subseeds, subseed_strength, prompts):
+5 -6
View File
@@ -4,7 +4,7 @@ import sys
import time
from collections import namedtuple
import gradio as gr
from modules import paths, script_callbacks, extensions, script_loading, scripts_postprocessing, errors
from modules import paths, script_callbacks, extensions, script_loading, scripts_postprocessing, errors, timer
from installer import log
@@ -226,13 +226,14 @@ def list_files_with_name(filename):
def load_scripts():
t = timer.Timer()
t0 = time.time()
global current_basedir # pylint: disable=global-statement
scripts_data.clear()
postprocessing_scripts_data.clear()
script_callbacks.clear_callbacks()
scripts_list = list_scripts("scripts", ".py")
syspath = sys.path
time_load = {}
def register_scripts_from_module(module, scriptfile):
for script_class in module.__dict__.values():
@@ -245,7 +246,6 @@ def load_scripts():
postprocessing_scripts_data.append(ScriptClassData(script_class, scriptfile.path, scriptfile.basedir, module))
for scriptfile in scripts_list:
t0 = time.time()
try:
if scriptfile.basedir != paths.script_path:
sys.path = [scriptfile.basedir] + sys.path
@@ -256,7 +256,7 @@ def load_scripts():
errors.display(e, f'Loading script: {scriptfile.filename}')
finally:
current_basedir = paths.script_path
time_load[scriptfile.basedir] = time_load.get(scriptfile.basedir, 0) + (time.time()-t0)
t.record(os.path.basename(scriptfile.basedir))
sys.path = syspath
global scripts_txt2img, scripts_img2img, scripts_postproc # pylint: disable=global-statement
@@ -264,8 +264,7 @@ def load_scripts():
scripts_img2img = ScriptRunner()
scripts_postproc = scripts_postprocessing.ScriptPostprocessingRunner()
time_summary = [f'{os.path.basename(k)}:{round(v,3)}s' for (k,v) in time_load.items() if v > 0.05]
log.debug(f'Scripts load: {time_summary}')
return t, time.time()-t0
def wrap_call(func, filename, funcname, *args, default=None, **kwargs):
+15 -10
View File
@@ -403,7 +403,8 @@ def load_model_weights(model: torch.nn.Module, checkpoint_info: CheckpointInfo,
try:
model.load_state_dict(state_dict, strict=False)
except Exception as e:
shared.log.error(f'Error loading model weights: {checkpoint_info.filename} {e}')
shared.log.error(f'Error loading model weights: {checkpoint_info.filename}')
shared.log.error(' '.join(str(e).splitlines()[:2]))
return False
del state_dict
timer.record("apply")
@@ -813,7 +814,8 @@ def load_diffuser(checkpoint_info=None, already_loaded_state_dict=None, timer=No
shared.opts.diffusers_move_base=True
shared.opts.diffusers_move_refiner=True
shared.log.debug('Moving base model to CPU')
model_data.sd_model.to(devices.cpu)
if model_data.sd_model is not None:
model_data.sd_model.to(devices.cpu)
devices.torch_gc(force=True)
sd_model.to(devices.device)
base_sent_to_cpu=True
@@ -1007,7 +1009,10 @@ def load_model(checkpoint_info=None, already_loaded_state_dict=None, timer=None,
model_data.sd_model = sd_model
current_checkpoint_info = None
unload_model_weights(op=op)
shared.log.debug(f'Model weights unloaded: {memory_stats()}')
shared.log.debug(f'Model weights unloaded: {memory_stats()} op={op}')
if op == 'refiner':
# shared.opts.data['sd_model_refiner'] = 'None'
shared.opts.sd_model_refiner = 'None'
return
else:
shared.log.debug(f'Model weights loaded: {memory_stats()}')
@@ -1062,12 +1067,12 @@ def reload_model_weights(sd_model=None, info=None, reuse_dict=False, op='model')
lowvram.send_everything_to_cpu()
else:
sd_model.to(devices.cpu)
if (reuse_dict or (shared.opts.model_reuse_dict and sd_model is not None)) and not sd_model.has_accelerate:
shared.log.info('Reusing previous model dictionary')
sd_hijack.model_hijack.undo_hijack(sd_model)
else:
unload_model_weights(op=op)
sd_model = None
if (reuse_dict or shared.opts.model_reuse_dict) and not sd_model.has_accelerate:
shared.log.info('Reusing previous model dictionary')
sd_hijack.model_hijack.undo_hijack(sd_model)
else:
unload_model_weights(op=op)
sd_model = None
timer = Timer()
state_dict = get_checkpoint_state_dict(checkpoint_info, timer)
checkpoint_config = sd_models_config.find_checkpoint_config(state_dict, checkpoint_info)
@@ -1095,7 +1100,7 @@ def reload_model_weights(sd_model=None, info=None, reuse_dict=False, op='model')
timer.record("hijack")
script_callbacks.model_loaded_callback(sd_model)
timer.record("callbacks")
if not shared.cmd_opts.lowvram and not shared.cmd_opts.medvram and not sd_model.has_accelerate:
if sd_model is not None and not shared.cmd_opts.lowvram and not shared.cmd_opts.medvram and not sd_model.has_accelerate:
sd_model.to(devices.device)
timer.record("device")
shared.log.info(f"Weights loaded in {timer.summary()}")
+2 -2
View File
@@ -635,7 +635,7 @@ options_templates.update(options_section(('extra_networks', "Extra Networks"), {
"extra_networks_height": OptionInfo(53, "UI height (%)", gr.Slider, {"minimum": 10, "maximum": 100, "step": 1}),
"extra_networks_sidebar_width": OptionInfo(35, "UI sidebar width (%)", gr.Slider, {"minimum": 10, "maximum": 80, "step": 1}),
"extra_networks_card_lazy": OptionInfo(True, "UI card preview lazy loading"),
"extra_networks_card_size": OptionInfo(200, "UI card size (px)", gr.Slider, {"minimum": 20, "maximum": 2000, "step": 1}),
"extra_networks_card_size": OptionInfo(160, "UI card size (px)", gr.Slider, {"minimum": 20, "maximum": 2000, "step": 1}),
"extra_networks_card_square": OptionInfo(True, "UI disable variable aspect ratio"),
"extra_networks_card_fit": OptionInfo("cover", "UI image contain method", gr.Radio, lambda: {"choices": ["contain", "cover", "fill"]}),
"extra_network_skip_indexing": OptionInfo(False, "Do not automatically build extra network pages", gr.Checkbox),
@@ -767,7 +767,7 @@ class Options:
d = {k: self.data.get(k, self.data_labels.get(k).default) for k in self.data_labels.keys()}
metadata = {
k: {
"is_stored": k in self.data,
"is_stored": k in self.data and self.data[k] != self.data_labels[k].default,
"tab_name": v.section[0]
} for k, v in self.data_labels.items()
}
+6 -9
View File
@@ -21,18 +21,15 @@ class Timer:
self.records[category] += e + extra_time
self.total += e + extra_time
def summary(self):
res = f"{self.total:.1f}s"
additions = [x for x in self.records.items() if x[1] >= 0.05]
def summary(self, min_time=0.05):
res = f"{self.total:.2f}s"
additions = [x for x in self.records.items() if x[1] >= min_time]
if not additions:
return res
res += " ("
res += " ".join([f"{category}={time_taken:.1f}s" for category, time_taken in additions])
res += ")"
res += " { " + " ".join([f"{category}={time_taken:.2f}s" for category, time_taken in additions]) + " }"
return res
def reset(self):
self.__init__()
startup = Timer()
+26 -38
View File
@@ -16,6 +16,8 @@ from modules.paths import script_path, data_path
from modules.shared import opts, cmd_opts, readfile
from modules.dml import directml_override_opts
from modules import prompt_parser
from modules import timer
import modules.ui_symbols as symbols
import modules.codeformer_model
import modules.generation_parameters_copypaste as parameters_copypaste
import modules.gfpgan_model
@@ -50,19 +52,6 @@ sample_img2img = "assets/stable-samples/img2img/sketch-mountains-input.jpg"
sample_img2img = sample_img2img if os.path.exists(sample_img2img) else None
paste_function = None
# Using constants for these since the variation selector isn't visible.
# Important that they exactly match script.js for tooltip to work.
random_symbol = '\U0001f3b2\ufe0f' # 🎲️
reuse_symbol = '\u267b\ufe0f' # ♻️
paste_symbol = '\U0001F4D8' # '\u2199\ufe0f' # ↙
refresh_symbol = '\U0001F504' # 🔄
save_style_symbol = '\U0001F6C5' # '\U0001f4be' # 💾
apply_style_symbol = '\U0001F9F3' # '\U0001f4cb' # 📋
clear_prompt_symbol = '\U0001F6AE' # '\U0001f5d1\ufe0f' # 🗑️
extra_networks_symbol = '\U0001F310' # '\U0001F3B4' # 🎴
switch_values_symbol = '\U000021C5' # ⇅
detect_image_size_symbol = '\U0001F4D0' # 📐
def create_output_panel(tabname, outdir): # may be referenced by extensions
a, b, c, _d, e = ui_common.create_output_panel(tabname, outdir)
@@ -161,13 +150,13 @@ def create_seed_inputs(tab, visible):
with FormRow(elem_id=f"{tab}_seed_row", variant="compact"):
seed = gr.Number(label='Seed', value=-1, elem_id=f"{tab}_seed")
seed.style(container=False)
random_seed = ToolButton(random_symbol, elem_id=f"{tab}_random_seed", label='Random seed')
reuse_seed = ToolButton(reuse_symbol, elem_id=f"{tab}_reuse_seed", label='Reuse seed')
random_seed = ToolButton(symbols.random, elem_id=f"{tab}_random_seed", label='Random seed')
reuse_seed = ToolButton(symbols.reuse, elem_id=f"{tab}_reuse_seed", label='Reuse seed')
with FormRow(visible=True, elem_id=f"{tab}_subseed_row"):
subseed = gr.Number(label='Variation seed', value=-1, elem_id=f"{tab}_subseed")
subseed.style(container=False)
random_subseed = ToolButton(random_symbol, elem_id=f"{tab}_random_subseed")
reuse_subseed = ToolButton(reuse_symbol, elem_id=f"{tab}_reuse_subseed")
random_subseed = ToolButton(symbols.random, elem_id=f"{tab}_random_subseed")
reuse_subseed = ToolButton(symbols.reuse, elem_id=f"{tab}_reuse_subseed")
subseed_strength = gr.Slider(label='Variation strength', value=0.0, minimum=0, maximum=1, step=0.01, elem_id=f"{tab}_subseed_strength")
with FormRow(visible=False):
seed_resize_from_w = gr.Slider(minimum=0, maximum=4096, step=8, label="Resize seed from width", value=0, elem_id=f"{tab}_seed_resize_from_w")
@@ -268,11 +257,11 @@ def create_toprow(is_img2img):
pause = gr.Button('Pause', elem_id=f"{id_part}_pause")
pause.click(fn=lambda: modules.shared.state.pause(), _js='checkPaused', inputs=[], outputs=[])
with gr.Row(elem_id=f"{id_part}_tools"):
paste = ToolButton(value=paste_symbol, elem_id="paste")
clear_prompt_button = ToolButton(value=clear_prompt_symbol, elem_id=f"{id_part}_clear_prompt_btn")
extra_networks_button = ToolButton(value=extra_networks_symbol, elem_id=f"{id_part}_extra_networks_btn")
prompt_style_apply = ToolButton(value=apply_style_symbol, elem_id=f"{id_part}_style_apply_btn")
save_style = ToolButton(value=save_style_symbol, elem_id=f"{id_part}_style_create_btn")
paste = ToolButton(value=symbols.paste, elem_id="paste")
clear_prompt_button = ToolButton(value=symbols.clear, elem_id=f"{id_part}_clear_prompt_btn")
extra_networks_button = ToolButton(value=symbols.networks, elem_id=f"{id_part}_extra_networks_btn")
prompt_style_apply = ToolButton(value=symbols.apply, elem_id=f"{id_part}_style_apply_btn")
save_style = ToolButton(value=symbols.save, elem_id=f"{id_part}_style_create_btn")
clear_prompt_button.click(fn=lambda *x: x, _js="confirm_clear_prompt", inputs=[prompt, negative_prompt], outputs=[prompt, negative_prompt])
with gr.Row(elem_id=f"{id_part}_counters"):
token_counter = gr.HTML(value="<span>0/75</span>", elem_id=f"{id_part}_token_counter", elem_classes=["token-counter"])
@@ -348,8 +337,7 @@ def create_override_settings_dropdown(tabname, row): # pylint: disable=unused-ar
def create_ui(startup_timer = None):
if startup_timer is None:
from modules import timer
startup_timer = timer.Timer()
timer.startup = timer.Timer()
reload_javascript()
parameters_copypaste.reset()
ui_defaults = readfile(cmd_opts.ui_config)
@@ -372,7 +360,7 @@ def create_ui(startup_timer = None):
with FormRow():
width = gr.Slider(minimum=64, maximum=4096, step=8, label="Width", value=512, elem_id="txt2img_width")
height = gr.Slider(minimum=64, maximum=4096, step=8, label="Height", value=512, elem_id="txt2img_height")
res_switch_btn = ToolButton(value=switch_values_symbol, elem_id="txt2img_res_switch_btn", label="Switch dims")
res_switch_btn = ToolButton(value=symbols.switch, elem_id="txt2img_res_switch_btn", label="Switch dims")
with FormRow(elem_classes="checkboxes-row", variant="compact"):
show_batch = gr.Checkbox(label='Batch', value=ui_defaults.get('txt2img/Batch/value', False), elem_id="txt2img_show_batch")
@@ -384,7 +372,7 @@ def create_ui(startup_timer = None):
with FormRow(elem_id="txt2img_row_batch"):
batch_count = gr.Slider(minimum=1, step=1, label='Batch count', value=1, elem_id="txt2img_batch_count")
batch_size = gr.Slider(minimum=1, maximum=32, step=1, label='Batch size', value=1, elem_id="txt2img_batch_size")
batch_switch_btn = ToolButton(value=switch_values_symbol, elem_id="txt2img_batch_switch_btn", label="Switch dims")
batch_switch_btn = ToolButton(value=symbols.switch, elem_id="txt2img_batch_switch_btn", label="Switch dims")
seed_group, seed, reuse_seed, subseed, reuse_subseed, subseed_strength, seed_resize_from_h, seed_resize_from_w = create_seed_inputs('txt2img', show_seed.value)
@@ -535,7 +523,7 @@ def create_ui(startup_timer = None):
ui_extra_networks.setup_ui(extra_networks_ui, txt2img_gallery)
log.debug(f'UI interface: tab=txt2img batch={show_batch.value} seed={show_seed.value} advanced={show_advanced.value} second_pass={show_second_pass.value}')
startup_timer.record("ui-txt2img")
timer.startup.record("ui-txt2img")
import modules.img2img # pylint: disable=redefined-outer-name
modules.scripts.scripts_current = modules.scripts.scripts_img2img
@@ -647,8 +635,8 @@ def create_ui(startup_timer = None):
height = gr.Slider(minimum=64, maximum=4096, step=8, label="Height", value=512, elem_id="img2img_height")
with gr.Column(elem_id="img2img_column_dim", scale=1, elem_classes="dimensions-tools"):
with FormRow():
res_switch_btn = ToolButton(value=switch_values_symbol, elem_id="img2img_res_switch_btn")
detect_image_size_btn = ToolButton(value=detect_image_size_symbol, elem_id="img2img_detect_image_size_btn")
res_switch_btn = ToolButton(value=symbols.switch, elem_id="img2img_res_switch_btn")
detect_image_size_btn = ToolButton(value=symbols.detect, elem_id="img2img_detect_image_size_btn")
with gr.Tab(label="Resize by") as tab_scale_by:
scale_by = gr.Slider(minimum=0.05, maximum=4.0, step=0.05, label="Scale", value=1.0, elem_id="img2img_scale")
@@ -895,21 +883,21 @@ def create_ui(startup_timer = None):
log.debug(f'UI interface: tab=img2img seed={show_seed.value} resize={show_resize.value} batch={show_batch.value} denoise={show_denoise.value} advanced={show_advanced.value}')
startup_timer.record("ui-img2img")
timer.startup.record("ui-img2img")
modules.scripts.scripts_current = None
with gr.Blocks(analytics_enabled=False) as extras_interface:
ui_postprocessing.create_ui()
startup_timer.record("ui-extras")
timer.startup.record("ui-extras")
with gr.Blocks(analytics_enabled=False) as train_interface:
ui_train.create_ui(txt2img_preview_params = [txt2img_prompt, txt2img_negative_prompt, steps, sampler_index, cfg_scale, seed, width, height])
startup_timer.record("ui-train")
timer.startup.record("ui-train")
with gr.Blocks(analytics_enabled=False) as models_interface:
ui_models.create_ui()
startup_timer.record("ui-models")
timer.startup.record("ui-models")
def create_setting_component(key, is_quicksettings=False):
def fun():
@@ -1015,7 +1003,7 @@ def create_ui(startup_timer = None):
return get_value_for_setting(key), opts.dumpjson()
with gr.Blocks(analytics_enabled=False) as settings_interface:
with gr.Row():
with gr.Row(elem_id="system_row"):
restart_submit = gr.Button(value="Restart server", variant='primary', elem_id="restart_submit")
shutdown_submit = gr.Button(value="Shutdown server", variant='primary', elem_id="shutdown_submit")
unload_sd_model = gr.Button(value='Unload checkpoint', variant='primary', elem_id="sett_unload_sd_model")
@@ -1025,7 +1013,7 @@ def create_ui(startup_timer = None):
global ui_system_tabs # pylint: disable=global-statement
ui_system_tabs = system_tabs
with gr.TabItem("Settings", id="system_settings", elem_id="tab_settings"):
with gr.Row():
with gr.Row(elem_id="settings_row"):
settings_submit = gr.Button(value="Apply settings", variant='primary', elem_id="settings_submit")
preview_theme = gr.Button(value="Preview theme", variant='primary', elem_id="settings_preview_theme")
defaults_submit = gr.Button(value="Restore defaults", variant='primary', elem_id="defaults_submit")
@@ -1096,7 +1084,7 @@ def create_ui(startup_timer = None):
request_notifications.click(fn=lambda: None, inputs=[], outputs=[], _js='function(){}')
preview_theme.click(fn=None, _js='preview_theme', inputs=[dummy_component], outputs=[dummy_component])
startup_timer.record("ui-settings")
timer.startup.record("ui-settings")
interfaces = [
(txt2img_interface, "From Text", "txt2img"),
@@ -1109,7 +1097,7 @@ def create_ui(startup_timer = None):
interfaces += [(settings_interface, "System", "system")]
extensions_interface = ui_extensions.create_ui()
interfaces += [(extensions_interface, "Extensions", "extensions")]
startup_timer.record("ui-extensions")
timer.startup.record("ui-extensions")
modules.shared.tab_names = []
for _interface, label, _ifid in interfaces:
@@ -1183,7 +1171,7 @@ def create_ui(startup_timer = None):
queue=False,
)
startup_timer.record("ui-defaults")
timer.startup.record("ui-defaults")
loadsave.dump_defaults()
demo.ui_loadsave = loadsave
return demo
+2 -5
View File
@@ -7,12 +7,10 @@ import subprocess
import gradio as gr
from modules import call_queue, shared
from modules.generation_parameters_copypaste import image_from_url_text
import modules.ui_symbols as symbols
import modules.images
folder_symbol = '\U0001f4c2' # 📂
def update_generation_info(generation_info, html_info, img_index):
try:
generation_info = json.loads(generation_info)
@@ -224,7 +222,6 @@ def create_refresh_button(refresh_component, refresh_method, refreshed_args, ele
return gr.update(**(args or {}))
from modules.ui_components import ToolButton
refresh_symbol = '\U0001f504' # 🔄
refresh_button = ToolButton(value=refresh_symbol, elem_id=elem_id)
refresh_button = ToolButton(value=symbols.refresh, elem_id=elem_id)
refresh_button.click(fn=refresh, inputs=[], outputs=[refresh_component])
return refresh_button
+3 -5
View File
@@ -13,15 +13,13 @@ from starlette.responses import FileResponse, JSONResponse
from modules import shared, scripts, modelloader
from modules.generation_parameters_copypaste import image_from_url_text
from modules.ui_components import ToolButton
import modules.ui_symbols as symbols
extra_pages = []
allowed_dirs = set()
dir_cache = {} # key=path, value=(mtime, listdir(path))
refresh_symbol = '\U0001f504' # 🔄
close_symbol = '\U0000274C' # ❌
def listdir(path):
if not os.path.exists(path):
@@ -344,8 +342,8 @@ def create_ui(container, button, tabname, skip_indexing = False):
ui.stored_extra_pages = extra_pages
ui.tabname = tabname
with gr.Tabs(elem_id=tabname+"_extra_tabs"):
button_refresh = ToolButton(refresh_symbol, elem_id=tabname+"_extra_refresh")
button_close = ToolButton(close_symbol, elem_id=tabname+"_extra_close")
button_refresh = ToolButton(symbols.refresh, elem_id=tabname+"_extra_refresh")
button_close = ToolButton(symbols.close, elem_id=tabname+"_extra_close")
ui.search = gr.Textbox('', show_label=False, elem_id=tabname+"_extra_search", placeholder="Search...", elem_classes="textbox", lines=1)
ui.description = gr.TextArea('', show_label=False, elem_id=tabname+"_description", placeholder="Save/Replace Extra Network Description...", elem_classes="textbox", lines=1)
ui.preview_target_filename = gr.Textbox('Preview save filename', elem_id=tabname+"_preview_filename", visible=False)
+1 -1
View File
@@ -174,7 +174,7 @@ class UiLoadsave:
def create_ui(self):
"""creates ui elements for editing defaults UI, without adding any logic to them"""
gr.HTML(f"Review changed values and apply them as new user interface defaults<br>Config file: {self.filename}")
with gr.Row():
with gr.Row(elem_id="config_row"):
self.ui_defaults_view = gr.Button(value='View changes', elem_id="ui_defaults_view", variant="secondary")
self.ui_defaults_apply = gr.Button(value='Set new defaults', elem_id="ui_defaults_apply", variant="primary")
self.ui_defaults_restore = gr.Button(value='Restore system defaults', elem_id="ui_defaults_restore", variant="primary")
+14
View File
@@ -0,0 +1,14 @@
refresh = '🔄'
close = '🛗'
load = '⬆️'
save = '⬇️'
apply = ''
clear = '🚮'
fill = ''
networks = '🌐'
switch = ''
detect = '📐'
folder = '📂'
random = '🎲️'
reuse = '♻️'
paste = '📘'
+3 -5
View File
@@ -3,7 +3,8 @@ import numpy as np
import gradio as gr
from modules import scripts_postprocessing, shared
from modules.ui_components import FormRow, ToolButton
from modules.ui import switch_values_symbol
import modules.ui_symbols as symbols
upscale_cache = {}
@@ -26,7 +27,7 @@ class ScriptPostprocessingUpscale(scripts_postprocessing.ScriptPostprocessing):
with gr.Row(elem_id="upscaling_column_size", scale=4):
upscaling_resize_w = gr.Slider(minimum=64, maximum=4096, step=8, label="Width", value=512, elem_id="extras_upscaling_resize_w")
upscaling_resize_h = gr.Slider(minimum=64, maximum=4096, step=8, label="Height", value=512, elem_id="extras_upscaling_resize_h")
upscaling_res_switch_btn = ToolButton(value=switch_values_symbol, elem_id="upscaling_res_switch_btn")
upscaling_res_switch_btn = ToolButton(value=symbols.switch, elem_id="upscaling_res_switch_btn")
upscaling_crop = gr.Checkbox(label='Crop to fit', value=True, elem_id="extras_upscaling_crop")
with FormRow():
@@ -114,7 +115,6 @@ class ScriptPostprocessingUpscaleSimple(ScriptPostprocessingUpscale):
with FormRow():
upscaler_name = gr.Dropdown(label='Upscaler', choices=[x.name for x in shared.sd_upscalers], value=shared.sd_upscalers[0].name)
upscale_by = gr.Slider(minimum=0.05, maximum=8.0, step=0.05, label="Upscale by", value=2)
return {
"upscale_by": upscale_by,
"upscaler_name": upscaler_name,
@@ -123,10 +123,8 @@ class ScriptPostprocessingUpscaleSimple(ScriptPostprocessingUpscale):
def process(self, pp: scripts_postprocessing.PostprocessedImage, upscale_by=2.0, upscaler_name=None): # pylint: disable=arguments-differ
if upscaler_name is None or upscaler_name == "None":
return
upscaler1 = next(iter([x for x in shared.sd_upscalers if x.name == upscaler_name]), None)
if upscaler1 is None:
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
+5 -6
View File
@@ -15,9 +15,7 @@ import modules.shared as shared
from modules import images, sd_samplers, processing, sd_models, sd_vae
from modules.processing import process_images, Processed, StableDiffusionProcessingTxt2Img
from modules.ui_components import ToolButton
fill_values_symbol = "\U0001f4d2" # 📒
AxisInfo = namedtuple('AxisInfo', ['axis', 'values'])
import modules.ui_symbols as symbols
def apply_field(field):
@@ -387,19 +385,19 @@ class Script(scripts.Script):
x_type = gr.Dropdown(label="X type", choices=[x.label for x in self.current_axis_options], value=self.current_axis_options[0].label, type="index", elem_id=self.elem_id("x_type"))
x_values = gr.Textbox(label="X values", lines=1, elem_id=self.elem_id("x_values"))
x_values_dropdown = gr.Dropdown(label="X values",visible=False,multiselect=True,interactive=True)
fill_x_button = ToolButton(value=fill_values_symbol, elem_id="xyz_grid_fill_x_tool_button", visible=False)
fill_x_button = ToolButton(value=symbols.fill, elem_id="xyz_grid_fill_x_tool_button", visible=False)
with gr.Row():
y_type = gr.Dropdown(label="Y type", choices=[x.label for x in self.current_axis_options], value=self.current_axis_options[0].label, type="index", elem_id=self.elem_id("y_type"))
y_values = gr.Textbox(label="Y values", lines=1, elem_id=self.elem_id("y_values"))
y_values_dropdown = gr.Dropdown(label="Y values",visible=False,multiselect=True,interactive=True)
fill_y_button = ToolButton(value=fill_values_symbol, elem_id="xyz_grid_fill_y_tool_button", visible=False)
fill_y_button = ToolButton(value=symbols.fill, elem_id="xyz_grid_fill_y_tool_button", visible=False)
with gr.Row():
z_type = gr.Dropdown(label="Z type", choices=[x.label for x in self.current_axis_options], value=self.current_axis_options[0].label, type="index", elem_id=self.elem_id("z_type"))
z_values = gr.Textbox(label="Z values", lines=1, elem_id=self.elem_id("z_values"))
z_values_dropdown = gr.Dropdown(label="Z values",visible=False,multiselect=True,interactive=True)
fill_z_button = ToolButton(value=fill_values_symbol, elem_id="xyz_grid_fill_z_tool_button", visible=False)
fill_z_button = ToolButton(value=symbols.fill, elem_id="xyz_grid_fill_z_tool_button", visible=False)
with gr.Row(variant="compact", elem_id="axis_options"):
draw_legend = gr.Checkbox(label='Draw legend', value=True, elem_id=self.elem_id("draw_legend"))
no_fixed_seeds = gr.Checkbox(label='Keep random for seeds', value=False, elem_id=self.elem_id("no_fixed_seeds"))
@@ -570,6 +568,7 @@ class Script(scripts.Script):
total_steps *= p.n_iter
image_cell_count = p.n_iter * p.batch_size
shared.log.info(f"XYZ grid: images={len(xs)*len(ys)*len(zs)*image_cell_count} grid={len(zs)} {len(xs)}x{len(ys)} cells={len(zs)} steps={total_steps}")
AxisInfo = namedtuple('AxisInfo', ['axis', 'values'])
shared.state.xyz_plot_x = AxisInfo(x_opt, xs)
shared.state.xyz_plot_y = AxisInfo(y_opt, ys)
shared.state.xyz_plot_z = AxisInfo(z_opt, zs)
+39 -67
View File
@@ -1,51 +1,18 @@
from __future__ import annotations
import os
import re
import sys
import glob
import signal
import asyncio
import logging
import warnings
import importlib
from threading import Thread
import urllib3
import modules.loader
import torch # pylint: disable=wrong-import-order
from modules import timer, errors, paths # pylint: disable=unused-import
startup_timer = timer.Timer()
local_url = None
logging.getLogger("DeepSpeed").disabled = True
import torch # pylint: disable=C0411
try:
import intel_extension_for_pytorch as ipex # pylint: disable=import-error, unused-import
except Exception:
pass
errors.log.debug(f'Loaded Torch=={torch.__version__}')
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
import torchvision # pylint: disable=W0611,C0411
import pytorch_lightning # pytorch_lightning should be imported after torch, but it re-enables warnings on import so import once to disable them # pylint: disable=W0611,C0411
if ".dev" in torch.__version__ or "+git" in torch.__version__:
torch.__long_version__ = torch.__version__
torch.__version__ = re.search(r'[\d.]+[\d]', torch.__version__).group(0)
logging.getLogger("xformers").addFilter(lambda record: 'A matching Triton is not available' not in record.getMessage())
logging.getLogger("pytorch_lightning").disabled = True
warnings.filterwarnings(action="ignore", category=DeprecationWarning)
warnings.filterwarnings(action="ignore", category=FutureWarning)
warnings.filterwarnings(action="ignore", category=UserWarning, module="torchvision")
startup_timer.record("torch")
from fastapi import FastAPI # pylint: disable=W0611,C0411
import gradio # pylint: disable=W0611,C0411
errors.log.debug(f'Loaded Gradio=={gradio.__version__}')
startup_timer.record("gradio")
errors.install([gradio])
import diffusers # pylint: disable=W0611,C0411
errors.log.debug(f'Loaded Diffusers=={diffusers.__version__}')
startup_timer.record("diffusers")
errors.log.debug('Loading Modules')
if not modules.loader.initialized:
errors.log.debug('Loading modules')
from installer import log, setup_logging, git_commit
import ldm.modules.encoders.modules # pylint: disable=W0611,C0411,E0401
from modules.call_queue import queue_lock, wrap_queued_call, wrap_gradio_gpu_call # pylint: disable=W0611,C0411,C0412
@@ -71,10 +38,12 @@ import modules.ui
from modules.shared import cmd_opts, opts
import modules.hypernetworks.hypernetwork
from modules.middleware import setup_middleware
startup_timer.record("libraries")
log.info('Libraries loaded')
log.setLevel(logging.DEBUG if cmd_opts.debug else logging.INFO)
logging.disable(logging.NOTSET if cmd_opts.debug else logging.DEBUG)
if not modules.loader.initialized:
timer.startup.record("libraries")
log.info('Loaded librareis')
log.setLevel(logging.DEBUG if cmd_opts.debug else logging.INFO)
logging.disable(logging.NOTSET if cmd_opts.debug else logging.DEBUG)
if cmd_opts.server_name:
server_name = cmd_opts.server_name
else:
@@ -92,7 +61,7 @@ fastapi_args = {
"deepLinking": False,
}
}
modules.loader.initialized = True
def check_rollback_vae():
if shared.cmd_opts.rollback_vae:
@@ -113,37 +82,38 @@ def initialize():
check_rollback_vae()
modules.sd_samplers.list_samplers()
startup_timer.record("samplers")
timer.startup.record("samplers")
modules.sd_vae.refresh_vae_list()
startup_timer.record("vae")
timer.startup.record("vae")
extensions.list_extensions()
startup_timer.record("extensions")
timer.startup.record("extensions")
modelloader.cleanup_models()
modules.sd_models.setup_model()
startup_timer.record("models")
timer.startup.record("models")
codeformer.setup_model(opts.codeformer_models_path)
startup_timer.record("codeformer")
timer.startup.record("codeformer")
gfpgan.setup_model(opts.gfpgan_models_path)
startup_timer.record("gfpgan")
timer.startup.record("gfpgan")
log.debug('Loading scripts')
modules.scripts.load_scripts()
startup_timer.record("scripts")
log.debug('Loading extensions')
t_timer, t_total = modules.scripts.load_scripts()
timer.startup.record("extensions")
timer.startup.records["extensions"] = t_total # scripts can reset the time
setup_logging() # reset since scripts can hijaack logging
log.info(f'Extensions time: {t_timer.summary()}')
modelloader.load_upscalers()
startup_timer.record("upscalers")
setup_logging() # needs a reset since scripts can hijaack logging
timer.startup.record("upscalers")
shared.opts.onchange("sd_vae", wrap_queued_call(lambda: modules.sd_vae.reload_vae_weights()), call=False)
shared.opts.onchange("temp_dir", ui_tempdir.on_tmpdir_changed)
shared.opts.onchange("gradio_theme", shared.reload_gradio_theme)
startup_timer.record("onchange")
timer.startup.record("onchange")
modules.textual_inversion.textual_inversion.list_textual_inversion_templates()
shared.reload_hypernetworks()
@@ -152,7 +122,7 @@ def initialize():
ui_extra_networks.register_default_pages()
extra_networks.initialize()
extra_networks.register_default_extra_networks()
startup_timer.record("extra-networks")
timer.startup.record("extra-networks")
if cmd_opts.tls_keyfile is not None and cmd_opts.tls_certfile is not None:
try:
@@ -165,7 +135,7 @@ def initialize():
log.error("TLS setup invalid, running webui without TLS")
else:
log.info("Running with TLS")
startup_timer.record("tls")
timer.startup.record("tls")
# make the program just exit at ctrl+c without waiting for anything
def sigint_handler(_sig, _frame):
@@ -198,7 +168,7 @@ def load_model():
shared.opts.onchange("sd_model_dict", wrap_queued_call(lambda: modules.sd_models.reload_model_weights(op='dict')), call=False)
shared.opts.onchange("sd_vae", wrap_queued_call(lambda: modules.sd_vae.reload_vae_weights()), call=False)
shared.opts.onchange("sd_backend", wrap_queued_call(lambda: modules.sd_models.change_backend()), call=False)
startup_timer.record("checkpoint")
timer.startup.record("checkpoint")
def create_api(app):
@@ -247,15 +217,15 @@ def start_common():
initialize()
if shared.opts.clean_temp_dir_at_start:
ui_tempdir.cleanup_tmpdr()
startup_timer.record("cleanup")
timer.startup.record("cleanup")
def start_ui():
log.debug('Creating UI')
modules.script_callbacks.before_ui_callback()
startup_timer.record("before-ui")
shared.demo = modules.ui.create_ui(startup_timer)
startup_timer.record("ui")
timer.startup.record("before-ui")
shared.demo = modules.ui.create_ui(timer.startup)
timer.startup.record("ui")
if cmd_opts.disable_queue:
log.info('Server queues disabled')
shared.demo.progress_tracking = False
@@ -303,19 +273,20 @@ def start_ui():
setup_middleware(app, cmd_opts)
if cmd_opts.subpath:
import gradio
gradio.mount_gradio_app(app, shared.demo, path=f"/{cmd_opts.subpath}")
shared.log.info(f'Redirector mounted: /{cmd_opts.subpath}')
startup_timer.record("launch")
timer.startup.record("launch")
modules.progress.setup_progress_api(app)
create_api(app)
startup_timer.record("api")
timer.startup.record("api")
ui_extra_networks.add_pages_to_demo(app)
modules.script_callbacks.app_started_callback(shared.demo, app)
startup_timer.record("app-started")
timer.startup.record("app-started")
time_setup = [f'{k}:{round(v,3)}s' for (k,v) in modules.scripts.time_setup.items() if v > 0.005]
shared.log.debug(f'Scripts setup: {time_setup}')
@@ -333,7 +304,7 @@ def webui(restart=False):
modules.sd_models.write_metadata()
load_model()
shared.opts.save(shared.config_filename)
log.info(f"Startup time: {startup_timer.summary()}")
log.info(f"Startup time: {timer.startup.summary()}")
if not restart:
# override all loggers to use the same handlers as the main logger
@@ -356,13 +327,14 @@ def webui(restart=False):
def api_only():
start_common()
from fastapi import FastAPI
app = FastAPI(**fastapi_args)
setup_middleware(app, cmd_opts)
api = create_api(app)
api.wants_restart = False
modules.script_callbacks.app_started_callback(None, app)
modules.sd_models.write_metadata()
log.info(f"Startup time: {startup_timer.summary()}")
log.info(f"Startup time: {timer.startup.summary()}")
server = api.launch()
return server