From 26a11776e4070af30b864ab0ddf25dcda21631a7 Mon Sep 17 00:00:00 2001 From: dvsilch <743422767@qq.com> Date: Mon, 17 Oct 2022 00:51:10 +0800 Subject: [PATCH 01/11] fix: add null check when start running project the currentButton is null --- javascript/imageviewer.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/javascript/imageviewer.js b/javascript/imageviewer.js index 65a33dd7..d4ab6984 100644 --- a/javascript/imageviewer.js +++ b/javascript/imageviewer.js @@ -31,7 +31,7 @@ function updateOnBackgroundChange() { } }) - if (modalImage.src != currentButton.children[0].src) { + if (currentButton?.children?.length > 0 && modalImage.src != currentButton.children[0].src) { modalImage.src = currentButton.children[0].src; if (modalImage.style.display === 'none') { modal.style.setProperty('background-image', `url(${modalImage.src})`) From c8045c5ad4f99deb3a19add06e0457de1df62b05 Mon Sep 17 00:00:00 2001 From: SGKoishi Date: Sun, 16 Oct 2022 10:08:23 -0700 Subject: [PATCH 02/11] The hide_ui_dir_config flag also restrict write attempt to path settings --- modules/shared.py | 10 ++++++++++ modules/ui.py | 8 +++++++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/modules/shared.py b/modules/shared.py index dcab0af9..c2775603 100644 --- a/modules/shared.py +++ b/modules/shared.py @@ -77,6 +77,16 @@ parser.add_argument("--disable-safe-unpickle", action='store_true', help="disabl cmd_opts = parser.parse_args() +restricted_opts = [ + "samples_filename_pattern", + "outdir_samples", + "outdir_txt2img_samples", + "outdir_img2img_samples", + "outdir_extras_samples", + "outdir_grids", + "outdir_txt2img_grids", + "outdir_save", +] devices.device, devices.device_interrogate, devices.device_gfpgan, devices.device_bsrgan, devices.device_esrgan, devices.device_scunet, devices.device_codeformer = \ (devices.cpu if any(y in cmd_opts.use_cpu for y in [x, 'all']) else devices.get_optimal_device() for x in ['sd', 'interrogate', 'gfpgan', 'bsrgan', 'esrgan', 'scunet', 'codeformer']) diff --git a/modules/ui.py b/modules/ui.py index 7b0d5a92..43dc88fc 100644 --- a/modules/ui.py +++ b/modules/ui.py @@ -25,7 +25,7 @@ import gradio.routes from modules import sd_hijack, sd_models from modules.paths import script_path -from modules.shared import opts, cmd_opts +from modules.shared import opts, cmd_opts, restricted_opts if cmd_opts.deepdanbooru: from modules.deepbooru import get_deepbooru_tags import modules.shared as shared @@ -1430,6 +1430,9 @@ Requested path was: {f} if comp_args and isinstance(comp_args, dict) and comp_args.get('visible') is False: continue + if cmd_opts.hide_ui_dir_config and key in restricted_opts: + continue + oldval = opts.data.get(key, None) opts.data[key] = value @@ -1447,6 +1450,9 @@ Requested path was: {f} if not opts.same_type(value, opts.data_labels[key].default): return gr.update(visible=True), opts.dumpjson() + if cmd_opts.hide_ui_dir_config and key in restricted_opts: + return gr.update(value=oldval), opts.dumpjson() + oldval = opts.data.get(key, None) opts.data[key] = value From a1d3cbf92cfde6b3e02a9c795412d01cdc268934 Mon Sep 17 00:00:00 2001 From: fortypercnt <114840933+fortypercnt@users.noreply.github.com> Date: Mon, 17 Oct 2022 05:25:34 +0200 Subject: [PATCH 03/11] Fix #2750 left / top alignment was necessary with gradio 3.4.1. In gradio 3.5 the parent div of the image mask is centered, so the left / top alignment put the mask in the wrong place as described in #2750 #2795 #2805. This fix was tested on Windows 10 / Chrome. --- javascript/imageMaskFix.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/javascript/imageMaskFix.js b/javascript/imageMaskFix.js index 3d77bfe9..9fe7a603 100644 --- a/javascript/imageMaskFix.js +++ b/javascript/imageMaskFix.js @@ -31,8 +31,8 @@ function imageMaskResize() { wrapper.style.width = `${wW}px`; wrapper.style.height = `${wH}px`; - wrapper.style.left = `${(w-wW)/2}px`; - wrapper.style.top = `${(h-wH)/2}px`; + wrapper.style.left = `0px`; + wrapper.style.top = `0px`; canvases.forEach( c => { c.style.width = c.style.height = ''; @@ -42,4 +42,4 @@ function imageMaskResize() { }); } - onUiUpdate(() => imageMaskResize()); \ No newline at end of file + onUiUpdate(() => imageMaskResize()); From 0fd130767102ebcf90e97c6c191ecf199a2d4091 Mon Sep 17 00:00:00 2001 From: MrCheeze Date: Sun, 16 Oct 2022 18:44:39 -0400 Subject: [PATCH 04/11] improve performance of 3-way merge on machines with not enough ram, by only accessing two of the models at a time --- modules/extras.py | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/modules/extras.py b/modules/extras.py index 0819ed37..340a45fd 100644 --- a/modules/extras.py +++ b/modules/extras.py @@ -175,11 +175,14 @@ def run_pnginfo(image): def run_modelmerger(primary_model_name, secondary_model_name, teritary_model_name, interp_method, multiplier, save_as_half, custom_name): - def weighted_sum(theta0, theta1, theta2, alpha): + def weighted_sum(theta0, theta1, alpha): return ((1 - alpha) * theta0) + (alpha * theta1) - def add_difference(theta0, theta1, theta2, alpha): - return theta0 + (theta1 - theta2) * alpha + def get_difference(theta1, theta2): + return theta1 - theta2 + + def add_difference(theta0, theta1_2_diff, alpha): + return theta0 + (alpha * theta1_2_diff) primary_model_info = sd_models.checkpoints_list[primary_model_name] secondary_model_info = sd_models.checkpoints_list[secondary_model_name] @@ -201,20 +204,24 @@ def run_modelmerger(primary_model_name, secondary_model_name, teritary_model_nam theta_2 = None theta_funcs = { - "Weighted sum": weighted_sum, - "Add difference": add_difference, + "Weighted sum": (None, weighted_sum), + "Add difference": (get_difference, add_difference), } - theta_func = theta_funcs[interp_method] + theta_func1, theta_func2 = theta_funcs[interp_method] print(f"Merging...") + if theta_func1: + for key in tqdm.tqdm(theta_1.keys()): + if 'model' in key: + t2 = theta_2.get(key, torch.zeros_like(theta_1[key])) + theta_1[key] = theta_func1(theta_1[key], t2) + del theta_2, teritary_model + for key in tqdm.tqdm(theta_0.keys()): if 'model' in key and key in theta_1: - t2 = (theta_2 or {}).get(key) - if t2 is None: - t2 = torch.zeros_like(theta_0[key]) - theta_0[key] = theta_func(theta_0[key], theta_1[key], t2, multiplier) + theta_0[key] = theta_func2(theta_0[key], theta_1[key], multiplier) if save_as_half: theta_0[key] = theta_0[key].half() From 6f7b7a3dcdc471ebe63baa8a7731952557859c5b Mon Sep 17 00:00:00 2001 From: AUTOMATIC <16777216c@gmail.com> Date: Mon, 17 Oct 2022 07:56:08 +0300 Subject: [PATCH 05/11] only read files with .py extension from the scripts dir --- modules/scripts.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/modules/scripts.py b/modules/scripts.py index 45230f9a..ac66d448 100644 --- a/modules/scripts.py +++ b/modules/scripts.py @@ -58,6 +58,9 @@ def load_scripts(basedir): for filename in sorted(os.listdir(basedir)): path = os.path.join(basedir, filename) + if os.path.splitext(path)[1].lower() != '.py': + continue + if not os.path.isfile(path): continue From 8aaadf56b3d5f06b9bd86718d7518883d94d70a0 Mon Sep 17 00:00:00 2001 From: DancingSnow <1121149616@qq.com> Date: Mon, 17 Oct 2022 09:34:18 +0800 Subject: [PATCH 06/11] add cache for workflow --- .github/workflows/on_pull_request.yaml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/on_pull_request.yaml b/.github/workflows/on_pull_request.yaml index 5270cba4..b097d180 100644 --- a/.github/workflows/on_pull_request.yaml +++ b/.github/workflows/on_pull_request.yaml @@ -22,6 +22,12 @@ jobs: uses: actions/setup-python@v3 with: python-version: 3.10.6 + - uses: actions/cache@v2 + with: + path: ~/.cache/pip + key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }} + restore-keys: | + ${{ runner.os }}-pip- - name: Install PyLint run: | python -m pip install --upgrade pip From 58f3ef77336663bce2321f5b692cf2aeacd3ac1c Mon Sep 17 00:00:00 2001 From: DenkingOfficial Date: Mon, 17 Oct 2022 03:10:59 +0500 Subject: [PATCH 07/11] Fix CLIP Interrogator and disable ranks for it --- modules/interrogate.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/interrogate.py b/modules/interrogate.py index 9263d65a..d85d7dcc 100644 --- a/modules/interrogate.py +++ b/modules/interrogate.py @@ -157,9 +157,9 @@ class InterrogateModels: matches = self.rank(image_features, items, top_count=topn) for match, score in matches: if include_ranks: - res += ", " + match - else: res += f", ({match}:{score})" + else: + res += ", " + match except Exception: print(f"Error interrogating", file=sys.stderr) From 5c94aaf290f8ad7bf4499a91c268ad0791b0432f Mon Sep 17 00:00:00 2001 From: AUTOMATIC <16777216c@gmail.com> Date: Mon, 17 Oct 2022 08:28:18 +0300 Subject: [PATCH 08/11] fix bug for latest model merge RAM improvement --- modules/extras.py | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/extras.py b/modules/extras.py index 340a45fd..8dbab240 100644 --- a/modules/extras.py +++ b/modules/extras.py @@ -201,6 +201,7 @@ def run_modelmerger(primary_model_name, secondary_model_name, teritary_model_nam teritary_model = torch.load(teritary_model_info.filename, map_location='cpu') theta_2 = sd_models.get_state_dict_from_checkpoint(teritary_model) else: + teritary_model = None theta_2 = None theta_funcs = { From b99d3cf6dd9bc817e51d0d0a6e8eb12c7c0ac6af Mon Sep 17 00:00:00 2001 From: AUTOMATIC <16777216c@gmail.com> Date: Mon, 17 Oct 2022 08:41:02 +0300 Subject: [PATCH 09/11] make CLIP interrogate ranks output sane values --- modules/interrogate.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/interrogate.py b/modules/interrogate.py index d85d7dcc..64b91eb4 100644 --- a/modules/interrogate.py +++ b/modules/interrogate.py @@ -123,7 +123,7 @@ class InterrogateModels: return caption[0] - def interrogate(self, pil_image, include_ranks=False): + def interrogate(self, pil_image): res = None try: @@ -156,8 +156,8 @@ class InterrogateModels: for name, topn, items in self.categories: matches = self.rank(image_features, items, top_count=topn) for match, score in matches: - if include_ranks: - res += f", ({match}:{score})" + if shared.opts.interrogate_return_ranks: + res += f", ({match}:{score/100:.3f})" else: res += ", " + match From 62edfae257e8982cd620d03862c7bdd44159d18f Mon Sep 17 00:00:00 2001 From: DepFA <35278260+dfaker@users.noreply.github.com> Date: Sun, 16 Oct 2022 20:28:15 +0100 Subject: [PATCH 10/11] print list of embeddings on reload --- modules/textual_inversion/textual_inversion.py | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/textual_inversion/textual_inversion.py b/modules/textual_inversion/textual_inversion.py index 7ec75018..3be69562 100644 --- a/modules/textual_inversion/textual_inversion.py +++ b/modules/textual_inversion/textual_inversion.py @@ -137,6 +137,7 @@ class EmbeddingDatabase: continue print(f"Loaded a total of {len(self.word_embeddings)} textual inversion embeddings.") + print("Embeddings:", ', '.join(self.word_embeddings.keys())) def find_embedding_at_position(self, tokens, offset): token = tokens[offset] From cccc5a20fce4bde9a4299f8790366790735f1d05 Mon Sep 17 00:00:00 2001 From: Greg Fuller Date: Sun, 16 Oct 2022 12:10:07 -0700 Subject: [PATCH 11/11] Safeguard setting restore logic against exceptions also useful for keeping settings cache and restore logic together, and nice for code reuse (other third party scripts can import this class) --- scripts/xy_grid.py | 48 +++++++++++++++++++++++++--------------------- 1 file changed, 26 insertions(+), 22 deletions(-) diff --git a/scripts/xy_grid.py b/scripts/xy_grid.py index 88ad3bf7..5cca168a 100644 --- a/scripts/xy_grid.py +++ b/scripts/xy_grid.py @@ -233,6 +233,21 @@ def draw_xy_grid(p, xs, ys, x_labels, y_labels, cell, draw_legend, include_lone_ return processed_result +class SharedSettingsStackHelper(object): + def __enter__(self): + self.CLIP_stop_at_last_layers = opts.CLIP_stop_at_last_layers + self.hypernetwork = opts.sd_hypernetwork + self.model = shared.sd_model + + def __exit__(self, exc_type, exc_value, tb): + modules.sd_models.reload_model_weights(self.model) + + hypernetwork.load_hypernetwork(self.hypernetwork) + hypernetwork.apply_strength() + + opts.data["CLIP_stop_at_last_layers"] = self.CLIP_stop_at_last_layers + + re_range = re.compile(r"\s*([+-]?\s*\d+)\s*-\s*([+-]?\s*\d+)(?:\s*\(([+-]\d+)\s*\))?\s*") re_range_float = re.compile(r"\s*([+-]?\s*\d+(?:.\d*)?)\s*-\s*([+-]?\s*\d+(?:.\d*)?)(?:\s*\(([+-]\d+(?:.\d*)?)\s*\))?\s*") @@ -267,9 +282,6 @@ class Script(scripts.Script): if not opts.return_grid: p.batch_size = 1 - - CLIP_stop_at_last_layers = opts.CLIP_stop_at_last_layers - def process_axis(opt, vals): if opt.label == 'Nothing': return [0] @@ -367,27 +379,19 @@ class Script(scripts.Script): return process_images(pc) - processed = draw_xy_grid( - p, - xs=xs, - ys=ys, - x_labels=[x_opt.format_value(p, x_opt, x) for x in xs], - y_labels=[y_opt.format_value(p, y_opt, y) for y in ys], - cell=cell, - draw_legend=draw_legend, - include_lone_images=include_lone_images - ) + with SharedSettingsStackHelper(): + processed = draw_xy_grid( + p, + xs=xs, + ys=ys, + x_labels=[x_opt.format_value(p, x_opt, x) for x in xs], + y_labels=[y_opt.format_value(p, y_opt, y) for y in ys], + cell=cell, + draw_legend=draw_legend, + include_lone_images=include_lone_images + ) if opts.grid_save: images.save_image(processed.images[0], p.outpath_grids, "xy_grid", prompt=p.prompt, seed=processed.seed, grid=True, p=p) - # restore checkpoint in case it was changed by axes - modules.sd_models.reload_model_weights(shared.sd_model) - - hypernetwork.load_hypernetwork(opts.sd_hypernetwork) - hypernetwork.apply_strength() - - - opts.data["CLIP_stop_at_last_layers"] = CLIP_stop_at_last_layers - return processed