diff --git a/CHANGELOG.md b/CHANGELOG.md index a9a50f095..c6f0223b4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,7 +21,7 @@ OPTIONAL: - masking api - preprocess api -## Update for 2023-01-23 +## Update for 2023-01-24 Another big release, highlights being: - A lot more functionality in the **Control** module: diff --git a/cli/install-sf.py b/cli/install-sf.py index 5a86856c5..7301b280e 100755 --- a/cli/install-sf.py +++ b/cli/install-sf.py @@ -1,12 +1,13 @@ #!/usr/bin/env python import os +import re import sys -ver = '1.0.1.dev20240109' torch_supported = ['211', '212'] cuda_supported = ['cu118', 'cu121'] python_supported = ['39', '310', '311'] repo_url = 'https://github.com/chengzeyi/stable-fast' +api_url = 'https://api.github.com/repos/chengzeyi/stable-fast/releases/tags/nightly' path_url = '/releases/download/nightly' @@ -18,6 +19,29 @@ def install_pip(arg: str): return result.returncode == 0 +def get_nightly(): + import requests + r = requests.get(api_url, timeout=10) + if r.status_code != 200: + print('Failed to get nightly version') + return None + json = r.json() + assets = json.get('assets', []) + if len(assets) == 0: + print('Failed to get nightly version') + return None + asset = assets[0].get('name', '') + pattern = r"-(.+?)\+" + match = re.search(pattern, asset) + if match: + ver = match.group(1) + print(f'Nightly version: {ver}') + return ver + else: + print('Failed to get nightly version') + return None + + def install_stable_fast(): import torch @@ -33,6 +57,7 @@ def install_stable_fast(): torch_ver, cuda_ver = torch.__version__.split('+') torch_ver = torch_ver.replace('.', '') + sf_ver = get_nightly() if torch_ver not in torch_supported: print(f'StableFast unsupported torch: {torch_ver} required {torch_supported}') @@ -42,9 +67,13 @@ def install_stable_fast(): print(f'StableFast unsupported CUDA: {cuda_ver} required {cuda_supported}') print('Installing from source...') url = 'git+https://github.com/chengzeyi/stable-fast.git@main#egg=stable-fast' + elif sf_ver is not None: + print('StableFast cannot determine version') + print('Installing from source...') + url = 'git+https://github.com/chengzeyi/stable-fast.git@main#egg=stable-fast' else: print('Installing wheel...') - file_url = f'stable_fast-{ver}+torch{torch_ver}{cuda_ver}-cp{python_ver}-cp{python_ver}-{bin_url}' + file_url = f'stable_fast-{sf_ver}+torch{torch_ver}{cuda_ver}-cp{python_ver}-cp{python_ver}-{bin_url}' url = f'{repo_url}/{path_url}/{file_url}' ok = install_pip(url) diff --git a/modules/control/run.py b/modules/control/run.py index 49dda469b..ac4181989 100644 --- a/modules/control/run.py +++ b/modules/control/run.py @@ -458,11 +458,11 @@ def control_run(units: List[unit.Unit], inputs, inits, mask, unit_type: str, is_ shared.sd_model = sd_models.set_diffuser_pipe(shared.sd_model, sd_models.DiffusersTaskType.IMAGE_2_IMAGE) # only controlnet supports img2img else: shared.sd_model = sd_models.set_diffuser_pipe(shared.sd_model, sd_models.DiffusersTaskType.TEXT_2_IMAGE) - if p.init_images is not None: + if hasattr(p, 'init_images') and p.init_images is not None: p.task_args['image'] = p.init_images # need to set explicitly for txt2img if unit_type == 'lite': instance.apply(selected_models, p.image, use_conditioning) - if p.init_images is None: + if hasattr(p, 'init_images') and p.init_images is None: del p.init_images # ip adapter diff --git a/modules/shared.py b/modules/shared.py index d3ee4ffe9..88b17d1e1 100644 --- a/modules/shared.py +++ b/modules/shared.py @@ -93,7 +93,8 @@ def readfile(filename, silent=False, lock=False): locked = False if lock and locking_available: try: - lock_file = fasteners.InterProcessReaderWriterLock(f"{filename}.lock", logger=log) + lock_file = fasteners.InterProcessReaderWriterLock(f"{filename}.lock") + lock_file.logger.disabled = True locked = lock_file.acquire_read_lock(blocking=True, timeout=3) except Exception as e: lock_file = None @@ -115,25 +116,24 @@ def readfile(filename, silent=False, lock=False): except Exception as e: if not silent: log.error(f'Reading failed: {filename} {e}') - finally: - try: - if lock_file is not None: - lock_file.release_read_lock() - if locked and os.path.exists(f"{filename}.lock"): - os.remove(f"{filename}.lock") - except Exception: - pass + try: + if locking_available and lock_file is not None: + lock_file.release_read_lock() + if locked and os.path.exists(f"{filename}.lock"): + os.remove(f"{filename}.lock") + except Exception: + locking_available = False return data def writefile(data, filename, mode='w', silent=False, atomic=False): - lock_file = None - locked = False import tempfile global locking_available # pylint: disable=global-statement + lock_file = None + locked = False def default(obj): - log.error(f"Saving: {filename} not a valid object: {obj}") + log.error(f'Saving: file="{filename}" not a valid object: {obj}') return str(obj) try: @@ -155,10 +155,13 @@ def writefile(data, filename, mode='w', silent=False, atomic=False): log.error(f'Saving failed: file="{filename}" {e}') return try: - lock_file = fasteners.InterProcessReaderWriterLock(f"{filename}.lock", logger=log) if locking_available else None - locked = lock_file.acquire_write_lock(blocking=True, timeout=3) if lock_file is not None else False + if locking_available: + lock_file = fasteners.InterProcessReaderWriterLock(f"{filename}.lock") if locking_available else None + lock_file.logger.disabled = True + locked = lock_file.acquire_write_lock(blocking=True, timeout=3) if lock_file is not None else False except Exception as e: locking_available = False + lock_file = None log.error(f'File write lock: file="{filename}" {e}') locked = False try: @@ -176,14 +179,14 @@ def writefile(data, filename, mode='w', silent=False, atomic=False): log.debug(f'Save: file="{filename}" json={len(data)} bytes={len(output)} time={t1-t0:.3f}') except Exception as e: log.error(f'Saving failed: file="{filename}" {e}') - finally: - try: - if lock_file is not None: - lock_file.release_read_lock() - if locked and os.path.exists(f"{filename}.lock"): - os.remove(f"{filename}.lock") - except Exception: - pass + try: + if locking_available and lock_file is not None: + lock_file.release_write_lock() + if locked and os.path.exists(f"{filename}.lock"): + os.remove(f"{filename}.lock") + except Exception: + print('HERE4') + locking_available = False # early select backend diff --git a/modules/styles.py b/modules/styles.py index dc6eac4c3..90c7e339a 100644 --- a/modules/styles.py +++ b/modules/styles.py @@ -62,7 +62,7 @@ def apply_styles_to_extra(p, style: Style): v = type(orig)(v) setattr(p, k, v) fields.append(f'{k}={v}') - log.info(f'Applying style: name="{style.name}" extra={fields}') + log.debug(f'Applying style: name="{style.name}" extra={fields}') class StyleDatabase: diff --git a/modules/ui_control.py b/modules/ui_control.py index ca55a266e..4d2fef1d2 100644 --- a/modules/ui_control.py +++ b/modules/ui_control.py @@ -386,7 +386,7 @@ def create_ui(_blocks: gr.Blocks=None): process_id = gr.Dropdown(label="Processor", choices=processors.list_models(), value='None') model_id = gr.Dropdown(label="ControlNet", choices=controlnet.list_models(), value='None') ui_common.create_refresh_button(model_id, controlnet.list_models, lambda: {"choices": controlnet.list_models(refresh=True)}, 'refresh_controlnet_models') - model_strength = gr.Slider(label="Strength", minimum=0.01, maximum=1.0, step=0.01, value=1.0-i/10) + model_strength = gr.Slider(label="Strength", minimum=0.01, maximum=2.0, step=0.01, value=1.0-i/10) control_start = gr.Slider(label="Start", minimum=0.0, maximum=1.0, step=0.05, value=0) control_end = gr.Slider(label="End", minimum=0.0, maximum=1.0, step=0.05, value=1.0) reset_btn = ui_components.ToolButton(value=ui_symbols.reset) diff --git a/scripts/ipadapter.py b/scripts/ipadapter.py index fe40ca87e..61bd312ae 100644 --- a/scripts/ipadapter.py +++ b/scripts/ipadapter.py @@ -87,8 +87,8 @@ def apply(pipe, p: processing.StableDiffusionProcessing, adapter_name, scale, im return False # load image encoder used by ip adapter - if getattr(pipe, 'image_encoder', None) is None or image_encoder_name != clip_repo + '/' + subfolder: - if image_encoder is None or image_encoder_type != shared.sd_model_type or checkpoint != shared.opts.sd_model_checkpoint or image_encoder_name != clip_repo + '/' + subfolder: + if getattr(pipe, 'image_encoder', None) is None or image_encoder_name != clip_repo + '/' + subfolder or image_encoder is None: + if image_encoder_type != shared.sd_model_type or checkpoint != shared.opts.sd_model_checkpoint or image_encoder_name != clip_repo + '/' + subfolder: if shared.sd_model_type != 'sd' and shared.sd_model_type != 'sdxl': shared.log.error(f'IP adapter: unsupported model type: {shared.sd_model_type}') return False @@ -108,7 +108,7 @@ def apply(pipe, p: processing.StableDiffusionProcessing, adapter_name, scale, im # main code # subfolder = 'models' if 'sd15' in adapter else 'sdxl_models' - if adapter != loaded or getattr(pipe.unet.config, 'encoder_hid_dim_type', None) is None or checkpoint != shared.opts.sd_model_checkpoint: + if adapter != loaded or getattr(pipe.unet.config, 'encoder_hid_dim_type', None) is None or checkpoint != shared.opts.sd_model_checkpoint or pipe.image_encoder is None: t0 = time.time() if loaded is not None: shared.log.debug('IP adapter: reset attention processor')