From 64021c9666876192076ec772518fc40208e026a5 Mon Sep 17 00:00:00 2001 From: livepeer-tessa Date: Tue, 24 Mar 2026 18:25:43 +0000 Subject: [PATCH] fix: add from_pretrained fallbacks for HF hub model IDs in _load_model MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit HuggingFace Hub model IDs (e.g. 'stabilityai/sd-turbo') cannot be loaded via from_single_file() — that method only accepts local .safetensors paths or direct blob URLs. When a hub ID was passed to _load_model the fallback chain was: 1. AutoPipelineForText2Image.from_pretrained — may fail if the repo lacks a top-level model_index.json (e.g. some SD-2.x models) 2. StableDiffusionPipeline.from_single_file — always fails for hub IDs 3. StableDiffusionXLPipeline.from_single_file — always fails for hub IDs All three exhausted → RuntimeError reported 22 times across 3 streams on staging (2026-03-24) for 'stabilityai/sd-turbo'. Changes: - Detect HF hub IDs (contains '/', not a .safetensors file, not an absolute/relative local path) and build a separate loading-methods list that uses from_pretrained() instead of from_single_file(). - For SDXL hub IDs: AutoPipeline → SDXL from_pretrained → SD from_pretrained - For non-SDXL hub IDs: AutoPipeline → SD from_pretrained → SDXL from_pretrained - Fix SDXL type-check retry to use from_pretrained when input is a hub ID. - Add a logger.warning when 'stabilityai/sd-turbo' (the non-SDXL SD 2.1 Turbo variant) is passed, suggesting 'stabilityai/sdxl-turbo' instead. Fixes daydreamlive/scope#734 Signed-off-by: livepeer-tessa --- src/streamdiffusion/wrapper.py | 55 +++++++++++++++++++++++++++++----- 1 file changed, 48 insertions(+), 7 deletions(-) diff --git a/src/streamdiffusion/wrapper.py b/src/streamdiffusion/wrapper.py index d84b3c6..4861dbf 100644 --- a/src/streamdiffusion/wrapper.py +++ b/src/streamdiffusion/wrapper.py @@ -1109,15 +1109,36 @@ def _load_model( # TODO: CAN we do this step with model_detection.py? is_sdxl_model = False model_path_lower = model_id_or_path.lower() - + + # Detect HuggingFace Hub path: no file extension and contains a '/' (org/model format), + # OR is an absolute/relative local directory path that doesn't end in .safetensors. + # from_single_file() only works for local .safetensors files or direct blob URLs; + # HF hub IDs (e.g. "stabilityai/sd-turbo") must use from_pretrained(). + is_hf_hub_id = ( + not model_id_or_path.endswith('.safetensors') + and not os.path.isabs(model_id_or_path) + and not model_id_or_path.startswith('./') + and '/' in model_id_or_path + ) + # Check path for SDXL indicators if any(indicator in model_path_lower for indicator in ['sdxl', 'xl', '1024']): is_sdxl_model = True logger.info(f"_load_model: Path suggests SDXL model: {model_id_or_path}") - - # For .safetensor files, we need to be more careful about pipeline selection + + # Warn when the non-SDXL sd-turbo variant is used — this pipeline is + # optimised for SDXL. We attempt to load it anyway so the caller can + # decide whether to remap to 'stabilityai/sdxl-turbo'. + if model_id_or_path == "stabilityai/sd-turbo": + logger.warning( + "_load_model: 'stabilityai/sd-turbo' is the non-SDXL SD 2.1 Turbo " + "variant. This pipeline is optimised for SDXL models. " + "Consider using 'stabilityai/sdxl-turbo' instead." + ) + + # For .safetensors files, we need to be more careful about pipeline selection if model_id_or_path.endswith('.safetensors'): - # For .safetensor files, try SDXL pipeline first if path suggests SDXL + # For .safetensors files, try SDXL pipeline first if path suggests SDXL if is_sdxl_model: loading_methods = [ (StableDiffusionXLPipeline.from_single_file, "SDXL from_single_file"), @@ -1130,8 +1151,24 @@ def _load_model( (StableDiffusionPipeline.from_single_file, "SD from_single_file"), (StableDiffusionXLPipeline.from_single_file, "SDXL from_single_file") ] + elif is_hf_hub_id: + # HuggingFace Hub IDs must use from_pretrained(); from_single_file() only + # accepts local .safetensors paths or direct blob URLs and will always fail + # for hub IDs like "stabilityai/sd-turbo". + if is_sdxl_model: + loading_methods = [ + (AutoPipelineForText2Image.from_pretrained, "AutoPipeline from_pretrained"), + (StableDiffusionXLPipeline.from_pretrained, "SDXL from_pretrained"), + (StableDiffusionPipeline.from_pretrained, "SD from_pretrained"), + ] + else: + loading_methods = [ + (AutoPipelineForText2Image.from_pretrained, "AutoPipeline from_pretrained"), + (StableDiffusionPipeline.from_pretrained, "SD from_pretrained"), + (StableDiffusionXLPipeline.from_pretrained, "SDXL from_pretrained"), + ] else: - # For regular model directories or checkpoints, use the original order + # For regular model directories or local checkpoints, use the original order loading_methods = [ (AutoPipelineForText2Image.from_pretrained, "AutoPipeline from_pretrained"), (StableDiffusionPipeline.from_single_file, "SD from_single_file"), @@ -1149,10 +1186,14 @@ def _load_model( # Verify that we have the right pipeline type for SDXL models if is_sdxl_model and not isinstance(pipe, StableDiffusionXLPipeline): logger.warning(f"_load_model: SDXL model detected but loaded with non-SDXL pipeline: {type(pipe)}") - # Try to explicitly load with SDXL pipeline instead + # Try to explicitly load with SDXL pipeline instead. + # Use from_pretrained for HF hub IDs; from_single_file for local paths. try: logger.info(f"_load_model: Retrying with StableDiffusionXLPipeline...") - pipe = StableDiffusionXLPipeline.from_single_file(model_id_or_path).to(dtype=self.dtype) + if is_hf_hub_id: + pipe = StableDiffusionXLPipeline.from_pretrained(model_id_or_path).to(dtype=self.dtype) + else: + pipe = StableDiffusionXLPipeline.from_single_file(model_id_or_path).to(dtype=self.dtype) logger.info(f"_load_model: Successfully loaded using SDXL pipeline on retry") except Exception as retry_error: logger.warning(f"_load_model: SDXL pipeline retry failed: {retry_error}")