☰
InternVL3_5-8B-Flash源码精读:pixel_shuffle、Gating路由与generate_flash实现原理全解析
2026/10/16 21:01:58 网站建设 项目流程

【免费下载链接】InternVL3_5-8B-Flash

项目地址:https://ai.gitcode.com/OpenGVLab/InternVL3_5-8B-Flash
点击查看免费下载

InternVL3_5-8B-Flash 是 OpenGVLab 开源的多模态大模型(Multimodal LLM),属于 InternVL3.5 系列中面向推理效率的 Flash 变体。它引入视觉分辨率路由器(ViR, Visual Resolution Router),对每个图像分块实时决定用 64 还是 256 个视觉 token 表示,在视觉 token 数平均减少约 50% 的同时,保持接近 100% 的基础模型性能。源码中三大核心机制分别是pixel_shuffle(空间压缩)、Gating(路由决策)与generate_flash(推理流水线)。本文不堆砌代码,面向新手逐一讲清它们的实现原理。

一、模型结构总览:三大件与一个"Token 漏斗" 🧭

InternVL3_5-8B-Flash 沿用经典的 "ViT – MLP – LLM" 三段式架构(详见 README.md 的 Model Architecture 章节):

组件作用关键数字
ViT 视觉编码器(InternViT)将每个 448×448 分块编码为 1024 个视觉 tokenpatch 14×14 → 32×32 网格,即 1024 个位置
MLP 投影器(mlp1/mlp2)把视觉 token 投影到语言模型维度256-token 通路用mlp1,64-token 通路用mlp2
LLM 语言模型(Qwen3-8B)基于视觉+文本 embedding 生成回答隐藏维度 4096

两个新手必须理解的背景知识:

  1. 动态分块(Dynamic Tiling):长边图像会被切成最多 12 个 448×448 分块,并额外附加一张缩略图(见 config.json 的min_dynamic_patch/max_dynamic_patch与use_thumbnail)。每个分块独立走下面描述的"token 漏斗"。
  2. Token 漏斗 1024 → 256 → 64:ViT 对每个分块输出 1024 个 token(modeling_intern_vit.py 的InternVisionModel);InternVL3.5 基础版先压缩到256;Flash 版再根据路由结果,把部分分块进一步压到64。

二、pixel_shuffle 精读:空间换通道的三行张量重排 🔍

实现位置:modeling_internvl_chat.py。

pixel_shuffle本质是计算机视觉里的经典space-to-depth(空间转深度)操作,核心思想一句话:把相邻 2×2 的 token 合并成 1 个 token,把省下的空间分辨率"换"成通道宽度——信息没有丢弃,空间分辨率降了,每个 token 的通道数翻倍。

以scale_factor=0.5为例,输入为单分块特征[B, 32, 32, 1024]:

  1. 先按"高减半、通道翻倍"重排:[B, 32, 16, 2048],并交换宽高两维;
  2. 再做一次"宽减半、通道再翻倍":得到[B, 16, 16, 4096];
  3. 展平后即256 个 token,每个 4096 维。

Flash 版把压缩率叠乘(scale_factor = downsample_ratio ** 2 = 0.25),同一套操作得到64 个 token,每个 16384 维。两条通路对比:

通路scale_factor每分块输出 token单 token 通道数投影器
基础通路(InternVL3.5)0.52564096mlp1
Flash 压缩通路0.256416384mlp2

投影器定义在 modeling_internvl_chat.py:mlp1是两层 Linear(4096→4096),mlp2是三层更宽的 Linear(16384→8192→4096),两者都把输出统一到 LLM 的 4096 维,从而保证无论走哪条通路,LLM 看到的 token 维度一致。

💡 一个小细节:ps_version参数控制最后是否把 H/W 换回原位。v1会输出转置图像(源码中甚至有告警提示),本模型 config.json 使用v2,无需担心。

三、Gating 路由:路由器如何决定"这块图要不要压缩"

动机来自 README.md 的 Visual Consistency Learning 章节:不同图像分块的语义密度差异极大——纯色天空几乎可以极限压缩,但公式、表格的文字区域一旦压缩就会明显掉信息。ViR 因此把"压缩率选择"建模为二分类问题:

  • 类别 0:压缩到 64 token(高压缩率 1/16)
  • 类别 1:保留 256 token(低压缩率 1/4)

路由由两个模块完成,均在 modeling_internvl_chat.py:

① CrossAttentionPooling(L79-L132)——给分块写"摘要"用一个可学习的 query 向量,通过多层交叉注意力反复读取该分块全部 1024 个 token,最终把 1024 个 token 池化成一个 1024 维的摘要向量。每个分块独立处理,相当于给路由器提供了一份"这块图的信息量报告"。(实现上的细节:第 2 层起的注意力层复用同一组权重。)

② Gating(L36-L76)——输出二分类概率摘要向量先经过 4 个残差 MLP 块(1024→4096→1024,GELU + Dropout + LayerNorm)充分混合,再经一个 2 路 Linear + softmax,输出两个"专家"概率:probs[0]是"压缩到 64 token"的信心分,probs[1]是"保留 256 token"的信心分。

③ 双重阈值决策(在generate_flash内执行):

relative_threshold_value = torch.quantile(gate_result[:, 0], 0.1) gate_result = (gate_result[:, 0] > relative_threshold_value) & (gate_result[:, 0] >= 0.5)
  • 绝对阈值 0.5:压缩概率至少要 0.5,保证路由器"有把握"才动手;
  • 相对阈值(10% 分位数):概率最低的后 10% 分块一律不压缩,相当于给整张图留了"安全垫",避免极端情况把全图都压掉。

两个阈值均可配置,见 config.json 的flash_relative_threshold: 0.1与flash_absolute_threshold: 0.5。

四、generate_flash 全流程:从图像输入到 50% Token 节省 ⚡

入口是 generate_flash,外层 generate 读取配置里的flash_mode,为true时走 Flash 分支,否则走普通的generate_normal(256 token 固定压缩,即 extract_feature 通路)。

完整流水线共 5 步:

  1. 双份特征提取(extract_feature_flash):ViT 先输出每分块 1024 token;随后同一次前向里同时算出 64-token 与 256-token 两版特征,路由器再为每个分块输出二分类概率;
  2. 逐分块决策:按上一节的"双阈值"规则,给每个分块打上压缩 / 保留标记;
  3. 句级占位符压缩(compress_visual_tokens_in_sentence):prompt 中每个分块原本是 256 个连续的<IMG_CONTEXT>占位符(由num_image_token决定,L157),对需要压缩的分块只保留前 64 个槽位、标记删除其余 192 个,并同步修正 attention mask 的位置索引;
  4. 特征回填:把选中通路(64 或 256)的特征按分块顺序写入占位符;
  5. LLM 生成:把压缩后的 embedding 序列交给 Qwen3-8B 做自回归生成。

Token 节省的本质:LLM 的 prefill 计算量与 KV cache 占用都与序列长度成正比,视觉 token 减半意味着这部分开销近似减半——这正是 Flash 版在"接近 100% 性能"下显著提速的来源。

📌 两个进阶点:generate_flash支持传入visual_features参数直接接收外部算好的视觉特征,配合 README 中的 Decoupled Vision-Language Deployment(DvD,README.md)可将 ViT/MLP/路由器部署在视觉服务器上、语言服务器只跑 LLM;训练侧的forward()(L294-L371)则固定走 256-token 通路,路由与压缩只作用于推理路径。

五、关键配置与文件索引:快速定位相关代码 📌

核心参数速查(config.json):

参数值含义
flash_modetrue启用generate_flash分支
flash_relative_threshold0.1路由相对阈值(10% 分位数)
flash_absolute_threshold0.5路由绝对阈值
downsample_ratio0.5基础 pixel_shuffle 压缩比例
ps_versionv2保证空间维度顺序正确
min_dynamic_patch/max_dynamic_patch1/12动态分块数量范围
force_image_size448分块边长(像素)

源码文件索引:

文件内容
modeling_internvl_chat.py主模型:Gating路由、CrossAttentionPooling、pixel_shuffle、generate_flash
modeling_intern_vit.pyInternViT 视觉编码器(embedding、注意力、编码器层)
configuration_internvl_chat.py模型配置类(downsample_ratio、ps_version等默认值)
config.json本模型实例化的全部推理参数
conversation.py对话模板(internvl2_5 模板)
README.md使用方式、ViCO 训练策略与 DvD 部署方案

总结:InternVL3_5-8B-Flash 的"快"不是靠缩水,而是靠"按需"——pixel_shuffle提供了 256 / 64 两档无损的空间压缩手段,Gating路由器基于每个分块的语义密度做出二选一路由,generate_flash把两者串成一条推理流水线,最终在视觉 token 减少约 50% 的情况下几乎不损失回答质量。理解了这三段源码,也基本掌握了当前多模态大模型"动态视觉分辨率"这一方向的核心实现范式。

【免费下载链接】InternVL3_5-8B-Flash

项目地址:https://ai.gitcode.com/OpenGVLab/InternVL3_5-8B-Flash
点击查看免费下载

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

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

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

立即咨询