From 9e72bebc8c2124a2f4bf12764c385737c52a516e Mon Sep 17 00:00:00 2001 From: CalamitousFelicitousness Date: Sat, 8 Aug 2026 02:43:23 +0100 Subject: [PATCH] fix(model): make saved modular pipelines self-contained and listed Saving a modular pipeline now rewrites the component references in its index to the destination folder, so a reload uses the saved quantized weights instead of following the specs back to the source repositories. The folder scan accepts modular_model_index.json for direct folders, matching the snapshot branch, so saved pipelines list in the model dropdown. --- modules/modelloader.py | 7 +++++-- modules/sd_models.py | 5 +++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/modules/modelloader.py b/modules/modelloader.py index d7a58efe3..b12337f99 100644 --- a/modules/modelloader.py +++ b/modules/modelloader.py @@ -152,10 +152,13 @@ def load_diffusers_models(clear=True): continue name = name.replace("--", "/") friendly = os.path.join(place, name) - has_index = os.path.exists(os.path.join(folder, 'model_index.json')) + index_file = os.path.join(folder, 'model_index.json') + if not os.path.exists(index_file): + index_file = os.path.join(folder, 'modular_model_index.json') # modular pipelines carry their own index flavor + has_index = os.path.exists(index_file) if has_index: # direct download of diffusers model - repo = { 'name': name, 'filename': name, 'friendly': friendly, 'folder': folder, 'path': folder, 'hash': None, 'mtime': os.path.getmtime(folder), 'model_info': os.path.join(folder, 'model_info.json'), 'model_index': os.path.join(folder, 'model_index.json') } + repo = { 'name': name, 'filename': name, 'friendly': friendly, 'folder': folder, 'path': folder, 'hash': None, 'mtime': os.path.getmtime(folder), 'model_info': os.path.join(folder, 'model_info.json'), 'model_index': index_file } diffuser_repos.append(repo) continue diff --git a/modules/sd_models.py b/modules/sd_models.py index c9c495781..c0ff1d3e3 100644 --- a/modules/sd_models.py +++ b/modules/sd_models.py @@ -1648,6 +1648,9 @@ def save_model(name: str, path: str | None = None, shard: str = "5GB", overwrite try: t0 = time.time() log.info(f'Save model: path="{model_name}" cls={shared.sd_model.__class__.__name__} start') + if hasattr(shared.sd_model, '_component_specs'): # modular pipeline: the saved index must reference the destination folder, not the source repos; save_sdnq_model lives in the sdnq submodule and does not pass this flag + import functools + shared.sd_model.save_pretrained = functools.partial(shared.sd_model.save_pretrained, overwrite_modular_index=True) save_sdnq_model( model=shared.sd_model, model_path=model_name, @@ -1662,6 +1665,8 @@ def save_model(name: str, path: str | None = None, shard: str = "5GB", overwrite errors.display(e, 'Save model') return f'Error: {e}' finally: + if 'save_pretrained' in vars(shared.sd_model): + del shared.sd_model.save_pretrained # drop the instance shadow, restoring the class method shared.state.end(jobid)