add wildcards to networks ui

Signed-off-by: Vladimir Mandic <mandic00@live.com>
This commit is contained in:
Vladimir Mandic
2025-08-13 20:23:35 -04:00
parent e30e8cbf4f
commit 114d097bb4
8 changed files with 84 additions and 25 deletions
+3 -1
View File
@@ -6,7 +6,7 @@
Several new models: [Qwen-Image](https://qwenlm.github.io/blog/qwen-image/) (plus *Lightning* variant) and [FLUX.1-Krea-Dev](https://www.krea.ai/blog/flux-krea-open-source-release)
Several updated models: [Chroma](https://huggingface.co/lodestones/Chroma), [SkyReels-V2](https://huggingface.co/Skywork/SkyReels-V2-DF-14B-720P-Diffusers), [Wan-VACE](https://huggingface.co/Wan-AI/Wan2.1-VACE-14B-diffusers), [HunyuanDiT](https://huggingface.co/Tencent-Hunyuan/HunyuanDiT-v1.2-Diffusers-Distilled)
Plus continuing with major **UI** work, we have new embedded **Docs/Wiki** search, redesigned real-time **hints**, built-in **GPU monitor**, **CivitAI** integration and more!
Plus continuing with major **UI** work, we have new embedded **Docs/Wiki** search, redesigned real-time **hints**, **wildcards** UI selector, built-in **GPU monitor**, **CivitAI** integration and more!
On the compute side, new profiles for high-vram GPUs, offloading improvements, support for new `torch` release and improved quality when using low-bit quantization!
And (*as always*) many bugfixes and improvements to existing features!
@@ -50,6 +50,8 @@ SD.Next will warn on startup on unused cache entries that can be removed. Also,
**Docs** search: fully-local and works in real-time on all document pages
**Wiki** search: uses github api to search online wiki pages
- updated real-time hints, thanks @CalamitousFelicitousness
- add **Wilcards** UI
in networks display
- every heading element is collapsible!
- quicksettings reset button to restore all quicksettings to default values
because things do sometimes get wrong...
+2 -2
View File
@@ -226,8 +226,8 @@ function sortExtraNetworks(fixed = 'no') {
case 0: return 0;
case 1: return a.dataset.name ? a.dataset.name.localeCompare(b.dataset.name) : 0;
case 2: return b.dataset.name ? b.dataset.name.localeCompare(a.dataset.name) : 0;
case 3: return a.dataset.mtime && !isNaN(a.dataset.mtime) ? parseFloat(b.dataset.mtime) - parseFloat(a.dataset.mtime) : 0;
case 4: return b.dataset.mtime && !isNaN(b.dataset.mtime) ? parseFloat(a.dataset.mtime) - parseFloat(b.dataset.mtime) : 0;
case 3: return a.dataset.mtime ? (new Date(b.dataset.mtime)).getTime() - (new Date(a.dataset.mtime)).getTime() : 0;
case 4: return b.dataset.mtime ? (new Date(a.dataset.mtime)).getTime() - (new Date(b.dataset.mtime)).getTime() : 0;
case 5: return a.dataset.size && !isNaN(a.dataset.size) ? parseFloat(b.dataset.size) - parseFloat(a.dataset.size) : 0;
case 6: return b.dataset.size && !isNaN(b.dataset.size) ? parseFloat(a.dataset.size) - parseFloat(b.dataset.size) : 0;
}
+3 -1
View File
@@ -503,6 +503,8 @@ def register_pages():
register_page(ExtraNetworksPageStyles())
from modules.ui_extra_networks_lora import ExtraNetworksPageLora
register_page(ExtraNetworksPageLora())
from modules.ui_extra_networks_wildcards import ExtraNetworksPageWildcards
register_page(ExtraNetworksPageWildcards())
if shared.opts.latent_history > 0:
from modules.ui_extra_networks_history import ExtraNetworksPageHistory
register_page(ExtraNetworksPageHistory())
@@ -515,7 +517,7 @@ def get_pages(title=None):
visible = shared.opts.extra_networks
pages = []
if 'All' in visible or visible == []: # default en sort order
visible = ['Model', 'Lora', 'Style', 'Embedding', 'VAE', 'History', 'Hypernetwork']
visible = ['Model', 'Lora', 'Style', 'Wildcards', 'Embedding', 'VAE', 'History', 'Hypernetwork']
titles = [page.title for page in shared.extra_networks]
if title is None:
+4 -4
View File
@@ -2,7 +2,7 @@ import os
import html
import json
import concurrent
from modules import shared, ui_extra_networks, sd_models
from modules import shared, ui_extra_networks, sd_models, modelstats
reference_dir = os.path.join('models', 'Reference')
@@ -46,7 +46,7 @@ class ExtraNetworksPageCheckpoints(ui_extra_networks.ExtraNetworksPage):
record = None
try:
checkpoint: sd_models.CheckpointInfo = sd_models.checkpoints_list.get(name)
exists = os.path.exists(checkpoint.filename)
size, mtime = modelstats.stat(checkpoint.filename)
record = {
"type": 'Model',
"name": checkpoint.name,
@@ -55,8 +55,8 @@ class ExtraNetworksPageCheckpoints(ui_extra_networks.ExtraNetworksPage):
"hash": checkpoint.shorthash,
"metadata": checkpoint.metadata,
"onclick": '"' + html.escape(f"selectCheckpoint({json.dumps(name)})") + '"',
"mtime": os.path.getmtime(checkpoint.filename) if exists else 0,
"size": os.path.getsize(checkpoint.filename) if exists else 0,
"mtime": mtime,
"size": size,
}
record["info"] = self.find_info(checkpoint.filename)
record["description"] = self.find_description(checkpoint.filename, record["info"])
+8 -7
View File
@@ -1,7 +1,7 @@
import os
import json
import concurrent
from modules import shared, ui_extra_networks
from modules import shared, ui_extra_networks, modelstats
from modules.lora import lora_load
@@ -85,6 +85,8 @@ class ExtraNetworksPageLora(ui_extra_networks.ExtraNetworksPage):
try:
# path, _ext = os.path.splitext(l.filename)
name = os.path.splitext(os.path.relpath(l.filename, shared.cmd_opts.lora_dir))[0]
size, mtime = modelstats.stat(l.filename)
info = self.find_info(l.filename)
item = {
"type": 'Lora',
"name": name,
@@ -93,14 +95,13 @@ class ExtraNetworksPageLora(ui_extra_networks.ExtraNetworksPage):
"hash": l.shorthash,
"prompt": json.dumps(f" <lora:{l.get_alias()}:{shared.opts.extra_networks_default_multiplier}>"),
"metadata": json.dumps(l.metadata, indent=4) if l.metadata else None,
"mtime": os.path.getmtime(l.filename),
"size": os.path.getsize(l.filename),
"mtime": mtime,
"size": size,
"version": l.sd_version,
"info": info,
"description": self.find_description(l.filename, info),
"tags": self.get_tags(l, info),
}
info = self.find_info(l.filename)
item["info"] = info
item["description"] = self.find_description(l.filename, info) # use existing info instead of double-read
item["tags"] = self.get_tags(l, info)
return item
except Exception as e:
shared.log.error(f'Networks: type=lora file="{name}" {e}')
@@ -1,6 +1,6 @@
import json
import os
from modules import shared, sd_models, ui_extra_networks, files_cache
from modules import shared, sd_models, ui_extra_networks, files_cache, modelstats
from modules.textual_inversion import Embedding
@@ -23,6 +23,8 @@ class ExtraNetworksPageTextualInversion(ui_extra_networks.ExtraNetworksPage):
if embedding.tag is not None:
tags[embedding.tag]=1
name = os.path.splitext(embedding.basename)[0]
size, mtime = modelstats.stat(embedding.filename)
info = self.find_info(embedding.filename)
record = {
"type": 'Embedding',
"name": name,
@@ -30,11 +32,11 @@ class ExtraNetworksPageTextualInversion(ui_extra_networks.ExtraNetworksPage):
"alias": os.path.splitext(os.path.basename(embedding.filename))[0],
"prompt": json.dumps(f" {os.path.splitext(embedding.name)[0]}"),
"tags": tags,
"mtime": os.path.getmtime(embedding.filename),
"size": os.path.getsize(embedding.filename),
"mtime": mtime,
"size": size,
"info": info,
"description": self.find_description(embedding.filename, info),
}
record["info"] = self.find_info(embedding.filename)
record["description"] = self.find_description(embedding.filename, record["info"])
except Exception as e:
shared.log.debug(f'Networks error: type=embedding file="{embedding.filename}" {e}')
return record
+7 -5
View File
@@ -1,7 +1,7 @@
import html
import json
import os
from modules import shared, ui_extra_networks, sd_vae, hashes
from modules import shared, ui_extra_networks, sd_vae, hashes, modelstats
class ExtraNetworksPageVAEs(ui_extra_networks.ExtraNetworksPage):
@@ -14,6 +14,8 @@ class ExtraNetworksPageVAEs(ui_extra_networks.ExtraNetworksPage):
def list_items(self):
for name, filename in sd_vae.vae_dict.items():
try:
size, mtime = modelstats.stat(filename)
info = self.find_info(filename)
record = {
"type": 'VAE',
"name": name,
@@ -25,11 +27,11 @@ class ExtraNetworksPageVAEs(ui_extra_networks.ExtraNetworksPage):
"local_preview": f"{os.path.splitext(filename)[0]}.{shared.opts.samples_format}",
"metadata": {},
"onclick": '"' + html.escape(f"""return selectVAE({json.dumps(name)})""") + '"',
"mtime": os.path.getmtime(filename),
"size": os.path.getsize(filename),
"mtime": mtime,
"size": size,
"info": info,
"description": self.find_description(filename, info),
}
record["info"] = self.find_info(filename)
record["description"] = self.find_description(filename, record["info"])
yield record
except Exception as e:
shared.log.debug(f'Networks error: type=vae file="{filename}" {e}')
+50
View File
@@ -0,0 +1,50 @@
import os
import json
from modules import shared, ui_extra_networks, modelstats, files_cache
wildcards_list = []
class ExtraNetworksPageWildcards(ui_extra_networks.ExtraNetworksPage):
def __init__(self):
super().__init__('Wildcards')
def parents(self, file):
folder = os.path.dirname(file)
if folder != shared.opts.wildcards_dir and folder not in wildcards_list:
wildcards_list.append(folder)
self.parents(folder)
def refresh(self):
wildcards_list.clear()
files = files_cache.list_files(shared.opts.wildcards_dir, ext_filter=[".txt"], recursive=True)
for file in files:
wildcards_list.append(file)
self.parents(file)
def list_items(self):
self.refresh()
for filename in wildcards_list:
relname = os.path.relpath(filename, shared.opts.wildcards_dir)
name = os.path.splitext(relname)[0]
size, mtime = modelstats.stat(filename)
try:
record = {
"type": 'Wildcard',
"name": name,
"filename": filename,
"preview": self.find_preview(filename),
"local_preview": f"{os.path.splitext(filename)[0]}.{shared.opts.samples_format}",
"prompt": json.dumps(f" __{name}__"),
"mtime": mtime,
"size": size,
"description": '',
"info": {},
}
yield record
except Exception as e:
shared.log.debug(f'Networks error: type=wildcard file="{filename}" {e}')
def allowed_directories_for_previews(self):
return [v for v in [shared.opts.wildcards_dir] if v is not None]