CoolFace
Modelpublic

yanziang/InternVideo3-8B-Instruct

sourceHugging Faceapache-2.0updated 4mo agoView on Hugging Face
10likes1.5kdownloads
processing_internvideo3.py238 linesDownload Raw Back to root
1# coding=utf-82# Copyright 2025 The InternVideo Team. All rights reserved.3#4# Licensed under the Apache License, Version 2.0 (the "License");5# you may not use this file except in compliance with the License.6# You may obtain a copy of the License at7#8#     http://www.apache.org/licenses/LICENSE-2.09#10# Unless required by applicable law or agreed to in writing, software11# distributed under the License is distributed on an "AS IS" BASIS,12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.13# See the License for the specific language governing permissions and14# limitations under the License.15"""Processor class for InternVideo3."""16 17from typing import Optional, Union18 19import numpy as np20 21from transformers.feature_extraction_utils import BatchFeature22from transformers.image_utils import ImageInput23from transformers.processing_utils import ImagesKwargs, ProcessingKwargs, ProcessorMixin, Unpack, VideosKwargs24from transformers.tokenization_utils_base import PreTokenizedInput, TextInput25from transformers.utils import logging26from transformers.video_utils import VideoInput27 28 29logger = logging.get_logger(__name__)30 31 32class InternVideo3VideosProcessorKwargs(VideosKwargs, total=False):33    pass34 35 36class InternVideo3ImagesKwargs(ImagesKwargs):37    min_pixels: Optional[int]38    max_pixels: Optional[int]39    patch_size: Optional[int]40    temporal_patch_size: Optional[int]41    merge_size: Optional[int]42 43 44class InternVideo3ProcessorKwargs(ProcessingKwargs, total=False):45    images_kwargs: InternVideo3ImagesKwargs46    videos_kwargs: InternVideo3VideosProcessorKwargs47    _defaults = {48        "text_kwargs": {49            "padding": False,50            "return_token_type_ids": False,51        },52        "videos_kwargs": {"return_metadata": True},53    }54 55 56class InternVideo3Processor(ProcessorMixin):57    r"""58    Constructs an InternVideo3 processor which wraps an image processor, a video processor,59    and a tokenizer into a single processor.60 61    Args:62        image_processor: The image processor.63        tokenizer: The tokenizer.64        video_processor: The video processor.65        chat_template (`str`, *optional*): A Jinja template for chat formatting.66    """67 68    attributes = ["image_processor", "tokenizer", "video_processor"]69    image_processor_class = "AutoImageProcessor"70    video_processor_class = "AutoVideoProcessor"71    tokenizer_class = ("Qwen2Tokenizer", "Qwen2TokenizerFast")72 73    def __init__(self, image_processor=None, tokenizer=None, video_processor=None, chat_template=None, **kwargs):74        super().__init__(image_processor, tokenizer, video_processor, chat_template=chat_template)75        self.image_token = "<|image_pad|>" if not hasattr(tokenizer, "image_token") else tokenizer.image_token76        self.video_token = "<|video_pad|>" if not hasattr(tokenizer, "video_token") else tokenizer.video_token77        self.image_token_id = (78            tokenizer.image_token_id79            if getattr(tokenizer, "image_token_id", None)80            else tokenizer.convert_tokens_to_ids(self.image_token)81        )82        self.video_token_id = (83            tokenizer.video_token_id84            if getattr(tokenizer, "video_token_id", None)85            else tokenizer.convert_tokens_to_ids(self.video_token)86        )87        self.vision_start_token = (88            "<|vision_start|>" if not hasattr(tokenizer, "vision_start_token") else tokenizer.vision_start_token89        )90        self.vision_end_token = (91            "<|vision_end|>" if not hasattr(tokenizer, "vision_end_token") else tokenizer.vision_end_token92        )93        self.vision_start_token_id = (94            tokenizer.vision_start_token_id95            if getattr(tokenizer, "vision_start_token_id", None)96            else tokenizer.convert_tokens_to_ids(self.vision_start_token)97        )98        self.vision_end_token_id = (99            tokenizer.vision_end_token_id100            if getattr(tokenizer, "vision_end_token_id", None)101            else tokenizer.convert_tokens_to_ids(self.vision_end_token)102        )103 104    def __call__(105        self,106        images: ImageInput = None,107        text: Union[TextInput, PreTokenizedInput, list[TextInput], list[PreTokenizedInput]] = None,108        videos: VideoInput = None,109        **kwargs: Unpack[InternVideo3ProcessorKwargs],110    ) -> BatchFeature:111        """112        Main method to prepare inputs for the model.113 114        Args:115            images: The image or batch of images to be prepared.116            text: The sequence or batch of sequences to be encoded.117            videos: The video or batch of videos to be prepared.118            return_tensors: If set, will return tensors of a particular framework.119 120        Returns:121            [`BatchFeature`]: A [`BatchFeature`] with the following fields:122            - **input_ids** -- Token ids to be fed to a model.123            - **attention_mask** -- Attention mask.124            - **pixel_values** -- Pixel values for images.125            - **pixel_values_videos** -- Pixel values for videos.126            - **image_grid_thw** -- Image 3D grid dimensions.127            - **video_grid_thw** -- Video 3D grid dimensions.128        """129        output_kwargs = self._merge_kwargs(130            InternVideo3ProcessorKwargs,131            tokenizer_init_kwargs=self.tokenizer.init_kwargs,132            **kwargs,133        )134 135        if images is not None:136            image_inputs = self.image_processor(images=images, **output_kwargs["images_kwargs"])137            image_grid_thw = image_inputs["image_grid_thw"]138        else:139            image_inputs = {}140            image_grid_thw = None141 142        if videos is not None:143            videos_inputs = self.video_processor(videos=videos, **output_kwargs["videos_kwargs"])144            video_grid_thw = videos_inputs["video_grid_thw"]145            # If user has not requested video metadata, pop it146            if "return_metadata" not in kwargs:147                video_metadata = videos_inputs.pop("video_metadata", None)148            else:149                video_metadata = videos_inputs.get("video_metadata", None)150            video_grid_thw = videos_inputs["video_grid_thw"]151        else:152            videos_inputs = {}153            video_grid_thw = None154            video_metadata = None155 156        if not isinstance(text, list):157            text = [text]158 159        text = text.copy()160        if image_grid_thw is not None:161            merge_length = self.image_processor.merge_size**2162            index = 0163            for i in range(len(text)):164                while self.image_token in text[i]:165                    num_image_tokens = image_grid_thw[index].prod() // merge_length166                    text[i] = text[i].replace(self.image_token, "<|placeholder|>" * num_image_tokens, 1)167                    index += 1168                text[i] = text[i].replace("<|placeholder|>", self.image_token)169 170        if video_grid_thw is not None:171            merge_length = self.video_processor.merge_size**2172            index = 0173            for i in range(len(text)):174                while self.video_token in text[i]:175                    metadata = video_metadata[index] if video_metadata else None176                    if metadata is not None:177                        if metadata.fps is None:178                            logger.warning_once(179                                "InternVideo3 requires frame timestamps to construct prompts, but the `fps` of the input video could not be inferred. "180                                "Defaulting to `fps=24`. Please provide `video_metadata` for more accurate results."181                            )182                            metadata.fps = 24183 184                        curr_timestamp = self._calculate_timestamps(185                            metadata.frames_indices,186                            metadata.fps,187                            self.video_processor.merge_size,188                        )189 190                        video_placeholder = ""191                        frame_seqlen = video_grid_thw[index][1:].prod() // merge_length192                        for frame_idx in range(video_grid_thw[index][0]):193                            curr_time = curr_timestamp[frame_idx]194                            video_placeholder += f"<{curr_time:.1f} seconds>"195                            video_placeholder += (196                                self.vision_start_token + "<|placeholder|>" * frame_seqlen + self.vision_end_token197                            )198                        if f"{self.vision_start_token}{self.video_token}{self.vision_end_token}" in text[i]:199                            text[i] = text[i].replace(200                                f"{self.vision_start_token}{self.video_token}{self.vision_end_token}", video_placeholder, 1201                            )202                        else:203                            text[i] = text[i].replace(self.video_token, video_placeholder, 1)204                    else:205                        num_video_tokens = video_grid_thw[index].prod() // merge_length206                        text[i] = text[i].replace(self.video_token, "<|placeholder|>" * num_video_tokens, 1)207                    index += 1208                text[i] = text[i].replace("<|placeholder|>", self.video_token)209 210        return_tensors = output_kwargs["text_kwargs"].pop("return_tensors", None)211        text_inputs = self.tokenizer(text, **output_kwargs["text_kwargs"])212 213        return BatchFeature(data={**text_inputs, **image_inputs, **videos_inputs}, tensor_type=return_tensors)214 215    def _calculate_timestamps(self, indices: Union[list[int], np.ndarray], video_fps: float, merge_size: int = 2):216        if not isinstance(indices, list):217            indices = indices.tolist()218        if len(indices) % merge_size != 0:219            indices.extend(indices[-1] for _ in range(merge_size - len(indices) % merge_size))220        timestamps = [idx / video_fps for idx in indices]221        timestamps = [222            (timestamps[i] + timestamps[i + merge_size - 1]) / 2 for i in range(0, len(timestamps), merge_size)223        ]224        return timestamps225 226    def post_process_image_text_to_text(227        self, generated_outputs, skip_special_tokens=True, clean_up_tokenization_spaces=False, **kwargs228    ):229        return self.tokenizer.batch_decode(230            generated_outputs,231            skip_special_tokens=skip_special_tokens,232            clean_up_tokenization_spaces=clean_up_tokenization_spaces,233            **kwargs,234        )235 236 237__all__ = ["InternVideo3Processor"]238