From ff00b6adbe153d665be05f389f972151175d0ef7 Mon Sep 17 00:00:00 2001 From: Mick Date: Tue, 18 Nov 2025 00:56:30 +0800 Subject: [PATCH] diffusion: fix loading with local model_path (#13445) --- .../multimodal_gen/configs/pipelines/base.py | 13 +- python/sglang/multimodal_gen/registry.py | 149 +++++++++--------- 2 files changed, 81 insertions(+), 81 deletions(-) diff --git a/python/sglang/multimodal_gen/configs/pipelines/base.py b/python/sglang/multimodal_gen/configs/pipelines/base.py index bbde1570e..d3c86f557 100644 --- a/python/sglang/multimodal_gen/configs/pipelines/base.py +++ b/python/sglang/multimodal_gen/configs/pipelines/base.py @@ -354,13 +354,14 @@ class PipelineConfig: # 2. Instantiate PipelineConfig if model_info is None: - logger.warning( - "Couldn't find model info for %s. Using the default pipeline config.", - model_path, + # The error is already logged in get_model_info. + # We raise an exception here to stop the execution. + raise ValueError( + f"Failed to get model info for '{model_path}'. " + "Please check the model path and ensure it is registered correctly." ) - pipeline_config = cls() - else: - pipeline_config = model_info.pipeline_config_cls() + + pipeline_config = model_info.pipeline_config_cls() # 3. Load PipelineConfig from a json file or a PipelineConfig object if provided if isinstance(pipeline_config_or_path, str): diff --git a/python/sglang/multimodal_gen/registry.py b/python/sglang/multimodal_gen/registry.py index 6897f8906..08c879179 100644 --- a/python/sglang/multimodal_gen/registry.py +++ b/python/sglang/multimodal_gen/registry.py @@ -11,6 +11,8 @@ import dataclasses import importlib import os import pkgutil +import re +from functools import lru_cache from typing import Any, Callable, Dict, List, Optional, Tuple, Type from sglang.multimodal_gen.configs.pipelines import ( @@ -141,8 +143,8 @@ def register_configs( model_name: str, sampling_param_cls: Any, pipeline_config_cls: Type[PipelineConfig], - model_path_to_name_mappings: Optional[Dict[str, str]] = None, - model_name_detectors: Optional[List[Tuple[str, Callable[[str], bool]]]] = None, + model_paths: Optional[List[str]] = None, + model_detectors: Optional[List[Callable[[str], bool]]] = None, ): """ Registers configuration classes for a new model family. @@ -156,16 +158,17 @@ def register_configs( sampling_param_cls=sampling_param_cls, pipeline_config_cls=pipeline_config_cls, ) - if model_path_to_name_mappings: - for path, name in model_path_to_name_mappings.items(): + if model_paths: + for path in model_paths: if path in _MODEL_PATH_TO_NAME: logger.warning( - f"Model path '{path}' is already mapped to '{_MODEL_PATH_TO_NAME[path]}' and will be overwritten by '{name}'." + f"Model path '{path}' is already mapped to '{_MODEL_PATH_TO_NAME[path]}' and will be overwritten by '{model_name}'." ) - _MODEL_PATH_TO_NAME[path] = name + _MODEL_PATH_TO_NAME[path] = model_name - if model_name_detectors: - _MODEL_NAME_DETECTORS.extend(model_name_detectors) + if model_detectors: + for detector in model_detectors: + _MODEL_NAME_DETECTORS.append((model_name, detector)) def _get_config_info(model_path: str) -> Optional[ConfigInfo]: @@ -175,11 +178,15 @@ def _get_config_info(model_path: str) -> Optional[ConfigInfo]: # 1. Exact match if model_path in _MODEL_PATH_TO_NAME: model_name = _MODEL_PATH_TO_NAME[model_path] + logger.debug(f"Resolved model name '{model_name}' from exact path match.") return _CONFIG_REGISTRY.get(model_name) - # 2. Partial match - for registered_id, model_name in _MODEL_PATH_TO_NAME.items(): - if registered_id in model_path: + # 2. Partial match: find the best (longest) match against all registered model names. + cleaned_model_path = re.sub(r"--", "/", model_path.lower()) + all_model_names = sorted(_CONFIG_REGISTRY.keys(), key=len, reverse=True) + for model_name in all_model_names: + if model_name in cleaned_model_path: + logger.debug(f"Resolved model name '{model_name}' from partial path match.") return _CONFIG_REGISTRY.get(model_name) # 3. Use detectors @@ -192,6 +199,9 @@ def _get_config_info(model_path: str) -> Optional[ConfigInfo]: for model_name, detector in _MODEL_NAME_DETECTORS: if detector(model_path.lower()) or detector(pipeline_name): + logger.debug( + f"Resolved model name '{model_name}' using a registered detector." + ) return _CONFIG_REGISTRY.get(model_name) return None @@ -212,6 +222,7 @@ class ModelInfo: pipeline_config_cls: Type[PipelineConfig] +@lru_cache(maxsize=1) def get_model_info(model_path: str) -> Optional[ModelInfo]: """ Resolves all necessary classes (pipeline, sampling, config) for a given model path. @@ -251,16 +262,12 @@ def get_model_info(model_path: str) -> Optional[ModelInfo]: # 3. Get configuration classes (sampling, pipeline config) config_info = _get_config_info(model_path) if not config_info: - logger.warning( - f"No specific configuration registered for '{model_path}'. " - f"Falling back to default SamplingParams and PipelineConfig." - ) - # Fallback to defaults if no specific config is found - from sglang.multimodal_gen.configs.sample.base import SamplingParams - - config_info = ConfigInfo( - sampling_param_cls=SamplingParams, pipeline_config_cls=PipelineConfig + logger.error( + f"Could not resolve configuration for model '{model_path}'. " + "It is not a registered model path or detected by any registered model family detectors. " + f"Known model paths: {list(_MODEL_PATH_TO_NAME.keys())}" ) + return None # 4. Combine and return the complete model info return ModelInfo( @@ -277,18 +284,18 @@ def _register_configs(): model_name="hunyuan", sampling_param_cls=HunyuanSamplingParams, pipeline_config_cls=HunyuanConfig, - model_path_to_name_mappings={ - "hunyuanvideo-community/HunyuanVideo": "hunyuan", - }, - model_name_detectors=[("hunyuan", lambda id: "hunyuan" in id.lower())], + model_paths=[ + "hunyuanvideo-community/HunyuanVideo", + ], + model_detectors=[lambda id: "hunyuan" in id.lower()], ) register_configs( model_name="fasthunyuan", sampling_param_cls=FastHunyuanSamplingParam, pipeline_config_cls=FastHunyuanConfig, - model_path_to_name_mappings={ - "FastVideo/FastHunyuan-diffusers": "fasthunyuan", - }, + model_paths=[ + "FastVideo/FastHunyuan-diffusers", + ], ) # StepVideo @@ -296,10 +303,10 @@ def _register_configs(): model_name="stepvideo", sampling_param_cls=StepVideoT2VSamplingParams, pipeline_config_cls=StepVideoT2VConfig, - model_path_to_name_mappings={ - "FastVideo/stepvideo-t2v-diffusers": "stepvideo", - }, - model_name_detectors=[("stepvideo", lambda id: "stepvideo" in id.lower())], + model_paths=[ + "FastVideo/stepvideo-t2v-diffusers", + ], + model_detectors=[lambda id: "stepvideo" in id.lower()], ) # Wan @@ -307,88 +314,86 @@ def _register_configs(): model_name="wan-t2v-1.3b", sampling_param_cls=WanT2V_1_3B_SamplingParams, pipeline_config_cls=WanT2V480PConfig, - model_path_to_name_mappings={ - "Wan-AI/Wan2.1-T2V-1.3B-Diffusers": "wan-t2v-1.3b", - }, - model_name_detectors=[("wanpipeline", lambda id: "wanpipeline" in id.lower())], + model_paths=[ + "Wan-AI/Wan2.1-T2V-1.3B-Diffusers", + ], + model_detectors=[lambda id: "wanpipeline" in id.lower()], ) register_configs( model_name="wan-t2v-14b", sampling_param_cls=WanT2V_14B_SamplingParams, pipeline_config_cls=WanT2V720PConfig, - model_path_to_name_mappings={ - "Wan-AI/Wan2.1-T2V-14B-Diffusers": "wan-t2v-14b", - }, + model_paths=[ + "Wan-AI/Wan2.1-T2V-14B-Diffusers", + ], ) register_configs( model_name="wan-i2v-14b-480p", sampling_param_cls=WanI2V_14B_480P_SamplingParam, pipeline_config_cls=WanI2V480PConfig, - model_path_to_name_mappings={ - "Wan-AI/Wan2.1-I2V-14B-480P-Diffusers": "wan-i2v-14b-480p", - }, - model_name_detectors=[ - ("wanimagetovideo", lambda id: "wanimagetovideo" in id.lower()) + model_paths=[ + "Wan-AI/Wan2.1-I2V-14B-480P-Diffusers", ], + model_detectors=[lambda id: "wanimagetovideo" in id.lower()], ) register_configs( model_name="wan-i2v-14b-720p", sampling_param_cls=WanI2V_14B_720P_SamplingParam, pipeline_config_cls=WanI2V720PConfig, - model_path_to_name_mappings={ - "Wan-AI/Wan2.1-I2V-14B-720P-Diffusers": "wan-i2v-14b-720p", - }, + model_paths=[ + "Wan-AI/Wan2.1-I2V-14B-720P-Diffusers", + ], ) register_configs( model_name="wan-fun-1.3b-inp", sampling_param_cls=Wan2_1_Fun_1_3B_InP_SamplingParams, pipeline_config_cls=WanI2V480PConfig, - model_path_to_name_mappings={ - "weizhou03/Wan2.1-Fun-1.3B-InP-Diffusers": "wan-fun-1.3b-inp", - }, + model_paths=[ + "weizhou03/Wan2.1-Fun-1.3B-InP-Diffusers", + ], ) register_configs( model_name="wan-ti2v-5b", sampling_param_cls=Wan2_2_TI2V_5B_SamplingParam, pipeline_config_cls=Wan2_2_TI2V_5B_Config, - model_path_to_name_mappings={ - "Wan-AI/Wan2.2-TI2V-5B-Diffusers": "wan-ti2v-5b", - }, + model_paths=[ + "Wan-AI/Wan2.2-TI2V-5B-Diffusers", + ], ) register_configs( model_name="fastwan-ti2v-5b", sampling_param_cls=Wan2_2_TI2V_5B_SamplingParam, pipeline_config_cls=FastWan2_2_TI2V_5B_Config, - model_path_to_name_mappings={ - "FastVideo/FastWan2.2-TI2V-5B-FullAttn-Diffusers": "fastwan-ti2v-5b", - "FastVideo/FastWan2.2-TI2V-5B-Diffusers": "fastwan-ti2v-5b", - }, + model_paths=[ + "FastVideo/FastWan2.2-TI2V-5B-FullAttn-Diffusers", + "FastVideo/FastWan2.2-TI2V-5B-Diffusers", + ], ) register_configs( model_name="wan-t2v-a14b", sampling_param_cls=Wan2_2_T2V_A14B_SamplingParam, pipeline_config_cls=Wan2_2_T2V_A14B_Config, - model_path_to_name_mappings={ - "Wan-AI/Wan2.2-T2V-A14B-Diffusers": "wan-t2v-a14b", - }, + model_paths=[ + "Wan-AI/Wan2.2-T2V-A14B-Diffusers", + ], ) register_configs( model_name="wan-i2v-a14b", sampling_param_cls=Wan2_2_I2V_A14B_SamplingParam, pipeline_config_cls=Wan2_2_I2V_A14B_Config, - model_path_to_name_mappings={ - "Wan-AI/Wan2.2-I2V-A14B-Diffusers": "wan-i2v-a14b", - }, + model_paths=[ + "Wan-AI/Wan2.2-I2V-A14B-Diffusers", + ], ) register_configs( model_name="fast-wan-t2v-1.3b", sampling_param_cls=FastWanT2V480PConfig, pipeline_config_cls=FastWan2_1_T2V_480P_Config, - model_path_to_name_mappings={ - "FastVideo/FastWan2.1-T2V-1.3B-Diffusers": "fast-wan-t2v-1.3b", - }, + model_paths=[ + "FastVideo/FastWan2.1-T2V-1.3B-Diffusers", + ], ) # FLUX @@ -396,10 +401,10 @@ def _register_configs(): model_name="flux", sampling_param_cls=FluxSamplingParams, pipeline_config_cls=FluxPipelineConfig, - model_path_to_name_mappings={ - "black-forest-labs/FLUX.1-dev": "flux", - }, - model_name_detectors=[("flux", lambda id: "flux" in id.lower())], + model_paths=[ + "black-forest-labs/FLUX.1-dev", + ], + model_detectors=[lambda id: "flux" in id.lower()], ) # Qwen-Image @@ -407,17 +412,11 @@ def _register_configs(): model_name="qwen-image", sampling_param_cls=QwenImageSamplingParams, pipeline_config_cls=QwenImagePipelineConfig, - model_path_to_name_mappings={ - "Qwen/Qwen-Image": "qwen-image", - }, ) register_configs( model_name="qwen-image-edit", sampling_param_cls=QwenImageSamplingParams, pipeline_config_cls=QwenImageEditPipelineConfig, - model_path_to_name_mappings={ - "Qwen/Qwen-Image-Edit": "qwen-image-edit", - }, )