Download modeling_nvila_lite.py from Efficient-Large-Model/NVILA-Lite-2B-hf: direct link, hf CLI and curl.
- Browser
- Download file 5.11 kB
-
https://huggingface.co/Efficient-Large-Model/NVILA-Lite-2B-hf/resolve/main/modeling_nvila_lite.py
- Command line
-
hf download hf://Efficient-Large-Model/NVILA-Lite-2B-hf/modeling_nvila_lite.py
-
curl -L -o modeling_nvila_lite.py https://huggingface.co/Efficient-Large-Model/NVILA-Lite-2B-hf/resolve/main/modeling_nvila_lite.py
5.11 kB
| import contextlib | |
| import math | |
| import einops | |
| import torch | |
| import torch.nn as nn | |
| import torch.nn.functional as F | |
| from torch import Tensor | |
| from transformers import Qwen2ForCausalLM, SiglipVisionModel | |
| from transformers.generation.utils import GenerationMixin | |
| from transformers.modeling_outputs import BaseModelOutputWithPooling, CausalLMOutputWithPast | |
| from transformers.modeling_utils import PreTrainedModel | |
| from .configuration_nvila_lite import NVILALiteConfig | |
| MM_HIDDEN_SIZE = 1152 | |
| class NVILALiteMultiModalProjectorDownsampleBlock(nn.Module): | |
| def forward(self, x: Tensor) -> Tensor: | |
| batch_size, sequence_length, hidden_size = x.shape | |
| feat_size = math.isqrt(sequence_length) | |
| features = x.reshape(batch_size, feat_size, feat_size, hidden_size) | |
| pad_after = (3 - feat_size % 3) % 3 | |
| if pad_after > 0: | |
| features = F.pad(features, (0, 0, 0, pad_after, 0, pad_after)) | |
| feat_size = feat_size + pad_after | |
| features = features.reshape(batch_size, feat_size // 3, 3, feat_size // 3, 3, hidden_size) | |
| features = features.permute(0, 1, 3, 2, 4, 5).contiguous() | |
| features = features.reshape(batch_size, -1, 9 * hidden_size) | |
| return features | |
| class NVILALiteMultiModalProjector(nn.Module): | |
| def __init__(self, config: NVILALiteConfig): | |
| super().__init__() | |
| self.layers = nn.Sequential( | |
| NVILALiteMultiModalProjectorDownsampleBlock(), | |
| nn.LayerNorm(MM_HIDDEN_SIZE * 9), | |
| nn.Linear(MM_HIDDEN_SIZE * 9, MM_HIDDEN_SIZE * 3), | |
| nn.GELU(), | |
| nn.LayerNorm(MM_HIDDEN_SIZE * 3), | |
| nn.Linear(MM_HIDDEN_SIZE * 3, config.text_config.hidden_size), | |
| nn.GELU(), | |
| nn.Linear(config.text_config.hidden_size, config.text_config.hidden_size), | |
| ) | |
| def forward(self, x: Tensor) -> Tensor: | |
| return self.layers(x) | |
| class NVILALiteForConditionalGeneration(PreTrainedModel, GenerationMixin): | |
| config_class = NVILALiteConfig | |
| base_model_prefix = "llm" | |
| _auto_class = "AutoModel" | |
| _supports_flash_attn = True | |
| _supports_sdpa = True | |
| def __init__(self, config: NVILALiteConfig): | |
| super().__init__(config) | |
| self.config: NVILALiteConfig | |
| def default_torch_dtype(dtype): | |
| original_dtype = torch.get_default_dtype() | |
| torch.set_default_dtype(dtype) | |
| try: | |
| yield | |
| finally: | |
| torch.set_default_dtype(original_dtype) | |
| with default_torch_dtype(config.torch_dtype): | |
| self.vision_tower = SiglipVisionModel(config.vision_config) | |
| self.mm_projector = NVILALiteMultiModalProjector(config) | |
| self.llm = Qwen2ForCausalLM(config.text_config) | |
| self.post_init() | |
| def forward( | |
| self, | |
| *, | |
| input_ids: Tensor | None = None, | |
| inputs_embeds: Tensor | None = None, | |
| pixel_values: Tensor | None = None, | |
| pixel_values_videos: Tensor | None = None, | |
| **kwargs, | |
| ) -> CausalLMOutputWithPast: | |
| assert (input_ids is None) != ( | |
| inputs_embeds is None | |
| ), "Exactly one of `input_ids` or `inputs_embeds` must be specified." | |
| if input_ids is not None and torch.any( | |
| torch.isin( | |
| input_ids, | |
| torch.tensor( | |
| [self.config.image_token_id, self.config.video_token_id], | |
| device=input_ids.device, | |
| ), | |
| ).any() | |
| ): # Prefill | |
| inputs_embeds = self._embed( | |
| input_ids=input_ids, | |
| pixel_values=pixel_values, | |
| pixel_values_videos=pixel_values_videos, | |
| ) | |
| input_ids = None | |
| outputs = self.llm( | |
| input_ids=input_ids, | |
| inputs_embeds=inputs_embeds, | |
| **kwargs, | |
| ) | |
| return outputs | |
| def _embed( | |
| self, | |
| *, | |
| input_ids: Tensor, | |
| pixel_values: Tensor | None, | |
| pixel_values_videos: Tensor | None, | |
| ) -> Tensor: | |
| inputs_embeds: Tensor = self.llm.model.embed_tokens(input_ids) | |
| for pixel_values, media_token_id in [ | |
| (pixel_values, self.config.image_token_id), | |
| (pixel_values_videos, self.config.video_token_id), | |
| ]: | |
| if pixel_values is None: | |
| continue | |
| vision_features = self._encode_vision(pixel_values) | |
| vision_features = einops.rearrange(vision_features, "n p d -> (n p) d") | |
| inputs_embeds[input_ids == media_token_id] = vision_features | |
| return inputs_embeds | |
| def _encode_vision(self, pixel_values: Tensor) -> Tensor: | |
| vision_tower_output: BaseModelOutputWithPooling = self.vision_tower( | |
| pixel_values, | |
| output_hidden_states=True, | |
| ) | |
| assert vision_tower_output.hidden_states is not None | |
| vision_features = vision_tower_output.hidden_states[-2] | |
| vision_features = self.mm_projector(vision_features) | |
| return vision_features | |