[MyPy] Fix mypy errors in vllm/model_executor/models/[kK]* (#59402)

Signed-off-by: Harry Mellor <19981378+hmellor@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Harry Mellor
2026-10-01 19:32:27 +00:00
committed by GitHub
co-authored by Claude Opus 5.5
parent 2a52715ef7
commit 7b44aad5db
10 changed files with 106 additions and 100 deletions
-8
View File
@@ -109,10 +109,6 @@ SEPARATE_GROUPS = [
"tests/v1/worker",
]
EXCLUDE = [
r"vllm/model_executor/models/[kK]",
]
def group_files(changed_files: list[str]) -> dict[str, list[str]]:
"""Group changed files into different mypy calls.
@@ -124,16 +120,12 @@ def group_files(changed_files: list[str]) -> dict[str, list[str]]:
A dictionary mapping file group names to lists of changed files.
"""
exclude_pattern = re.compile(f"^{'|'.join(EXCLUDE)}.*")
silent_pattern = re.compile(f"^({'|'.join(SILENT_GROUPS)}).*")
file_groups: dict[str, list[str]] = {"": []}
file_groups.update({k: [] for k in SEPARATE_GROUPS})
# Longest path first so a sub-directory is not shadowed by its parent
separate_groups = sorted(SEPARATE_GROUPS, key=len, reverse=True)
for changed_file in changed_files:
# Skip files which should be ignored completely
if exclude_pattern.match(changed_file):
continue
# Already-fixed paths go in the default group, which runs at the
# stricter follow_imports setting from pyproject.toml
if silent_pattern.match(changed_file):
+28 -17
View File
@@ -502,6 +502,7 @@ class K2HorizonSparseMoeBlock(nn.Module):
self.gate.bias = nn.Parameter(self.gate.bias.float(), requires_grad=False)
self.num_shared_experts = config.num_shared_experts
self.shared_experts: K2HorizonMLP | None
if config.num_shared_experts > 0:
self.shared_experts = K2HorizonMLP(
hidden_size=config.hidden_size,
@@ -644,6 +645,14 @@ class K2HorizonAttention(nn.Module):
rope_parameters=rope_parameters,
dual_chunk_attention_config=dual_chunk_attention_config,
)
attn_kwargs: dict[str, Any] = (
{
"layer_idx": extract_layer_index(prefix),
"dual_chunk_attention_config": dual_chunk_attention_config,
}
if dual_chunk_attention_config
else {}
)
self.attn = Attention(
self.num_heads,
self.head_dim,
@@ -652,12 +661,7 @@ class K2HorizonAttention(nn.Module):
cache_config=cache_config,
quant_config=quant_config,
prefix=f"{prefix}.attn",
**{
"layer_idx": extract_layer_index(prefix),
"dual_chunk_attention_config": dual_chunk_attention_config,
}
if dual_chunk_attention_config
else {},
**attn_kwargs,
)
self.query_key_norm = query_key_norm
@@ -842,6 +846,14 @@ class K2HorizonMoVAAttention(nn.Module):
rope_parameters=rope_parameters,
dual_chunk_attention_config=dual_chunk_attention_config,
)
attn_kwargs: dict[str, Any] = (
{
"layer_idx": extract_layer_index(prefix),
"dual_chunk_attention_config": dual_chunk_attention_config,
}
if dual_chunk_attention_config
else {}
)
self.attn = Attention(
self.num_heads,
self.head_dim,
@@ -850,12 +862,7 @@ class K2HorizonMoVAAttention(nn.Module):
cache_config=cache_config,
quant_config=quant_config,
prefix=f"{prefix}.attn",
**{
"layer_idx": extract_layer_index(prefix),
"dual_chunk_attention_config": dual_chunk_attention_config,
}
if dual_chunk_attention_config
else {},
**attn_kwargs,
)
self.query_key_norm = query_key_norm
@@ -1228,9 +1235,10 @@ class K2HorizonModel(nn.Module, EagleModelMixin):
expert_params_mapping = self.get_expert_mapping()
for name, loaded_weight in weights:
if "scale" in name or "zero_point" in name:
name = maybe_remap_kv_scale_name(name, params_dict)
if name is None:
remapped_name = maybe_remap_kv_scale_name(name, params_dict)
if remapped_name is None:
continue
name = remapped_name
# QK norm weights
if name.endswith(".self_attn.q_norm.weight") or name.endswith(
@@ -1267,7 +1275,9 @@ class K2HorizonModel(nn.Module, EagleModelMixin):
kv_rank
]
weight_loader = getattr(param, "weight_loader", default_weight_loader)
weight_loader: Callable[..., Any] = getattr(
param, "weight_loader", default_weight_loader
)
weight_loader(param, loaded_weight)
loaded_params.add(name)
continue
@@ -1380,9 +1390,10 @@ class K2HorizonModel(nn.Module, EagleModelMixin):
continue
if name.endswith("scale"):
# Remapping the name of FP8 kv-scale.
name = maybe_remap_kv_scale_name(name, params_dict)
if name is None:
remapped_name = maybe_remap_kv_scale_name(name, params_dict)
if remapped_name is None:
continue
name = remapped_name
if name not in params_dict:
continue
+16 -15
View File
@@ -2,7 +2,7 @@
# SPDX-FileCopyrightText: Copyright contributors to the vLLM project
from collections.abc import Iterable, Mapping, Sequence
from functools import partial
from typing import Annotated, Literal, TypeAlias
from typing import Annotated, Any, Literal, TypeAlias, cast
import numpy as np
import regex as re
@@ -288,7 +288,7 @@ class CustomQwen2VLVE(Qwen2VisionTransformer):
"""Drop-in replacement for the HF `_from_config` constructor."""
return cls(config)
def forward(
def forward( # type: ignore[override]
self,
pixel_values: torch.Tensor,
grid_thw: torch.Tensor,
@@ -331,12 +331,12 @@ class CustomQwen2VLVE(Qwen2VisionTransformer):
# Pre-compute seqlens for attention backend.
max_seqlen = self.compute_attn_mask_seqlen(cu_seqlens)
encoder_states = () if output_hidden_states else None
encoder_states: tuple[torch.Tensor, ...] = ()
for blk in self.blocks:
if output_hidden_states:
# Store patch-level states (S, D).
encoder_states = encoder_states + (x.squeeze(1),)
encoder_states += (x.squeeze(1),)
x = blk(
x,
@@ -348,14 +348,15 @@ class CustomQwen2VLVE(Qwen2VisionTransformer):
# Final hidden state at patch level (S, D).
hidden_states = x.squeeze(1)
all_hidden_states = None
if output_hidden_states:
encoder_states = encoder_states + (hidden_states,)
all_hidden_states = encoder_states + (hidden_states,)
if not return_dict:
return tuple(v for v in [hidden_states, encoder_states] if v is not None)
return tuple(v for v in [hidden_states, all_hidden_states] if v is not None)
return BaseModelOutput(
last_hidden_state=hidden_states,
hidden_states=encoder_states,
hidden_states=all_hidden_states,
)
def get_num_tokens(self) -> int:
@@ -479,7 +480,7 @@ class KananaVMultiModalProcessor(BaseMultiModalProcessor[KananaVProcessingInfo])
assert isinstance(prompt_text, str)
# Images
image_inputs = hf_data.get("images", [])
image_inputs = cast(list[Any], hf_data.get("images", []))
pixel_sizes = []
if not isinstance(image_inputs[0], Image.Image):
image_inputs = [Image.fromarray(image) for image in image_inputs]
@@ -487,9 +488,9 @@ class KananaVMultiModalProcessor(BaseMultiModalProcessor[KananaVProcessingInfo])
image_processor = self.info.get_hf_processor().image_processor
processor_output = [image_processor(image) for image in image_inputs]
pixel_values = [o["pixel_values"] for o in processor_output]
image_meta = [o["image_meta"] for o in processor_output]
image_meta_list = [o["image_meta"] for o in processor_output]
# list of dict -> dict of list
image_meta = {k: [d[k] for d in image_meta] for k in image_meta[0]}
image_meta = {k: [d[k] for d in image_meta_list] for k in image_meta_list[0]}
for pixel_value in pixel_values:
pixel_sizes.append(pixel_value.shape[0])
@@ -545,7 +546,7 @@ class KananaVMultiModalProcessor(BaseMultiModalProcessor[KananaVProcessingInfo])
) -> Sequence[PromptUpdate]:
tokenizer = self.info.get_tokenizer()
def get_replacement(idx: int) -> Sequence[int]:
def get_replacement(idx: int) -> list[int]:
out_item = out_mm_kwargs["image"][idx]
image_token_thw = out_item["image_token_thw"].data
assert isinstance(image_token_thw, torch.Tensor)
@@ -683,7 +684,7 @@ class KananaVForConditionalGeneration(nn.Module, SupportsMultiModal, SupportsPP)
def _get_visual_feature_at(
self,
v_output: Sequence[torch.Tensor],
layer_index: int | Sequence[int],
layer_index: int | list[int] | tuple[int, ...],
) -> torch.Tensor:
if isinstance(layer_index, (list, tuple)):
visual_features = torch.stack(v_output, dim=1)[
@@ -696,7 +697,7 @@ class KananaVForConditionalGeneration(nn.Module, SupportsMultiModal, SupportsPP)
def forward_vision(
self,
pixel_values: torch.Tensor,
image_metas: dict | None = None,
image_metas: dict,
) -> torch.Tensor:
vision_model_args = {
"pixel_values": pixel_values,
@@ -714,7 +715,7 @@ class KananaVForConditionalGeneration(nn.Module, SupportsMultiModal, SupportsPP)
def forward_projector(
self,
visual_features: torch.Tensor,
image_metas: dict | None = None,
image_metas: dict,
) -> torch.Tensor:
visual_embeds = self.abstractor(
visual_features,
@@ -725,7 +726,7 @@ class KananaVForConditionalGeneration(nn.Module, SupportsMultiModal, SupportsPP)
def forward_and_project_vision(
self,
pixel_values: torch.Tensor,
image_metas: dict | None = None,
image_metas: dict,
) -> torch.Tensor:
assert pixel_values is not None
visual_features = self.forward_vision(pixel_values, image_metas=image_metas)
+29 -34
View File
@@ -208,8 +208,8 @@ class KeyeVisionEmbeddings(nn.Module):
self.num_patches = (self.image_size // self.patch_size) ** 2
self.num_positions = self.num_patches
self.cache_position_embedding = dict()
self.cache_position_count = dict()
self.cache_position_embedding: dict[tuple[int, int], torch.Tensor] = {}
self.cache_position_count: dict[tuple[int, int], int] = {}
self.position_embedding = nn.Embedding(self.num_positions, self.embed_dim)
self.packing_position_embedding = nn.Embedding(32768, self.embed_dim)
@@ -264,7 +264,7 @@ class KeyeVisionEmbeddings(nn.Module):
if len(self.cache_position_embedding) >= max_cache:
min_hit_grid = min(
self.cache_position_count,
key=self.cache_position_count.get,
key=self.cache_position_count.__getitem__,
)
self.cache_position_count.pop(min_hit_grid)
self.cache_position_embedding.pop(min_hit_grid)
@@ -278,8 +278,7 @@ class KeyeVisionEmbeddings(nn.Module):
self,
pixel_values: torch.FloatTensor,
position_ids: torch.Tensor | None = None,
image_grid_thw: list[tuple[int, int, int] | list[tuple[int, int, int]]]
| None = None,
image_grid_thw: list[tuple[int, int, int]] | None = None,
interpolate_pos_encoding=False,
) -> torch.Tensor:
if pixel_values.dim() == 4:
@@ -408,7 +407,7 @@ class KeyeSiglipAttention(nn.Module):
hidden_states: torch.Tensor,
attention_mask: torch.Tensor | None = None,
output_attentions: bool | None = False,
cu_seqlens: list[torch.Tensor] | None = None,
cu_seqlens: torch.Tensor | None = None,
rope_emb: tuple[torch.Tensor, torch.Tensor] | None = None,
) -> torch.Tensor:
qkv, _ = self.qkv_proj(hidden_states)
@@ -417,6 +416,8 @@ class KeyeSiglipAttention(nn.Module):
dim=-1,
)
if cu_seqlens is None:
raise ValueError("cu_seqlens cannot be None.")
max_seqlen = (cu_seqlens[1:] - cu_seqlens[:-1]).max()
if rope_emb is None:
@@ -432,8 +433,6 @@ class KeyeSiglipAttention(nn.Module):
self.head_dim,
)
else:
if cu_seqlens is None:
raise ValueError("cu_seqlens cannot be None when rope_emb is not None.")
cos, sin = rope_emb
q = q.view(*q.shape[:-1], self.num_heads, self.head_dim)
k = k.view(
@@ -511,7 +510,7 @@ class KeyeSiglipEncoderLayer(nn.Module):
hidden_states: torch.Tensor,
attention_mask: torch.Tensor,
output_attentions: bool | None = False,
cu_seqlens: list[torch.Tensor] | None = None,
cu_seqlens: torch.Tensor | None = None,
rope_emb: tuple[torch.Tensor, torch.Tensor] | None = None,
) -> tuple[torch.FloatTensor]:
residual = hidden_states
@@ -576,13 +575,12 @@ class KeyeSiglipEncoder(nn.Module):
attention_mask: torch.Tensor | None = None,
output_attentions: bool | None = None,
output_hidden_states: bool | None = None,
cu_seqlens: list[torch.Tensor] | None = None,
image_grid_thw: list[tuple[int, int, int] | list[tuple[int, int, int]]]
| None = None,
cu_seqlens: torch.Tensor | None = None,
image_grid_thw: list[tuple[int, int, int]] | None = None,
height_position_ids: torch.Tensor | None = None,
width_position_ids: torch.Tensor | None = None,
use_rope: bool | None = False,
window_size: bool | None = -1,
window_size: int = -1,
vision_or_text: str = "vision",
) -> BaseModelOutput:
device = inputs_embeds.device
@@ -662,14 +660,13 @@ class KeyeSiglipVisionTransformer(nn.Module):
position_ids: torch.Tensor | None = None,
height_position_ids: torch.Tensor | None = None,
width_position_ids: torch.Tensor | None = None,
cu_seqlens: list[torch.Tensor] | None = None,
cu_seqlens: torch.Tensor | None = None,
padding_mask: torch.Tensor | None = None,
vision_return_embed_list: bool | None = False,
image_grid_thw: list[tuple[int, int, int] | list[tuple[int, int, int]]]
| None = None,
image_grid_thw: list[tuple[int, int, int]] | None = None,
return_pooler_output: bool | None = True,
use_rope: bool | None = False,
window_size: bool | None = -1,
window_size: int = -1,
) -> BaseModelOutputWithPooling:
hidden_states = self.embeddings(
pixel_values,
@@ -757,12 +754,11 @@ class KeyeSiglipVisionModel(nn.Module):
interpolate_pos_encoding: bool = False,
position_ids: torch.Tensor | None = None,
vision_return_embed_list: bool | None = False,
image_grid_thw: list[tuple[int, int, int] | list[tuple[int, int, int]]]
| None = None,
cu_seqlens: list[torch.Tensor] | None = None,
image_grid_thw: list[tuple[int, int, int]] | None = None,
cu_seqlens: torch.Tensor | None = None,
return_pooler_output: bool | None = True,
use_rope: bool | None = False,
window_size: bool | None = -1,
window_size: int = -1,
) -> BaseModelOutputWithPooling:
return self.vision_model(
pixel_values=pixel_values,
@@ -1337,7 +1333,7 @@ class BaseKeyeModule(nn.Module, SupportsMultiModal):
def _process_video_embeds(
self,
video_type: Literal["video_embeds", "pixel_values_videos"],
video_grid_thw: list[torch.Tensor],
video_grid_thw: torch.Tensor,
pixel_values_videos: torch.Tensor | None = None,
) -> torch.Tensor | list[torch.Tensor]:
siglip_position_ids = list()
@@ -1361,6 +1357,7 @@ class BaseKeyeModule(nn.Module, SupportsMultiModal):
"Video embeddings are not supported for this processing path."
)
else:
assert pixel_values_videos is not None
pixel_values_videos = pixel_values_videos.type(self.visual.dtype)
# These are host-built; concat straight into pinned buffers so
# the H2D copies stay non-blocking.
@@ -1535,12 +1532,11 @@ class KeyeForConditionalGeneration(
image_grid_thw=image_grid_thw,
)
if image_embeds is not None:
return KeyeImageEmbeddingInputs(
type="image_embeds",
image_embeds=image_embeds,
image_grid_thw=image_grid_thw,
)
return KeyeImageEmbeddingInputs(
type="image_embeds",
image_embeds=image_embeds,
image_grid_thw=image_grid_thw,
)
def _parse_and_validate_video_input(
self, **kwargs: object
@@ -1559,12 +1555,11 @@ class KeyeForConditionalGeneration(
video_grid_thw=video_grid_thw,
)
if video_embeds is not None:
return KeyeVideoEmbeddingInputs(
type="video_embeds",
video_embeds=video_embeds,
video_grid_thw=video_grid_thw,
)
return KeyeVideoEmbeddingInputs(
type="video_embeds",
video_embeds=video_embeds,
video_grid_thw=video_grid_thw,
)
def _process_video_input(
self, video_input: KeyeVideoInputs
+13 -15
View File
@@ -75,7 +75,7 @@ def split_thw(grid_thw: torch.Tensor) -> torch.Tensor:
def get_num_patches(
grid_thw: torch.Tensor, num_frames: list[int] | torch.Tensor
) -> list[int]:
) -> torch.Tensor:
"""Return num_patches per video.
Args:
@@ -84,7 +84,7 @@ def get_num_patches(
num_frames: List or tensor indicating the number of frames per video
Returns:
List of ints representing the number of patches for each video
Tensor of the number of patches for each video
Examples:
>>> # Suppose there are 2 videos with a total of 3 grids
@@ -538,12 +538,11 @@ class KeyeVL1_5ForConditionalGeneration(
image_grid_thw=image_grid_thw,
)
if image_embeds is not None:
return KeyeVL1_5ImageEmbeddingInputs(
type="image_embeds",
image_embeds=image_embeds,
image_grid_thw=image_grid_thw,
)
return KeyeVL1_5ImageEmbeddingInputs(
type="image_embeds",
image_embeds=image_embeds,
image_grid_thw=image_grid_thw,
)
def _parse_and_validate_video_input(
self, **kwargs: object
@@ -564,13 +563,12 @@ class KeyeVL1_5ForConditionalGeneration(
num_frames=num_frames,
)
if video_embeds is not None:
return KeyeVL1_5VideoEmbeddingInputs(
type="video_embeds",
video_embeds=video_embeds,
video_grid_thw=video_grid_thw,
num_frames=num_frames,
)
return KeyeVL1_5VideoEmbeddingInputs(
type="video_embeds",
video_embeds=video_embeds,
video_grid_thw=video_grid_thw,
num_frames=num_frames,
)
def _process_video_input(
self, video_input: KeyeVL1_5VideoInputs
+3 -1
View File
@@ -18,6 +18,7 @@ from vllm.config.speech_to_text import SpeechToTextParams
from vllm.inputs import PromptType, TokensPrompt
from vllm.model_executor.model_loader import DefaultModelLoader
from vllm.model_executor.models.interfaces import (
MultiModalEmbeddings,
SupportsMultiModal,
SupportsPP,
SupportsTranscription,
@@ -240,6 +241,7 @@ class KimiAudioMultiModalProcessor(BaseMultiModalProcessor[KimiAudioProcessingIn
# KimiAudioProcessor expects raw numpy arrays
mm_data = hf_inputs.hf_data
if audios := mm_data.pop("audio", []):
assert isinstance(audios, Sequence)
audio_arrays = []
for aud in audios:
if isinstance(aud, (tuple, list)) and len(aud) == 2:
@@ -485,7 +487,7 @@ class KimiAudioForConditionalGeneration(
def embed_input_ids(
self,
input_ids: torch.Tensor,
multimodal_embeddings: tuple[torch.Tensor, ...] | None = None,
multimodal_embeddings: MultiModalEmbeddings | None = None,
*,
is_multimodal: torch.Tensor | None = None,
) -> torch.Tensor:
+12 -6
View File
@@ -136,9 +136,9 @@ class KimiK25ProcessingInfo(BaseProcessingInfo):
# may remap token IDs vs config.json.
config_token_id = hf_config.media_placeholder_token_id
resolved_token_id = tokenizer.convert_tokens_to_ids("<|media_pad|>")
unk_token_id = getattr(tokenizer, "unk_token_id", None)
is_valid_resolved = isinstance(resolved_token_id, int) and (
tokenizer.unk_token_id is None
or resolved_token_id != tokenizer.unk_token_id
unk_token_id is None or resolved_token_id != unk_token_id
)
if is_valid_resolved and resolved_token_id != config_token_id:
logger.warning_once(
@@ -165,7 +165,7 @@ class KimiK25ProcessingInfo(BaseProcessingInfo):
)
self.media_tokens_calculator = image_processor.media_tokens_calculator
def get_hf_processor(self):
def get_hf_processor(self, **kwargs: object):
return self.hf_processor
def get_hf_config(self):
@@ -191,7 +191,11 @@ class KimiK25DummyInputsBuilder(BaseDummyInputsBuilder[KimiK25ProcessingInfo]):
)
video_chunk_dummy_item = VisionChunkVideo(
type="video_chunk", video_chunk=dummy_videos
type="video_chunk",
video_chunk=dummy_videos,
uuid=None,
prompt="",
video_idx=0,
)
video_chunk_num_tokens = self.info.media_tokens_calculator(
video_chunk_dummy_item
@@ -204,6 +208,7 @@ class KimiK25DummyInputsBuilder(BaseDummyInputsBuilder[KimiK25ProcessingInfo]):
width=MaxImageTokenMeta.width,
num_images=1,
)[0],
uuid=None,
)
image_num_tokens = self.info.media_tokens_calculator(image_dummy_item)
# return the larger one
@@ -377,7 +382,7 @@ class KimiK25ForConditionalGeneration(
)
self.media_placeholder: int = self.config.media_placeholder_token_id
def _maybe_ignore_quant_config(self, quant_config: QuantizationConfig):
def _maybe_ignore_quant_config(self, quant_config: QuantizationConfig | None):
if isinstance(quant_config, compressed_tensors.CompressedTensorsConfig):
return None
return quant_config
@@ -392,6 +397,7 @@ class KimiK25ForConditionalGeneration(
if isinstance(pixel_values, list):
pixel_values = torch.cat(pixel_values, dim=0)
assert isinstance(pixel_values, torch.Tensor)
if len(pixel_values.shape) == 5 or len(pixel_values.shape) == 3:
pixel_values = pixel_values.reshape(
@@ -612,7 +618,7 @@ class KimiK25ForConditionalGeneration(
grid_thw_list = [[1, ho * kh, wo * kw] for _ in range(max_batch_size)]
ps = self.vision_tower.patch_size
ps: int | tuple[int, int] = self.vision_tower.patch_size
if isinstance(ps, int):
ps = (ps, ps)
total_patches = max_batch_size * ho * kh * wo * kw
+1 -1
View File
@@ -804,7 +804,7 @@ class MoonViT3dPretrainedModel(nn.Module):
self,
grid_thw_list: list[list[int]],
*,
max_batch_size: int,
max_batch_size: int | None,
max_seqlen_override: int | None = None,
device: torch.device,
) -> dict[str, torch.Tensor | None]:
+3 -2
View File
@@ -268,6 +268,7 @@ class KimiVLMultiModalProcessor(BaseMultiModalProcessor[KimiVLProcessingInfo]):
if isinstance(images, ImageEmbeddingItems):
num_image_tokens = images.get_feature_size(item_idx)
else:
assert isinstance(images, ImageProcessorItems)
image_size = images.get_image_size(item_idx)
num_image_tokens = self.info.get_num_image_tokens(
image_width=image_size.width,
@@ -317,7 +318,7 @@ class KimiVLForConditionalGeneration(
assert isinstance(config.vision_config, MoonViTConfig)
self.use_data_parallel = (
model_config.multimodal_config.mm_encoder_tp_mode == "data"
model_config.get_multimodal_config().mm_encoder_tp_mode == "data"
)
self.hidden_size = config.text_config.hidden_size
@@ -469,7 +470,7 @@ class KimiVLForConditionalGeneration(
)
grid_hws_list = [(ho * kh, wo * kw) for _ in range(max_batch_size)]
patch_size = self.config.vision_config.patch_size
patch_size: int | tuple[int, int] = self.config.vision_config.patch_size
if isinstance(patch_size, int):
patch_size = (patch_size, patch_size)
+1 -1
View File
@@ -30,7 +30,7 @@ class KimiVLConfig(PreTrainedConfig):
text_config = DeepseekV2Config()
elif isinstance(text_config, dict):
text_config = DeepseekV2Config(**text_config)
self.text_config = text_config
self.text_config: DeepseekV2Config = text_config
self.ignore_index = ignore_index
self.media_placeholder_token_id = media_placeholder_token_id