From 5b9187d38bb70a09c36ef85558394a3b7b5842c1 Mon Sep 17 00:00:00 2001 From: Vladimir Mandic Date: Mon, 24 Apr 2023 10:30:23 -0400 Subject: [PATCH] combo patch --- TODO.md | 15 +++------ .../SwinIR/scripts/swinir_model.py | 2 +- extensions-builtin/sd-webui-controlnet | 2 +- .../stable-diffusion-webui-images-browser | 2 +- modules/lora | 2 +- modules/processing.py | 3 +- modules/progress.py | 29 ++++------------- modules/sd_samplers_common.py | 2 -- modules/shared.py | 8 ++--- modules/styles.py | 9 ++---- requirements.txt | 1 - setup.py | 32 ++++++++++++------- 12 files changed, 43 insertions(+), 64 deletions(-) diff --git a/TODO.md b/TODO.md index 6c58525e1..92cb7d247 100644 --- a/TODO.md +++ b/TODO.md @@ -7,8 +7,7 @@ Stuff to be fixed... - ClipSkip not updated on read gen info - Usage of `sd_vae` in quick settings - Run VAE with hires at 1280 -- Make TensorFlow optional - +- Transformers version ## Features @@ -58,11 +57,7 @@ Tech that can be integrated as part of the core workflow... ### Pending Code Updates -- fix VAE dtype - should fix most issues with NaN or black images -- add built-in Gradio themes -- fix setup race conditions -- reduce requirements -- more AMD specific work -- initial work on Apple platform support -- additional PR merges +- Use samples format for live preview +- Identify race condition where generate locks up while fetching preview +- Use **Approx NN** for live preview +- Create default `styles.csv` diff --git a/extensions-builtin/SwinIR/scripts/swinir_model.py b/extensions-builtin/SwinIR/scripts/swinir_model.py index 6e8cb864a..86672cd9a 100644 --- a/extensions-builtin/SwinIR/scripts/swinir_model.py +++ b/extensions-builtin/SwinIR/scripts/swinir_model.py @@ -89,7 +89,7 @@ class UpscalerSwinIR(Upscaler): with progress.open(filename, 'rb', description=f'Loading weights: [cyan]{filename}', auto_refresh=True) as f: pretrained_model = torch.load(filename) - if params is not None: + if params is not None and params in pretrained_model: model.load_state_dict(pretrained_model[params], strict=True) else: model.load_state_dict(pretrained_model, strict=True) diff --git a/extensions-builtin/sd-webui-controlnet b/extensions-builtin/sd-webui-controlnet index 1ce36722a..c5984671c 160000 --- a/extensions-builtin/sd-webui-controlnet +++ b/extensions-builtin/sd-webui-controlnet @@ -1 +1 @@ -Subproject commit 1ce36722acb09cf546979de3e92c53577761ef4b +Subproject commit c5984671ccd7da7d554f239143648b8157ae1c39 diff --git a/extensions-builtin/stable-diffusion-webui-images-browser b/extensions-builtin/stable-diffusion-webui-images-browser index 0029d95a5..704e42c10 160000 --- a/extensions-builtin/stable-diffusion-webui-images-browser +++ b/extensions-builtin/stable-diffusion-webui-images-browser @@ -1 +1 @@ -Subproject commit 0029d95a5f720b387c530e916a9e166277aa66e2 +Subproject commit 704e42c10d01e6c6965493ec956a82bb8fc2da51 diff --git a/modules/lora b/modules/lora index 25c8279f2..852481e14 160000 --- a/modules/lora +++ b/modules/lora @@ -1 +1 @@ -Subproject commit 25c8279f2692983f262f7e024b52defff852ae46 +Subproject commit 852481e14d08d510377813790ade557b4e2313f5 diff --git a/modules/processing.py b/modules/processing.py index 12251870d..1bed52ac8 100644 --- a/modules/processing.py +++ b/modules/processing.py @@ -442,9 +442,8 @@ def create_random_tensors(shape, seeds, subseeds=None, subseed_strength=0.0, see def decode_first_stage(model, x): - with devices.autocast(disable=x.dtype == devices.dtype_vae): + with devices.autocast(disable = x.dtype==devices.dtype_vae): x = model.decode_first_stage(x) - return x diff --git a/modules/progress.py b/modules/progress.py index 07a5eba1d..93246eb08 100644 --- a/modules/progress.py +++ b/modules/progress.py @@ -1,11 +1,7 @@ import base64 import io import time - -from pydantic import BaseModel, Field - -from modules.shared import opts - +from pydantic import BaseModel, Field # pylint: disable=no-name-in-module import modules.shared as shared @@ -15,18 +11,15 @@ finished_tasks = [] def start_task(id_task): - global current_task - + global current_task # pylint: disable=global-statement current_task = id_task pending_tasks.pop(id_task, None) def finish_task(id_task): - global current_task - + global current_task # pylint: disable=global-statement if current_task == id_task: current_task = None - finished_tasks.append(id_task) if len(finished_tasks) > 16: finished_tasks.pop(0) @@ -60,39 +53,31 @@ def progressapi(req: ProgressRequest): active = req.id_task == current_task queued = req.id_task in pending_tasks completed = req.id_task in finished_tasks - if not active: return ProgressResponse(active=active, queued=queued, completed=completed, id_live_preview=-1, textinfo="In queue..." if queued else "Waiting...") - progress = 0 - job_count, job_no = shared.state.job_count, shared.state.job_no sampling_steps, sampling_step = shared.state.sampling_steps, shared.state.sampling_step - if job_count > 0: progress += job_no / job_count if sampling_steps > 0 and job_count > 0: progress += 1 / job_count * sampling_step / sampling_steps - progress = min(progress, 1) - elapsed_since_start = time.time() - shared.state.time_start predicted_duration = elapsed_since_start / progress if progress > 0 else None eta = predicted_duration - elapsed_since_start if predicted_duration is not None else None - id_live_preview = req.id_live_preview shared.state.set_current_image() - if opts.live_previews_enable and shared.state.id_live_preview != req.id_live_preview: + if shared.opts.live_previews_enable and shared.state.id_live_preview != req.id_live_preview: image = shared.state.current_image if image is not None: buffered = io.BytesIO() - image.save(buffered, format="png") - live_preview = 'data:image/png;base64,' + base64.b64encode(buffered.getvalue()).decode("ascii") + fmt = 'jpeg' if shared.opts.samples_format == 'jpg' else shared.opts.samples_format + image.save(buffered, format=fmt) + live_preview = f'data:image/{fmt};base64,{base64.b64encode(buffered.getvalue()).decode("ascii")}' id_live_preview = shared.state.id_live_preview else: live_preview = None else: live_preview = None - return ProgressResponse(active=active, queued=queued, completed=completed, progress=progress, eta=eta, live_preview=live_preview, id_live_preview=id_live_preview, textinfo=shared.state.textinfo) - diff --git a/modules/sd_samplers_common.py b/modules/sd_samplers_common.py index a1aac7cf0..888f9a30e 100644 --- a/modules/sd_samplers_common.py +++ b/modules/sd_samplers_common.py @@ -28,14 +28,12 @@ approximation_indexes = {"Full": 0, "Approx NN": 1, "Approx cheap": 2} def single_sample_to_image(sample, approximation=None): if approximation is None: approximation = approximation_indexes.get(opts.show_progress_type, 0) - if approximation == 2: x_sample = sd_vae_approx.cheap_approximation(sample) elif approximation == 1: x_sample = sd_vae_approx.model()(sample.to(devices.device, devices.dtype).unsqueeze(0))[0].detach() else: x_sample = processing.decode_first_stage(shared.sd_model, sample.unsqueeze(0))[0] - x_sample = torch.clamp((x_sample + 1.0) / 2.0, min=0.0, max=1.0) x_sample = 255. * np.moveaxis(x_sample.cpu().numpy(), 0, 2) x_sample = x_sample.astype(np.uint8) diff --git a/modules/shared.py b/modules/shared.py index 664620561..a2e202735 100644 --- a/modules/shared.py +++ b/modules/shared.py @@ -112,7 +112,6 @@ class State: "sampling_step": self.sampling_step, "sampling_steps": self.sampling_steps, } - return obj def begin(self): @@ -142,20 +141,17 @@ class State: """sets self.current_image from self.current_latent if enough sampling steps have been made after the last call to this""" if not parallel_processing_allowed: return - if self.sampling_step - self.current_image_sampling_step >= opts.show_progress_every_n_steps and opts.live_previews_enable and opts.show_progress_every_n_steps != -1: self.do_set_current_image() def do_set_current_image(self): if self.current_latent is None: return - import modules.sd_samplers # pylint: disable=W0621 if opts.show_progress_grid: self.assign_current_image(modules.sd_samplers.samples_to_image_grid(self.current_latent)) else: self.assign_current_image(modules.sd_samplers.sample_to_image(self.current_latent)) - self.current_image_sampling_step = self.sampling_step def assign_current_image(self, image): @@ -425,8 +421,8 @@ options_templates.update(options_section(('ui', "Live previews"), { "show_progressbar": OptionInfo(True, "Show progressbar"), "live_previews_enable": OptionInfo(True, "Show live previews of the created image"), "show_progress_grid": OptionInfo(True, "Show previews of all images generated in a batch as a grid"), - "show_progress_every_n_steps": OptionInfo(-1, "Show new live preview image every N sampling steps. Set to -1 to show after completion of batch.", gr.Slider, {"minimum": -1, "maximum": 32, "step": 1}), - "show_progress_type": OptionInfo("Full", "Image creation progress preview mode", gr.Radio, {"choices": ["Full", "Approx NN", "Approx cheap"]}), + "show_progress_every_n_steps": OptionInfo(1, "Show new live preview image every N sampling steps. Set to -1 to show after completion of batch.", gr.Slider, {"minimum": -1, "maximum": 32, "step": 1}), + "show_progress_type": OptionInfo("Approx NN", "Image creation progress preview mode", gr.Radio, {"choices": ["Full", "Approx NN", "Approx cheap"]}), "live_preview_content": OptionInfo("Combined", "Live preview subject", gr.Radio, {"choices": ["Combined", "Prompt", "Negative prompt"]}), "live_preview_refresh_period": OptionInfo(250, "Progressbar/preview update period, in milliseconds") })) diff --git a/modules/styles.py b/modules/styles.py index 990d56236..e7c33025d 100644 --- a/modules/styles.py +++ b/modules/styles.py @@ -49,7 +49,8 @@ class StyleDatabase: self.styles.clear() if not os.path.exists(self.path): - return + print(f'Creating styles database: {self.path}') + self.save_styles(self.path) with open(self.path, "r", encoding="utf-8-sig", newline='') as file: reader = csv.DictReader(file) @@ -79,9 +80,5 @@ class StyleDatabase: # and collections.NamedTuple has explicit documentation for accessing _fields. Same goes for _asdict() writer = csv.DictWriter(file, fieldnames=PromptStyle._fields) writer.writeheader() - writer.writerows(style._asdict() for k, style in self.styles.items()) - - # Always keep a backup file around - if os.path.exists(path): - shutil.move(path, path + ".bak") + writer.writerows(style._asdict() for k, style in self.styles.items()) shutil.move(temp_path, path) diff --git a/requirements.txt b/requirements.txt index 4519a69c8..3f7db3419 100644 --- a/requirements.txt +++ b/requirements.txt @@ -49,7 +49,6 @@ tqdm voluptuous yapf scikit-image - accelerate==0.18.0 opencv-python==4.7.0.72 diffusers==0.15.0 diff --git a/setup.py b/setup.py index b2e5f7441..dc2792e66 100644 --- a/setup.py +++ b/setup.py @@ -217,7 +217,7 @@ def check_torch(): log.debug(f'Cannot install xformers package: {e}') try: tensorflow_package = os.environ.get('TENSORFLOW_PACKAGE', 'tensorflow==2.12.0') - install(f'--no-deps {tensorflow_package}', ignore=True) + install(tensorflow_package, ignore=True) except Exception as e: log.debug(f'Cannot install tensorflow package: {e}') @@ -237,7 +237,6 @@ def install_packages(): def install_repositories(): def d(name): return os.path.join(os.path.dirname(__file__), 'repositories', name) - log.info('Installing repositories') os.makedirs(os.path.join(os.path.dirname(__file__), 'repositories'), exist_ok=True) stable_diffusion_repo = os.environ.get('STABLE_DIFFUSION_REPO', "https://github.com/Stability-AI/stablediffusion.git") @@ -263,7 +262,7 @@ def run_extension_installer(folder): if not os.path.isfile(path_installer): return try: - log.debug(f"Running extension installer: {path_installer}") + log.debug(f"Running extension installer: {folder} / {path_installer}") env = os.environ.copy() env['PYTHONPATH'] = os.path.abspath(".") result = subprocess.run(f'"{sys.executable}" "{path_installer}"', shell=True, env=env, check=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=folder) @@ -334,7 +333,7 @@ def install_submodules(): def ensure_package(pkg): try: - import pkg + import pkg # type: ignore except ImportError: install(pkg) @@ -394,6 +393,13 @@ def check_extensions(): # check version of the main repo and optionally upgrade it def check_version(): + if not os.path.exists('.git'): + log.error('Not a git repository') + exit(1) + status = git('status') + if 'branch' not in status: + log.error('Cannot get git repository status') + exit(1) ver = git('log -1 --pretty=format:"%h %ad"') log.info(f'Version: {ver}') commit = git('rev-parse HEAD') @@ -420,17 +426,20 @@ def check_version(): log.error('Error upgrading repository') else: log.info(f'Latest published version: {commits["commit"]["sha"]} {commits["commit"]["commit"]["author"]["date"]}') - if not args.noupdate: - log.info('Updating Wiki') - try: - update(os.path.join(os.path.dirname(__file__), "wiki")) - update(os.path.join(os.path.dirname(__file__), "wiki", "origin-wiki")) - except: - log.error('Error updating wiki') except Exception as e: log.error(f'Failed to check version: {e} {commits}') +def update_wiki(): + if not args.noupdate: + log.info('Updating Wiki') + try: + update(os.path.join(os.path.dirname(__file__), "wiki")) + update(os.path.join(os.path.dirname(__file__), "wiki", "origin-wiki")) + except: + log.error('Error updating wiki') + + # check if we can run setup in quick mode def check_timestamp(): if not quick_allowed or not os.path.isfile('setup.log'): @@ -535,6 +544,7 @@ def run_setup(): install_repositories() install_submodules() install_extensions() + update_wiki() if errors == 0: log.debug(f'Setup complete without errors: {round(time.time())}') else: