Qwen3-VL-2B 在 RK3576 上的部署实践:RKNN + RKLLM 全流程

本文记录一次完整、可复现的工程实践:

RK3576 平台上,将多模态大模型 Qwen3-VL-2B 拆分并部署到 NPU 上运行。

目标不是介绍工具功能,而是让读者:

按照本文步骤执行代码,最终在板端成功跑起多模态推理 Demo。


一、整体部署流程总览(先看全局)

在 RK 平台上,多模态模型无法以单一模型部署,必须拆分为两个子模型:

  • Vision Encoder → .rknn
  • LLM Decoder → .rkllm

整体流程如下:

本文最终产物:

复制代码
qwen3-vl_vision_rk3576.rknn
qwen3-vl-2b-instruct_w8a8_rk3576.rkllm

二、环境准备(必须一致)

1️⃣ 主机环境(模型转换)

项目 版本
OS Ubuntu 22.04 x86_64
Python 3.10
工具 Miniforge / Conda

2️⃣ 开发板环境

项目 说明
芯片 RK3576
系统 Linux
推理 NPU

三、模型准备

拉取 Qwen3-VL-2B 模型(HuggingFace / ModelScope 均可):

bash 复制代码
git clone https://huggingface.co/Qwen/Qwen3-VL-2B-Instruct

假设模型路径为:

bash 复制代码
/workspace/Qwen3-VL-2B-Instruct

四、LLM 部分:RKLLM 转换与量化(核心)

4.1 加载模型

ini 复制代码
from rkllm.api import RKLLM

llm = RKLLM()

ret = llm.load_huggingface(
    model="/workspace/Qwen3-VL-2B-Instruct",
    device="cpu",
    dtype="float16",
)

if ret != 0:
    raise RuntimeError("load_huggingface failed")

说明:

  • 使用 CPU 转换,避免显存不足
  • FP16 对 w8a8 量化足够

4.2 构建量化数据集(关键步骤)

多模态模型不能直接量化原始图像输入,需要先构造 inputs_embeds

ini 复制代码
inputs_embeds = model.get_input_embeddings()(inputs["input_ids"])

image_mask = inputs["input_ids"] == model.config.image_token_id
image_embeds = model.visual(
    inputs["pixel_values"],
    grid_thw=inputs["image_grid_thw"]
)

inputs_embeds[image_mask] = image_embeds

inputs_embeds 保存为 numpy,用于量化校准:

javascript 复制代码
import numpy as np
np.save("inputs_embeds.npy", inputs_embeds.cpu().numpy())

最终生成 inputs.json,作为 RKLLM 的校准数据集。


4.3 构建并导出 RKLLM 模型

ini 复制代码
ret = llm.build(
    do_quantization=True,
    quantized_dtype="w8a8",
    quantized_algorithm="normal",
    target_platform="RK3576",
    num_npu_core=2,
    dataset="data/inputs.json"
)

if ret != 0:
    raise RuntimeError("build failed")

llm.export_rkllm(
    "qwen3-vl-2b-instruct_w8a8_rk3576.rkllm"
)

五、Vision 部分:ONNX → RKNN

5.1 导出 Vision ONNX

css 复制代码
python export_vision.py \
  --path /workspace/Qwen3-VL-2B-Instruct \
  --model_name qwen3-vl \
  --height 448 \
  --width 448

输出:

复制代码
qwen3-vl_vision.onnx

5.2 ONNX 转 RKNN

css 复制代码
python export_vision_rknn.py \
  --path qwen3-vl_vision.onnx \
  --target-platform rk3576 \
  --height 448 \
  --width 448

输出:

复制代码
qwen3-vl_vision_rk3576.rknn

六、板端部署与运行

6.1 拷贝文件到开发板

vbnet 复制代码
qwen3-vl_vision_rk3576.rknn
qwen3-vl-2b-instruct_w8a8_rk3576.rkllm
demo
lib/

6.2 设置运行环境

bash 复制代码
export LD_LIBRARY_PATH=./lib:$LD_LIBRARY_PATH

6.3 运行 Demo

bash 复制代码
./demo demo.jpg \
  qwen3-vl_vision_rk3576.rknn \
  qwen3-vl-2b-instruct_w8a8_rk3576.rkllm \
  256 2048 2 \
  "<|vision_start|>" "<|vision_end|>" "<|image_pad|>"

参数说明:

  • vision_start / vision_end:标识视觉 embedding 边界
  • image_pad:多图或补齐占位符

七、结果验证

运行成功后,终端会输出模型对图片内容的描述或回答。

至此,一个 完整的端侧多模态推理流程部署完成


八、实践总结

  1. RK 平台多模态模型必须拆分
  2. RKLLM 的核心是量化与运行时管理
  3. 量化数据准备是成功关键
  4. w8a8 是当前最稳妥的工程选择
相关推荐
倒头就睡的小比特16 小时前
算法竞赛C++常用的STL
c++·算法
小羊没烦恼!16 小时前
初探性能优化——2个月到4小时的性能提升
java·开发语言·windows·算法·c#
猎头南楼17 小时前
知识社区推荐系统实践:新用户冷启动与长短期兴趣建模的挑战 资深推荐算法工程师
人工智能·深度学习·算法·机器学习
旖旎夜光18 小时前
力控面试题 01.01: 判定字符是否唯一(位运算) —— 题解
c++·学习·算法·leetcode·力控
wzdark18 小时前
大规模并行计算中的负载均衡算法研究4
算法
Because_of_Her118 小时前
并查集-听课笔记
笔记·算法·并查集
码流子18 小时前
高速公路安全监测实践:碰撞监测预警+物联网底座,从感知到处置的闭环
大数据·人工智能·物联网·算法·架构
another heaven19 小时前
【算法/C++ MD5算法能否逆解码?原理、C++实现与同类哈希算法对比】
c++·算法·哈希算法
wzdark19 小时前
从算法设计模式看编程思维的抽象能力4
算法
2601_9622186119 小时前
万象生鲜系统称重自动多退少补算法解决生鲜非标品痛点
大数据·数据库·人工智能·python·算法