Qwen3-VL 视觉语言模型入门教程

155 阅读5分钟

Qwen3-VL 视觉语言模型入门教程

今年9月份,阿里巴巴通义千问团队推出了多模态视觉语言模型Qwen3-VL,该模型能同时理解图片、文字甚至视频。【AI大模型教程】

本期,我们将介绍如何使用 Qwen3-VL 视觉语言模型执行文档理解任务,包括 OCR 和信息提取。

什么是视觉语言模型?

视觉语言模型 是能够同时处理图像和文本输入,并生成文本响应的多模态 AI 模型。

这类模型直接理解图像内容,无需依赖中间处理步骤。

为什么需要视觉语言模型?

传统文档处理采用 OCR + LLM 的组合方案,但存在两个主要问题:

OCR 技术存在缺陷。传统 OCR 引擎在处理小文本、倾斜图像或垂直文本时经常出错。

OCR 输出的质量问题直接影响下游任务效果。

文本的视觉位置信息至关重要。在某些场景下,文本在图像中的空间位置直接关系到语义理解。

考虑上图中的复选框示例。如果只是对文本进行OCR处理,就会丢失被勾选复选框的视觉位置,因此很难知道三个文档中哪个是相关的。
使用视觉语言模型能很好地解决这个任务,因为它能够直接理解视觉布局。

Qwen3-VL 模型概述

Qwen3-VL 是阿里巴巴推出的视觉语言模型系列。

该系列包含多个版本:235B-A22B、30B-A3B,以及密集的 4B 和 8B 版本。本文使用 4B 版本进行测试。

环境准备

安装依赖

安装所需的 Python 包:

pip install torch accelerate pillow torchvisionpip install git+https://github.com/huggingface/transformers

Transformers 库需要从 GitHub 源码安装,因为 Qwen3-VL 尚未包含在官方发布版本中。

核心代码实现

from transformers import Qwen3VLForConditionalGeneration, AutoProcessorfrom PIL import Imageimport osimport time# 加载模型model = Qwen3VLForConditionalGeneration.from_pretrained(    "Qwen/Qwen3-VL-4B-Instruct", dtype="auto", device_map="auto")processor = AutoProcessor.from_pretrained("Qwen/Qwen3-VL-4B-Instruct")def_resize_image_if_needed(image_path: str, max_size: int = 1024) -> str:    """调整图像尺寸,保持宽高比"""    img = Image.open(image_path)    width, height = img.size    if width <= max_size and height <= max_size:        return image_path    ratio = min(max_size / width, max_size / height)    new_width = int(width * ratio)    new_height = int(height * ratio)    img_resized = img.resize((new_width, new_height), Image.Resampling.LANCZOS)    base_name = os.path.splitext(image_path)[0]    ext = os.path.splitext(image_path)[1]    resized_path = f"{base_name}_resized{ext}"    img_resized.save(resized_path)    return resized_pathdef_build_messages(system_prompt: str, user_prompt: str, image_paths: list[str] | None = None, max_image_size: int | None = None):    messages = [\        {"role": "system", "content": [{"type": "text", "text": system_prompt}]}\    ]    user_content = []    if image_paths:        if max_image_size isnotNone:            processed_paths = [_resize_image_if_needed(path, max_image_size) for path in image_paths]        else:            processed_paths = image_paths        user_content.extend([\            {"type": "image", "min_pixels": 512*32*32, "max_pixels": 2048*32*32, "image": image_path}\            for image_path in processed_paths\        ])    user_content.append({"type": "text", "text": user_prompt})    messages.append({        "role": "user",        "content": user_content,    })    return messagesdefinference(system_prompt: str, user_prompt: str, max_new_tokens: int = 1024, image_paths: list[str] | None = None, max_image_size: int | None = None):    messages = _build_messages(system_prompt, user_prompt, image_paths, max_image_size)    inputs = processor.apply_chat_template(        messages,        tokenize=True,        add_generation_prompt=True,        return_dict=True,        return_tensors="pt"    )    inputs = inputs.to(model.device)    start_time = time.time()    generated_ids = model.generate(**inputs, max_new_tokens=max_new_tokens)    generated_ids_trimmed = [\        out_ids[len(in_ids):] for in_ids, out_ids inzip(inputs.input_ids, generated_ids)\    ]    output_text = processor.batch_decode(        generated_ids_trimmed, skip_special_tokens=True, clean_up_tokenization_spaces=False    )    end_time = time.time()    print(f"Time taken: {end_time - start_time} seconds")    return output_text[0]

代码说明:

  • • _resize_image_if_needed:调整图像尺寸以适应模型限制
  • • _build_messages:构建多模态输入消息
  • • inference:执行模型推理

测试数据

挪威奥斯陆市规划局提供的公开文档。(链接:contributor.insightmediagroup.io/wp-content/…

执行 OCR 任务

OCR 提示词

按照 Qwen3-VL 官方文档建议,使用简单直接的提示词:

user_prompt = "Read all the text in the image."

执行代码

system_prompt = """You are a helpful assistant that can answer questions and help with tasks."""user_prompt = "Read all the text in the image."max_new_tokens = 1024image_paths = ["example-doc-site-plan-cropped.jpg"]output = inference(system_prompt, user_prompt, max_new_tokens, image_paths, max_image_size=1536)print(output)

输出结果

Plan- ogbygningsetatenDato: 23.01.2014Bruker: HKNMålestokk 1:500Ekvidistanse 1mHøydegrunnlag: Oslo lokalKoordinatsystem: EUREF89 - UTM sone 32© Plan- og bygningsetaten,Oslo kommuneOriginalformat A3Adresse:Camilla Colletts vei 15Gnr/Bnr:.Kartet er sammenstilt for:.PlotID: / Best.nr.:27661 /Deres ref: Camilla Colletts vei 15Kommentar:Gjeldende kommunedelplaner:KDP-BB, KDP-13, KDP-5Kartutsnittet gjelder vertikalinvå 2.I tillegg finnes det regulering ifølgende vertikalinvå:(Hvis blank: Ingen øvrige.)Det er ikke registrertnaturn mangfold innenforSe tegnforklaring på eget ark.Beskrivelse:NR:Dato:Revidert dato:

程序准确提取了图像中的所有文本内容。

执行信息提取任务

JSON 格式信息提取

user_prompt = """Extract the following information from the image, and reply in JSON format:{    "date": "The date of the document. In format YYYY-MM-DD.",    "address": "The address mentioned in the document.",    "gnr": "The street number (Gnr) mentioned in the document.",    "scale": "The scale (målestokk) mentioned in the document.",}If you cannot find the information, reply with None. The return object must be a valid JSON object. Reply only the JSON object, no other text."""max_new_tokens = 1024image_paths = ["example-doc-site-plan-cropped.jpg"]output = inference(system_prompt, user_prompt, max_new_tokens, image_paths, max_image_size=1536)print(output)

提取结果

{    "date": "2014-01-23",    "address": "Camilla Colletts vei 15",    "gnr": "15",    "scale": "1:500"}

所有字段都被正确提取。虽然文档中 Gnr 字段显示为空白,但模型从地址中推断出了街道编号。

处理缺失信息

user_prompt = """Extract the following information from the image, and reply in JSON format:{    "date": "The date of the document. In format YYYY-MM-DD.",    "address": "The address mentioned in the document.",    "Bnr": "The building number (Bnr) mentioned in the document.",    "scale": "The scale (målestokk) mentioned in the document.",}If you cannot find the information, reply with None. The return object must be a valid JSON object. Reply only the JSON object, no other text."""max_new_tokens = 1024image_paths = ["example-doc-site-plan-cropped.jpg"]output = inference(system_prompt, user_prompt, max_new_tokens, image_paths, max_image_size=1536)print(output)

输出正确反映了缺失信息:

{    "date": "2014-01-23",    "address": "Camilla Colletts vei 15",    "Bnr": None,    "scale": "1:500"}

视觉语言模型的局限性

文本遗漏问题是 OCR 任务中的常见缺陷。模型有时会忽略文档的某些部分。

计算资源需求是另一个重要考量。视觉语言模型需要大量内存和处理能力。

在本地环境中,处理高分辨率图像或多页文档时会遇到硬件限制。

总结

本文通过 Qwen3-VL 实例,演示了视觉语言模型在 OCR 和信息提取任务上的应用。

与传统 OCR 方案相比,视觉语言模型提供了更直接的解决方案。