diff --git a/launch.py b/launch.py
index 6afbd7458..ab1530fac 100644
--- a/launch.py
+++ b/launch.py
@@ -150,12 +150,12 @@ def start_server(immediate=True, server=None):
server.wants_restart = False
else:
if args.api_only:
- server = server.api_only()
+ uvicorn = server.api_only()
else:
- server = server.webui(restart=not immediate)
+ uvicorn = server.webui(restart=not immediate)
if args.profile:
installer.print_profile(pr, 'WebUI')
- return server
+ return uvicorn, server
if __name__ == "__main__":
@@ -207,20 +207,21 @@ if __name__ == "__main__":
# installer.log.debug(f"Args: {vars(args)}")
logging.disable(logging.NOTSET if args.debug else logging.DEBUG)
- instance = start_server(immediate=True, server=None)
+ uv, instance = start_server(immediate=True, server=None)
while True:
try:
- alive = instance.thread.is_alive()
- requests = instance.server_state.total_requests if hasattr(instance, 'server_state') else 0
+ alive = uv.thread.is_alive()
+ requests = uv.server_state.total_requests if hasattr(uv, 'server_state') else 0
except Exception:
alive = False
requests = 0
if round(time.time()) % 120 == 0:
- installer.log.debug(f'Server alive={alive} requests={requests} memory {get_memory_stats()} ')
+ state = f'job="{instance.state.job}" {instance.state.job_no}/{instance.state.job_count}'
+ installer.log.debug(f'Server alive={alive} requests={requests} memory {get_memory_stats()} {state}')
if not alive:
if instance.wants_restart:
installer.log.info('Server restarting...')
- instance = start_server(immediate=False, server=instance)
+ uv, instance = start_server(immediate=False, server=instance)
else:
installer.log.info('Exiting...')
break
diff --git a/modules/api/api.py b/modules/api/api.py
index ce5bda675..39436d14a 100644
--- a/modules/api/api.py
+++ b/modules/api/api.py
@@ -263,7 +263,7 @@ class Api:
p.scripts = script_runner
p.outpath_grids = shared.opts.outdir_grids or shared.opts.outdir_txt2img_grids
p.outpath_samples = shared.opts.outdir_samples or shared.opts.outdir_txt2img_samples
- shared.state.begin()
+ shared.state.begin('api-txt2img')
script_args = self.init_script_args(p, txt2imgreq, self.default_script_arg_txt2img, selectable_scripts, selectable_script_idx, script_runner)
if selectable_scripts is not None:
processed = scripts.scripts_txt2img.run(p, *script_args) # Need to pass args as list here
@@ -311,7 +311,7 @@ class Api:
p.scripts = script_runner
p.outpath_grids = shared.opts.outdir_img2img_grids
p.outpath_samples = shared.opts.outdir_img2img_samples
- shared.state.begin()
+ shared.state.begin('api-img2img')
script_args = self.init_script_args(p, img2imgreq, self.default_script_arg_img2img, selectable_scripts, selectable_script_idx, script_runner)
if selectable_scripts is not None:
processed = scripts.scripts_img2img.run(p, *script_args) # Need to pass args as list here
@@ -513,7 +513,7 @@ class Api:
def create_embedding(self, args: dict):
try:
- shared.state.begin()
+ shared.state.begin('api-create-embedding')
filename = create_embedding(**args) # create empty embedding
sd_hijack.model_hijack.embedding_db.load_textual_inversion_embeddings() # reload embeddings so new one can be immediately used
shared.state.end()
@@ -524,7 +524,7 @@ class Api:
def create_hypernetwork(self, args: dict):
try:
- shared.state.begin()
+ shared.state.begin('api-create-hypernetwork')
filename = create_hypernetwork(**args) # create empty embedding # pylint: disable=E1111
shared.state.end()
return models.CreateResponse(info = f"create hypernetwork filename: {filename}")
@@ -534,7 +534,7 @@ class Api:
def preprocess(self, args: dict):
try:
- shared.state.begin()
+ shared.state.begin('api-preprocess')
preprocess(**args) # quick operation unless blip/booru interrogation is enabled
shared.state.end()
return models.PreprocessResponse(info = 'preprocess complete')
@@ -550,7 +550,7 @@ class Api:
def train_embedding(self, args: dict):
try:
- shared.state.begin()
+ shared.state.begin('api-train-embedding')
apply_optimizations = False
error = None
filename = ''
@@ -571,7 +571,7 @@ class Api:
def train_hypernetwork(self, args: dict):
try:
- shared.state.begin()
+ shared.state.begin('api-train-hypernetwork')
shared.loaded_hypernetworks = []
apply_optimizations = False
error = None
diff --git a/modules/call_queue.py b/modules/call_queue.py
index 568d79344..d75ae55cd 100644
--- a/modules/call_queue.py
+++ b/modules/call_queue.py
@@ -19,6 +19,7 @@ def wrap_queued_call(func):
def wrap_gradio_gpu_call(func, extra_outputs=None):
+ name = func.__name__
def f(*args, **kwargs):
# if the first argument is a string that says "task(...)", it is treated as a job id
if len(args) > 0 and type(args[0]) == str and args[0][0:5] == "task(" and args[0][-1] == ")":
@@ -27,7 +28,6 @@ def wrap_gradio_gpu_call(func, extra_outputs=None):
else:
id_task = None
with queue_lock:
- shared.state.begin()
progress.start_task(id_task)
res = [None, '', '', '']
try:
@@ -42,13 +42,15 @@ def wrap_gradio_gpu_call(func, extra_outputs=None):
progress.finish_task(id_task)
shared.state.end()
return res
- return wrap_gradio_call(f, extra_outputs=extra_outputs, add_stats=True)
+ return wrap_gradio_call(f, extra_outputs=extra_outputs, add_stats=True, name=name)
-def wrap_gradio_call(func, extra_outputs=None, add_stats=False):
+def wrap_gradio_call(func, extra_outputs=None, add_stats=False, name=None):
+ job_name = name if name is not None else func.__name__
def f(*args, extra_outputs_array=extra_outputs, **kwargs):
t = time.perf_counter()
shared.mem_mon.reset()
+ shared.state.begin(job_name)
try:
if shared.cmd_opts.profile:
pr = cProfile.Profile()
@@ -67,15 +69,10 @@ def wrap_gradio_call(func, extra_outputs=None, add_stats=False):
print('Profile Exec:', s.getvalue())
except Exception as e:
errors.display(e, 'gradio call')
- shared.state.job = ""
- shared.state.job_count = 0
if extra_outputs_array is None:
extra_outputs_array = [None, '']
res = extra_outputs_array + [f"
{html.escape(type(e).__name__+': '+str(e))}
"]
- shared.state.skipped = False
- shared.state.interrupted = False
- shared.state.paused = False
- shared.state.job_count = 0
+ shared.state.end()
if not add_stats:
return tuple(res)
elapsed = time.perf_counter() - t
diff --git a/modules/extras.py b/modules/extras.py
index f13b61306..6e61b8426 100644
--- a/modules/extras.py
+++ b/modules/extras.py
@@ -54,9 +54,7 @@ def to_half(tensor, enable):
def run_modelmerger(id_task, primary_model_name, secondary_model_name, tertiary_model_name, interp_method, multiplier, save_as_half, custom_name, checkpoint_format, config_source, bake_in_vae, discard_weights, save_metadata): # pylint: disable=unused-argument
- shared.state.begin()
- shared.state.job = 'model-merge'
-
+ shared.state.begin('model-merge')
save_as_half = save_as_half == 0
def fail(message):
@@ -321,9 +319,7 @@ def run_modelconvert(model, checkpoint_formats, precision, conv_type, custom_nam
"vae": vae_conv,
"other": others_conv
}
- shared.state.begin()
- shared.state.job = 'model-convert'
-
+ shared.state.begin('model-convert')
model_info = sd_models.checkpoints_list[model]
shared.state.textinfo = f"Loading {model_info.filename}..."
shared.log.info(f"Model convert loading: {model_info.filename}")
diff --git a/modules/interrogate.py b/modules/interrogate.py
index be465d9b2..61bb14cc9 100644
--- a/modules/interrogate.py
+++ b/modules/interrogate.py
@@ -181,8 +181,7 @@ class InterrogateModels:
def interrogate(self, pil_image):
res = ""
- shared.state.begin()
- shared.state.job = 'interrogate'
+ shared.state.begin('interrogate')
try:
if shared.cmd_opts.lowvram or shared.cmd_opts.medvram:
lowvram.send_everything_to_cpu()
diff --git a/modules/modelloader.py b/modules/modelloader.py
index bb0639389..38b9c8377 100644
--- a/modules/modelloader.py
+++ b/modules/modelloader.py
@@ -65,8 +65,7 @@ def download_civit_preview(model_path: str, preview_url: str):
total_size = int(req.headers.get('content-length', 0))
block_size = 16384 # 16KB blocks
written = 0
- shared.state.begin()
- shared.state.job = 'download preview'
+ shared.state.begin('civitai-download-preview')
try:
with open(preview_file, 'wb') as f:
with p.Progress(p.TextColumn('[cyan]{task.description}'), p.DownloadColumn(), p.BarColumn(), p.TaskProgressColumn(), p.TimeRemainingColumn(), p.TimeElapsedColumn(), p.TransferSpeedColumn()) as progress:
@@ -105,8 +104,7 @@ def download_civit_model(model_url: str, model_name: str, model_path: str, model
total_size = int(req.headers.get('content-length', 0))
block_size = 16384 # 16KB blocks
written = 0
- shared.state.begin()
- shared.state.job = 'download model'
+ shared.state.begin('civitai-download-model')
try:
with open(model_file, 'wb') as f:
with p.Progress(p.TextColumn('[cyan]{task.description}'), p.DownloadColumn(), p.BarColumn(), p.TaskProgressColumn(), p.TimeRemainingColumn(), p.TimeElapsedColumn(), p.TransferSpeedColumn()) as progress:
@@ -136,8 +134,7 @@ def download_civit_model(model_url: str, model_name: str, model_path: str, model
def download_diffusers_model(hub_id: str, cache_dir: str = None, download_config: Dict[str, str] = None, token = None, variant = None, revision = None, mirror = None):
from diffusers import DiffusionPipeline
import huggingface_hub as hf
- shared.state.begin()
- shared.state.job = 'download model'
+ shared.state.begin('huggingface-download-model')
if download_config is None:
download_config = {
"force_download": False,
diff --git a/modules/postprocessing.py b/modules/postprocessing.py
index 4ff648461..c82aac540 100644
--- a/modules/postprocessing.py
+++ b/modules/postprocessing.py
@@ -10,8 +10,7 @@ from modules.shared import opts
def run_postprocessing(extras_mode, image, image_folder: List[tempfile.NamedTemporaryFile], input_dir, output_dir, show_extras_results, *args, save_output: bool = True):
devices.torch_gc()
- shared.state.begin()
- shared.state.job = 'extras'
+ shared.state.begin('extras')
image_data = []
image_names = []
image_ext = []
diff --git a/modules/sd_vae.py b/modules/sd_vae.py
index d632618a1..0360d83b3 100644
--- a/modules/sd_vae.py
+++ b/modules/sd_vae.py
@@ -232,6 +232,8 @@ def reload_vae_weights(sd_model=None, vae_file=unspecified):
from modules import lowvram, sd_hijack
if not sd_model:
sd_model = shared.sd_model
+ if sd_model is None:
+ return
global checkpoint_info # pylint: disable=global-statement
checkpoint_info = sd_model.sd_checkpoint_info
checkpoint_file = checkpoint_info.filename
diff --git a/modules/shared.py b/modules/shared.py
index ebc142a63..fe2ec4e4d 100644
--- a/modules/shared.py
+++ b/modules/shared.py
@@ -137,19 +137,20 @@ class State:
}
return obj
- def begin(self):
- self.sampling_step = 0
- self.job_count = -1
- self.processing_has_refined_job_count = False
- self.job_no = 0
- self.job_timestamp = datetime.datetime.now().strftime("%Y%m%d%H%M%S")
- self.current_latent = None
+ def begin(self, title=""):
self.current_image = None
self.current_image_sampling_step = 0
+ self.current_latent = None
self.id_live_preview = 0
- self.skipped = False
self.interrupted = False
+ self.job = title
+ self.job_count = -1
+ self.job_no = 0
+ self.job_timestamp = datetime.datetime.now().strftime("%Y%m%d%H%M%S")
self.paused = False
+ self.processing_has_refined_job_count = False
+ self.sampling_step = 0
+ self.skipped = False
self.textinfo = None
self.time_start = time.time()
devices.torch_gc()
@@ -157,7 +158,10 @@ class State:
def end(self):
self.job = ""
self.job_count = 0
+ self.job_no = 0
self.paused = False
+ self.interrupted = False
+ self.skipped = False
devices.torch_gc()
def set_current_image(self):
@@ -278,8 +282,9 @@ def temp_disable_extensions():
for ext in ['sd-webui-controlnet', 'multidiffusion-upscaler-for-automatic1111', 'a1111-sd-webui-lycoris']:
if ext not in opts.disabled_extensions:
disabled.append(ext)
- log.warning(f'Diffusers disabling uncompatible extensions: {disabled}')
+ log.info(f'Diffusers disabling uncompatible extensions: {disabled}')
if opts.lyco_patch_lora and backend != Backend.DIFFUSERS:
+ cmd_opts.lyco_dir = opts.lora_dir
if 'Lora' not in opts.disabled_extensions:
disabled.append('Lora')
return disabled
@@ -428,7 +433,7 @@ options_templates.update(options_section(('system-paths', "System Paths"), {
"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"),
- "sd_lora": OptionInfo("", "Add LoRA to prompt", gr.CheckboxGroup, {"choices": [], "visible": False}),
+ "sd_lora": OptionInfo("", "Add LoRA to prompt", gr.Textbox, {"choices": [], "visible": False}),
"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"),
diff --git a/modules/ui_extra_networks.py b/modules/ui_extra_networks.py
index 17cf429b9..1f5274e1f 100644
--- a/modules/ui_extra_networks.py
+++ b/modules/ui_extra_networks.py
@@ -219,7 +219,7 @@ class ExtraNetworksPage:
else:
return ''
t1 = time.time()
- shared.log.debug(f'Extra networks: {self.name} items={len(self.items)} subdirs={len(subdirs)} tab={tabname} time={round(t1-t0, 2)}')
+ shared.log.debug(f'Extra networks: page={self.name} items={len(self.items)} subdirs={len(subdirs)} tab={tabname} dirs={self.allowed_directories_for_previews()} time={round(t1-t0, 2)}')
threading.Thread(target=self.create_thumb).start()
def list_items(self):
diff --git a/webui.py b/webui.py
index 6624934cd..fb32f809f 100644
--- a/webui.py
+++ b/webui.py
@@ -39,6 +39,7 @@ from modules.shared import cmd_opts, opts
import modules.hypernetworks.hypernetwork
from modules.middleware import setup_middleware
+state = shared.state
if not modules.loader.initialized:
timer.startup.record("libraries")
log.info('Loaded librareis')
@@ -152,8 +153,7 @@ def initialize():
def load_model():
if opts.sd_checkpoint_autoload:
- shared.state.begin()
- shared.state.job = 'load model'
+ shared.state.begin('load model')
thread_model = Thread(target=lambda: shared.sd_model)
thread_model.start()
thread_refiner = Thread(target=lambda: shared.sd_refiner)