☰
多图对话的两种玩法:InternVL3-78B-Pretrained拼接图像与独立图像详解
2026/10/22 1:42:18 网站建设 项目流程

【免费下载链接】InternVL3-78B-Pretrained

项目地址:https://ai.gitcode.com/OpenGVLab/InternVL3-78B-Pretrained
点击查看免费下载

InternVL3-78B-Pretrained是书生(InternVL)系列的多模态大语言模型(MLLM),支持一次对话中同时理解多张图片。本文将带你快速搞懂它在多图对话时的两种官方玩法:拼接图像(combined images)与独立图像(separate images)——何时该用哪种、num_patches_list参数到底在做什么、以及两种写法的完整示例。

一、先搞懂:动态分辨率决定了"每张图有多少块"

在讲玩法之前,先理解一个关键机制,它是两种玩法差异的根源。

InternVL3 采用动态分辨率策略:一张图会被切成若干个 448×448 像素的 tile(块),图片越大、比例越"方",切出的块数越多;若开启了use_thumbnail(本项目配置为开启),还会额外追加一张缩略图作为"全局视角"。

也就是说,每张图贡献给模型的视觉块数(patch 数)是不一样的。config.json 中的max_dynamic_patch: 12表示单张图最多切 12 块。

image1.jpg ──> [tile][tile][tile][thumb] → 4 个视觉块 image2.jpg ──> [tile][tile][thumb] → 3 个视觉块

模型内部用<IMG_CONTEXT>占位符来承接这些视觉块,占位符的个数必须和实际切出的块数严格对应。这正是"拼接"与"独立"两种写法分歧所在。

二、玩法一:拼接图像(combined images)

什么时候用?

把多张图的视觉块首尾相接成一个整体,在提问中只放一个<image>占位符。此时模型会把所有视觉内容当作"一张大拼图"来理解,写法最简单。

关键步骤

  1. 分别加载两张图(load_image已内置动态切块逻辑);
  2. 用torch.cat在维度 0 上拼接,得到合并的pixel_values;
  3. 提问中只写一个<image>,不需要传num_patches_list——chat 方法 内部默认把所有视觉块算作一张图:
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)

完整可运行示例见 README.md。

特点

  • ✅ 写法最少,一个<image>搞定;
  • ⚠️ 模型无法从结构上区分哪些块来自图1、哪些来自图2,做"两张图的相似/差异对比"时,指代可能不够精确;
  • ⚠️ 若某张图恰好是单块,其缩略图与主 tile 内容相近,拼接后信息略有冗余。

三、玩法二:独立图像(separate images)

什么时候用?

当你需要模型明确区分每张图(比如"图1和图2有什么不同"),就应使用独立图像模式。核心是给model.chat传一个num_patches_list参数,声明"前 N 块属于图1,后 M 块属于图2"。

关键步骤

  1. 拼接视觉块时,记下每张图各自的块数;
  2. 提问中为每张图各放一个<image>,并加上Image-1:、Image-2:这样的编号提示;
  3. 把块数列表传给num_patches_list:
pixel_values = torch.cat((pixel_values1, pixel_values2), dim=0) num_patches_list = [pixel_values1.size(0), pixel_values2.size(0)] # 如 [4, 3] 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)

完整示例见 README.md。

内部发生了什么?

在 modeling_internvl_chat.py 中,chat方法会按num_patches_list逐个替换每个<image>占位符:每替换一个,就为该图展开对应数量的<IMG_CONTEXT>token。例如num_patches_list=[4, 3]时:

  • 第 1 个<image>→<img>+ 4×256 个<IMG_CONTEXT>+</img>
  • 第 2 个<image>→<img>+ 3×256 个<IMG_CONTEXT>+</img>

这样每个图的视觉块就被"框"在各自的<img></img>边界内,模型天然知道图的边界在哪里。若传错块数(总数对不上),第 262 行 的assert会直接报错提醒你。

四、选型对比:一张表看懂该选哪个

对比维度拼接图像(combined)独立图像(separate)
提问中的占位符1 个<image>每张图 1 个<image>
是否需要num_patches_list否(默认全部算一张图)必须,且总数要等于视觉块总数
图片边界感知弱,视为一张"大图"强,<img></img>明确分隔
适合场景整体描述、氛围理解图片对比、"图1是什么/图2是什么"类问答
写法复杂度⭐ 最简单⭐⭐ 多一步记录块数

💡经验法则:做图片对比(相似点/差异点)时优先用独立图像模式;只是让模型"综合看看这几张图"时,拼接模式足够且更省事。

五、环境准备与上手清单

在跑多图对话之前,先确认这几件事:

  • 硬件:load_in_8bit=True时约需 2 张 80GB 显卡;16-bit(bf16)至少 3 张 80GB 显卡(见 README.md);
  • 依赖:transformers>=4.37.2,并设置trust_remote_code=True加载本仓库的自定义代码;
  • 上下文长度:多图意味着视觉 token 更多,必要时调大session_len/上下文窗口;
  • 批量与视频场景:batch_chat与视频多轮对话同样依赖num_patches_list来划分每个样本的视觉块,用法与本文一致。

六、相关文件速查

内容路径
快速开始与完整多图示例README.md
chat/batch_chat多图实现源码modeling_internvl_chat.py
动态分辨率配置(max_dynamic_patch、use_thumbnail)config.json
视觉塔(ViT)实现modeling_intern_vit.py
对话模板定义conversation.py
示例图片 1examples/image1.jpg
示例图片 2examples/image2.jpg

掌握"拼接"与"独立"这两种多图对话方式后,你就能充分发挥 InternVL3-78B-Pretrained 的多图理解能力:简单场景用最省事的拼接模式,对比分析类任务则切换到带num_patches_list的独立模式,让模型真正看清"哪张是哪张"。

【免费下载链接】InternVL3-78B-Pretrained

项目地址:https://ai.gitcode.com/OpenGVLab/InternVL3-78B-Pretrained
点击查看免费下载
上一篇:深度解析Script-IDE:Godot脚本编辑器的架构级性能优化方案
下一篇:如何快速使用Motion-X数据集:10分钟入门教程 - 终极指南

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询