Qwen3-VL-2B-Instruct 转 RKNN + RKLLM 部署到 RK3588 实战记录

本文记录一次将 Qwen3-VL-2B-Instruct 转换为瑞芯微 RK3588 可部署模型的完整过程。
多模态模型需要拆成两部分:Vision 部分导出为 .rknn,LLM 部分导出为 .rkllm

一、背景说明

Qwen3-VL 属于视觉语言模型,整体可以理解为:

图片输入
  ↓
Vision Encoder / Projector
  ↓
图像特征
  ↓
Qwen3 LLM
  ↓
文本输出

在 RK3588 上部署时,通常需要拆成两份模型:

Vision + Projector  →  RKNN 模型
LLM                 →  RKLLM 模型

最终需要得到两个文件:

qwen3-vl_vision_rk3588.rknn
qwen3-vl-2b-instruct_w8a8_rk3588.rkllm

本文使用的工程为:

rknn-llm

模型为:

Qwen/Qwen3-VL-2B-Instruct

二、环境说明

1. 模型与工程路径

本文中的路径仅作为示例,请按自己的实际路径替换。

Windows 侧模型路径:

E:\Desktop\lbcat4\Qwen3-VL-2B-Instruct

Linux 侧模型路径:

/home/kickpi/Qwen3-VL-2B-Instruct

Linux 侧工程路径:

/home/kickpi/rknn-llm

多模态转换目录:

/home/kickpi/rknn-llm/examples/multimodal_model_demo

2. 工具版本

本次成功使用的关键工具:

rknn-toolkit2: 2.3.0
rkllm-toolkit: 1.3.0
Python: 3.10
目标平台: RK3588

建议配置:

系统:Ubuntu x86_64
内存:至少 16GB,推荐 32GB 或以上
Swap:建议 32GB 或以上
磁盘:建议保留 80GB 以上空间

注意:rkllm-toolkit 工程里提供的是 linux_x86_64 的 wheel,因此导出 .rkllm 建议在 x86_64 Linux 环境中完成。


三、下载模型

可以直接从 HuggingFace 拉取:

git clone https://huggingface.co/Qwen/Qwen3-VL-2B-Instruct

模型目录中应包含:

config.json
model.safetensors
tokenizer.json
tokenizer_config.json
preprocessor_config.json

其中 model.safetensors 大约 4GB。


四、整体转换流程

整体流程如下:

Qwen3-VL-2B-Instruct
      │
      ├── Vision 部分
      │       ├── export_vision.py
      │       ├── qwen3-vl_vision.onnx
      │       └── export_vision_rknn.py
      │               ↓
      │          qwen3-vl_vision_rk3588.rknn
      │
      └── LLM 部分
              ├── make_input_embeds_for_quantize.py
              ├── data/inputs.json
              └── export_rkllm.py
                      ↓
                 qwen3-vl-2b-instruct_w8a8_rk3588.rkllm

五、导出 Vision ONNX

进入多模态示例目录:

cd ~/rknn-llm/examples/multimodal_model_demo

Qwen3-VL 使用通用脚本 export/export_vision.py,不要使用旧的 Qwen2-VL 专用脚本。

执行:

python export/export_vision.py \
  --path /home/kickpi/Qwen3-VL-2B-Instruct \
  --model_name qwen3-vl \
  --batch_size 1 \
  --height 448 \
  --width 448 \
  --device cpu

成功后会生成:

./onnx/qwen3-vl_vision.onnx

确认文件:

ls -lh ./onnx/qwen3-vl_vision.onnx

关于输入尺寸

Qwen3-VL 的 patch_size16,本次使用:

height = 448
width  = 448

转换 RKNN 时也必须保持相同尺寸。


六、ONNX 转 RKNN

这一步需要 rknn-toolkit2 环境。

执行:

python export/export_vision_rknn.py \
  --path ./onnx/qwen3-vl_vision.onnx \
  --model_name qwen3-vl \
  --target-platform rk3588 \
  --batch_size 1 \
  --height 448 \
  --width 448

如果目标板是 RK3576,则改为:

--target-platform rk3576

成功日志类似:

I rknn building ...
I rknn building done.

成功后生成:

./rknn/qwen3-vl_vision_rk3588.rknn

确认:

ls -lh ./rknn/

常见 Warning

可能会看到:

W load_onnx: The input 'grid_thw' will be removed from the model
Please don't forget to remove the corresponding 'mean'/'std' of 'grid_thw' in rknn.config!

本次实测不影响最终生成 .rknn。只要最后出现:

I rknn building done.

并且 .rknn 文件生成,就可以继续下一步。


七、生成 LLM 量化输入

rkllm-toolkit 导出 LLM 时需要量化校准数据。工程中已经提供了脚本:

data/make_input_embeds_for_quantize.py

执行:

python data/make_input_embeds_for_quantize.py \
  --path /home/kickpi/Qwen3-VL-2B-Instruct \
  --model_type qwen3vl

成功后生成:

data/llm_inputs.json
data/llm_inputs/

但是 export/export_rkllm.py 默认读取的是:

data/inputs.json

所以需要复制一份:

cp data/llm_inputs.json data/inputs.json

确认文件:

ls -lh data/llm_inputs.json
ls -lh data/inputs.json
ls -lh data/llm_inputs | head

本次生成的量化输入目录大小约为:

47M

八、安装 RKLLM 环境

建议单独创建环境,不要和 rknn-toolkit2 混用。

conda create -n rkllm130 python=3.10 -y
conda activate rkllm130

1. 安装 PyTorch CPU 版

pip install torch==2.6.0 torchvision==0.21.0 --index-url https://download.pytorch.org/whl/cpu

2. 安装 rkllm-toolkit

进入工程根目录:

cd ~/rknn-llm

安装 wheel:

pip install --no-deps rkllm-toolkit/packages/rkllm_toolkit-1.3.0-cp310-cp310-linux_x86_64.whl

3. 补充依赖

pip install \
  colorlog==6.8.2 \
  addict==2.4.0 \
  easydict==1.13 \
  einops==0.4.1 \
  flatbuffers==24.3.25 \
  jsonlines==4.0.0 \
  jsonschema==4.23.0 \
  tabulate==0.9.0 \
  transformers-stream-generator==0.0.5 \
  Jinja2==3.1.4 \
  pillow==10.4.0 \
  "protobuf>=4.21.6,<=4.25.4" \
  pyarrow==21.0.0 \
  safetensors==0.5.3 \
  sentencepiece==0.2.0 \
  datasets==4.1.1 \
  accelerate==1.5.2 \
  scipy \
  matplotlib \
  timm==1.0.19 \
  "tiktoken>=0.7.0,<=0.9.0" \
  transformers==4.57.0 \
  optimum==1.23.3 \
  -i https://mirrors.aliyun.com/pypi/simple

验证:

python -c "from rkllm.api import RKLLM; print('rkllm ok')"
python -c "from transformers import Qwen3VLForConditionalGeneration; print('qwen3vl ok')"

如果输出:

rkllm ok
qwen3vl ok

说明环境可用。


九、导出 RKLLM

进入多模态示例目录:

cd ~/rknn-llm/examples/multimodal_model_demo

执行:

python export/export_rkllm.py \
  --path /home/kickpi/Qwen3-VL-2B-Instruct \
  --target-platform rk3588 \
  --num_npu_core 3 \
  --quantized_dtype w8a8 \
  --device cpu

本次实测日志如下:

INFO: rkllm-toolkit version: 1.3.0
WARNING: rkllm-toolkit only exports Qwen3ForCausalLM of Qwen3VLForConditionalGeneration!
Building model: 100%
Generating train split: 20 examples
Optimizing model: 100%| 28/28 [1:12:19]
INFO: Setting max_context_limit to 4096
INFO: Exporting the model, please wait ....
INFO: Model saved to ./rkllm/qwen3-vl-2b-instruct_w8a8_rk3588.rkllm!

最终生成:

./rkllm/qwen3-vl-2b-instruct_w8a8_rk3588.rkllm

确认:

ls -lh ./rkllm/

十、最终产物

转换完成后,应该得到两个核心模型文件:

Vision RKNN:
./rknn/qwen3-vl_vision_rk3588.rknn

LLM RKLLM:
./rkllm/qwen3-vl-2b-instruct_w8a8_rk3588.rkllm

这两个文件是一套完整的 Qwen3-VL 板端部署模型。


十一、板端运行参考

工程提供了 C++ demo:

examples/multimodal_model_demo/deploy

编译:

cd deploy
./build-linux.sh

将 demo 和模型推到板端后,运行示例大致如下:

./demo demo.jpg \
  ./qwen3-vl_vision_rk3588.rknn \
  ./qwen3-vl-2b-instruct_w8a8_rk3588.rkllm \
  2048 \
  4096 \
  3 \
  rk3588 \
  "<|vision_start|>" \
  "<|vision_end|>" \
  "<|image_pad|>"

参数说明:

demo.jpg                          输入图片
qwen3-vl_vision_rk3588.rknn       Vision 模型
qwen3-vl-2b-instruct_w8a8.rkllm   LLM 模型
2048                              max_new_tokens
4096                              max_context_len
3                                 rknn_core_num
rk3588                            platform
<|vision_start|>                  图像开始 token
<|vision_end|>                    图像结束 token
<|image_pad|>                     图像占位 token

十二、踩坑记录

1. Qwen3VLForConditionalGeneration 没有 visual 属性

报错:

AttributeError: 'Qwen3VLForConditionalGeneration' object has no attribute 'visual'

原因是不同版本 transformers 中 Qwen3-VL 的视觉模块挂载位置不同。

有的版本是:

model.visual

而旧脚本可能写的是:

vlm.visual

解决思路是兼容两种结构:

def get_visual_module(vlm):
    if hasattr(vlm, "visual"):
        return vlm.visual
    if hasattr(vlm, "model") and hasattr(vlm.model, "visual"):
        return vlm.model.visual
    raise AttributeError(f"{type(vlm).__name__} has no visual module")

然后将脚本里的:

self.vpm = vlm.visual

替换为:

self.vpm = get_visual_module(vlm)

2. 导出 ONNX 时缺少 onnx

报错:

torch.onnx.errors.OnnxExporterError: Module onnx is not installed!

解决:

pip install onnx==1.18.0

3. ONNX 转 RKNN 被系统杀死

现象:

已杀死

通常是内存不足,被 Linux OOM Killer 杀掉。

建议:

sudo fallocate -l 32G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
free -h

如果磁盘空间充足,也可以使用 64GB swap。

4. 生成量化输入时缺少 torchvision

报错:

ModuleNotFoundError: No module named 'torchvision'

解决:

pip install torchvision -i https://mirrors.aliyun.com/pypi/simple

5. transformers 版本过旧

报错:

ImportError: cannot import name 'Qwen2_5_VLForConditionalGeneration' from 'transformers'

解决:

pip install transformers==4.57.0 -i https://mirrors.aliyun.com/pypi/simple

如果当前环境是 Python 3.8,建议新建 Python 3.10 环境。

6. 缺少 rkllm 模块

报错:

ModuleNotFoundError: No module named 'rkllm'

说明当前环境没有安装 rkllm-toolkit

解决:

pip install --no-deps rkllm-toolkit/packages/rkllm_toolkit-1.3.0-cp310-cp310-linux_x86_64.whl

7. 缺少 colorlog

报错:

ModuleNotFoundError: No module named 'colorlog'

解决:

pip install colorlog==6.8.2 -i https://mirrors.aliyun.com/pypi/simple

8. RKLLM 优化阶段很慢

日志:

Optimizing model: 28/28 [1:12:19]

这是正常现象。本次在 CPU 环境下耗时约 1 小时 12 分钟。

建议:

1. 优先使用物理机或服务器,不建议使用低配虚拟机;
2. 有 NVIDIA GPU 且环境支持时,可以尝试 --device cuda;
3. 内存建议 32GB 以上;
4. 不建议中途停止,停止后通常需要重新跑。

十三、总结

Qwen3-VL 在 RK3588 上部署时,关键是将模型拆成两部分:

Vision → RKNN
LLM    → RKLLM

本次最终成功产物:

qwen3-vl_vision_rk3588.rknn
qwen3-vl-2b-instruct_w8a8_rk3588.rkllm

实际经验是:

1. Vision ONNX 可以在 Windows 或 Linux 导出;
2. ONNX 转 RKNN 建议在 Linux 中完成;
3. RKLLM 导出必须使用 x86_64 Linux 环境;
4. 量化优化阶段耗时较长,CPU 下 1 小时以上属于正常;
5. 不同 transformers 版本可能导致模型结构路径不同,需要注意 visual 模块位置。

至此,Qwen3-VL-2B-Instruct 到 RK3588 的 RKNN + RKLLM 转换流程完成。

Logo

欢迎加入DeepSeek 技术社区。在这里,你可以找到志同道合的朋友,共同探索AI技术的奥秘。

更多推荐