diff --git a/python/sglang/srt/utils/hf_transformers/config.py b/python/sglang/srt/utils/hf_transformers/config.py index f66ea9a67..c1cb0b526 100644 --- a/python/sglang/srt/utils/hf_transformers/config.py +++ b/python/sglang/srt/utils/hf_transformers/config.py @@ -51,6 +51,44 @@ def _apply_deepseek_ocr_overrides(config, model): config._name_or_path = model +def _is_legacy_glm_moe_dsa_layer_types_error(error: Exception) -> bool: + error_msg = str(error) + return ( + "validate_layer_type" in error_msg and "deepseek_sparse_attention" in error_msg + ) + + +def _load_glm_moe_dsa_config_without_legacy_layer_types( + model, + revision: Optional[str] = None, + **kwargs, +): + from transformers import PretrainedConfig + from transformers.models.auto.configuration_auto import CONFIG_MAPPING + + raw_config, unused_kwargs = PretrainedConfig.get_config_dict( + model, revision=revision, **kwargs + ) + if raw_config.get("model_type") != "glm_moe_dsa" or raw_config.get( + "architectures" + ) != ["GlmMoeDsaForCausalLM"]: + return None + + layer_types = raw_config.get("layer_types") + if not isinstance(layer_types, list) or any( + layer_type != "deepseek_sparse_attention" for layer_type in layer_types + ): + return None + + raw_config = dict(raw_config) + raw_config.pop("layer_types", None) + config = CONFIG_MAPPING[raw_config["model_type"]].from_dict( + raw_config, **unused_kwargs + ) + config._name_or_path = model + return config + + @register_model_config_parser("hf") class HfModelConfigParser(ModelConfigParserBase): def parse( @@ -60,12 +98,23 @@ class HfModelConfigParser(ModelConfigParserBase): revision: Optional[str] = None, **kwargs, ): - config = AutoConfig.from_pretrained( - model, - trust_remote_code=trust_remote_code, - revision=revision, - **kwargs, - ) + try: + config = AutoConfig.from_pretrained( + model, + trust_remote_code=trust_remote_code, + revision=revision, + **kwargs, + ) + except Exception as e: + config = ( + _load_glm_moe_dsa_config_without_legacy_layer_types( + model, revision, **kwargs + ) + if _is_legacy_glm_moe_dsa_layer_types_error(e) + else None + ) + if config is None: + raise if ( config.architectures is not None diff --git a/python/sglang/srt/utils/hf_transformers/tokenizer.py b/python/sglang/srt/utils/hf_transformers/tokenizer.py index 40b1693a3..fbf63da8a 100644 --- a/python/sglang/srt/utils/hf_transformers/tokenizer.py +++ b/python/sglang/srt/utils/hf_transformers/tokenizer.py @@ -159,6 +159,33 @@ def _resolve_tokenizer_name(tokenizer_name, kwargs): return tokenizer_name +# TODO: Remove after bumping huggingface transformers to v5.12 +def _retry_auto_tokenizer_with_glm_moe_dsa_config( + tokenizer_name, args, common_kwargs, error +): + from .config import ( + _is_legacy_glm_moe_dsa_layer_types_error, + _load_glm_moe_dsa_config_without_legacy_layer_types, + ) + + if not _is_legacy_glm_moe_dsa_layer_types_error(error): + return None + + config = _load_glm_moe_dsa_config_without_legacy_layer_types( + tokenizer_name, revision=common_kwargs.get("tokenizer_revision") + ) + if config is None: + return None + + tokenizer = AutoTokenizer.from_pretrained( + tokenizer_name, *args, **{**common_kwargs, "config": config} + ) + logging.getLogger(tokenizer.__class__.__module__).addFilter( + TokenizerWarningsFilter() + ) + return tokenizer + + def _auto_tokenizer_from_pretrained(tokenizer_name, *args, **common_kwargs): """Call ``AutoTokenizer.from_pretrained`` with error handling.""" try: @@ -170,6 +197,11 @@ def _auto_tokenizer_from_pretrained(tokenizer_name, *args, **common_kwargs): ) return tokenizer except TypeError as e: + tokenizer = _retry_auto_tokenizer_with_glm_moe_dsa_config( + tokenizer_name, args, common_kwargs, e + ) + if tokenizer is not None: + return tokenizer err_msg = ( "Failed to load the tokenizer. If you are using a LLaMA V1 model " f"consider using '{_FAST_LLAMA_TOKENIZER}' instead of the " @@ -177,6 +209,11 @@ def _auto_tokenizer_from_pretrained(tokenizer_name, *args, **common_kwargs): ) raise RuntimeError(err_msg) from e except ValueError as e: + tokenizer = _retry_auto_tokenizer_with_glm_moe_dsa_config( + tokenizer_name, args, common_kwargs, e + ) + if tokenizer is not None: + return tokenizer # MistralCommon tokenizers reject standard HF kwargs like # trust_remote_code, use_fast etc. Retry without them. if "are not supported by" in str(e) and "MistralCommon" in str(e): @@ -197,6 +234,13 @@ def _auto_tokenizer_from_pretrained(tokenizer_name, *args, **common_kwargs): ) raise RuntimeError(err_msg) from e raise + except Exception as e: + tokenizer = _retry_auto_tokenizer_with_glm_moe_dsa_config( + tokenizer_name, args, common_kwargs, e + ) + if tokenizer is not None: + return tokenizer + raise def _resolve_tokenizers_backend(tokenizer_name, *args, **common_kwargs): @@ -218,7 +262,16 @@ def _resolve_tokenizers_backend(tokenizer_name, *args, **common_kwargs): tokenizer = AutoTokenizer.from_pretrained( tokenizer_name, *args, **common_kwargs ) - except (ValueError, TypeError, OSError, ImportError, RuntimeError) as e: + except Exception as e: + tokenizer = _retry_auto_tokenizer_with_glm_moe_dsa_config( + tokenizer_name, args, common_kwargs, e + ) + if tokenizer is not None: + return tokenizer + if not isinstance( + e, (ValueError, TypeError, OSError, ImportError, RuntimeError) + ): + raise raise RuntimeError( f"Retry with use_fast=False for {tokenizer_name} also failed " f"(initial load returned TokenizersBackend): {e}"