CoolFace
Modelpublic

FriendliAI/InternVL2_5-2B

sourceHugging Facemitupdated 1y agoView on Hugging Face
0likes19downloads
README.md678 linesDownload Raw Back to root
1---2license: mit3pipeline_tag: image-text-to-text4library_name: transformers5base_model:6  - OpenGVLab/InternViT-300M-448px-V2_57  - internlm/internlm2_5-1_8b-chat8base_model_relation: merge9language:10  - multilingual11tags:12  - internvl13  - custom_code14datasets:15  - HuggingFaceFV/finevideo16---17 18# InternVL2_5-2B19 20[\[📂 GitHub\]](https://github.com/OpenGVLab/InternVL)  [\[📜 InternVL 1.0\]](https://huggingface.co/papers/2312.14238)  [\[📜 InternVL 1.5\]](https://huggingface.co/papers/2404.16821)  [\[📜 Mini-InternVL\]](https://arxiv.org/abs/2410.16261)  [\[📜 InternVL 2.5\]](https://huggingface.co/papers/2412.05271)21 22[\[🆕 Blog\]](https://internvl.github.io/blog/)  [\[🗨️ Chat Demo\]](https://internvl.opengvlab.com/)  [\[🤗 HF Demo\]](https://huggingface.co/spaces/OpenGVLab/InternVL)  [\[🚀 Quick Start\]](#quick-start)  [\[📖 Documents\]](https://internvl.readthedocs.io/en/latest/)23 24<div align="center">25  <img width="500" alt="image" src="https://cdn-uploads.huggingface.co/production/uploads/64006c09330a45b03605bba3/zJsd2hqd3EevgXo6fNgC-.png">26</div>27 28## Introduction29 30We are excited to introduce **InternVL 2.5**, an advanced multimodal large language model (MLLM) series that builds upon InternVL 2.0, maintaining its core model architecture while introducing significant enhancements in training and testing strategies as well as data quality.31 32![image/png](https://cdn-uploads.huggingface.co/production/uploads/64119264f0f81eb569e0d569/5HDAGOQOZvS1EtI107Ac-.png)33 34## InternVL 2.5 Family35 36In the following table, we provide an overview of the InternVL 2.5 series.37 38|   Model Name    |                                       Vision Part                                       |                                 Language Part                                  |                           HF Link                           |39| :-------------: | :-------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------: | :---------------------------------------------------------: |40| InternVL2_5-1B  | [InternViT-300M-448px-V2_5](https://huggingface.co/OpenGVLab/InternViT-300M-448px-V2_5) |   [Qwen2.5-0.5B-Instruct](https://huggingface.co/Qwen/Qwen2.5-0.5B-Instruct)   | [🤗 link](https://huggingface.co/OpenGVLab/InternVL2_5-1B)  |41| InternVL2_5-2B  | [InternViT-300M-448px-V2_5](https://huggingface.co/OpenGVLab/InternViT-300M-448px-V2_5) | [internlm2_5-1_8b-chat](https://huggingface.co/internlm/internlm2_5-1_8b-chat) | [🤗 link](https://huggingface.co/OpenGVLab/InternVL2_5-2B)  |42| InternVL2_5-4B  | [InternViT-300M-448px-V2_5](https://huggingface.co/OpenGVLab/InternViT-300M-448px-V2_5) |     [Qwen2.5-3B-Instruct](https://huggingface.co/Qwen/Qwen2.5-3B-Instruct)     | [🤗 link](https://huggingface.co/OpenGVLab/InternVL2_5-4B)  |43| InternVL2_5-8B  | [InternViT-300M-448px-V2_5](https://huggingface.co/OpenGVLab/InternViT-300M-448px-V2_5) |   [internlm2_5-7b-chat](https://huggingface.co/internlm/internlm2_5-7b-chat)   | [🤗 link](https://huggingface.co/OpenGVLab/InternVL2_5-8B)  |44| InternVL2_5-26B |   [InternViT-6B-448px-V2_5](https://huggingface.co/OpenGVLab/InternViT-6B-448px-V2_5)   |  [internlm2_5-20b-chat](https://huggingface.co/internlm/internlm2_5-20b-chat)  | [🤗 link](https://huggingface.co/OpenGVLab/InternVL2_5-26B) |45| InternVL2_5-38B |   [InternViT-6B-448px-V2_5](https://huggingface.co/OpenGVLab/InternViT-6B-448px-V2_5)   |    [Qwen2.5-32B-Instruct](https://huggingface.co/Qwen/Qwen2.5-32B-Instruct)    | [🤗 link](https://huggingface.co/OpenGVLab/InternVL2_5-38B) |46| InternVL2_5-78B |   [InternViT-6B-448px-V2_5](https://huggingface.co/OpenGVLab/InternViT-6B-448px-V2_5)   |    [Qwen2.5-72B-Instruct](https://huggingface.co/Qwen/Qwen2.5-72B-Instruct)    | [🤗 link](https://huggingface.co/OpenGVLab/InternVL2_5-78B) |47 48## Model Architecture49 50As shown in the following figure, InternVL 2.5 retains the same model architecture as its predecessors, InternVL 1.5 and 2.0, following the "ViT-MLP-LLM" paradigm. In this new version, we integrate a newly incrementally pre-trained InternViT with various pre-trained LLMs, including InternLM 2.5 and Qwen 2.5, using a randomly initialized MLP projector.51 52![image/png](https://cdn-uploads.huggingface.co/production/uploads/64119264f0f81eb569e0d569/BiiyXN6NOk0p-3rl3ueyL.png)53 54As in the previous version, we applied a pixel unshuffle operation, reducing the number of visual tokens to one-quarter of the original. Besides, we adopted a similar dynamic resolution strategy as InternVL 1.5, dividing images into tiles of 448×448 pixels. The key difference, starting from InternVL 2.0, is that we additionally introduced support for multi-image and video data.55 56## Training Strategy57 58### Dynamic High-Resolution for Multimodal Data59 60In InternVL 2.0 and 2.5, we extend the dynamic high-resolution training approach, enhancing its capabilities to handle multi-image and video datasets.61 62![image/png](https://cdn-uploads.huggingface.co/production/uploads/64119264f0f81eb569e0d569/xoMY6rwRrNxbAGYPNyU8g.png)63 64- For single-image datasets, the total number of tiles `n_max` are allocated to a single image for maximum resolution. Visual tokens are enclosed in `<img>` and `</img>` tags.65 66- For multi-image datasets, the total number of tiles `n_max` are distributed across all images in a sample. Each image is labeled with auxiliary tags like `Image-1` and enclosed in `<img>` and `</img>` tags.67 68- For videos, each frame is resized to 448×448. Frames are labeled with tags like `Frame-1` and enclosed in `<img>` and `</img>` tags, similar to images.69 70### Single Model Training Pipeline71 72The training pipeline for a single model in InternVL 2.5 is structured across three stages, designed to enhance the model's visual perception and multimodal capabilities.73 74![image/png](https://cdn-uploads.huggingface.co/production/uploads/64119264f0f81eb569e0d569/5NduZeCPLgPJTFr0RGTq3.png)75 76- **Stage 1: MLP Warmup.** In this stage, only the MLP projector is trained while the vision encoder and language model are frozen. A dynamic high-resolution training strategy is applied for better performance, despite increased cost. This phase ensures robust cross-modal alignment and prepares the model for stable multimodal training.77 78- **Stage 1.5: ViT Incremental Learning (Optional).** This stage allows incremental training of the vision encoder and MLP projector using the same data as Stage 1. It enhances the encoder’s ability to handle rare domains like multilingual OCR and mathematical charts. Once trained, the encoder can be reused across LLMs without retraining, making this stage optional unless new domains are introduced.79 80- **Stage 2: Full Model Instruction Tuning.** The entire model is trained on high-quality multimodal instruction datasets. Strict data quality controls are enforced to prevent degradation of the LLM, as noisy data can cause issues like repetitive or incorrect outputs. After this stage, the training process is complete.81 82### Progressive Scaling Strategy83 84We introduce a progressive scaling strategy to align the vision encoder with LLMs efficiently. This approach trains with smaller LLMs first (e.g., 20B) to optimize foundational visual capabilities and cross-modal alignment before transferring the vision encoder to larger LLMs (e.g., 72B) without retraining. This reuse skips intermediate stages for larger models.85 86![image/png](https://cdn-uploads.huggingface.co/production/uploads/64006c09330a45b03605bba3/UoNUyS7ctN5pBxNv9KnzH.png)87 88Compared to Qwen2-VL's 1.4 trillion tokens, InternVL2.5-78B uses only 120 billion tokens—less than one-tenth. This strategy minimizes redundancy, maximizes pre-trained component reuse, and enables efficient training for complex vision-language tasks.89 90### Training Enhancements91 92To improve real-world adaptability and performance, we introduce two key techniques:93 94- **Random JPEG Compression**: Random JPEG compression with quality levels between 75 and 100 is applied as a data augmentation technique. This simulates image degradation from internet sources, enhancing the model's robustness to noisy images.95 96- **Loss Reweighting**: To balance the NTP loss across responses of different lengths, we use a reweighting strategy called **square averaging**. This method balances contributions from responses of varying lengths, mitigating biases toward longer or shorter responses.97 98### Data Organization99 100#### Dataset Configuration101 102In InternVL 2.0 and 2.5, the organization of the training data is controlled by several key parameters to optimize the balance and distribution of datasets during training.103 104![image/png](https://cdn-uploads.huggingface.co/production/uploads/64119264f0f81eb569e0d569/2LJe24b1ua3gjI9gDitVl.png)105 106- **Data Augmentation:** JPEG compression is applied conditionally: enabled for image datasets to enhance robustness and disabled for video datasets to maintain consistent frame quality.107 108- **Maximum Tile Number:** The parameter `n_max` controls the maximum tiles per dataset. For example, higher values (24–36) are used for multi-image or high-resolution data, lower values (6–12) for standard images, and 1 for videos.109 110- **Repeat Factor:** The repeat factor `r` adjusts dataset sampling frequency. Values below 1 reduce a dataset's weight, while values above 1 increase it. This ensures balanced training across tasks and prevents overfitting or underfitting.111 112#### Data Filtering Pipeline113 114During development, we found that LLMs are highly sensitive to data noise, with even small anomalies—like outliers or repetitive data—causing abnormal behavior during inference. Repetitive generation, especially in long-form or CoT reasoning tasks, proved particularly harmful.115 116![image/png](https://cdn-uploads.huggingface.co/production/uploads/64119264f0f81eb569e0d569/aka8ZRiKF3ajdyZBnNFZI.png)117 118To address this challenge and support future research, we designed an efficient data filtering pipeline to remove low-quality samples.119 120![image/png](https://cdn-uploads.huggingface.co/production/uploads/64119264f0f81eb569e0d569/70l1UxnX-Arn0NoOGwpth.png)121 122The pipeline includes two modules, for **pure-text data**, three key strategies are used:123 1241. **LLM-Based Quality Scoring**: Each sample is scored (0–10) using a pre-trained LLM with domain-specific prompts. Samples scoring below a threshold (e.g., 7) are removed to ensure high-quality data.1252. **Repetition Detection**: Repetitive samples are flagged using LLM-based prompts and manually reviewed. Samples scoring below a stricter threshold (e.g., 3) are excluded to avoid repetitive patterns.1263. **Heuristic Rule-Based Filtering**: Anomalies like abnormal sentence lengths or duplicate lines are detected using rules. Flagged samples undergo manual verification to ensure accuracy before removal.127 128For **multimodal data**, two strategies are used:129 1301. **Repetition Detection**: Repetitive samples in non-academic datasets are flagged and manually reviewed to prevent pattern loops. High-quality datasets are exempt from this process.1312. **Heuristic Rule-Based Filtering**: Similar rules are applied to detect visual anomalies, with flagged data verified manually to maintain integrity.132 133#### Training Data134 135As shown in the following figure, from InternVL 1.5 to 2.0 and then to 2.5, the fine-tuning data mixture has undergone iterative improvements in scale, quality, and diversity. For more information about the training data, please refer to our technical report.136 137![image/png](https://cdn-uploads.huggingface.co/production/uploads/64119264f0f81eb569e0d569/GaTY9Lde02YzclASMthDa.png)138 139## Evaluation on Multimodal Capability140 141### Multimodal Reasoning and Mathematics142 143![image/png](https://cdn-uploads.huggingface.co/production/uploads/64119264f0f81eb569e0d569/ihFWMRHbF0lpFTkLqnnj1.png)144 145![image/png](https://cdn-uploads.huggingface.co/production/uploads/64119264f0f81eb569e0d569/Nrzq0kjlitjp_jrJCqtwX.png)146 147### OCR, Chart, and Document Understanding148 149![image/png](https://cdn-uploads.huggingface.co/production/uploads/64119264f0f81eb569e0d569/3yCMoLjlbsqY7ZJViGzih.png)150 151### Multi-Image & Real-World Comprehension152 153![image/png](https://cdn-uploads.huggingface.co/production/uploads/64119264f0f81eb569e0d569/DSnalmEyhDVQ9GE0GPCla.png)154 155### Comprehensive Multimodal & Hallucination Evaluation156 157![image/png](https://cdn-uploads.huggingface.co/production/uploads/64119264f0f81eb569e0d569/Z7Raj3TGDiV1H81pDHtoG.png)158 159### Visual Grounding160 161![image/png](https://cdn-uploads.huggingface.co/production/uploads/64119264f0f81eb569e0d569/lPcIrng8MPSg_PM1hpDPt.png)162 163### Multimodal Multilingual Understanding164 165![image/png](https://cdn-uploads.huggingface.co/production/uploads/64119264f0f81eb569e0d569/BPpbAOX36RV8RTnm3j-gs.png)166 167### Video Understanding168 169![image/png](https://cdn-uploads.huggingface.co/production/uploads/64006c09330a45b03605bba3/tcwH-i1qc8H16En-7AZ5M.png)170 171## Evaluation on Language Capability172 173Training InternVL 2.0 models led to a decline in pure language capabilities. InternVL 2.5 addresses this by collecting more high-quality open-source data and filtering out low-quality data, achieving better preservation of pure language performance.174 175![image/png](https://cdn-uploads.huggingface.co/production/uploads/64119264f0f81eb569e0d569/mxuSKvSY-kfI8zePpXj6y.png)176 177## Quick Start178 179We provide an example code to run `InternVL2_5-2B` using `transformers`.180 181> Please use transformers>=4.37.2 to ensure the model works normally.182 183### Model Loading184 185#### 16-bit (bf16 / fp16)186 187```python188import torch189from transformers import AutoTokenizer, AutoModel190path = "OpenGVLab/InternVL2_5-2B"191model = AutoModel.from_pretrained(192    path,193    torch_dtype=torch.bfloat16,194    low_cpu_mem_usage=True,195    use_flash_attn=True,196    trust_remote_code=True).eval().cuda()197```198 199#### BNB 8-bit Quantization200 201```python202import torch203from transformers import AutoTokenizer, AutoModel204path = "OpenGVLab/InternVL2_5-2B"205model = AutoModel.from_pretrained(206    path,207    torch_dtype=torch.bfloat16,208    load_in_8bit=True,209    low_cpu_mem_usage=True,210    use_flash_attn=True,211    trust_remote_code=True).eval()212```213 214#### Multiple GPUs215 216The reason for writing the code this way is to avoid errors that occur during multi-GPU inference due to tensors not being on the same device. By ensuring that the first and last layers of the large language model (LLM) are on the same device, we prevent such errors.217 218```python219import math220import torch221from transformers import AutoTokenizer, AutoModel222 223def split_model(model_name):224    device_map = {}225    world_size = torch.cuda.device_count()226    num_layers = {227        'InternVL2_5-1B': 24, 'InternVL2_5-2B': 24, 'InternVL2_5-4B': 36, 'InternVL2_5-8B': 32,228        'InternVL2_5-26B': 48, 'InternVL2_5-38B': 64, 'InternVL2_5-78B': 80}[model_name]229    # Since the first GPU will be used for ViT, treat it as half a GPU.230    num_layers_per_gpu = math.ceil(num_layers / (world_size - 0.5))231    num_layers_per_gpu = [num_layers_per_gpu] * world_size232    num_layers_per_gpu[0] = math.ceil(num_layers_per_gpu[0] * 0.5)233    layer_cnt = 0234    for i, num_layer in enumerate(num_layers_per_gpu):235        for j in range(num_layer):236            device_map[f'language_model.model.layers.{layer_cnt}'] = i237            layer_cnt += 1238    device_map['vision_model'] = 0239    device_map['mlp1'] = 0240    device_map['language_model.model.tok_embeddings'] = 0241    device_map['language_model.model.embed_tokens'] = 0242    device_map['language_model.output'] = 0243    device_map['language_model.model.norm'] = 0244    device_map['language_model.model.rotary_emb'] = 0245    device_map['language_model.lm_head'] = 0246    device_map[f'language_model.model.layers.{num_layers - 1}'] = 0247 248    return device_map249 250path = "OpenGVLab/InternVL2_5-2B"251device_map = split_model('InternVL2_5-2B')252model = AutoModel.from_pretrained(253    path,254    torch_dtype=torch.bfloat16,255    low_cpu_mem_usage=True,256    use_flash_attn=True,257    trust_remote_code=True,258    device_map=device_map).eval()259```260 261### Inference with Transformers262 263```python264import numpy as np265import torch266import torchvision.transforms as T267from decord import VideoReader, cpu268from PIL import Image269from torchvision.transforms.functional import InterpolationMode270from transformers import AutoModel, AutoTokenizer271 272IMAGENET_MEAN = (0.485, 0.456, 0.406)273IMAGENET_STD = (0.229, 0.224, 0.225)274 275def build_transform(input_size):276    MEAN, STD = IMAGENET_MEAN, IMAGENET_STD277    transform = T.Compose([278        T.Lambda(lambda img: img.convert('RGB') if img.mode != 'RGB' else img),279        T.Resize((input_size, input_size), interpolation=InterpolationMode.BICUBIC),280        T.ToTensor(),281        T.Normalize(mean=MEAN, std=STD)282    ])283    return transform284 285def find_closest_aspect_ratio(aspect_ratio, target_ratios, width, height, image_size):286    best_ratio_diff = float('inf')287    best_ratio = (1, 1)288    area = width * height289    for ratio in target_ratios:290        target_aspect_ratio = ratio[0] / ratio[1]291        ratio_diff = abs(aspect_ratio - target_aspect_ratio)292        if ratio_diff < best_ratio_diff:293            best_ratio_diff = ratio_diff294            best_ratio = ratio295        elif ratio_diff == best_ratio_diff:296            if area > 0.5 * image_size * image_size * ratio[0] * ratio[1]:297                best_ratio = ratio298    return best_ratio299 300def dynamic_preprocess(image, min_num=1, max_num=12, image_size=448, use_thumbnail=False):301    orig_width, orig_height = image.size302    aspect_ratio = orig_width / orig_height303 304    # calculate the existing image aspect ratio305    target_ratios = set(306        (i, j) for n in range(min_num, max_num + 1) for i in range(1, n + 1) for j in range(1, n + 1) if307        i * j <= max_num and i * j >= min_num)308    target_ratios = sorted(target_ratios, key=lambda x: x[0] * x[1])309 310    # find the closest aspect ratio to the target311    target_aspect_ratio = find_closest_aspect_ratio(312        aspect_ratio, target_ratios, orig_width, orig_height, image_size)313 314    # calculate the target width and height315    target_width = image_size * target_aspect_ratio[0]316    target_height = image_size * target_aspect_ratio[1]317    blocks = target_aspect_ratio[0] * target_aspect_ratio[1]318 319    # resize the image320    resized_img = image.resize((target_width, target_height))321    processed_images = []322    for i in range(blocks):323        box = (324            (i % (target_width // image_size)) * image_size,325            (i // (target_width // image_size)) * image_size,326            ((i % (target_width // image_size)) + 1) * image_size,327            ((i // (target_width // image_size)) + 1) * image_size328        )329        # split the image330        split_img = resized_img.crop(box)331        processed_images.append(split_img)332    assert len(processed_images) == blocks333    if use_thumbnail and len(processed_images) != 1:334        thumbnail_img = image.resize((image_size, image_size))335        processed_images.append(thumbnail_img)336    return processed_images337 338def load_image(image_file, input_size=448, max_num=12):339    image = Image.open(image_file).convert('RGB')340    transform = build_transform(input_size=input_size)341    images = dynamic_preprocess(image, image_size=input_size, use_thumbnail=True, max_num=max_num)342    pixel_values = [transform(image) for image in images]343    pixel_values = torch.stack(pixel_values)344    return pixel_values345 346# If you want to load a model using multiple GPUs, please refer to the `Multiple GPUs` section.347path = 'OpenGVLab/InternVL2_5-2B'348model = AutoModel.from_pretrained(349    path,350    torch_dtype=torch.bfloat16,351    low_cpu_mem_usage=True,352    use_flash_attn=True,353    trust_remote_code=True).eval().cuda()354tokenizer = AutoTokenizer.from_pretrained(path, trust_remote_code=True, use_fast=False)355 356# set the max number of tiles in `max_num`357pixel_values = load_image('./examples/image1.jpg', max_num=12).to(torch.bfloat16).cuda()358generation_config = dict(max_new_tokens=1024, do_sample=True)359 360# pure-text conversation (纯文本对话)361question = 'Hello, who are you?'362response, history = model.chat(tokenizer, None, question, generation_config, history=None, return_history=True)363print(f'User: {question}\nAssistant: {response}')364 365question = 'Can you tell me a story?'366response, history = model.chat(tokenizer, None, question, generation_config, history=history, return_history=True)367print(f'User: {question}\nAssistant: {response}')368 369# single-image single-round conversation (单图单轮对话)370question = '<image>\nPlease describe the image shortly.'371response = model.chat(tokenizer, pixel_values, question, generation_config)372print(f'User: {question}\nAssistant: {response}')373 374# single-image multi-round conversation (单图多轮对话)375question = '<image>\nPlease describe the image in detail.'376response, history = model.chat(tokenizer, pixel_values, question, generation_config, history=None, return_history=True)377print(f'User: {question}\nAssistant: {response}')378 379question = 'Please write a poem according to the image.'380response, history = model.chat(tokenizer, pixel_values, question, generation_config, history=history, return_history=True)381print(f'User: {question}\nAssistant: {response}')382 383# multi-image multi-round conversation, combined images (多图多轮对话,拼接图像)384pixel_values1 = load_image('./examples/image1.jpg', max_num=12).to(torch.bfloat16).cuda()385pixel_values2 = load_image('./examples/image2.jpg', max_num=12).to(torch.bfloat16).cuda()386pixel_values = torch.cat((pixel_values1, pixel_values2), dim=0)387 388question = '<image>\nDescribe the two images in detail.'389response, history = model.chat(tokenizer, pixel_values, question, generation_config,390                               history=None, return_history=True)391print(f'User: {question}\nAssistant: {response}')392 393question = 'What are the similarities and differences between these two images.'394response, history = model.chat(tokenizer, pixel_values, question, generation_config,395                               history=history, return_history=True)396print(f'User: {question}\nAssistant: {response}')397 398# multi-image multi-round conversation, separate images (多图多轮对话,独立图像)399pixel_values1 = load_image('./examples/image1.jpg', max_num=12).to(torch.bfloat16).cuda()400pixel_values2 = load_image('./examples/image2.jpg', max_num=12).to(torch.bfloat16).cuda()401pixel_values = torch.cat((pixel_values1, pixel_values2), dim=0)402num_patches_list = [pixel_values1.size(0), pixel_values2.size(0)]403 404question = 'Image-1: <image>\nImage-2: <image>\nDescribe the two images in detail.'405response, history = model.chat(tokenizer, pixel_values, question, generation_config,406                               num_patches_list=num_patches_list,407                               history=None, return_history=True)408print(f'User: {question}\nAssistant: {response}')409 410question = 'What are the similarities and differences between these two images.'411response, history = model.chat(tokenizer, pixel_values, question, generation_config,412                               num_patches_list=num_patches_list,413                               history=history, return_history=True)414print(f'User: {question}\nAssistant: {response}')415 416# batch inference, single image per sample (单图批处理)417pixel_values1 = load_image('./examples/image1.jpg', max_num=12).to(torch.bfloat16).cuda()418pixel_values2 = load_image('./examples/image2.jpg', max_num=12).to(torch.bfloat16).cuda()419num_patches_list = [pixel_values1.size(0), pixel_values2.size(0)]420pixel_values = torch.cat((pixel_values1, pixel_values2), dim=0)421 422questions = ['<image>\nDescribe the image in detail.'] * len(num_patches_list)423responses = model.batch_chat(tokenizer, pixel_values,424                             num_patches_list=num_patches_list,425                             questions=questions,426                             generation_config=generation_config)427for question, response in zip(questions, responses):428    print(f'User: {question}\nAssistant: {response}')429 430# video multi-round conversation (视频多轮对话)431def get_index(bound, fps, max_frame, first_idx=0, num_segments=32):432    if bound:433        start, end = bound[0], bound[1]434    else:435        start, end = -100000, 100000436    start_idx = max(first_idx, round(start * fps))437    end_idx = min(round(end * fps), max_frame)438    seg_size = float(end_idx - start_idx) / num_segments439    frame_indices = np.array([440        int(start_idx + (seg_size / 2) + np.round(seg_size * idx))441        for idx in range(num_segments)442    ])443    return frame_indices444 445def load_video(video_path, bound=None, input_size=448, max_num=1, num_segments=32):446    vr = VideoReader(video_path, ctx=cpu(0), num_threads=1)447    max_frame = len(vr) - 1448    fps = float(vr.get_avg_fps())449 450    pixel_values_list, num_patches_list = [], []451    transform = build_transform(input_size=input_size)452    frame_indices = get_index(bound, fps, max_frame, first_idx=0, num_segments=num_segments)453    for frame_index in frame_indices:454        img = Image.fromarray(vr[frame_index].asnumpy()).convert('RGB')455        img = dynamic_preprocess(img, image_size=input_size, use_thumbnail=True, max_num=max_num)456        pixel_values = [transform(tile) for tile in img]457        pixel_values = torch.stack(pixel_values)458        num_patches_list.append(pixel_values.shape[0])459        pixel_values_list.append(pixel_values)460    pixel_values = torch.cat(pixel_values_list)461    return pixel_values, num_patches_list462 463video_path = './examples/red-panda.mp4'464pixel_values, num_patches_list = load_video(video_path, num_segments=8, max_num=1)465pixel_values = pixel_values.to(torch.bfloat16).cuda()466video_prefix = ''.join([f'Frame{i+1}: <image>\n' for i in range(len(num_patches_list))])467question = video_prefix + 'What is the red panda doing?'468# Frame1: <image>\nFrame2: <image>\n...\nFrame8: <image>\n{question}469response, history = model.chat(tokenizer, pixel_values, question, generation_config,470                               num_patches_list=num_patches_list, history=None, return_history=True)471print(f'User: {question}\nAssistant: {response}')472 473question = 'Describe this video in detail.'474response, history = model.chat(tokenizer, pixel_values, question, generation_config,475                               num_patches_list=num_patches_list, history=history, return_history=True)476print(f'User: {question}\nAssistant: {response}')477```478 479#### Streaming Output480 481Besides this method, you can also use the following code to get streamed output.482 483```python484from transformers import TextIteratorStreamer485from threading import Thread486 487# Initialize the streamer488streamer = TextIteratorStreamer(tokenizer, skip_prompt=True, skip_special_tokens=True, timeout=10)489# Define the generation configuration490generation_config = dict(max_new_tokens=1024, do_sample=False, streamer=streamer)491# Start the model chat in a separate thread492thread = Thread(target=model.chat, kwargs=dict(493    tokenizer=tokenizer, pixel_values=pixel_values, question=question,494    history=None, return_history=False, generation_config=generation_config,495))496thread.start()497 498# Initialize an empty string to store the generated text499generated_text = ''500# Loop through the streamer to get the new text as it is generated501for new_text in streamer:502    if new_text == model.conv_template.sep:503        break504    generated_text += new_text505    print(new_text, end='', flush=True)  # Print each new chunk of generated text on the same line506```507 508## Finetune509 510Many repositories now support fine-tuning of the InternVL series models, including [InternVL](https://github.com/OpenGVLab/InternVL), [SWIFT](https://github.com/modelscope/ms-swift), [XTurner](https://github.com/InternLM/xtuner), and others. Please refer to their documentation for more details on fine-tuning.511 512## Deployment513 514### LMDeploy515 516LMDeploy is a toolkit for compressing, deploying, and serving LLMs & VLMs.517 518```sh519pip install lmdeploy>=0.6.4520```521 522LMDeploy abstracts the complex inference process of multi-modal Vision-Language Models (VLM) into an easy-to-use pipeline, similar to the Large Language Model (LLM) inference pipeline.523 524#### A 'Hello, world' Example525 526```python527from lmdeploy import pipeline, TurbomindEngineConfig528from lmdeploy.vl import load_image529 530model = 'OpenGVLab/InternVL2_5-2B'531image = load_image('https://raw.githubusercontent.com/open-mmlab/mmdeploy/main/tests/data/tiger.jpeg')532pipe = pipeline(model, backend_config=TurbomindEngineConfig(session_len=8192))533response = pipe(('describe this image', image))534print(response.text)535```536 537If `ImportError` occurs while executing this case, please install the required dependency packages as prompted.538 539#### Multi-images Inference540 541When dealing with multiple images, you can put them all in one list. Keep in mind that multiple images will lead to a higher number of input tokens, and as a result, the size of the context window typically needs to be increased.542 543```python544from lmdeploy import pipeline, TurbomindEngineConfig545from lmdeploy.vl import load_image546from lmdeploy.vl.constants import IMAGE_TOKEN547 548model = 'OpenGVLab/InternVL2_5-2B'549pipe = pipeline(model, backend_config=TurbomindEngineConfig(session_len=8192))550 551image_urls=[552    'https://raw.githubusercontent.com/open-mmlab/mmdeploy/main/demo/resources/human-pose.jpg',553    'https://raw.githubusercontent.com/open-mmlab/mmdeploy/main/demo/resources/det.jpg'554]555 556images = [load_image(img_url) for img_url in image_urls]557# Numbering images improves multi-image conversations558response = pipe((f'Image-1: {IMAGE_TOKEN}\nImage-2: {IMAGE_TOKEN}\ndescribe these two images', images))559print(response.text)560```561 562#### Batch Prompts Inference563 564Conducting inference with batch prompts is quite straightforward; just place them within a list structure:565 566```python567from lmdeploy import pipeline, TurbomindEngineConfig568from lmdeploy.vl import load_image569 570model = 'OpenGVLab/InternVL2_5-2B'571pipe = pipeline(model, backend_config=TurbomindEngineConfig(session_len=8192))572 573image_urls=[574    "https://raw.githubusercontent.com/open-mmlab/mmdeploy/main/demo/resources/human-pose.jpg",575    "https://raw.githubusercontent.com/open-mmlab/mmdeploy/main/demo/resources/det.jpg"576]577prompts = [('describe this image', load_image(img_url)) for img_url in image_urls]578response = pipe(prompts)579print(response)580```581 582#### Multi-turn Conversation583 584There are two ways to do the multi-turn conversations with the pipeline. One is to construct messages according to the format of OpenAI and use above introduced method, the other is to use the `pipeline.chat` interface.585 586```python587from lmdeploy import pipeline, TurbomindEngineConfig, GenerationConfig588from lmdeploy.vl import load_image589 590model = 'OpenGVLab/InternVL2_5-2B'591pipe = pipeline(model, backend_config=TurbomindEngineConfig(session_len=8192))592 593image = load_image('https://raw.githubusercontent.com/open-mmlab/mmdeploy/main/demo/resources/human-pose.jpg')594gen_config = GenerationConfig(top_k=40, top_p=0.8, temperature=0.8)595sess = pipe.chat(('describe this image', image), gen_config=gen_config)596print(sess.response.text)597sess = pipe.chat('What is the woman doing?', session=sess, gen_config=gen_config)598print(sess.response.text)599```600 601#### Service602 603LMDeploy's `api_server` enables models to be easily packed into services with a single command. The provided RESTful APIs are compatible with OpenAI's interfaces. Below are an example of service startup:604 605```shell606lmdeploy serve api_server OpenGVLab/InternVL2_5-2B --server-port 23333607```608 609To use the OpenAI-style interface, you need to install OpenAI:610 611```shell612pip install openai613```614 615Then, use the code below to make the API call:616 617```python618from openai import OpenAI619 620client = OpenAI(api_key='YOUR_API_KEY', base_url='http://0.0.0.0:23333/v1')621model_name = client.models.list().data[0].id622response = client.chat.completions.create(623    model=model_name,624    messages=[{625        'role':626        'user',627        'content': [{628            'type': 'text',629            'text': 'describe this image',630        }, {631            'type': 'image_url',632            'image_url': {633                'url':634                'https://modelscope.oss-cn-beijing.aliyuncs.com/resource/tiger.jpeg',635            },636        }],637    }],638    temperature=0.8,639    top_p=0.8)640print(response)641```642 643## License644 645This project is released under the MIT License. This project uses the pre-trained internlm2_5-1_8b-chat as a component, which is licensed under the Apache License 2.0.646 647## Citation648 649If you find this project useful in your research, please consider citing:650 651```BibTeX652@article{chen2024expanding,653  title={Expanding Performance Boundaries of Open-Source Multimodal Models with Model, Data, and Test-Time Scaling},654  author={Chen, Zhe and Wang, Weiyun and Cao, Yue and Liu, Yangzhou and Gao, Zhangwei and Cui, Erfei and Zhu, Jinguo and Ye, Shenglong and Tian, Hao and Liu, Zhaoyang and others},655  journal={arXiv preprint arXiv:2412.05271},656  year={2024}657}658@article{gao2024mini,659  title={Mini-internvl: A flexible-transfer pocket multimodal model with 5\% parameters and 90\% performance},660  author={Gao, Zhangwei and Chen, Zhe and Cui, Erfei and Ren, Yiming and Wang, Weiyun and Zhu, Jinguo and Tian, Hao and Ye, Shenglong and He, Junjun and Zhu, Xizhou and others},661  journal={arXiv preprint arXiv:2410.16261},662  year={2024}663}664@article{chen2024far,665  title={How Far Are We to GPT-4V? Closing the Gap to Commercial Multimodal Models with Open-Source Suites},666  author={Chen, Zhe and Wang, Weiyun and Tian, Hao and Ye, Shenglong and Gao, Zhangwei and Cui, Erfei and Tong, Wenwen and Hu, Kongzhi and Luo, Jiapeng and Ma, Zheng and others},667  journal={arXiv preprint arXiv:2404.16821},668  year={2024}669}670@inproceedings{chen2024internvl,671  title={Internvl: Scaling up vision foundation models and aligning for generic visual-linguistic tasks},672  author={Chen, Zhe and Wu, Jiannan and Wang, Wenhai and Su, Weijie and Chen, Guo and Xing, Sen and Zhong, Muyan and Zhang, Qinglong and Zhu, Xizhou and Lu, Lewei and others},673  booktitle={Proceedings of the IEEE/CVF Conference on Computer Vision and Pattern Recognition},674  pages={24185--24198},675  year={2024}676}677```678