0x00 背景

4 月底拿到手这块 可乐派 CPM-3588S,8GB LPDDR4 + 6 TOPS NPU,Ubuntu 22.04。一开始只是想跑个 YOLOv5 玩玩,结果越折腾越上头,干脆盯上了 Qwen3-VL 2B 多模态大模型。

说干就干。从配环境到模型跑通,整整 1 周时间。中间踩了一堆坑(rknn-toolkit2 版本不兼容、量化报错、tokenizer 路径错位……),现在把整个过程复盘一遍,希望能给同样想玩边缘 AI 的兄弟省点时间。

🎯 最终成果 CokePi (RK3588S, 8GB) 上跑通 Qwen3-VL 2B 量化版,NPU 推理 10.8 tok/s,CPU 模式 1.2 tok/s。视觉编码 + 语言模型全在板载完成,无需联网。

0x01 硬件与软件

硬件平台

  • SBC: 可乐派 CPM-3588S V10
  • SoC: Rockchip RK3588S (4×A55 + 4×A76)
  • NPU: 6 TOPS (int4/int8/int16/FP16)
  • 内存: 8GB LPDDR4
  • 存储: eMMC 64GB
  • 系统: Ubuntu 22.04.4 LTS (arm64)

软件栈

  • Python 3.10.12
  • rknn-toolkit2 2.3.2
  • rkllama 0.4 (rockchip-qi’s fork)
  • Qwen3-VL-2B-Instruct (官方 + rkllama 量化版)

0x02 环境准备

首先是 rknn-toolkit2。Rockchip 官方给的 wheel 装起来很丝滑:

# 检查 NPU 驱动
ls /dev/dri/renderD128
cat /sys/kernel/debug/rknpu/version

# 安装 rknn-toolkit2 (cp310)
pip3 install rknn-toolkit2-2.3.2-cp310-cp310-manylinux_2_17_aarch64.whl

# 验证安装
python3 -c "from rknn.api import RKNN; print('OK')"

# 安装 rkllama
git clone https://github.com/NotPunchnox/rkllama.git

⚠️ 坑 1:版本兼容性 rknn-toolkit2 2.x 需要 numpy < 2.0,如果之前装过新版 numpy 必须降级,否则导入直接报错。

0x03 模型转换

这一步最折腾。从 HuggingFace 下载 Qwen3-VL-2B-Instruct,然后转成 RKNN 格式:

# 下载模型 (需要梯子)
huggingface-cli download Qwen/Qwen3-VL-2B-Instruct --local-dir ./Qwen3-VL-2B

# 转 RKNN 格式
python3 convert.py --src ./Qwen3-VL-2B --dst ./Qwen3-VL-2B-rk3588 \
    --quantize w8a8 --target rk3588

转换过程中的几个关键选项

  • 量化策略: w8a8 (8-bit weight, 8-bit activation) 是质量/性能平衡点
  • 目标平台: rk3588 (注意不是 rk3588s,虽然板子是 S 版,NPU 内核一样)
  • 视觉编码器: 默认会自动转 ViT 部分

⚠️ 坑 2:ViT 转换 OOM Qwen3-VL 的视觉编码器相对较大,转换时需要至少 6GB 内存,8GB 板子勉强能跑。建议关掉其他大进程,或者用 swap 顶一顶。

0x04 推理部署

用 rkllama 启动服务,本质上是个 OpenAI 兼容的 API:

# 启动 rkllama server
python3 -m rkllama.server --model ./Qwen3-VL-2B-rk3588 \
    --port 8080 --host 0.0.0.0

然后客户端调用:

import requests
import base64

# 读取图片
with open("test.jpg", "rb") as f:
    img_b64 = base64.b64encode(f.read()).decode()

# 调用 API
resp = requests.post(
    "http://localhost:8080/v1/chat/completions",
    json={
        "model": "qwen3-vl-2b",
        "messages": [{
            "role": "user",
            "content": [
                {"type": "image_url", "image_url": {"url": f"data:image/jpeg;base64,{img_b64}"}},
                {"type": "text", "text": "描述这张图片里有什么"}
            ]
        }],
        "max_tokens": 200
    }
)

0x05 性能测试

上 NPU 监控(sudo cat /sys/kernel/debug/rknpu/load),跑一轮 benchmark:

$ rkllama-bench --model ./Qwen3-VL-2B-rk3588
Model: qwen3-vl-2b-rk3588
Quantization: w8a8
Target: rk3588

====== Pure Text ======
NPU mode:   10.8 tok/s
CPU mode:   1.2 tok/s  (FP16)

====== Vision + Text ======
Image encode: 380ms
First token:  1.2s
Subsequent:   10.2 tok/s

NPU 比纯 CPU 快了 9 倍,这就是 6 TOPS 的威力。

0x06 踩坑汇总

  1. numpy 版本: 2.x 不兼容 rknn-toolkit2 2.x,必须 <2.0
  2. ViT 转换 OOM: 8GB 板子勉强够,转换时关闭其他大进程
  3. tokenizer 路径: 必须放在模型同目录,文件名固定 tokenizer.json
  4. NPU 调度: 多线程推理时需要设置 RKNN_RUNTIME_PRIORITY_HIGH
  5. 图片分辨率: 超过 4096×4096 视觉编码会爆显存,建议预处理 resize

0x07 后续计划

  • 试试 Qwen3-VL 7B 量化版,看 8GB 够不够跑
  • 接入 语音识别 (Whisper),做个完整的语音 + 视觉 AI 助手
  • 把推理服务打包成 systemd 服务,开机自启

总之,RK3588S 跑多模态大模型是真的可以,6 TOPS NPU 加上 8GB 内存,本地化部署完全可行。后面我继续折腾 7B 版,有进展再写一篇 🚀