diff --git a/CHANGELOG.md b/CHANGELOG.md index 40a7ed833..4185af6e6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -37,6 +37,9 @@ Some highlights: [OpenVINO](https://github.com/vladmandic/automatic/wiki/OpenVIN - extend support for [Free-U](https://github.com/ChenyangSi/FreeU) improve generations quality at no cost (other than finding params that work for you) - **General** + - attempt to auto-fix invalid samples which occure due to math errors in lower precision + example: `RuntimeWarning: invalid value encountered in cast: sample = sample.astype(np.uint8)` + begone **black images** *(note: if it proves as working, this solution will need to be expanded to cover all scenarios)* - add **Lora OFT** support, thanks @antis0007 and @ai-casanova - **Upscalers** - **compile** option, thanks @disty0 @@ -54,10 +57,11 @@ Some highlights: [OpenVINO](https://github.com/vladmandic/automatic/wiki/OpenVIN - UI switch core font in default theme to **noto-sans** previously default font was simply *system-ui*, but it lead to too much variations between browsers and platforms - updated **Context menu** - right-click on prompt or generate button + right-click on any button (e.g. generate button) - **Extra networks** - sort by name, size, date, etc. - switch between *gallery* and *list* views + - faster enumeration of all networks on server startup - **Packages** - updated `diffusers` to 0.22.0, `transformers` to 4.34.1 - update **openvino**, thanks @disty0 diff --git a/extensions-builtin/Lora/ui_extra_networks_lora.py b/extensions-builtin/Lora/ui_extra_networks_lora.py index d8049ce84..22ac1da19 100644 --- a/extensions-builtin/Lora/ui_extra_networks_lora.py +++ b/extensions-builtin/Lora/ui_extra_networks_lora.py @@ -14,7 +14,6 @@ class ExtraNetworksPageLora(ui_extra_networks.ExtraNetworksPage): def create_item(self, name): l = networks.available_networks.get(name) - # alias = lora_on_disk.get_alias() try: path, _ext = os.path.splitext(l.filename) possible_tags = l.metadata.get('ss_tag_frequency', {}) if l.metadata is not None else {} @@ -39,6 +38,9 @@ class ExtraNetworksPageLora(ui_extra_networks.ExtraNetworksPage): if words[0] == '{}': words[0] = 0 tags[' '.join(words[1:])] = words[0] + possible_tags = l.metadata.get('tags', []) if l.metadata is not None else [] + for tag in possible_tags: + tags[tag] = 1 name = os.path.splitext(os.path.relpath(l.filename, shared.cmd_opts.lora_dir))[0] item = { "type": 'Lora', @@ -47,8 +49,6 @@ class ExtraNetworksPageLora(ui_extra_networks.ExtraNetworksPage): "hash": l.shorthash, "search_term": self.search_terms_from_path(l.filename) + ' '.join(tags.keys()), "preview": self.find_preview(l.filename), - "description": self.find_description(l.filename), - "info": self.find_info(l.filename), "prompt": json.dumps(f" "), "local_preview": f"{path}.{shared.opts.samples_format}", "metadata": json.dumps(l.metadata, indent=4) if l.metadata else None, @@ -56,51 +56,13 @@ class ExtraNetworksPageLora(ui_extra_networks.ExtraNetworksPage): "mtime": os.path.getmtime(l.filename), "size": os.path.getsize(l.filename), } + item["info"] = self.find_info(l.filename) + item["description"] = self.find_description(l.filename, item["info"]) # use existing info instead of double-read return item except Exception as e: shared.log.debug(f"Extra networks error: type=lora file={name} {e}") return None - """ - item = { - "name": name, - "filename": lora_on_disk.filename, - "shorthash": lora_on_disk.shorthash, - "preview": self.find_preview(path), - "description": self.find_description(path), - "search_term": self.search_terms_from_path(lora_on_disk.filename) + " " + (lora_on_disk.hash or ""), - "local_preview": f"{path}.{shared.opts.samples_format}", - "metadata": lora_on_disk.metadata, - "sort_keys": {'default': index, **self.get_sort_keys(lora_on_disk.filename)}, - "sd_version": lora_on_disk.sd_version.name, - } - self.read_user_metadata(item) - activation_text = item["user_metadata"].get("activation text") - preferred_weight = item["user_metadata"].get("preferred weight", 0.0) - item["prompt"] = quote_js(f"") - if activation_text: - item["prompt"] += " + " + quote_js(" " + activation_text) - sd_version = item["user_metadata"].get("sd version") - if sd_version in network.SdVersion.__members__: - item["sd_version"] = sd_version - sd_version = network.SdVersion[sd_version] - else: - sd_version = lora_on_disk.sd_version - if shared.opts.lora_show_all or not enable_filter: - pass - elif sd_version == network.SdVersion.Unknown: - model_version = network.SdVersion.SDXL if shared.sd_model.is_sdxl else network.SdVersion.SD2 if shared.sd_model.is_sd2 else network.SdVersion.SD1 - if model_version.name in shared.opts.lora_hide_unknown_for_versions: - return None - elif shared.sd_model.is_sdxl and sd_version != network.SdVersion.SDXL: - return None - elif shared.sd_model.is_sd2 and sd_version != network.SdVersion.SD2: - return None - elif shared.sd_model.is_sd1 and sd_version != network.SdVersion.SD1: - return None - return item - """ - def list_items(self): for _index, name in enumerate(networks.available_networks): item = self.create_item(name) diff --git a/javascript/contextMenus.js b/javascript/contextMenus.js index 40e93f4e4..9cfe2dcb3 100644 --- a/javascript/contextMenus.js +++ b/javascript/contextMenus.js @@ -104,7 +104,7 @@ function initContextMenu() { }; for (const tab of ['txt2img', 'img2img']) { - for (const el of ['prompt > label > textarea', 'generate']) { + for (const el of ['generate', 'interrupt', 'skip', 'pause', 'paste', 'clear_prompt', 'extra_networks_btn']) { const id = `#${tab}_${el}`; appendContextMenuOption(id, 'Copy to clipboard', () => navigator.clipboard.writeText(document.querySelector(`#${tab}_prompt > label > textarea`).value)); appendContextMenuOption(id, 'Generate forever', () => generateForever(`#${tab}_generate`)); diff --git a/modules/processing.py b/modules/processing.py index 12a590b30..b0213db25 100644 --- a/modules/processing.py +++ b/modules/processing.py @@ -727,7 +727,6 @@ def process_images(p: StableDiffusionProcessing) -> Processed: def validate_sample(sample): - sample[0][0][0] = np.nan with warnings.catch_warnings(record=True) as w: cast = sample.astype(np.uint8) if len(w) > 0: diff --git a/modules/processing_diffusers.py b/modules/processing_diffusers.py index 3207ee147..a12bd6d86 100644 --- a/modules/processing_diffusers.py +++ b/modules/processing_diffusers.py @@ -143,6 +143,7 @@ def process_diffusers(p: StableDiffusionProcessing, seeds, prompts, negative_pro decoded = full_vae_decode(latents=latents, model=shared.sd_model) else: decoded = taesd_vae_decode(latents=latents) + # decoded = validate_sample(decoded) # TODO validate sample imgs = model.image_processor.postprocess(decoded, output_type=output_type) shared.state.job = prev_job return imgs diff --git a/modules/ui.py b/modules/ui.py index a4cb0be12..361c82e23 100644 --- a/modules/ui.py +++ b/modules/ui.py @@ -263,7 +263,7 @@ 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"): - button_paste = gr.Button(value='Restore', variant='secondary', elem_id="paste") # symbols.paste + button_paste = gr.Button(value='Restore', variant='secondary', elem_id=f"{id_part}_paste") # symbols.paste button_clear = gr.Button(value='Clear', variant='secondary', elem_id=f"{id_part}_clear_prompt_btn") # symbols.clear button_extra = gr.Button(value='Networks', variant='secondary', elem_id=f"{id_part}_extra_networks_btn") # symbols.networks button_clear.click(fn=lambda *x: ['', ''], inputs=[prompt, negative_prompt], outputs=[prompt, negative_prompt], show_progress=False) diff --git a/modules/ui_extra_networks.py b/modules/ui_extra_networks.py index 9cc5c24cc..0cc87b0cf 100644 --- a/modules/ui_extra_networks.py +++ b/modules/ui_extra_networks.py @@ -49,12 +49,12 @@ card_list = ''' def listdir(path): - debug(f'EN list-dir: {path}') if not os.path.exists(path): return [] if path in dir_cache and os.path.getmtime(path) == dir_cache[path][0]: return dir_cache[path][1] else: + # debug(f'EN list-dir list: {path}') dir_cache[path] = (os.path.getmtime(path), [os.path.join(path, f) for f in os.listdir(path)]) return dir_cache[path][1] @@ -138,6 +138,9 @@ class ExtraNetworksPage: self.refresh_time = 0 self.page_time = 0 self.list_time = 0 + self.info_time = 0 + self.desc_time = 0 + self.dirs = {} self.view = shared.opts.extra_networks_view self.card = card_full if shared.opts.extra_networks_view == 'gallery' else card_list @@ -210,7 +213,6 @@ class ExtraNetworksPage: self.missing_thumbs.clear() def create_items(self, tabname): - debug(f'EN create-items: {self.name}') if self.refresh_time is not None and self.refresh_time > refresh_time: # cached results return t0 = time.time() @@ -223,7 +225,8 @@ class ExtraNetworksPage: for item in self.items: self.metadata[item["name"]] = item.get("metadata", {}) t1 = time.time() - self.list_time = round(t1-t0, 2) + debug(f'EN create-items: page={self.name} items={len(self.items)} time={t1-t0:.2f}') + self.list_time += t1-t0 def create_page(self, tabname, skip = False): @@ -263,7 +266,7 @@ class ExtraNetworksPage: self.html = f"
{subdirs_html}
{self.html}
" else: return '' - 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={self.list_time}") + shared.log.debug(f"Extra networks: page='{self.name}' items={len(self.items)} subdirs={len(subdirs)} tab={tabname} dirs={self.allowed_directories_for_previews()} list={self.list_time:.2f} desc={self.desc_time:.2f} info={self.info_time:.2f}") if len(self.missing_thumbs) > 0: threading.Thread(target=self.create_thumb).start() return self.html @@ -305,8 +308,9 @@ class ExtraNetworksPage: def find_preview_file(self, path): fn = os.path.splitext(path)[0] preview_extensions = ["jpg", "jpeg", "png", "webp", "tiff", "jp2"] + files = listdir(os.path.dirname(path)) for file in [f'{fn}{mid}{ext}' for ext in preview_extensions for mid in ['.thumb.', '.preview.', '.']]: - if os.path.exists(file): + if file in files: return file return 'html/card-no-preview.png' @@ -315,14 +319,16 @@ class ExtraNetworksPage: return self.link_preview('html/card-no-preview.png') fn = os.path.splitext(path)[0] preview_extensions = ["jpg", "jpeg", "png", "webp", "tiff", "jp2"] + files = listdir(os.path.dirname(path)) for file in [f'{fn}{mid}{ext}' for ext in preview_extensions for mid in ['.thumb.', '.', '.preview.']]: - if os.path.exists(file): + if file in files: if '.thumb.' not in file: self.missing_thumbs.append(file) return self.link_preview(file) return self.link_preview('html/card-no-preview.png') - def find_description(self, path): + def find_description(self, path, info=None): + t0 = time.time() class HTMLFilter(HTMLParser): text = "" def handle_data(self, data): @@ -332,7 +338,8 @@ class ExtraNetworksPage: self.text += '\n' fn = os.path.splitext(path)[0] + '.txt' - if os.path.exists(fn): + # if os.path.exists(fn): + if fn in listdir(os.path.dirname(path)): try: with open(fn, "r", encoding="utf-8", errors="replace") as f: txt = f.read() @@ -340,20 +347,27 @@ class ExtraNetworksPage: return txt except OSError: pass - info = self.find_info(path) + if info is None: + info = self.find_info(path) desc = info.get('description', '') or '' f = HTMLFilter() f.feed(desc) + t1 = time.time() + self.desc_time += t1-t0 return f.text def find_info(self, path): + t0 = time.time() fn = os.path.splitext(path)[0] + '.json' - if os.path.exists(fn): + # if os.path.exists(fn): + data = {} + if fn in listdir(os.path.dirname(path)): data = shared.readfile(fn, silent=True) if type(data) is list: data = data[0] - return data - return {} + t1 = time.time() + self.info_time += t1-t0 + return data def initialize(): @@ -524,8 +538,8 @@ def create_ui(container, button_parent, tabname, skip_indexing = False): for page in get_pages(): page.create_page(ui.tabname, skip_indexing) with gr.Tab(page.title, id=page.title.lower().replace(" ", "_"), elem_classes="extra-networks-tab") as tab: - hmtl = gr.HTML(page.html, elem_id=f'{tabname}{page.name}_extra_page', elem_classes="extra-networks-page") - ui.pages.append(hmtl) + page_html = gr.HTML(page.html, elem_id=f'{tabname}{page.name}_extra_page', elem_classes="extra-networks-page") + ui.pages.append(page_html) tab.select(ui_tab_change, _js="getENActivePage", inputs=[ui.button_details], outputs=[ui.button_scan, ui.button_save, ui.button_model]) # ui.tabs.change(fn=ui_tab_change, inputs=[], outputs=[ui.button_scan, ui.button_save]) diff --git a/modules/ui_extra_networks_checkpoints.py b/modules/ui_extra_networks_checkpoints.py index b2ffbd80f..bf071c720 100644 --- a/modules/ui_extra_networks_checkpoints.py +++ b/modules/ui_extra_networks_checkpoints.py @@ -26,13 +26,13 @@ class ExtraNetworksPageCheckpoints(ui_extra_networks.ExtraNetworksPage): "search_term": self.search_terms_from_path(checkpoint.title), "preview": self.find_preview(fn), "local_preview": f"{fn}.{shared.opts.samples_format}", - "description": self.find_description(fn), - "info": self.find_info(fn), "metadata": checkpoint.metadata, "onclick": '"' + html.escape(f"""return selectCheckpoint({json.dumps(name)})""") + '"', "mtime": os.path.getmtime(checkpoint.filename), "size": os.path.getsize(checkpoint.filename), } + record["info"] = self.find_info(fn) + record["description"] = self.find_description(fn, record["info"]) yield record except Exception as e: shared.log.debug(f"Extra networks error: type=model file={name} {e}") diff --git a/modules/ui_extra_networks_textual_inversion.py b/modules/ui_extra_networks_textual_inversion.py index 5c750b813..bd5b59fb9 100644 --- a/modules/ui_extra_networks_textual_inversion.py +++ b/modules/ui_extra_networks_textual_inversion.py @@ -45,13 +45,11 @@ class ExtraNetworksPageTextualInversion(ui_extra_networks.ExtraNetworksPage): if embedding.tag is not None: tags[embedding.tag]=1 name = os.path.splitext(embedding.basename)[0] - yield { + record = { "type": 'Embedding', "name": name, "filename": embedding.filename, "preview": self.find_preview(path), - "description": self.find_description(path), - "info": self.find_info(path), "search_term": self.search_terms_from_path(name), "prompt": json.dumps(os.path.splitext(embedding.name)[0]), "local_preview": f"{path}.{shared.opts.samples_format}", @@ -59,6 +57,9 @@ class ExtraNetworksPageTextualInversion(ui_extra_networks.ExtraNetworksPage): "mtime": os.path.getmtime(embedding.filename), "size": os.path.getsize(embedding.filename), } + record["info"] = self.find_info(embedding.filename) + record["description"] = self.find_description(embedding.filename, record["info"]) + yield record except Exception as e: shared.log.debug(f"Extra networks error: type=embedding file={embedding.filename} {e}") diff --git a/modules/ui_extra_networks_vae.py b/modules/ui_extra_networks_vae.py index 09e7565e9..e1bac425b 100644 --- a/modules/ui_extra_networks_vae.py +++ b/modules/ui_extra_networks_vae.py @@ -24,13 +24,13 @@ class ExtraNetworksPageVAEs(ui_extra_networks.ExtraNetworksPage): "search_term": self.search_terms_from_path(fn), "preview": self.find_preview(fn), "local_preview": f"{fn}.{shared.opts.samples_format}", - "description": self.find_description(fn), - "info": self.find_info(fn), "metadata": {}, "onclick": '"' + html.escape(f"""return selectVAE({json.dumps(name)})""") + '"', "mtime": os.path.getmtime(filename), "size": os.path.getsize(filename), } + record["info"] = self.find_info(fn) + record["description"] = self.find_description(fn, record["info"]) yield record except Exception as e: shared.log.debug(f"Extra networks error: type=vae file={filename} {e}") diff --git a/wiki b/wiki index ec2246272..e999774e3 160000 --- a/wiki +++ b/wiki @@ -1 +1 @@ -Subproject commit ec22462722be4ced60391dabe242fa66183f2408 +Subproject commit e999774e3096ceb89a264548fdfaaa76d891c0df