【AI大模型前沿】InternVL:OpenGVLab开源多模态大模型,解锁视觉问答与多语言翻译的全能应用图鉴

发布于:2025-05-23 ⋅ 阅读:(17) ⋅ 点赞:(0)

系列篇章💥

No. 文章
1 【AI大模型前沿】深度剖析瑞智病理大模型 RuiPath:如何革新癌症病理诊断技术
2 【AI大模型前沿】清华大学 CLAMP-3:多模态技术引领音乐检索新潮流
3 【AI大模型前沿】浙大携手阿里推出HealthGPT:医学视觉语言大模型助力智能医疗新突破
4 【AI大模型前沿】阿里 QwQ-32B:320 亿参数推理大模型,性能比肩 DeepSeek-R1,免费开源
5 【AI大模型前沿】TRELLIS:微软、清华、中科大联合推出的高质量3D生成模型
6 【AI大模型前沿】Migician:清华、北大、华科联手打造的多图像定位大模型,一键解决安防监控与自动驾驶难题
7 【AI大模型前沿】DeepSeek-V3-0324:AI 模型的全面升级与技术突破
8 【AI大模型前沿】BioMedGPT-R1:清华联合水木分子打造的多模态生物医药大模型,开启智能研发新纪元
9 【AI大模型前沿】DiffRhythm:西北工业大学打造的10秒铸就完整歌曲的AI歌曲生成模型
10 【AI大模型前沿】R1-Omni:阿里开源全模态情感识别与强化学习的创新结合
11 【AI大模型前沿】Qwen2.5-Omni:阿里巴巴的多模态大模型,实现看、听、说、写一体化
12 【AI大模型前沿】SmolDocling:256M参数的轻量级多模态文档处理利器,10分钟搞定百页PDF
13 【AI大模型前沿】Stable Virtual Camera:Stability AI 推出的2D图像转3D视频模型,一键生成沉浸式视频
14 【AI大模型前沿】阿里 Qwen3 震撼开源,模型新王诞生,开启全球大模型新纪元
15 【AI大模型前沿】InternVL:OpenGVLab开源多模态大模型,解锁视觉问答与多语言翻译的全能应用图鉴


前言

在人工智能领域,多模态大模型的发展正以前所未有的速度改变着我们与技术的交互方式。从视觉到语言,从图像到文本,多模态模型正逐渐成为连接人类感知与机器理解的桥梁。今天,我们将深入探讨一个备受瞩目的开源多模态大模型——InternVL。由OpenGVLab推出,InternVL凭借其强大的技术架构和广泛的应用场景,正在成为多模态领域的重要力量。本文将从项目概述、技术原理、功能特点、应用场景、部署使用等多个方面,全面剖析InternVL,帮助读者快速了解这一前沿技术。

一、项目概述

InternVL 是上海人工智能实验室 OpenGVLab推出的一款开源多模态大模型,旨在通过融合视觉与语言信息,实现高效、灵活的多模态交互。它采用了先进的“ViT-MLP-LLM”架构,通过动态高分辨率处理、像素洗牌等技术,能够高效处理高分辨率图像和视频数据,同时支持多语言处理和多种模态输入输出。InternVL在视觉问答、文档理解、多语言翻译等任务上表现出色,广泛应用于教育、电商、智能客服等领域。其开源特性促进了学术界和工业界的交流与合作,推动了多模态技术的创新和应用。

在这里插入图片描述

二、技术原理

(一)核心架构

InternVL采用了先进的多模态融合架构,其核心组件包括视觉编码器(Vision Encoder)、MLP投影器(MLP Projector)和语言模型(LLM)。

  1. 视觉编码器(Vision Encoder):InternVL使用改进的Vision Transformer(ViT)模型作为视觉编码器,例如InternViT。这种模型能够将输入的图像或视频转换为高维特征向量,从而提取出丰富的视觉信息。
  2. MLP投影器(MLP Projector):该组件的作用是将视觉特征映射到与语言模型相同的特征空间,使得视觉信息和语言信息能够有效地融合。
  3. 语言模型(LLM):基于InternLM的语言模型是InternVL的核心部分,负责处理文本输入和生成文本输出。

(二)创新技术

InternVL在技术上引入了多项创新,以提升模型的性能和效率。

  1. 动态高分辨率(Dynamic High Resolution):通过将图像分割成多个小块(瓦片),并动态调整分辨率,InternVL能够高效处理高分辨率图像,同时保持计算效率。
  2. 像素洗牌(Pixel Shuffle):该技术通过减少视觉标记的数量,降低计算复杂度,同时保留图像的细节信息。
  3. 渐进式训练策略(Progressive Training Strategy):InternVL采用了一种渐进式训练策略,先使用小模型在大量带噪数据上进行预训练,再用大模型在精选数据上进行对齐。这种策略能够有效减少训练资源的消耗。

三、功能特点

(一)多模态输入与输出

InternVL支持多种模态的输入和输出,包括文本、图像、视频等。它可以处理复杂的多模态任务,例如视觉问答(VQA)、文档理解(DocVQA)和信息图表问答(ChartQA)。

(二)多语言支持

InternVL支持多语言处理,能够处理和生成多种语言的文本。这一特性使得InternVL在跨语言交流和国际商务中具有广阔的应用前景。

(三)高效处理高分辨率图像

通过动态高分辨率技术和像素洗牌技术,InternVL能够高效处理高分辨率图像,同时保持计算效率。

(四)强大的视觉和语言理解能力

InternVL在多个基准测试中表现出色,例如在MMMU benchmark上得分超过70,显示了其强大的视觉和语言理解能力。

四、应用场景

(一)视觉问答(VQA)

InternVL能够处理与图像或视频内容相关的问题,广泛应用于教育、电子商务和客户服务等领域。

(二)文档和图表理解

InternVL在文档理解(DocVQA)和信息图表问答(ChartQA)任务中表现出色,能够提取文档中的关键信息,解析表格和图表,生成文档摘要或图表解释。

(三)多语言翻译和理解

InternVL支持多语言处理,能够处理和生成多种语言的文本,在跨语言交流和国际商务中具有广阔的应用前景。

(四)图像和视频分析

InternVL可用于自动标注、分类和理解图像和视频内容。在安防监控领域,它可以实时分析监控视频,识别异常行为;在内容审核方面,能够快速识别违规内容。

(五)智能客服

InternVL可以作为智能客服的核心技术,支持多模态交互。用户可以通过上传图片或视频描述问题,模型能够理解并提供解决方案。

五、部署使用

(一)环境准备

在部署InternVL之前,需要确保系统满足以下基本要求:

  • 硬件环境:推荐使用具有高性能GPU的服务器,以加速模型的推理过程。
  • 软件环境:需要安装Python、PyTorch等基础软件,并确保版本兼容。

(二)安装步骤

  1. 克隆项目仓库:通过以下命令克隆InternVL的GitHub仓库:
git clone https://github.com/OpenGVLab/InternVL.git
  1. 安装依赖:进入项目目录后,运行以下命令安装所需的Python依赖:
pip install -r requirements.txt
  1. 下载模型权重
git lfs install
git clone https://huggingface.co/OpenGVLab/InternVL2_5-8B

(三)推理示例

以InternVL2_5-8B模型为例推理如下:

import numpy as np
import torch
import torchvision.transforms as T
from decord import VideoReader, cpu
from PIL import Image
from torchvision.transforms.functional import InterpolationMode
from transformers import AutoModel, AutoTokenizer

IMAGENET_MEAN = (0.485, 0.456, 0.406)
IMAGENET_STD = (0.229, 0.224, 0.225)

def build_transform(input_size):
    MEAN, STD = IMAGENET_MEAN, IMAGENET_STD
    transform = T.Compose([
        T.Lambda(lambda img: img.convert('RGB') if img.mode != 'RGB' else img),
        T.Resize((input_size, input_size), interpolation=InterpolationMode.BICUBIC),
        T.ToTensor(),
        T.Normalize(mean=MEAN, std=STD)
    ])
    return transform

def find_closest_aspect_ratio(aspect_ratio, target_ratios, width, height, image_size):
    best_ratio_diff = float('inf')
    best_ratio = (1, 1)
    area = width * height
    for ratio in target_ratios:
        target_aspect_ratio = ratio[0] / ratio[1]
        ratio_diff = abs(aspect_ratio - target_aspect_ratio)
        if ratio_diff < best_ratio_diff:
            best_ratio_diff = ratio_diff
            best_ratio = ratio
        elif ratio_diff == best_ratio_diff:
            if area > 0.5 * image_size * image_size * ratio[0] * ratio[1]:
                best_ratio = ratio
    return best_ratio

def dynamic_preprocess(image, min_num=1, max_num=12, image_size=448, use_thumbnail=False):
    orig_width, orig_height = image.size
    aspect_ratio = orig_width / orig_height

    # calculate the existing image aspect ratio
    target_ratios = set(
        (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) if
        i * j <= max_num and i * j >= min_num)
    target_ratios = sorted(target_ratios, key=lambda x: x[0] * x[1])

    # find the closest aspect ratio to the target
    target_aspect_ratio = find_closest_aspect_ratio(
        aspect_ratio, target_ratios, orig_width, orig_height, image_size)

    # calculate the target width and height
    target_width = image_size * target_aspect_ratio[0]
    target_height = image_size * target_aspect_ratio[1]
    blocks = target_aspect_ratio[0] * target_aspect_ratio[1]

    # resize the image
    resized_img = image.resize((target_width, target_height))
    processed_images = []
    for i in range(blocks):
        box = (
            (i % (target_width // image_size)) * image_size,
            (i // (target_width // image_size)) * image_size,
            ((i % (target_width // image_size)) + 1) * image_size,
            ((i // (target_width // image_size)) + 1) * image_size
        )
        # split the image
        split_img = resized_img.crop(box)
        processed_images.append(split_img)
    assert len(processed_images) == blocks
    if use_thumbnail and len(processed_images) != 1:
        thumbnail_img = image.resize((image_size, image_size))
        processed_images.append(thumbnail_img)
    return processed_images

def load_image(image_file, input_size=448, max_num=12):
    image = Image.open(image_file).convert('RGB')
    transform = build_transform(input_size=input_size)
    images = dynamic_preprocess(image, image_size=input_size, use_thumbnail=True, max_num=max_num)
    pixel_values = [transform(image) for image in images]
    pixel_values = torch.stack(pixel_values)
    return pixel_values

# If you have an 80G A100 GPU, you can put the entire model on a single GPU.
# Otherwise, you need to load a model using multiple GPUs, please refer to the `Multiple GPUs` section.
path = 'OpenGVLab/InternVL2_5-8B'
model = AutoModel.from_pretrained(
    path,
    torch_dtype=torch.bfloat16,
    low_cpu_mem_usage=True,
    trust_remote_code=True).eval().cuda()
tokenizer = AutoTokenizer.from_pretrained(path, trust_remote_code=True, use_fast=False)

# set the max number of tiles in `max_num`
pixel_values = load_image('./examples/image1.jpg', max_num=12).to(torch.bfloat16).cuda()
generation_config = dict(max_new_tokens=1024, do_sample=False)

# pure-text conversation (纯文本对话)
question = 'Hello, who are you?'
response, history = model.chat(tokenizer, None, question, generation_config, history=None, return_history=True)
print(f'User: {question}\nAssistant: {response}')

question = 'Can you tell me a story?'
response, history = model.chat(tokenizer, None, question, generation_config, history=history, return_history=True)
print(f'User: {question}\nAssistant: {response}')

# single-image single-round conversation (单图单轮对话)
question = '<image>\nPlease describe the image shortly.'
response = model.chat(tokenizer, pixel_values, question, generation_config)
print(f'User: {question}\nAssistant: {response}')

# single-image multi-round conversation (单图多轮对话)
question = '<image>\nPlease describe the image in detail.'
response, history = model.chat(tokenizer, pixel_values, question, generation_config, history=None, return_history=True)
print(f'User: {question}\nAssistant: {response}')

question = 'Please write a poem according to the image.'
response, history = model.chat(tokenizer, pixel_values, question, generation_config, history=history, return_history=True)
print(f'User: {question}\nAssistant: {response}')

# multi-image multi-round conversation, combined images (多图多轮对话,拼接图像)
pixel_values1 = load_image('./examples/image1.jpg', max_num=12).to(torch.bfloat16).cuda()
pixel_values2 = load_image('./examples/image2.jpg', max_num=12).to(torch.bfloat16).cuda()
pixel_values = torch.cat((pixel_values1, pixel_values2), dim=0)

question = '<image>\nDescribe the two images in detail.'
response, history = model.chat(tokenizer, pixel_values, question, generation_config,
                               history=None, return_history=True)
print(f'User: {question}\nAssistant: {response}')

question = 'What are the similarities and differences between these two images.'
response, history = model.chat(tokenizer, pixel_values, question, generation_config,
                               history=history, return_history=True)
print(f'User: {question}\nAssistant: {response}')

# multi-image multi-round conversation, separate images (多图多轮对话,独立图像)
pixel_values1 = load_image('./examples/image1.jpg', max_num=12).to(torch.bfloat16).cuda()
pixel_values2 = load_image('./examples/image2.jpg', max_num=12).to(torch.bfloat16).cuda()
pixel_values = torch.cat((pixel_values1, pixel_values2), dim=0)
num_patches_list = [pixel_values1.size(0), pixel_values2.size(0)]

question = 'Image-1: <image>\nImage-2: <image>\nDescribe the two images in detail.'
response, history = model.chat(tokenizer, pixel_values, question, generation_config,
                               num_patches_list=num_patches_list,
                               history=None, return_history=True)
print(f'User: {question}\nAssistant: {response}')

question = 'What are the similarities and differences between these two images.'
response, history = model.chat(tokenizer, pixel_values, question, generation_config,
                               num_patches_list=num_patches_list,
                               history=history, return_history=True)
print(f'User: {question}\nAssistant: {response}')

# batch inference, single image per sample (单图批处理)
pixel_values1 = load_image('./examples/image1.jpg', max_num=12).to(torch.bfloat16).cuda()
pixel_values2 = load_image('./examples/image2.jpg', max_num=12).to(torch.bfloat16).cuda()
num_patches_list = [pixel_values1.size(0), pixel_values2.size(0)]
pixel_values = torch.cat((pixel_values1, pixel_values2), dim=0)

questions = ['<image>\nDescribe the image in detail.'] * len(num_patches_list)
responses = model.batch_chat(tokenizer, pixel_values,
                             num_patches_list=num_patches_list,
                             questions=questions,
                             generation_config=generation_config)
for question, response in zip(questions, responses):
    print(f'User: {question}\nAssistant: {response}')

# video multi-round conversation (视频多轮对话)
def get_index(bound, fps, max_frame, first_idx=0, num_segments=32):
    if bound:
        start, end = bound[0], bound[1]
    else:
        start, end = -100000, 100000
    start_idx = max(first_idx, round(start * fps))
    end_idx = min(round(end * fps), max_frame)
    seg_size = float(end_idx - start_idx) / num_segments
    frame_indices = np.array([
        int(start_idx + (seg_size / 2) + np.round(seg_size * idx))
        for idx in range(num_segments)
    ])
    return frame_indices

def load_video(video_path, bound=None, input_size=448, max_num=1, num_segments=32):
    vr = VideoReader(video_path, ctx=cpu(0), num_threads=1)
    max_frame = len(vr) - 1
    fps = float(vr.get_avg_fps())

    pixel_values_list, num_patches_list = [], []
    transform = build_transform(input_size=input_size)
    frame_indices = get_index(bound, fps, max_frame, first_idx=0, num_segments=num_segments)
    for frame_index in frame_indices:
        img = Image.fromarray(vr[frame_index].asnumpy()).convert('RGB')
        img = dynamic_preprocess(img, image_size=input_size, use_thumbnail=True, max_num=max_num)
        pixel_values = [transform(tile) for tile in img]
        pixel_values = torch.stack(pixel_values)
        num_patches_list.append(pixel_values.shape[0])
        pixel_values_list.append(pixel_values)
    pixel_values = torch.cat(pixel_values_list)
    return pixel_values, num_patches_list

video_path = './examples/red-panda.mp4'
pixel_values, num_patches_list = load_video(video_path, num_segments=8, max_num=1)
pixel_values = pixel_values.to(torch.bfloat16).cuda()
video_prefix = ''.join([f'Frame-{i+1}: <image>\n' for i in range(len(num_patches_list))])
question = video_prefix + 'What is the red panda doing?'
# Frame1: <image>\nFrame2: <image>\n...\nFrame8: <image>\n{question}
response, history = model.chat(tokenizer, pixel_values, question, generation_config,
                               num_patches_list=num_patches_list, history=None, return_history=True)
print(f'User: {question}\nAssistant: {response}')

question = 'Describe this video in detail.'
response, history = model.chat(tokenizer, pixel_values, question, generation_config,
                               num_patches_list=num_patches_list, history=history, return_history=True)
print(f'User: {question}\nAssistant: {response}')

六、结语

InternVL作为OpenGVLab推出的一个开源多模态大模型,凭借其强大的技术架构和广泛的应用场景,正在成为多模态领域的重要力量。它不仅在视觉问答、文档理解等任务上表现出色,还在多语言支持、图像生成等方面具备强大的能力。通过开源,InternVL希望能够促进学术界和工业界的交流与合作,加速多模态技术的创新和应用。未来,随着技术的不断进步和应用场景的不断拓展,InternVL有望在更多领域发挥更大的作用。

七、项目地址

  • GitHub仓库:https://github.com/OpenGVLab/InternVL
  • arXiv技术论文:https://arxiv.org/pdf/2312.14238
  • 在线体验Demo:https://huggingface.co/spaces/OpenGVLab/InternVL

在这里插入图片描述

🎯🔖更多专栏系列文章:AI大模型提示工程完全指南AI大模型探索之路(零基础入门)AI大模型预训练微调进阶AI大模型开源精选实践AI大模型RAG应用探索实践🔥🔥🔥 其他专栏可以查看博客主页📑

😎 作者介绍:资深程序老猿,从业10年+、互联网系统架构师,目前专注于AIGC的探索(CSDN博客之星|AIGC领域优质创作者)
📖专属社群:欢迎关注【小兵的AI视界】公众号或扫描下方👇二维码,回复‘入群’ 即刻上车,获取邀请链接。
💘领取三大专属福利:1️⃣免费赠送AI+编程📚500本,2️⃣AI技术教程副业资料1套,3️⃣DeepSeek资料教程1套🔥(限前500人)
如果文章内容对您有所触动,别忘了点赞、⭐关注,收藏!加入我们,一起携手同行AI的探索之旅,开启智能时代的大门!


网站公告

今日签到

点亮在社区的每一天
去签到