基于 FastAPI 部署 Qwen2-VL-2B-Instruct:构建图片与视频多模态问答 API

📅 发布时间:2026/9/20 5:38:52
基于 FastAPI 部署 Qwen2-VL-2B-Instruct:构建图片与视频多模态问答 API
大模型人工智能教程本地部署微调【免费下载链接】self-llm《开源大模型食用指南》针对中国宝宝量身打造的基于Linux环境快速微调全参数/Lora、部署国内外开源大模型LLM/多模态大模型MLLM教程项目地址https://gitcode.com/datawhalechina/self-llm点击查看免费下载本文是《开源大模型食用指南》中 Qwen2-VL 系列的核心实战篇章。本教程将带领读者在 Linux 环境下以 ModelScope 为模型源、FastAPI Uvicorn 为服务框架完整落地Qwen2-VL-2B-Instruct的图片问答与视频问答两类多模态 API 服务。学完本指南你将掌握多模态大模型的 HTTP 服务封装思路、qwen_vl_utils视觉数据预处理底层原理并能用requests以标准 OpenAI 风格消息结构调用部署好的服务。环境准备与依赖安装本文默认学习者已具备基于 CUDA 的 PyTorch 运行环境推荐基础环境如下---------------- ubuntu 22.04 python 3.12 cuda 12.1 pytorch 2.3.0 ----------------若尚未安装 PyTorch (CUDA) 环境请先自行完成安装再进行后续步骤。首先通过pip换源加速下载并安装依赖包。其中qwen_vl_utils视觉信息处理工具库会作为参考代码一并提供因此只需安装如下核心依赖pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple pip install modelscope1.20.0 pip install fastapi0.115.4 pip install uvicorn0.32.0 pip install transformers4.46.2 pip install accelerate1.1.1 pip install torchvision0.19.0 pip install av13.1.0完整依赖清单可对照 参考代码 requirements.txt。其中torchvision0.19.0与av13.1.0分别服务于图片缩放与视频解码transformers4.46.2对应 Qwen2-VL 官方推荐的适配版本torchvision版本需与torch严格匹配否则视频读取 APItorchvision.io.read_video可能不可用。考虑到部分学习者配置环境可能遇到问题项目已在 AutoDL 平台准备了 Qwen2-VL 环境镜像可直接创建对应示例环境跳过手动安装。模型下载基于 ModelScopeQwen2-VL-2B-Instruct权重体积适中单卡即可完成推理。使用modelscope中的snapshot_download函数下载模型第一个参数为模型名称参数cache_dir为模型下载路径。该方法对国内用户十分友好。新建model_download.py文件输入以下代码并运行python model_download.py执行下载# model_download.py from modelscope import snapshot_download model_dir snapshot_download(Qwen/Qwen2-VL-2B-Instruct, cache_dir/root/autodl-tmp, revisionmaster)注意请记得修改cache_dir为你自己的模型下载路径。下载完成后模型权重会保存在cache_dir下的Qwen/Qwen2-VL-2B-Instruct目录中后续代码中的model_name_or_path需要指向该路径。图像问答 API 服务端代码实现新建api_image.py文件粘贴以下内容完整源码见 参考代码 api_server_image.py# api_server_image.py from transformers import Qwen2VLForConditionalGeneration, AutoProcessor from qwen_vl_utils.vision_process import process_vision_info from fastapi import FastAPI, Request import uvicorn from pydantic import BaseModel from typing import List, Dict, Union # 创建FastAPI应用 app FastAPI() # 下载好的模型本地路径 model_name_or_path /root/autodl-tmp/Qwen/Qwen2-VL-2B-Instruct # 初始化模型和处理器 model Qwen2VLForConditionalGeneration.from_pretrained( model_name_or_path, torch_dtypeauto, device_mapauto ) processor AutoProcessor.from_pretrained(model_name_or_path) # 定义请求体模型 class MessageContent(BaseModel): type: str text: str None image: str None class ChatMessage(BaseModel): messages: List[Dict[str, Union[str, List[Dict[str, str]]]]] # 处理POST请求的端点 app.post(/generate) async def generate_response(chat_message: ChatMessage): # 直接使用请求中的 messages text processor.apply_chat_template( chat_message.messages, tokenizeFalse, add_generation_promptTrue ) # 预先写好的辅助函数位于参考代码中 image_inputs, video_inputs process_vision_info(chat_message.messages) inputs processor( text[text], imagesimage_inputs, videosvideo_inputs, paddingTrue, return_tensorspt, ) inputs inputs.to(cuda) # 生成输出 generated_ids model.generate(**inputs, max_new_tokens1024) generated_ids_trimmed [ out_ids[len(in_ids):] for in_ids, out_ids in zip(inputs.input_ids, generated_ids) ] output_text processor.batch_decode( generated_ids_trimmed, skip_special_tokensTrue, clean_up_tokenization_spacesFalse ) return {response: output_text[0]} if __name__ __main__: # 启动FastAPI应用端口为8000 uvicorn.run(app, host0.0.0.0, port8000)注意同样记得修改model_name_or_path为你自己的模型下载路径。关键设计点解析1模型与处理器在模块加载时初始化。model Qwen2VLForConditionalGeneration.from_pretrained(...)位于全局作用域意味着服务进程启动时模型只加载一次之后每个 HTTP 请求都复用同一份显存中的权重避免反复加载带来的秒级延迟。torch_dtypeauto会自动读取模型配置文件中的精度设置device_mapauto则让 Accelerate 自动将模型分配到可用的 GPU 设备上。2请求体沿用 OpenAI 风格消息结构。ChatMessage.messages是角色与内容的列表content中每个元素是{type, text/image}字典。服务端只依赖messages字段因此前端可以灵活组合「图片 文本」的混合对话内容。3apply_chat_template负责构造对话提示词。将原始消息结构渲染成 Qwen2-VL 期望的模板格式add_generation_promptTrue会在末尾追加模型回复的起始标记这是生成阶段的标准做法。4process_vision_info完成视觉数据解析。该函数由项目参考代码目录中的 vision_process.py 提供它扫描messages中的image/image_url/video字段分别调用fetch_image与fetch_video完成原始数据到模型输入张量的转换最终返回(image_inputs, video_inputs)元组交由AutoProcessor统一编码。启动图像问答 API 服务在终端输入以下命令启动 API 服务python api_server_image.py加载完毕后出现如下信息说明服务启动成功Uvicorn 监听0.0.0.0:8000使用 requests 调用图片问答接口服务启动后可以使用 Python 的requests库请求/generate端点调用Qwen2-VL-2B-Instruct的多模态图片理解能力生成回复。示例代码如下完整源码见 fastapi_request_image.py# fastapi_request_image.py import requests url http://localhost:8000/generate payload { messages: [ { role: user, content: [ { type: image, image: https://qianwen-res.oss-cn-beijing.aliyuncs.com/Qwen-VL/assets/demo.jpeg }, { type: text, text: Describe this image. } ] } ] } response requests.post(url, jsonpayload) print(response.json())执行python fastapi_request_image.py得到的返回结果如下{response: The image depicts a serene beach scene with a woman and a dog. The woman is sitting on the sand, wearing a plaid shirt and black pants, and appears to be smiling. She is holding the dogs paw in a high-five gesture. The dog, which is a large breed, is sitting on the sand with its front paws raised, possibly in response to the womans gesture. The background shows the ocean with gentle waves, and the sky is clear with a soft light, suggesting it might be either sunrise or sunset. The overall atmosphere is peaceful and joyful.}对照请求中的demo.jpeg图片可以看到模型的回复质量很高正确且完整地叙述了图片中的场景、人物与动作细节。图像预处理的源码级原理为了更深入地理解服务端能力边界这里剖析 vision_process.py 中图像处理的核心逻辑。Qwen2-VL 采用「动态分辨率」视觉编码策略图像不会统一缩放到固定尺寸而是在保持长宽比的前提下缩放到满足约束的分辨率从而保留更多细节。smart_resize的约束条件对应源码中的常量常量值含义IMAGE_FACTOR28宽高必须是 28 的倍数与 ViT patch size 对齐MIN_PIXELS4 × 28 × 28 3136缩放后像素总量下限MAX_PIXELS16384 × 28 × 28缩放后像素总量上限MAX_RATIO200长宽比最大允许值超出则抛异常fetch_image对图片输入的支持非常灵活从源码fetch_image的分支可以看出它支持以下五种输入形式本地路径Image.open(image)直接读取HTTP(S) URLrequests.get(image, streamTrue)流式拉取file://协议路径剥离前缀后按本地文件读取Base64 数据data:image/...;base64,xxx形式先解码再打开PIL.Image 对象内存中直接处理。因此在你的请求 payload 中image字段既可以填远程 URL也可以填本地绝对路径或 Base64 字符串服务端无需任何改动即可兼容这为客户端接入如移动端上传、表单文件提供了很大便利。进阶实践让 API 服务支持视频问答由于Qwen2-VL-2B-Instruct具备强大的多模态能力除了图片问答之外还支持视频形式的交互。我们需要对原先的api_image.py代码稍作修改使 FastAPI 服务支持视频流推理。新建api_server_image_and_video.py复制如下代码完整源码见 api_server_image_and_video.py# api_server_image_and_video.py from transformers import Qwen2VLForConditionalGeneration, AutoProcessor from qwen_vl_utils.vision_process import process_vision_info from fastapi import FastAPI, Request import uvicorn from pydantic import BaseModel from typing import List, Dict, Union app FastAPI() model_name_or_path /root/autodl-tmp/Qwen/Qwen2-VL-2B-Instruct model Qwen2VLForConditionalGeneration.from_pretrained( model_name_or_path, torch_dtypeauto, device_mapauto ) processor AutoProcessor.from_pretrained(model_name_or_path) # 定义请求体模型 class MessageContent(BaseModel): type: str text: str None image: str None video: str None # 添加对video的支持 class ChatMessage(BaseModel): messages: List[Dict[str, Union[str, List[Dict[str, str]]]]] app.post(/generate) async def generate_response(chat_message: ChatMessage): # 直接使用请求中的 messages text processor.apply_chat_template( chat_message.messages, tokenizeFalse, add_generation_promptTrue ) image_inputs, video_inputs process_vision_info(chat_message.messages) inputs processor( text[text], imagesimage_inputs, videosvideo_inputs, paddingTrue, return_tensorspt, ) inputs inputs.to(cuda) # 生成输出 generated_ids model.generate(**inputs, max_new_tokens1024) generated_ids_trimmed [ out_ids[len(in_ids):] for in_ids, out_ids in zip(inputs.input_ids, generated_ids) ] output_text processor.batch_decode( generated_ids_trimmed, skip_special_tokensTrue, clean_up_tokenization_spacesFalse ) return {response: output_text[0]} if __name__ __main__: uvicorn.run(app, host0.0.0.0, port8000)与图片版相比改动集中在MessageContent中新增了video: str None字段。服务端处理逻辑完全复用process_vision_info会识别video字段并触发视频帧抽取。视频预处理的源码级原理从 vision_process.py 的源码可以看到视频处理比图像多出「帧采样」环节视频读取后端自动选择。get_video_reader_backend()会优先检查是否安装了decord通过importlib.util.find_spec探测否则回退到torchvision.io.read_video开发者还可以通过环境变量FORCE_QWENVL_VIDEO_READER强制指定后端。当前环境安装的torchvision0.19.0正好满足torchvision 0.19.0的版本要求支持从 HTTP/HTTPS 直接读取视频而旧版本只能读本地路径。帧采样策略smart_nframes。视频不会逐帧送入模型而是按策略抽样默认参数为常量值含义FPS2.0默认按每秒 2 帧采样FPS_MIN_FRAMES4采样帧数下限FPS_MAX_FRAMES768采样帧数上限FRAME_FACTOR2采样帧数必须是 2 的倍数采样帧数 视频总帧数 / 视频fps × 2并夹在[4, 768]区间内、对齐到 2 的倍数。视频分辨率同样受VIDEO_MIN_PIXELS128×28×28、VIDEO_MAX_PIXELS768×28×28、VIDEO_TOTAL_PIXELS24576×28×28约束。这意味着超长视频会被抽帧压缩从而控制视觉 token 数量、节省显存与计算量。视频问答 API 服务启动与调用在终端输入以下命令启动 API 服务python api_server_image_and_video.py加载完毕后出现如下信息说明服务启动成功同样的使用 Python 的requests库请求服务端口调用多模态能力生成回复。示例代码如下完整源码见 fastapi_request_video.pyimport requests url http://localhost:8000/generate payload { messages: [ { role: user, content: [ { type: video, video: ./space_woaudio.mp4 }, { type: text, text: Describe this video. } ] } ] } response requests.post(url, jsonpayload) print(response.json())上述代码在messages.content中添加了一个视频示例视频文件space_woaudio.mp4位于 参考代码目录执行python fastapi_request_video.py此时得到的模型返回结果如下{response: The video shows a man standing in a Mission Control Center, speaking to the camera. The center is equipped with various monitors and control panels, and there are several large screens displaying maps and data. The man appears to be giving a presentation or explaining something related to the centers operations.}模型准确识别出了视频中的场景任务控制中心、人物动作面对镜头讲解以及环境细节监视器、控制面板、大屏幕验证了 2B 规模的多模态模型已具备扎实的视频理解能力。参考代码及其使用本次教程涉及代码文件较多项目额外提供了完整参考代码供读者对照使用但依然建议初学者在理解的基础上妥善使用。参考代码目录结构如下01-Qwen2-VL-2B-Instruct FastApi 参考代码/ ├── qwen_vl_utils/ │ ├── __init__.py │ └── vision_process.py # 视觉信息预处理图像/视频解析核心 ├── api_server_image.py # 图像问答 API 服务端 ├── api_server_image_and_video.py # 图像视频问答 API 服务端 ├── fastapi_request_image.py # 图像问答客户端请求示例 ├── fastapi_request_video.py # 视频问答客户端请求示例 ├── model_download.py # ModelScope 模型下载脚本 ├── requirements.txt # 依赖清单 └── space_woaudio.mp4 # 视频问答测试样例完成上述所有步骤后的目录结构应与下图类似文件路径请读者根据实际存放情况进行修正总结与延伸本教程完整走通了「环境搭建 → 模型下载 → FastAPI 服务封装 → 图片/视频问答调用」全流程。核心要点回顾服务端模型全局加载一次/generate端点接收 OpenAI 风格messages经apply_chat_templateprocess_vision_info预处理后送入模型生成预处理库qwen_vl_utils.vision_process是图片/视频解析的关键模块动态分辨率缩放与智能抽帧策略决定了模型输入质量与显存开销源码中的smart_resize、smart_nframes、fetch_image、fetch_video均可在 vision_process.py 中直接查阅客户端仅需requests.post(url, jsonpayload)即可完成多模态推理image字段支持本地路径、URL、Base64 多种形式video字段支持本地路径与网络视频。在此基础上你可以进一步探索同仓库的进阶教程Qwen2-VL Web Demo 部署基于 Gradio 的图形化交互、vLLM 部署调用更高吞吐的推理服务以及 Lora 微调针对特定场景定制模型能力。如果觉得 2B 模型理解能力有限可以按相同流程替换为 7B 甚至 72B 的 Qwen2-VL 系列权重服务代码无需改动。赞分享大模型人工智能教程本地部署微调【免费下载链接】self-llm《开源大模型食用指南》针对中国宝宝量身打造的基于Linux环境快速微调全参数/Lora、部署国内外开源大模型LLM/多模态大模型MLLM教程项目地址https://gitcode.com/datawhalechina/self-llm点击查看免费下载相关推荐Qwen2-VL-2B-Instruct Web Demo 部署指南基于 Gradio 构建图片与视频多模态对话界面Qwen2 VL 2B Instruct Web Demo 部署指南基于 Gradio 构建图片与视频多模态对话界面 本文是 self llm《开源大模型食用教程大模型本地部署微调基于 Gradio 的 Qwen2-VL-2B-Instruct 多模态 Web Demo 部署全指南基于 Gradio 的 Qwen2 VL 2B Instruct 多模态 Web Demo 部署全指南 本教程基于 Datawhale《开源大模型食用指南》s大模型人工智能教程本地部署微调Qwen3-VL-4B-Instruct 基于 FastAPI 的多模态部署调用实战指南图像问答 视频问答Qwen3 VL 4B Instruct 基于 FastAPI 的多模态部署调用实战指南图像问答 视频问答 Qwen3 VL 4B Instruct 是大模型人工智能教程本地部署微调创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考