utils - vLLM
Skip to content

vllm.model_executor.model_loader.utils

Utilities for selecting and loading models.

Functions:

_MODEL_ARCH_BY_HASH = dict[int, tuple[type[nn.Module], str]]() module-attribute

Caches the outputs of _get_model_architecture.

configure_quant_config(quant_config, model_class)

Pass packed_modules_mapping by reference to quant_config so that quant_config can properly match fused modules

Note that model attributes are passed by reference to quant_config, enabling them to be updated by model_class.new (ex. chatglm, qwen)

Once the SupportsQuant mixin has been added to all models, this function can be removed

Source code in vllm/model_executor/model_loader/utils.py
def configure_quant_config(
    quant_config: QuantizationConfig, model_class: type[nn.Module]
):
    """
    Pass packed_modules_mapping by reference to quant_config so that
    quant_config can properly match fused modules

    Note that model attributes are passed by reference to quant_config,
    enabling them to be updated by model_class.__new__ (ex. chatglm, qwen)

    Once the `SupportsQuant` mixin has been added to all models, this
    function can be removed
    """
    if not issubclass(model_class, SupportsQuant):
        hf_to_vllm_mapper = getattr(model_class, "hf_to_vllm_mapper", None)
        packed_mapping = getattr(model_class, "packed_modules_mapping", None)

        # pass mappings by reference to quant_config
        if hf_to_vllm_mapper is not None:
            quant_config.apply_vllm_mapper(hf_to_vllm_mapper.get_rename_mapper())
        if packed_mapping is not None:
            quant_config.packed_modules_mapping = packed_mapping

initialize_model(vllm_config, *, prefix='', model_class=None, model_config=None)

Initialize a model with the given configurations.

Source code in vllm/model_executor/model_loader/utils.py
@instrument(span_name="Initialize model")
def initialize_model(
    vllm_config: VllmConfig,
    *,
    prefix: str = "",
    model_class: type[nn.Module] | None = None,
    model_config: ModelConfig | None = None,
) -> nn.Module:
    """Initialize a model with the given configurations."""
    if model_config is None:
        model_config = vllm_config.model_config
    if model_class is None:
        model_class, _ = get_model_architecture(model_config)

    if vllm_config.quant_config is not None:
        configure_quant_config(vllm_config.quant_config, model_class)

    signatures = inspect.signature(model_class.__init__)
    all_params = [param.name for param in signatures.parameters.values()]
    if "vllm_config" in all_params and "prefix" in all_params:
        # new-style model class
        with set_current_vllm_config(vllm_config, check_compile=True, prefix=prefix):
            model = model_class(vllm_config=vllm_config, prefix=prefix)
            record_metadata_for_reloading(model)
            return model

    msg = (
        "vLLM model class should accept `vllm_config` and `prefix` as "
        "input arguments. Possibly you have an old-style model class"
        " registered from out of tree and it is used for new vLLM version. "
        "Check https://docs.vllm.ai/en/latest/design/arch_overview.html "
        "for the design and update the model class accordingly."
    )
    warnings.warn(msg, DeprecationWarning, stacklevel=2)

    logger.warning(
        "Trying to guess the arguments for old-style model class %s",
        model_class,
    )
    # try to be compatible with old-style model class
    kwargs: dict[str, Any] = {}
    if "prefix" in all_params:
        kwargs["prefix"] = prefix
    if "config" in all_params:
        kwargs["config"] = model_config.hf_config
    if "cache_config" in all_params:
        kwargs["cache_config"] = vllm_config.cache_config
    if "quant_config" in all_params:
        kwargs["quant_config"] = vllm_config.quant_config
    if "lora_config" in all_params:
        kwargs["lora_config"] = vllm_config.lora_config
    if "scheduler_config" in all_params:
        kwargs["scheduler_config"] = vllm_config.scheduler_config
    with set_current_vllm_config(vllm_config, check_compile=True, prefix=prefix):
        model = model_class(**kwargs)
        record_metadata_for_reloading(model)

    return model

process_weights_after_loading(model, model_config, target_device)

Post-process loaded weights into runtime format.

Under weights_already_processed (weight cache IPC loader), quant methods skip tensor transforms and must declare supports_pre_processed_weights, otherwise this raises RuntimeError.

Source code in vllm/model_executor/model_loader/utils.py
def process_weights_after_loading(
    model: nn.Module, model_config: ModelConfig, target_device: torch.device
) -> None:
    """Post-process loaded weights into runtime format.

    Under ``weights_already_processed`` (weight cache IPC loader), quant
    methods skip tensor transforms and must declare
    ``supports_pre_processed_weights``, otherwise this raises ``RuntimeError``.
    """
    # Reclaim memory when an explicit lm_head has been
    # loaded, but it is identical to the input embeddings.
    maybe_retie_word_embeddings(model, model_config)

    for name, module in model.named_modules():
        quant_method = getattr(module, "quant_method", None)
        if isinstance(quant_method, QuantizeMethodBase):
            if (
                is_weights_pre_processed()
                and not quant_method.supports_pre_processed_weights
            ):
                raise RuntimeError(
                    f"layer {name or '<root>'}: {type(quant_method).__name__} "
                    "does not support pre-processed weights"
                )
            # When quant methods need to process weights after loading
            # (for repacking, quantizing, etc), they typically expect parameters
            # to be on the global target device. This scope is for the
            # case where cpu offloading is used, where we will move the
            # parameters onto device for processing and back off after.
            # Methods that can process weights in place (e.g. PLE scale
            # validation) set requires_device_loading=False to skip this move.
            loading_context = (
                device_loading_context(module, target_device)
                if quant_method.requires_device_loading
                else nullcontext()
            )
            with loading_context:
                quant_method.process_weights_after_loading(module)
            # process_weights_after_loading may swap in freshly-created
            # Parameters (e.g. FP8 requantization), which are stamped with the
            # global rank in BasevLLMParameter.__init__. Re-reconcile their TP
            # state to the layer so a later weight reload / RL weight-refit
            # narrows replicated (disable_tp) weights at the correct offset.
            if hasattr(module, "update_param_tp_status"):
                module.update_param_tp_status()
            # Repacking transients above can leave large amounts of memory in
            # the caching allocator, which starves the OS on UMA devices.
            release_device_memory_under_pressure(target_device)

    # Initialize post-load attention weights for any attention layer and MM
    # encoder. NOTE: Happens after other modules so we can easily decompress
    # weights.
    for _, module in model.named_modules():
        if is_deferred_attention_layer(module):
            # TODO(lucas): see if there is a way to unify the signatures
            # of process_weights_after_loading
            with device_loading_context(module, target_device):
                module.process_weights_after_loading(model_config.dtype)

    # Process HPC modules (HpcRopeNorm, etc.) that rely on
    # process_weights_after_loading being called from the model's
    # load_weights(). When using DummyModelLoader (e.g. profiling or
    # sleep/wake_up reload), the model's load_weights() is not called, so we
    # must handle HPC modules here generically.
    for _, module in model.named_modules():
        if isinstance(module, HpcModule):
            module.process_weights_after_loading(model)

    # Model-level post-load hook, after the per-layer quant finalize.
    if hasattr(model, "process_weights_after_loading"):
        model.process_weights_after_loading()

    # Needed for torchao model reloading via model.reload_weights
    # @kylesayrs @jerryzh168 this can be removed if callers move to `reload_weights`
    if model_config.quantization == "torchao":
        set_torchao_reload_attrs(model, model_config)