| 1 | # SPDX-License-Identifier: Apache-2.0 |
| 2 | # SPDX-FileCopyrightText: Copyright contributors to the vLLM project |
| 3 | from typing import Any |
| 4 | |
| 5 | from transformers import PreTrainedConfig |
| 6 | |
| 7 | |
| 8 | class DeepseekV41Config(PreTrainedConfig): |
| 9 | """DeepSeek V4.1 config. |
| 10 | |
| 11 | The HF config nests the text model under ``text_config`` and the vision |
| 12 | tower under ``vision_config``. The vLLM model code (ported from |
| 13 | ``deepseek_v4``) reads flat attributes, so both sub-configs are flattened |
| 14 | onto the top level here: text fields are exposed as-is, vision fields |
| 15 | with the ``vision_*`` naming used by ``deepseek_v41.common.vision``. |
| 16 | """ |
| 17 | |
| 18 | model_type = "deepseek_v41" |
| 19 | |
| 20 | def __init__( |
| 21 | self, |
| 22 | text_config: dict[str, Any] | None = None, |
| 23 | vision_config: dict[str, Any] | None = None, |
| 24 | **kwargs, |
| 25 | ): |
| 26 | text_config = dict(text_config or {}) |
| 27 | vision_config = dict(vision_config or {}) |
| 28 | |
| 29 | # ``rope_scaling`` is a property in Transformers v5 (backed by |
| 30 | # ``rope_parameters``); capture it here and restore after |
| 31 | # super().__init__, which re-standardizes rope params. |
| 32 | rope_scaling = text_config.pop("rope_scaling", None) |
| 33 | |
| 34 | for key, value in text_config.items(): |
| 35 | if key == "model_type": |
| 36 | continue |
| 37 | # Don't clobber PreTrainedConfig properties (e.g. is_encoder_decoder). |
| 38 | if isinstance(getattr(type(self), key, None), property): |
| 39 | continue |
| 40 | setattr(self, key, value) |
| 41 | |
| 42 | super().__init__(**kwargs) |
| 43 | if rope_scaling is not None: |
| 44 | self.rope_parameters = rope_scaling |
| 45 | |
| 46 | # The v4.1 quantization_config carries the expert dtype; the model |
| 47 | # code reads it from the top-level hf_config. |
| 48 | quant_cfg = getattr(self, "quantization_config", None) or {} |
| 49 | if not hasattr(self, "expert_dtype") and "expert_dtype" in quant_cfg: |
| 50 | self.expert_dtype = quant_cfg["expert_dtype"] |
| 51 | |
| 52 | vision_n_layers = vision_config.get("num_hidden_layers", 0) |
| 53 | self.vision_n_layers = vision_n_layers |
| 54 | self.vision_dim = vision_config.get("hidden_size", 1024) |
| 55 | self.vision_n_heads = vision_config.get("num_attention_heads", 16) |
| 56 | self.vision_inter_dim = vision_config.get("intermediate_size", 2816) |
| 57 | self.vision_patch_size = vision_config.get("patch_size", 14) |
| 58 | self.vision_rope_theta = vision_config.get("rope_theta", 10000.0) |
| 59 | self.vision_downsample_ratio = vision_config.get("downsample_ratio", 3) |
| 60 | self.vision_max_n_token = vision_config.get("max_image_tokens", 1024) |
| 61 | self.vision_min_pixels = vision_config.get("min_pixels", 295936) |
| 62 | self.vision_max_wh_ratio = vision_config.get("max_wh_ratio") |