From a319a98e59bfde39ffadef7b63596509ae965e78 Mon Sep 17 00:00:00 2001 From: vladmandic Date: Tue, 23 Dec 2025 10:23:14 +0100 Subject: [PATCH] error handling of meta embeds Signed-off-by: vladmandic --- CHANGELOG.md | 3 ++- modules/processing_args.py | 6 ++++++ modules/sd_models.py | 31 ++++++++++++++++++++++++------- pipelines/generic.py | 1 + 4 files changed, 33 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8ec80ea3a..56be1740e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Change Log for SD.Next -## Update for 2025-12-22 +## Update for 2025-12-23 - **Models** - [LongCat Image](https://github.com/meituan-longcat/LongCat-Image) in *Image* and *Image Edit* variants @@ -31,6 +31,7 @@ - torch.compile skip offloading steps - kanvas css with standardui - control input media with non-english locales + - handle embeds when on meta device ## Update for 2025-12-11 diff --git a/modules/processing_args.py b/modules/processing_args.py index 4f55e841c..686f024a5 100644 --- a/modules/processing_args.py +++ b/modules/processing_args.py @@ -237,6 +237,11 @@ def set_pipeline_args(p, model, prompts:list, negative_prompts:list, prompts_2:t embeds = prompt_parser_diffusers.embedder('prompt_embeds') if embeds is None: shared.log.warning('Prompt parser encode: empty prompt embeds') + prompt_parser_diffusers.embedder = None + args['prompt'] = prompts + elif embeds.device == torch.device('meta'): + shared.log.warning('Prompt parser encode: embeds on meta device') + prompt_parser_diffusers.embedder = None args['prompt'] = prompts else: args['prompt_embeds'] = embeds @@ -273,6 +278,7 @@ def set_pipeline_args(p, model, prompts:list, negative_prompts:list, prompts_2:t args['negative_prompt'] = negative_prompts[0] else: args['negative_prompt'] = negative_prompts + if 'complex_human_instruction' in possible: chi = shared.opts.te_complex_human_instruction p.extra_generation_params["CHI"] = chi diff --git a/modules/sd_models.py b/modules/sd_models.py index 05bda24f8..682706223 100644 --- a/modules/sd_models.py +++ b/modules/sd_models.py @@ -184,6 +184,23 @@ def set_diffuser_options(sd_model, vae=None, op:str='model', offload:bool=True, def move_model(model, device=None, force=False): + def set_execution_device(module, device): + if device == torch.device('cpu'): + return + if hasattr(module, "_hf_hook") and hasattr(module._hf_hook, "execution_device"): # pylint: disable=protected-access + try: + """ + for k, v in module.named_parameters(recurse=True): + if v.device == torch.device('meta'): + from accelerate.utils import set_module_tensor_to_device + set_module_tensor_to_device(module, k, device, tied_params_map=module._hf_hook.tied_params_map) + """ + module._hf_hook.execution_device = device # pylint: disable=protected-access + # module._hf_hook.offload = True + except Exception as e: + if os.environ.get('SD_MOVE_DEBUG', None): + shared.log.error(f'Model move execution device: device={device} {e}') + if model is None or device is None: return @@ -204,20 +221,20 @@ def move_model(model, device=None, force=False): if not isinstance(m, torch.nn.Module) or name in model._exclude_from_cpu_offload: # pylint: disable=protected-access continue for module in m.modules(): - if (hasattr(module, "_hf_hook") and hasattr(module._hf_hook, "execution_device") and module._hf_hook.execution_device is not None): # pylint: disable=protected-access - try: - module._hf_hook.execution_device = device # pylint: disable=protected-access - except Exception as e: - if os.environ.get('SD_MOVE_DEBUG', None): - shared.log.error(f'Model move execution device: device={device} {e}') + set_execution_device(module, device) + # set_execution_device(model, device) + if getattr(model, 'has_accelerate', False) and not force: return if hasattr(model, "device") and devices.normalize_device(model.device) == devices.normalize_device(device) and not force: return + try: t0 = time.time() try: - if hasattr(model, 'to'): + if model.device == torch.device('meta'): + set_execution_device(model, device) + elif hasattr(model, 'to'): model.to(device) if hasattr(model, "prior_pipe"): model.prior_pipe.to(device) diff --git a/pipelines/generic.py b/pipelines/generic.py index 911cdc3c6..d6dad46c8 100644 --- a/pipelines/generic.py +++ b/pipelines/generic.py @@ -56,6 +56,7 @@ def load_transformer(repo_id, cls_name, load_config=None, subfolder="transformer shared.log.debug(f'Load model: transformer="{local_file}" cls={cls_name.__name__} quant="{quant_type}" loader={_loader("diffusers")} args={load_args}') if dtype is not None: load_args['torch_dtype'] = dtype + load_args.pop('device_map', None) # single-file uses different syntax loader = cls_name.from_single_file if hasattr(cls_name, 'from_single_file') else cls_name.from_pretrained transformer = loader( local_file,