Qwen2-VL 多模态模型实战指南:在 Transformers 中用 PyTorch 完成图像与视频理解推理

发布时间:2026/9/8 23:05:51
Qwen2-VL 多模态模型实战指南:在 Transformers 中用 PyTorch 完成图像与视频理解推理 Qwen2-VL 多模态模型实战指南在 Transformers 中用 PyTorch 完成图像与视频理解推理【免费下载链接】transformers Transformers: the model-definition framework for state-of-the-art machine learning models in text, vision, audio, and multimodal models, for both inference and training.项目地址: https://gitcode.com/GitHub_Trending/tra/transformersQwen2-VL 是阿里巴巴 Qwen 团队在 Qwen-VL 基础上的大版本升级本文以 qwen2_vl.md 文档为主体结合仓库中该模型的配置、处理器与建模源码系统讲解如何在 Transformers 中加载 Qwen2-VL 完成单图、单视频以及批量混合媒体推理并深入解释 Naive Dynamic Resolution动态分辨率、M-RoPE多模态旋转位置编码、min_pixels/max_pixels 调参与 FlashAttention-2 加速背后的源码级原理。读完本文你将掌握一套可直接运行、可精确控制显存与精度的 Qwen2-VL 图像/视频推理方案。一、模型概览Qwen2-VL 相比 Qwen-VL 带来了什么Qwen2-VL 由阿里 Qwen 团队提出是对 Qwen-VL 的一次重大架构升级。根据该模型官方博客摘要的说明其核心改进可以概括为四个方面更强的图像理解能力、进阶的视频理解能力、集成视觉智能体visual agent功能以及更完善的多语言支持。在架构上Qwen2-VL 通过Naive Dynamic Resolution Support朴素动态分辨率支持实现了对任意分辨率图像的处理并引入M-RoPEMultimodal Rotary Position Embedding多模态旋转位置编码来同时处理一维文本数据与多维视觉数据。在仓库中Qwen2-VL 的完整实现分布在src/transformers/models/qwen2_vl/目录下包含 7 个 Python 文件各自职责明确文件职责configuration_qwen2_vl.py定义Qwen2VLConfig、Qwen2VLTextConfig文本 LLM 部分与Qwen2VLVisionConfig视觉编码器部分image_processing_qwen2_vl.py动态缩放、patchify 等图像预处理image_processing_pil_qwen2_vl.py基于 PIL 后端的图像处理变体video_processing_qwen2_vl.py视频抽帧与预处理processing_qwen2_vl.py串联图像/视频处理器与 tokenizer 的总处理器modeling_qwen2_vl.pyPyTorch 模型实现视觉塔 文本解码器 融合模型__init__.py模块导出该模型于 2024-08-26 合入 Transformers相关论文于 2024-09-18 在 HF Papers 发布文档页面标注其支持 FlashAttention 与 Tensor parallelism并注明了贡献者 simonJJJ。从源码结构看Qwen2-VL 沿用了视觉编码器 PatchMerger 投影 类 Qwen2 文本解码器的标准多模态大模型VLM形态其文本解码器在 configuration_qwen2_vl.py 中通过Qwen2VLTextConfig独立配置并且预设了完整的张量并行colwise/rowwise与流水线并行切分计划这也是它能支持大规模并行推理的架构基础。二、环境与模型加载约定运行本示例需要安装了torch、transformers使用当前仓库源码如需加载官方 checkpoint 还需要联网访问 Hugging Face Hub支持半精度推理的 GPU示例中使用device_mapauto自动分配设备模型建议以torch.bfloat16/torch.float16加载官方发布权重即为 bf16。Qwen2-VL 的官方指令模型 checkpoint 形如Qwen/Qwen2-VL-7B-Instruct。加载时同时实例化两个对象from transformers import AutoProcessor, Qwen2VLForConditionalGeneration model Qwen2VLForConditionalGeneration.from_pretrained(Qwen/Qwen2-VL-7B-Instruct, device_mapauto) processor AutoProcessor.from_pretrained(Qwen/Qwen2-VL-7B-Instruct)需要特别说明的是Qwen2-VL 的对话输入必须经过 chat template 处理即把对话组织为{role: ..., content: [...]}的消息列表后调用processor.apply_chat_template(..., tokenizeTrue, return_tensorspt)。此时处理器会自动完成三件事把对话中的图片/视频经视觉处理器编码成pixel_values视频为pixel_values与对应帧结构用占位符|image_pad|/|video_pad|把多模态内容插入文本序列同时输出文本所需的input_ids与描述视觉 token 空间网格的image_grid_thw/video_grid_thw张量。这正是 processing_qwen2_vl.py 中Qwen2VLProcessor的关键逻辑它会解析出 tokenizer 中的图像/视频占位 token再在replace_image_token与replace_video_token方法中按网格信息计算出实际需要的占位符数量。三、单媒体推理让模型看图说话与看懂视频3.1 图像输入推理以下代码是图像理解最基础的用法传入一张图片并让模型描述内容。from transformers import AutoProcessor, Qwen2VLForConditionalGeneration # Load the model in half-precision on the available device(s) model Qwen2VLForConditionalGeneration.from_pretrained(Qwen/Qwen2-VL-7B-Instruct, device_mapauto) processor AutoProcessor.from_pretrained(Qwen/Qwen2-VL-7B-Instruct) conversation [ { role:user, content:[ { type:image, url: https://qianwen-res.oss-cn-beijing.aliyuncs.com/Qwen-VL/assets/demo.jpeg }, { type:text, text:Describe this image. } ] } ] inputs processor.apply_chat_template( conversation, add_generation_promptTrue, tokenizeTrue, return_dictTrue, return_tensorspt ).to(model.device) # Inference: Generation of the output output_ids model.generate(**inputs, max_new_tokens128) generated_ids [output_ids[len(input_ids):] for input_ids, output_ids in zip(inputs.input_ids, output_ids)] output_text processor.batch_decode(generated_ids, skip_special_tokensTrue, clean_up_tokenization_spacesTrue) print(output_text)图片内容块中的url表示从远程地址加载图片若使用本地文件则改为type: image, path: /path/to/image.jpg即可。解码环节用processor.batch_decode而非裸 tokenizer 解码这样能确保skip_special_tokens与空格清理行为与模板一致。3.2 视频输入推理视频输入与图像输入结构几乎完全相同只是在 content 中加入{type: video, path: ...}并在apply_chat_template中增加fps参数控制抽帧密度# Video conversation [ { role: user, content: [ {type: video, path: /path/to/video.mp4}, {type: text, text: What happened in the video?}, ], } ] inputs processor.apply_chat_template( conversation, fps1, add_generation_promptTrue, tokenizeTrue, return_dictTrue, return_tensorspt ).to(model.device) # Inference: Generation of the output output_ids model.generate(**inputs, max_new_tokens128) generated_ids [output_ids[len(input_ids):] for input_ids, output_ids in zip(inputs.input_ids, output_ids)] output_text processor.batch_decode(generated_ids, skip_special_tokensTrue, clean_up_tokenization_spacesTrue) print(output_text)这里的fps1意味着每秒均匀采样一帧作为输入。在 video_processing_qwen2_vl.py 的源码中fps与num_frames是互斥参数——当二者同时传入时会直接抛出ValueError(num_framesandfpsare mutually exclusive arguments, please use only one!)。若使用fps处理器会结合视频元数据总帧数、原生 fps推算出应采样的帧数若使用num_frames则固定从视频中均匀采样指定数量的帧。两种方式最终都会把采样帧数对齐到temporal_patch_size默认 2的整数倍保证后续时序维度可以整块切分。四、批量混合媒体推理一张 batch 里既有图又有视频还有纯文本真实业务场景中一个 batch 内往往混有不同类型与数量的媒体。Qwen2-VL 的处理器支持把图像、视频、纯文本对话任意混排后一次性前向推理。下面构造 4 个对话单图对话、双图对话、纯文本对话、图视频混合对话。# Conversation for the first image conversation1 [ { role: user, content: [ {type: image, path: /path/to/image1.jpg}, {type: text, text: Describe this image.} ] } ] # Conversation with two images conversation2 [ { role: user, content: [ {type: image, path: /path/to/image2.jpg}, {type: image, path: /path/to/image3.jpg}, {type: text, text: What is written in the pictures?} ] } ] # Conversation with pure text conversation3 [ { role: user, content: who are you? } ] # Conversation with mixed media conversation4 [ { role: user, content: [ {type: image, path: /path/to/image3.jpg}, {type: image, path: /path/to/image4.jpg}, {type: video, path: /path/to/video.jpg}, {type: text, text: What are the common elements in these media?}, ], } ] conversations [conversation1, conversation2, conversation3, conversation4] # Preparation for batch inference inputs processor.apply_chat_template( conversations, fps1, add_generation_promptTrue, tokenizeTrue, return_dictTrue, return_tensorspt ).to(model.device) # Batch Inference output_ids model.generate(**inputs, max_new_tokens128) generated_ids [output_ids[len(input_ids):] for input_ids, output_ids in zip(inputs.input_ids, output_ids)] output_text processor.batch_decode(generated_ids, skip_special_tokensTrue, clean_up_tokenization_spacesTrue) print(output_text)可以看到与单样本推理相比只改动了一处把多个对话组装成conversations列表传给apply_chat_template其余调用链完全一致。这得益于处理器会为 batch 内每一段对话独立统计媒体数量与网格信息并最终 padding 到统一长度纯文本对话conversation3的 content 可以直接写成字符串处理器同样按模板处理。批量推理的输出与输入是一一对应的列表output_text中第 i 个元素即第 i 段对话的生成结果。五、实用技巧一分辨率取舍与 min_pixels / max_pixelsQwen2-VL 的核心卖点之一是Naive Dynamic Resolution模型不做任何等比缩到固定尺寸的预处理而是保留原始宽高比把高分辨率图片切成若干 14×14 的 patch 再送入视觉编码器。因此输入分辨率越高视觉 patch 越多理解细节越好但计算量与 KV 显存也同步上升。5.1 默认行为与像素上下限默认情况下处理器使用图像原生分辨率即不强制缩放到正方形。用户可以通过min_pixels与max_pixels控制单张图片参与编码的像素范围min_pixels 224*224 max_pixels 2048*2048 processor AutoProcessor.from_pretrained(Qwen/Qwen2-VL-7B-Instruct, min_pixelsmin_pixels, max_pixelsmax_pixels)该参数会持久化为该 processor 实例的缩放策略低于min_pixels的图会被放大高于max_pixels的图会被等比缩小。处理器类级别的默认值为shortest_edge 56*56、longest_edge 28*28*1280见 image_processing_qwen2_vl.py对应 Qwen2-VL 训练时采用的默认像素区间。5.2 显存受限时的降分辨率方案在 GPU 显存有限的场景下官方推荐把每张图的 token 开销压缩到 256~1024 之间min_pixels 256*28*28 max_pixels 1024*28*28 processor AutoProcessor.from_pretrained(Qwen/Qwen2-VL-7B-Instruct, min_pixelsmin_pixels, max_pixelsmax_pixels)这样每张图像最终约用 256~1024 个 token 编码。这里的数字28的来历是模型视觉编码器的空间 patch size 为 14而时间维度 patchtemporal patch与空间 merge size 均为 214 × 2 28因此像素维度总是按 28 的倍数对齐——例如256*28*28恰好对应 256 个 28×28 单元的像素量。5.3 源码印证smart_resize 的三条铁律上述行为在源码中由smart_resize实现image_processing_qwen2_vl.py它严格保证三条约束宽高都能被 factor28整除先round(height / factor) * factor对齐总像素落在 [min_pixels, max_pixels] 内超出上限则按比例缩小math.floor不足下限则放大math.ceil尽量维持原始宽高比通过缩放因子beta同时调整宽高。另外当图像的绝对宽高比大于 200如超长条形图时会抛出异常提示absolute aspect ratio must be smaller than 200。resize阶段传入的factorpatch_size * merge_size而patchify阶段则把图像按(grid_h, grid_w)切成grid_h × grid_w个 patchimage_processing_qwen2_vl.py并输出image_grid_thw网格描述模型端据此还原空间结构。5.4 视觉 token 是如何计数的图像经过视觉塔后还要经过PatchMerger源码见 modeling_qwen2_vl.py把相邻的spatial_merge_size × spatial_merge_size默认 2×2个 patch 合并为 1 个 token 送入 LLM。因此单张图片最终占用的 LLM 侧 token 数等于image_grid_thw三个维度之积除以merge_size²。这个换算关系在 processing_qwen2_vl.py 的replace_image_token/replace_video_token中被用来决定文本序列中|image_pad|/|video_pad|的重复次数也是5.2节256~1024 tokens估算的由来。六、实用技巧二多图/多视频输入与 add_vision_id 标注当一次对话中出现多张图片或多个视频时模型容易混淆这段话到底在指哪张图。为此处理器支持在视觉内容前自动插入形如Picture 1:、Video 1:的编号前缀通过add_vision_idTrue开启。下面是一段包含多轮对话、多图一视频的完整示例conversation [ { role: user, content: [ {type: image}, {type: text, text: Hello, how are you?} ] }, { role: assistant, content: Im doing well, thank you for asking. How can I assist you today? }, { role: user, content: [ {type: text, text: Can you describe these images and video?}, {type: image}, {type: image}, {type: video}, {type: text, text: These are from my vacation.} ] }, { role: assistant, content: Id be happy to describe the images and video for you. Could you please provide more context about your vacation? }, { role: user, content: It was a trip to the mountains. Can you see the details in the images and video? } ] # default: prompt_without_id processor.apply_chat_template(conversation, add_generation_promptTrue) # Excepted output: |im_start|system\nYou are a helpful assistant.|im_end|\n|im_start|user\n|vision_start||image_pad||vision_end|Hello, how are you?|im_end|\n|im_start|assistant\nIm doing well, thank you for asking. How can I assist you today?|im_end|\n|im_start|user\nCan you describe these images and video?|vision_start||image_pad||vision_end||vision_start||image_pad||vision_end||vision_start||video_pad||vision_end|These are from my vacation.|im_end|\n|im_start|assistant\nId be happy to describe the images and video for you. Could you please provide more context about your vacation?|im_end|\n|im_start|user\nIt was a trip to the mountains. Can you see the details in the images and video?|im_end|\n|im_start|assistant\n # add ids prompt_with_id processor.apply_chat_template(conversation, add_generation_promptTrue, add_vision_idTrue) # Excepted output: |im_start|system\nYou are a helpful assistant.|im_end|\n|im_start|user\nPicture 1: |vision_start||image_pad||vision_end|Hello, how are you?|im_end|\n|im_start|assistant\nIm doing well, thank you for asking. How can I assist you today?|im_end|\n|im_start|user\nCan you describe these images and video?Picture 2: |vision_start||image_pad||vision_end|Picture 3: |vision_start||image_pad||vision_end|Video 1: |vision_start||video_pad||vision_end|These are from my vacation.|im_end|\n|im_start|assistant\nId be happy to describe the images and video for you. Could you please provide more context about your vacation?|im_end|\n|im_start|user\nIt was a trip to the mountains. Can you see the details in the images and video?|im_end|\n|im_start|assistant\n对比两种输出可以清晰看到模板的编号规则关闭add_vision_id时每个视觉内容以|vision_start|开始、|vision_end|结束中间是对应数量的|image_pad|或|video_pad|占位符开启后处理器按出现顺序对图片依次编号为Picture 1:、Picture 2:、Picture 3:全部图片统一编号对视频独立编号为Video 1:前缀紧贴在|vision_start|之前。注意示例的 content 里只写了{type: image}而没有提供path/url——这是合法的占位写法适用于先拿到媒体内容、后在apply_chat_template时通过额外参数传入实际像素的场景若推理链路里没有真实像素注入则必须保证媒体 token 数量与后面传入的视觉特征严格一致否则会引发形状不匹配错误。七、实用技巧三用 FlashAttention-2 加速生成长上下文 多图多视频会带来大量注意力计算FlashAttention-2 可以从内核层面显著提速并降低显存。使用前需保证两点安装了与当前 CUDA/PyTorch 匹配的最新版 FlashAttention-2pip install -U flash-attn --no-build-isolation硬件支持 FlashAttention-2详见其官方仓库说明并且模型以torch.float16或torch.bfloat16精度加载——FlashAttention-2 只支持这两种半精度格式。满足条件后只需在加载模型时显式传入attn_implementationflash_attention_2from transformers import Qwen2VLForConditionalGeneration model Qwen2VLForConditionalGeneration.from_pretrained( Qwen/Qwen2-VL-7B-Instruct, attn_implementationflash_attention_2, device_mapauto)从 modeling_qwen2_vl.py 的导入ALL_ATTENTION_FUNCTIONS、is_flash_attention_requested、maybe_autocast等工具可以看出Qwen2-VL 的注意力已接入 Transformers 统一的可插拔注意力分发框架除 flash_attention_2 外还支持 sdpa 等实现若忘记半精度加载框架会给出精度相关的警告或错误提示。作为对照想要复现文档宣称的显存/速度收益建议在相同输入下分别以 sdpa 与 flash_attention_2 各跑一次generate再做取舍。八、配置体系与参数解读三类 Config 怎么用Qwen2-VL 是双引擎架构因此配置被拆成视觉与文本两份独立 Config再组装进顶层Qwen2VLConfig。三个配置类定义于 configuration_qwen2_vl.py。8.1 Qwen2VLVisionConfig视觉编码器对应 7B-Instruct 模型视觉塔是一个深度 32 层的类 ViT 网络。类中字段的默认值即官方 7B 权重所采用的配置字段默认值含义depth32视觉 transformer 层数embed_dim1280patch 嵌入维度hidden_size3584隐藏层维度hidden_actquick_gelu激活函数mlp_ratio4MLP 隐藏层相对倍率num_heads16注意力头数in_channels3输入通道RGBpatch_size14空间 patch 尺寸spatial_merge_size2空间方向 patch 合并粒度temporal_patch_size2时间方向 patch 尺寸initializer_range0.02参数初始化范围配置代码见 configuration_qwen2_vl.py。8.2 Qwen2VLTextConfig文本解码器文本侧与 Qwen2 系列解码器一脉相承RMSNorm、SwiGLU MLP、GQA 注意力默认vocab_size152064、80 层、64 个 Q 头与 8 个 KV 头。值得关注的是该 Config 声明了default_theta 1000000.0RoPE 基础频率并设置了ignore_keys_at_rope_validation {mrope_section}——这是因为文本词元的 RoPE 位置编码需要与视觉部分协同工作验证时需要豁免 mrope 专用键详见 configuration_qwen2_vl.py。此外该 Config 内置了完整的基础模型张量并行方案base_model_tp_planq_proj/k_proj/v_proj按 colwise、o_proj/down_proj按 rowwise 切分与流水线并行方案base_model_pp_plan说明模型从设计之初即为大规模并行部署预留了切分接口。8.3 Qwen2VLConfig顶层配置与特殊 token顶层Qwen2VLConfigconfiguration_qwen2_vl.py把上述两份子配置通过text_config/vision_config字段组合起来并维护一组关键 token id字段默认值含义image_token_id151655\|image_pad\|占位符video_token_id151656\|video_pad\|占位符vision_start_token_id151652\|vision_start\|起始符vision_end_token_id151653\|vision_end\|结束符tie_word_embeddingsFalse是否绑定输入输出词嵌入从代码细节看Qwen2VLConfig.__post_init__会自动把 dict 形式的vision_config/text_config实例化为对应的子 Config 对象并兼容从 Hub 加载的扁平 dict 旧格式旧 checkpoint 把tie_word_embeddings存在 text_config 内v5 前向兼容逻辑会将其提升到顶层因此直接Qwen2VLConfig.from_pretrained(Qwen/Qwen2-VL-7B-Instruct)即可得到完整配置树。九、深入源码动态分辨率与 M-RoPE 的配合机制理解 Qwen2-VL 的推理行为关键在于理解它的两条设计主线非均匀视觉 token 序列与三维位置编码。第一步视觉 token 不再等长。由于 Naive Dynamic Resolution不同图片切出的 patch 数不同进入 LLM 的视觉 token 数也不同。为此处理器产出了描述网格的image_grid_thw/video_grid_thw格式为[batch, T, H, W]结构的合并网格。模型在 modeling_qwen2_vl.py 的视觉塔前向中先用Qwen2VLRotaryEmbedding/VisionRotaryEmbedding按网格生成三维的旋转位置编码再执行包含 3D 注意力的视觉 transformer视觉塔输出的特征再经PatchMerger合并把时间、空间相邻的 2×2×2 patch 合并得到与占位符数量严格一致的视觉 token 序列。第二步文本与视觉共用一套三维 一维位置编码。文本 token 只有序列维而视觉 token 有 T、H、W 三个维度的坐标。模型通过get_rope_index与compute_3d_position_ids见 modeling_qwen2_vl.py 与 modeling_qwen2_vl.py为每一段输入构造混合位置 id文本部分用连续的 1D 位置视觉部分用展平后的 3D 位置。随后apply_multimodal_rotary_pos_embmodeling_qwen2_vl.py按mrope_section把旋转位置嵌入拆分到不同维度通道上——这就是M-RoPE一部分通道承载时间信息另一部分承载空间高/宽信息让模型在解码时能同时区分第几帧、第几行、第几列。第三步可选滑动窗口注意力。文本 Config 中的use_sliding_window、sliding_window4096、max_window_layers80字段与layer_types一起决定了解码器各层使用full_attention还是sliding_attention。默认use_sliding_windowFalse时所有层都走全量注意力开启后modeling_qwen2_vl.py 中的create_sliding_window_causal_mask会被用于构造局部窗口掩码可显著压缩超长视觉序列的注意力开销。需要留意的是M-RoPE 的完整细节如通道切分配置随 checkpoint 的rope_scaling/rope_parameters一起保存加载时由 Config 的convert_rope_params_to_dict统一标准化configuration_qwen2_vl.py普通用户不必手工干预。十、API 全景文档标注的类都在哪里原文档末尾通过 autodoc 罗列了本模型的全部公开 API本文整理其对应实现位置便于按需查阅类名作用源码位置Qwen2VLConfig顶层总配置configuration_qwen2_vl.pyQwen2VLVisionConfig视觉编码器配置configuration_qwen2_vl.pyQwen2VLTextConfig文本解码器配置configuration_qwen2_vl.pyQwen2VLImageProcessor图像预处理preprocessimage_processing_qwen2_vl.pyQwen2VLVideoProcessor视频抽帧与预处理preprocessvideo_processing_qwen2_vl.pyQwen2VLImageProcessorPilPIL 后端图像预处理image_processing_pil_qwen2_vl.pyQwen2VLProcessor图像视频tokenizer 总处理器__call__、apply_chat_template、batch_decodeprocessing_qwen2_vl.pyQwen2VLTextModel纯文本解码器模型forwardmodeling_qwen2_vl.pyQwen2VLModel视觉文本主干模型forward /get_video_features/get_image_featuresmodeling_qwen2_vl.pyQwen2VLForConditionalGeneration条件生成模型提供generate接口forward / 两个特征提取方法modeling_qwen2_vl.py其中Qwen2VLModel.get_image_features/get_video_features与Qwen2VLForConditionalGeneration上的同名方法支持不经过文本对话模板、直接提取纯视觉特征的用法适合做图像/视频检索、embedding 等非生成式下游任务。十一、进阶验证与阅读建议单元测试是最好的运行手册仓库在 tests/models/qwen2_vl/ 下为该模型配备了 4 个测试文件——test_modeling_qwen2_vl.py 覆盖前向与生成逻辑、test_image_processing_qwen2_vl.py 覆盖图像预处理、test_video_processing_qwen2_vl.py 覆盖视频抽帧、test_processing_qwen2_vl.py 覆盖图像/视频/文本混合处理链路。阅读这些测试可以直观理解 grid_thw 形状、占位符替换、padding 等边界行为。处理器一致性Qwen2VLProcessor的__call__会把对话拆解为视觉输入与文本输入两部分单独调用时它会自动把图片喂给 image processor、视频喂给 video processor因此在多模态推理时统一使用 processor 即可无需手动管理三种预处理器的调用顺序。精度与框架限制本文所有示例均以device_mapauto半精度推理为前提FlashAttention-2 仅在float16/bfloat16下可用。在 CPU 或无 GPU 环境运行时请去掉device_map并使用torch.float32同时预期推理耗时显著上升。通过本文的组合方案——apply_chat_template组织多模态对话 min_pixels/max_pixels控制 token 预算 add_vision_id区分多视觉对象 FlashAttention-2 内核加速你可以在可控显存预算内把 Qwen2-VL 的图片理解、视频理解与混合批量推理稳定落地到自己的业务流水线中。【免费下载链接】transformers Transformers: the model-definition framework for state-of-the-art machine learning models in text, vision, audio, and multimodal models, for both inference and training.项目地址: https://gitcode.com/GitHub_Trending/tra/transformers创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考