diff --git a/CHANGELOG.md b/CHANGELOG.md index fc12bf637..c10add9ba 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,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**, **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! +On the compute side, new profiles for high-vram GPUs, offloading improvements, parallel-load for large models, support for new `torch` release and improved quality when using low-bit quantization! And (*as always*) many bugfixes and improvements to existing features! *Note*: Change-in-behavior - locations of downloaded HuggingFace models and components are changed to allow for de-duplication of common modules and switched from using system default cache folder to `models/huggingface` @@ -109,6 +109,8 @@ SD.Next will warn on startup on unused cache entries that can be removed. Also, add `allura-org/Gemma-3-Glitter-4B`, `Qwen/Qwen3-4B-Instruct-2507`, `Qwen/Qwen2.5-VL-3B-Instruct` model support improve system prompt - **schedulers** add **Flash FlowMatch** + - **model loader** add parallel loader option + enabled by default, selectable in *settings -> model loading* - **API** - add `/sdapi/v1/checkpoint` POST endpoint to simply load a model - add `/sdapi/v1/modules` GET endpoint to get info on model components/modules @@ -143,6 +145,8 @@ SD.Next will warn on startup on unused cache entries that can be removed. Also, - fix ui tab detection for networks - fix ui checkbox/radio styling for non-default themes - fix loading custom transformers and t5 safetensors tunes + - add mtime to reference models + - patch torch version so 3rd party libraries can use expected format - unified stat size/mtime calls - reapply offloading on ipadapter load - api set default script-name diff --git a/installer.py b/installer.py index a35fd490e..23d31d074 100644 --- a/installer.py +++ b/installer.py @@ -1310,6 +1310,7 @@ def install_requirements(): # set environment variables controling the behavior of various libraries def set_environment(): + from modules.paths import models_path log.debug('Setting environment tuning') os.environ.setdefault('ACCELERATE', 'True') os.environ.setdefault('ATTN_PRECISION', 'fp16') @@ -1336,7 +1337,7 @@ def set_environment(): os.environ.setdefault('DO_NOT_TRACK', '1') os.environ.setdefault('UV_INDEX_STRATEGY', 'unsafe-any-match') os.environ.setdefault('UV_NO_BUILD_ISOLATION', '1') - os.environ.setdefault('HF_HUB_CACHE', opts.get('hfcache_dir', os.path.join(os.path.expanduser('~'), '.cache', 'huggingface', 'hub'))) + os.environ.setdefault('HF_HUB_CACHE', opts.get('hfcache_dir', os.path.join(models_path, 'huggingface'))) allocator = f'garbage_collection_threshold:{opts.get("torch_gc_threshold", 80)/100:0.2f},max_split_size_mb:512' if opts.get("torch_malloc", "native") == 'cudaMallocAsync': allocator += ',backend:cudaMallocAsync' diff --git a/modules/models_hf.py b/modules/models_hf.py index 801fafc04..c767bcde0 100644 --- a/modules/models_hf.py +++ b/modules/models_hf.py @@ -8,6 +8,7 @@ def hf_init(): os.environ.setdefault('HF_HUB_DISABLE_SYMLINKS_WARNING', '1') os.environ.setdefault('HF_HUB_DISABLE_IMPLICIT_TOKEN', '1') os.environ.setdefault('HUGGINGFACE_HUB_VERBOSITY', 'warning') + os.environ.setdefault('HF_ENABLE_PARALLEL_LOADING', 'true') def hf_search(keyword): diff --git a/modules/modelstats.py b/modules/modelstats.py index a91104fa5..3657e523a 100644 --- a/modules/modelstats.py +++ b/modules/modelstats.py @@ -14,7 +14,7 @@ def walk(folder: str): def stat(fn: str): if fn is None or len(fn) == 0 or not os.path.exists(fn): - return 0, None + return 0, datetime.fromtimestamp(0) fs_stat = os.stat(fn, follow_symlinks=False) mtime = datetime.fromtimestamp(fs_stat.st_mtime).replace(microsecond=0) if os.path.islink(fn): diff --git a/modules/shared.py b/modules/shared.py index 1059cf5bf..7d5ebee44 100644 --- a/modules/shared.py +++ b/modules/shared.py @@ -142,6 +142,7 @@ options_templates.update(options_section(('sd', "Model Loading"), { "advanced_sep": OptionInfo("

Advanced Options

", "", gr.HTML), "sd_checkpoint_autoload": OptionInfo(True, "Model auto-load on start"), + "sd_parallel_load": OptionInfo(True, "Model auto-load on start"), "sd_checkpoint_autodownload": OptionInfo(True, "Model auto-download on demand"), "stream_load": OptionInfo(False, "Model load using streams", gr.Checkbox), "diffusers_to_gpu": OptionInfo(False, "Model load model direct to GPU"), diff --git a/modules/ui_extra_networks.py b/modules/ui_extra_networks.py index ce701602a..30b90c726 100644 --- a/modules/ui_extra_networks.py +++ b/modules/ui_extra_networks.py @@ -283,6 +283,7 @@ class ExtraNetworksPage: htmls = [] if len(self.items) > 0 and self.items[0].get('mtime', None) is not None: + shared.opts.extra_networks_sort = 'Date [Newest]' if shared.opts.extra_networks_sort == 'Default': pass elif shared.opts.extra_networks_sort == 'Name [A-Z]': diff --git a/modules/ui_extra_networks_checkpoints.py b/modules/ui_extra_networks_checkpoints.py index ff050bd1e..520492761 100644 --- a/modules/ui_extra_networks_checkpoints.py +++ b/modules/ui_extra_networks_checkpoints.py @@ -26,16 +26,18 @@ class ExtraNetworksPageCheckpoints(ui_extra_networks.ExtraNetworksPage): else: continue preview = v.get('preview', v['path']) + preview_file = self.find_preview_file(os.path.join(reference_dir, preview)) + _size, mtime = modelstats.stat(preview_file) yield { "type": 'Model', "name": os.path.join(reference_dir, k), "title": os.path.join(reference_dir, k), "filename": url, "preview": self.find_preview(os.path.join(reference_dir, preview)), - "local_preview": self.find_preview_file(os.path.join(reference_dir, preview)), + "local_preview": preview_file, "onclick": '"' + html.escape(f"selectReference({json.dumps(url)})") + '"', "hash": None, - "mtime": 0, + "mtime": mtime, "size": 0, "info": {}, "metadata": {}, diff --git a/modules/ui_extra_networks_styles.py b/modules/ui_extra_networks_styles.py index 3cd17b07a..84d9f7b95 100644 --- a/modules/ui_extra_networks_styles.py +++ b/modules/ui_extra_networks_styles.py @@ -1,6 +1,7 @@ import os import html import json +from datetime import datetime from modules import shared, extra_networks, ui_extra_networks, styles @@ -90,7 +91,7 @@ class ExtraNetworksPageStyles(ui_extra_networks.ExtraNetworksPage): "wildcards": getattr(style, 'wildcards', ''), "local_preview": f"{fn}.{shared.opts.samples_format}", "onclick": '"' + html.escape(f"""return selectStyle({json.dumps(name)})""") + '"', - "mtime": getattr(style, 'mtime', 0), + "mtime": getattr(style, 'mtime', datetime.fromtimestamp(0)), "size": os.path.getsize(style.filename), } except Exception as e: