05.RK3588部署Qwen3-VL - 模型量化

1.整体量化转换过程

整个转换路径分为两步

第一步是将多模态的大语言模型中的视觉部分转为rknn格式,即safetensors->onnx->rknn,其中onnx->rknn的过程依赖rknn-toolkit2工具;

第二步是将多模态的大语言模型中的语言部分(LLM)转为rkllm格式,即safetensors->onnx->rkllm,其中onnx->rkllm的过程依赖rkllm-toolkit工具。

整个转换在 rknn-llm/examples/multimodal_model_demo 目录进行

2.用到的转换文件

查看路径:examples/multimodal_model_demo/export下的内容,可以看到很多python脚本:

复制代码
export_rkllm.py
export_vision.py
export_vision_qwen2.py
export_vision_rknn.py
modeling_deepseekv2.py

整个转换过程会用到其中三个:

  • export_vision.py:用于视觉相关模块转为onnx
  • export_vision_rknn.py:用于将export_vision.py导出的onnx(也就是视觉相关模块)转为rknn格式
  • export_rkllm.py:用于LLM相关模块的量化与导出为rkllm格式的模型
    在后面的量化过程中还需要examples/multimodal_model_demo/data/make_input_embeds_for_quantize.py脚本来生成校准数据。

3.视觉模型的转换

safetensors转onnx

该过程使用rknn-llm虚拟环境,export_vision.py脚本,该脚本的目的是将模型中的视觉相关部分转换为onnx。

3.1激活虚拟环境

此处使用虚拟环境rknn-llm

复制代码
conda activate rknn-llm

3.2模型下载

模型下载可以通过HuggingFace下载,也可以通过modelscope下载,国内首选modelscope模搭社区

要使用modelscope需要先安装:

复制代码
pip install modelscope

安装好后执行以下命令下载模型:

复制代码
modelscope download --model Qwen/Qwen3-VL-2B-Instruct

直接执行模型文件会下载到home目录的.cache文件夹内,具体路径为:

复制代码
~/.cache/modelscope/hub/models/Qwen/Qwen3-VL-2B-Instruct/

3.3命令参数

在执行转换之前我们可以通过-h命令查看脚本的帮助信息:

复制代码
python export/export_vision.py -h
usage: export_vision.py [-h] [--path PATH] [--model_name MODEL_NAME] [--batch_size BATCH_SIZE] [--height HEIGHT] [--width WIDTH]
[--device DEVICE]
options:
-h, --help            show this help message and exit
--path PATH           model path
--model_name MODEL_NAME
model name
--batch_size BATCH_SIZE
batch size
--height HEIGHT       image height
--width WIDTH         image width
--device DEVICE       cpu or cuda

参数解释:
--path:下载的qwen3vl-2b目录的绝对路径

--model_name:模型的名称,如qwen3-vl

--batch_size:批处理大小,值越大:处理速度越快,但需要更多显存(内存),默认为1。

--height:多模态中的图片高度,值越大理论上精度更高

--width:多模态中的图片宽度,值越大理论上精度更高

--device:处理转换的设备,默认是cpu,可以指定gpu序号

3.4大模型 --> onnx

执行如下模型转换命令,把原始模safetensors型转换为.onnx格式

复制代码
python export/export_vision.py --path /home/wssheng/.cache/modelscope/hub/models/Qwen/Qwen3-VL-2B-Instruct/ --model_name=qwen3-vl --height=224 --width=224

该过程会有一些提示信息,无需理会,看到最后出现Exported to ./onnx/qwen3-vl_vision.onnx字样说明导出成功。

导出成功后会在当前目录下生成onnx文件夹,其中包含文件qwen3-vl_vision.onnx,大小约为1.6GB。

3.5 onnx --> rknn

该过程使用rknn-toolkit2虚拟环境(因为要将模型转为rknn格式,所以要用到rknn-toolkit2工具),export_vision_rknn.py脚本,该脚本的目的是将上一节生成的qwen3-vl_vision.onnx转为rknn模型。

在执行转换之前我们同样可以通过-h命令查看脚本的帮助信息:

复制代码
python export/export_vision_rknn.py -h
usage: export_vision_rknn.py [-h] [--path PATH] [--model_name MODEL_NAME] [--target-platform TARGET_PLATFORM]
[--batch_size BATCH_SIZE] [--height HEIGHT] [--width WIDTH]
optional arguments:
-h, --help                show this help message and exit
--path PATH               model path
--model_name MODEL_NAME   model name
--target-platform TARGET_PLATFORM     target platform
--batch_size BATCH_SIZE     batch size
--height HEIGHT       image height
--width WIDTH         image width

参数解释:

--path:上一节3.1.1导出的onnx路径,可以是相对路径或绝对路径

--model_name:模型的名称,如qwen3-vl

--target-platform:导出的平台,其实就是芯片名称,默认rk3588,看rknn-llm官方文档支持如下列表的芯片:

RK3588 Series

RK3576 Series

RK3562 Series

RV1126B Series

--batch_size:批处理大小,值越大:处理速度越快,但需要更多显存(内存),默认为1。

--height:多模态中的图片高度,值越大理论上精度更高

--width:多模态中的图片宽度,值越大理论上精度更高

执行转换

复制代码
python export/export_vision_rknn.py --path /home/wssheng/rk3588/rknn-llm/examples/multimodal_model_demo/onnx/qwen3-vl_vision.onnx --model_name qwen3-vl --height 224 --width 224 --target-platform rk3588

该过程耗时稍微有点长,耐心等待,会有进度条显示,如:

复制代码
I Loading : 100%|████████████████████████████████████████████████| 316/316 [00:01<00:00, 261.44it/s]
I OpFusing 0: 100%|███████████████████████████████████████████████| 100/100 [00:04<00:00, 23.60it/s]
I OpFusing 1 : 100%|██████████████████████████████████████████████| 100/100 [00:08<00:00, 12.34it/s]
I OpFusing 0 : 100%|██████████████████████████████████████████████| 100/100 [01:46<00:00,  1.06s/it]
I OpFusing 1 : 100%|██████████████████████████████████████████████| 100/100 [01:46<00:00,  1.06s/it]
I OpFusing 2 : 100%|██████████████████████████████████████████████| 100/100 [01:46<00:00,  1.07s/it]
I OpFusing 0 : 100%|██████████████████████████████████████████████| 100/100 [01:50<00:00,  1.10s/it]
I OpFusing 1 : 100%|██████████████████████████████████████████████| 100/100 [01:50<00:00,  1.10s/it]
I OpFusing 2 : 100%|██████████████████████████████████████████████| 100/100 [01:54<00:00,  1.15s/it]
I Saving : 100%|█████████████████████████████████████████████████| 259/259 [00:00<00:00, 275.91it/s]
I rknn building ...
E RKNN: [11:06:43.239] Unkown op target: 0
I rknn building done.

看到I rknn building done.说明构建已经完成,构建完成后会在当前文件夹生成rknn文件夹,其中包含文件qwen3-vl_vision_rk3588.rknn,大小约为795M。

至此,视觉模块+投影模块的转换已完成。

4.大语言模型的转换

转换路径为:准备量化用的校准数据->量化并导出 RKLLM 模型

1.激活环境

整个过程在rknn-llm-export虚拟环境中进行,因此,需要激活虚拟环境

复制代码
conda activate rknn-llm-export

2.准备量化数据

在examples/multimodal_model_demo路径下,有个data文件夹,准备量化数据需要的脚本就在该路径下,即:data/make_input_embeds_for_quantize.py。

但该脚本是适配Qwen2VL系列模型的,所以我们需要修改一下,直接复制以下脚本内容替换原脚本内容即可。

复制代码
import torch
import os
import torchvision.transforms as T
from torchvision.transforms.functional import InterpolationMode
from PIL import Image
import json
import numpy as np
from tqdm import tqdm
from transformers import AutoModel, AutoTokenizer, AutoProcessor, Qwen2VLForConditionalGeneration
from transformers import AutoModel, AutoTokenizer, AutoProcessor, Qwen3VLForConditionalGeneration
import argparse
argparse = argparse.ArgumentParser()
argparse.add_argument('--path', type=str, default='Qwen/Qwen2-VL-2B-Instruct', help='model path', required=False)
argparse.add_argument('--path', type=str, default='Qwen/Qwen3-VL-2B-Instruct', help='model path', required=False)
args = argparse.parse_args()
path = args.path
model = Qwen2VLForConditionalGeneration.from_pretrained(
model = Qwen3VLForConditionalGeneration.from_pretrained(
path, torch_dtype="auto", device_map="cpu",
low_cpu_mem_usage=True,
trust_remote_code=True).eval()
processor = AutoProcessor.from_pretrained(path)
datasets = json.load(open("data/datasets.json", 'r'))
for data in datasets:
image_name = data["image"].split(".")[0]
imgp = os.path.join(data["image_path"], data["image"])
image = Image.open(imgp)
conversation = [
    {
        "role": "user",
        "content": [
            {
                "type": "image",
            },
            {"type": "text", "text": data["input"]},
        ],
    }
]
text_prompt = processor.apply_chat_template(conversation, add_generation_prompt=True)
inputs = processor(
    text=[text_prompt], images=[image], padding=True, return_tensors="pt"
)
inputs = inputs.to(model.device)
# inputs_embeds = model.model.embed_tokens(inputs["input_ids"])
inputs_embeds = model.model.language_model.embed_tokens(inputs["input_ids"])
# pixel_values = inputs["pixel_values"].type(model.visual.get_dtype())
pixel_values = inputs["pixel_values"].to(model.dtype)
image_mask = inputs["input_ids"] == model.config.image_token_id
# image_embeds = model.visual(pixel_values, grid_thw=inputs["image_grid_thw"]).to(inputs_embeds.device)
image_embeds = model.visual(pixel_values, grid_thw=inputs["image_grid_thw"])[0].to(inputs_embeds.device)
inputs_embeds[image_mask] = image_embeds
print("inputs_embeds", inputs_embeds.shape)
os.makedirs("data/inputs_embeds/", exist_ok=True)
np.save("data/inputs_embeds/{}".format(image_name), inputs_embeds.to(dtype=torch.float16).cpu().detach().numpy())

with open('data/inputs.json', 'w') as json_file:
json_file.write('[\n')
first = True
for data in tqdm(datasets):
input_embed = np.load(os.path.join("data/inputs_embeds", data["image"].split(".")[0]+'.npy'))
target = data["target"]
input_dict = {
"input_embed": input_embed.tolist(),
"target": target
}
if not first:
json_file.write(',\n')
else:
first = False
json.dump(input_dict, json_file)
json_file.write('\n]')
print("Done")

执行脚本

复制代码
python data/make_input_embeds_for_quantize.py --path /home/wssheng/.cache/modelscope/hub/models/Qwen/Qwen3-VL-2B-Instruct/

执行结束后会在data目录下生成inputs_embeds文件夹与inputs.json文件。

3.量化并导出rkllm

3.1参数说明

通过export/export_rkllm.py -h查看帮助信息:

复制代码
usage: export_rkllm.py [-h] [--path PATH] [--target-platform TARGET_PLATFORM] [--num_npu_core NUM_NPU_CORE]
[--quantized_dtype QUANTIZED_DTYPE] [--device DEVICE] [--savepath SAVEPATH]
options:
-h, --help            show this help message and exit
--path PATH           model path
--target-platform TARGET_PLATFORM    target platform
--num_npu_core NUM_NPU_CORE    npu core num
--quantized_dtype QUANTIZED_DTYPE    quantized dtype
--device DEVICE       device
--savepath SAVEPATH   save path

参数说明:

  • --path:输入模型的路径
  • --target-platform:目标平台
  • --num_npu_core:NPU核心数量,指定使用的神经网络处理器核心数量,影响模型并行计算能力,需要根据芯片平台实际的NPU核心个数指定
  • --quantized_dtype:量化数据类型
  • --device:指定模型转换时使用的设备
  • --savepath:指定转换后RKLLM模型文件名

3.2执行量化导出

这里是rk3588,--num_npu_core为3,因为rk3588有3个NPU芯片

复制代码
python export/export_rkllm.py --path /home/wssheng/.cache/modelscope/hub/models/Qwen/Qwen3-VL-2B-Instruct/ --target-platform rk3588 --num_npu_core 3 --quantized_dtype w8a8 --savepath ./rkllm/qwen3-vl-2b-instruct_w8a8_rk3588.rkllm

其中--quantized_dtype w8a8表示权重(weights)和激活值(activations)都使用8位整数量化的混合精度量化策略。推理速度快,但模型精度有一定损失。

执行成功后,会在当前文件夹生成rkllm文件夹,在该文件夹中生成了文件:qwen3-vl-2b-instruct_w8a8_rk3588.rkllm,大小约2.3GB。

4.报错解决

报错:ModuleNotFoundError: No module named 'pkg_resources'
pkg_resources是在setuptools里,当前setuptools是82.0.0,在81.0.0里是最后一版支持pkg_resources
解决办法:降级setuptools为81.0.0版本

复制代码
python -m pip install setuptools==81.0.0 --force-reinstall

至此,我们完成了qwen3-vl 2b模型的转换,共得到了两个文件:

  • rknn/qwen3-vl_vision_rk3588.rknn:视觉相关模块
  • qwen3-vl-2b-instruct_w8a8_rk3588.rkllm:LLM相关模块
相关推荐
蜡台8 小时前
Agency-Agents 智能体系统从零搭建实战指南
ai·agent
猿小猴子9 小时前
主流 Agent 之 「Zed」和 「ZCode」 介绍
ide·ai·agent·zed·zhipu·ade·zcode
JaydenAI9 小时前
[基于OpenEvals的自动化评估-11]针对Agent对话的评估[下篇]
ai·langchain·agent·evaluation·openevals
hust_wangyajun12 小时前
我用 Agent Reach 生成了 Claude Code 年度生态报告:一篇实战演练
ai·agent·claude code
wang_yb12 小时前
如何快速构建一个数据科学应用?从零到上线
ai·databook
神奇霸王龙13 小时前
MCP 微软教材背书:5 国产基座 Agent 承接力实测
microsoft·ai·ai作画·agent·ai编程·ai写作·mcp
呆呆敲代码的小Y14 小时前
awesome-llm-apps 开源项目详解:100+ AI Agent 与 RAG 模板一键复用
人工智能·ai·开源·ai编程·ai agent·awesome·llm应用
VIP_CQCRE14 小时前
Ace Data Cloud 创收联盟:把 AI 能力变成可运营的产品
ai·aigc·api·云服务·开发者工具
全栈技术负责人14 小时前
Ollama + Open WebUI 搭建本地大模型
人工智能·ai·ai编程