#                🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨
#           This file was automatically generated from src/transformers/models/muse_glimmer/modular_muse_glimmer.py.
#               Do NOT edit this file manually as any edits will be overwritten by the generation of
#             the file from the modular. If any change should be done, please apply the change to the
#                          modular_muse_glimmer.py file directly. One of our CI enforces this.
#                🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨
# Copyright 2026 the HuggingFace Team. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from huggingface_hub.dataclasses import strict

from ...configuration_utils import PreTrainedConfig
from ...modeling_rope_utils import RopeParameters
from ...utils import auto_docstring, logging


logger = logging.get_logger(__name__)


@auto_docstring(checkpoint="meta-models/Muse-Glimmer-30B")
@strict
class MuseGlimmerVisionConfig(PreTrainedConfig):
    r"""
    pos_emb_height (`int`, *optional*):
        Initial position embedding height.
    pos_emb_width (`int`, *optional*):
        Initial position embedding width.
    patch_temporal (`int`, *optional*):
        The temporal patch size used to embed inputs.
    merge_size (`tuple[int] | list[int]`, *optional*):
        Kernel size for patch merging.
    """

    model_type = "muse_glimmer_vision"

    patch_size: int = 14
    pos_emb_height: int = 32
    pos_emb_width: int = 32
    num_attention_heads: int = 16
    num_hidden_layers: int = 50

    hidden_size: int = 1536
    intermediate_size: int = 8960
    hidden_act: str = "gelu"
    rope_parameters: dict | None = None  # defaults set by `RopeConfigMixin`
    max_position_embeddings: int = 32 * 32  # == `pos_h * pos_w`
    patch_temporal: int = 2
    merge_size: int = 2
    layer_norm_eps: float = 1e-05
    layer_types: list[str] | None = None

    def __post_init__(self, **kwargs):
        if self.layer_types is None:
            self.layer_types = [
                "full_attention" if (i + 1) % 4 == 0 or i == self.num_hidden_layers - 1 else "window_attention"
                for i in range(self.num_hidden_layers)
            ]
        super().__post_init__(**kwargs)


@auto_docstring(checkpoint="meta-models/Muse-Glimmer-30B")
@strict
class MuseGlimmerTextConfig(PreTrainedConfig):
    r"""
    final_logit_softcapping (`float`, *optional*, defaults to 20.0):
        scaling factor when applying tanh softcapping on the logits.
    qk_scale_factor (`float`, *optional*, defaults to 3.87):
        Multiplier applied to Q after the scaleless QK-norm, on top of the standard `1/sqrt(head_dim)`
        attention scaling.
    output_multiplier (`float`, *optional*, defaults to 0.19611613513818404):
        Scale applied to logits before the final tanh softcap. Equal to `1/sqrt(hidden_size / 256)` for the
        released checkpoint.
    post_norm_eps (`float`, *optional*, defaults to 1e-8):
        Epsilon used for the post-attention and post-FFN norms (which sit between the sub-layer output and the residual).
    layer_rope_theta (`list[float]`, *optional*):
        Per-layer RoPE base theta; `0` disables rotary (NoPE) for that layer. Overrides the global
        `rope_parameters["rope_theta"]`. Defaults to the global theta everywhere except every 4th layer
        counted backward from the last, which is NoPE.
    """

    model_type = "muse_glimmer_text"
    keys_to_ignore_at_inference = ["past_key_values"]
    base_model_tp_plan = {
        "layers.*.self_attn.q_proj": "colwise",
        "layers.*.self_attn.k_proj": "colwise",
        "layers.*.self_attn.v_proj": "colwise",
        "layers.*.self_attn.gate_proj": "colwise",
        "layers.*.self_attn.o_proj": "rowwise",
        "layers.*.mlp.gate_proj": "colwise",
        "layers.*.mlp.up_proj": "colwise",
        "layers.*.mlp.down_proj": "rowwise",
    }
    base_model_pp_plan = {
        "embed_tokens": (["input_ids"], ["inputs_embeds"]),
        "layers": (["hidden_states", "attention_mask"], ["hidden_states"]),
        "norm": (["hidden_states"], ["hidden_states"]),
    }

    vocab_size: int = 202_048
    hidden_size: int = 6656
    intermediate_size: int = 19968
    num_hidden_layers: int = 52
    num_attention_heads: int = 32
    num_key_value_heads: int = 2
    head_dim: int = 128
    hidden_activation: str = "silu"
    max_position_embeddings: int = 131_072
    initializer_range: float = 0.02
    rms_norm_eps: float = 1e-5
    use_cache: bool = True
    pad_token_id: int | None = None
    eos_token_id: int | list[int] | None = 200_001
    bos_token_id: int | None = 200_000
    tie_word_embeddings: bool = False
    rope_parameters: RopeParameters | dict | None = None
    attention_bias: bool = False
    attention_dropout: int | float | None = 0.0
    sliding_window: int | None = 2048
    layer_types: list[str] | None = None
    final_logit_softcapping: float = 20.0

    # MuseGlimmer-specific fields
    qk_scale_factor: float = 3.87
    output_multiplier: float = 0.19611613513818404
    post_norm_eps: float = 1e-8
    layer_rope_theta: list[float | int] | None = None

    def __post_init__(self, **kwargs):
        # Full attention on NoPE layers (every 4th, counted backward from the last), sliding otherwise —
        # the reference config's sliding_window_pattern [w, w, w, 0].
        if self.layer_types is None:
            self.layer_types = [
                "full_attention" if (self.num_hidden_layers - 1 - i) % 4 == 0 else "sliding_attention"
                for i in range(self.num_hidden_layers)
            ]

        super().__post_init__(**kwargs)

        # Per-layer RoPE base theta (0 => NoPE). Needs `rope_parameters`, so runs after the super post-init. Not sure if it's the cleanest...
        if self.layer_rope_theta is None:
            self.layer_rope_theta = [
                0 if (self.num_hidden_layers - 1 - i) % 4 == 0 else self.rope_parameters["rope_theta"]
                for i in range(self.num_hidden_layers)
            ]

    def validate_architecture(self):
        """Part of `@strict`-powered validation. Validates the architecture of the config."""
        if self.hidden_size % self.num_attention_heads != 0:
            raise ValueError(
                f"The hidden size ({self.hidden_size}) is not a multiple of the number of attention "
                f"heads ({self.num_attention_heads})."
            )


@auto_docstring(checkpoint="meta-models/Muse-Glimmer-30B")
@strict
class MuseGlimmerConfig(PreTrainedConfig):
    r"""
    out_hidden_size (`int`, *optional*, defaults to 6144):
        Output dimension of the vision encoder after patch merging (input width of the multimodal projection).
    projector_hidden_size (`int`, *optional*, defaults to 4096):
        Intermediate dimension of the multimodal projection.

    Example:

    ```python
    >>> from transformers import MuseGlimmerForConditionalGeneration, MuseGlimmerConfig

    >>> # Initializing an MuseGlimmer style configuration
    >>> configuration = MuseGlimmerConfig()

    >>> # Initializing a model from the configuration
    >>> model = MuseGlimmerForConditionalGeneration(configuration)

    >>> # Accessing the model configuration
    >>> configuration = model.config
    ```"""

    model_type = "muse_glimmer"
    sub_configs = {"text_config": MuseGlimmerTextConfig, "vision_config": MuseGlimmerVisionConfig}

    text_config: dict | PreTrainedConfig | None = None
    vision_config: dict | PreTrainedConfig | None = None
    image_token_id: int = 200092
    video_token_id: int = 200091
    out_hidden_size: int = 6144
    projector_hidden_size: int = 4096
    projector_hidden_act: str = "gelu"

    def __post_init__(self, **kwargs):
        if self.text_config is None:
            self.text_config = MuseGlimmerTextConfig()
            logger.info("text_config is None, using default MuseGlimmerTextConfig text config.")
        elif isinstance(self.text_config, dict):
            self.text_config = MuseGlimmerTextConfig(**self.text_config)

        if isinstance(self.vision_config, dict):
            self.vision_config = MuseGlimmerVisionConfig(**self.vision_config)
        elif self.vision_config is None:
            self.vision_config = MuseGlimmerVisionConfig()
            logger.info("vision_config is None, using default MuseGlimmerVisionConfig vision config.")

        super().__post_init__(**kwargs)


__all__ = ["MuseGlimmerTextConfig", "MuseGlimmerVisionConfig", "MuseGlimmerConfig"]
