不用 GPU!RK3588 跑视觉大模型,Qwen3.5-2B VLM 端侧落地

一、项目核心释义

这是一套面向瑞芯微RK3588 NPU硬件加速的Qwen3.5-2B视觉语言模型推理实现,完全基于原生C++构建,配套专用大模型运行时与神经网络加速引擎,完整支持单图像理解与视频序列分析两种模式。

方案采用W8A8量化的大语言模型搭配FP16精度的视觉编码器,在3GB左右总内存占用下实现完整的多模态推理能力,冷启动仅需数秒,单图推理秒级响应,非常适合嵌入式设备、边缘终端、离线智能硬件等场景部署。

核心能力:

  • 双模式自动切换:自动识别单图/多图视频序列,切换对应推理管线
  • NPU全链路加速:视觉编码与语言推理全部跑在NPU上,CPU仅做前后处理
  • 动态KV缓存:最大支持16384token上下文,支持多轮对话与长视频序列
  • 流式输出:逐字输出推理结果,交互体验流畅

二、行业核心技术知识点

2.1 端侧多模态推理的核心痛点

传统云端多模态API依赖网络、延迟高、隐私性差,而端侧部署一直面临几个核心问题:

  • 算力有限:端侧CPU算力弱,跑大模型慢,GPU功耗高不适合嵌入式
  • 内存紧张:视觉+语言双模型占用内存大,低端设备塞不下
  • 部署复杂:Python框架依赖重,嵌入式系统适配难
  • 功耗过高:GPU持续运行发热大,电池类设备扛不住

NPU专用加速就是针对这些痛点的端侧方案,专用AI硬件做计算,功耗低、算力密度高,是嵌入式多模态的最优技术路线。

2.2 RK3588 NPU:端侧AI的核心算力

RK3588是面向高端嵌入式场景的旗舰SoC,集成6TOPS算力的NPU,支持INT8/FP16混合精度,专门针对Transformer、卷积等AI算子做了硬件级优化。

  • 算力:6TOPS INT8,适合2B级别的大模型与视觉模型
  • 内存:共享内存架构,模型权重、KV缓存、图像缓冲统一寻址
  • 功耗:NPU满负载仅几瓦,远低于GPU,适合嵌入式长时间运行
  • 生态:配套完整的模型转换与部署工具链,支持主流模型落地

2.3 视觉语言模型的两阶段架构

现代视觉语言模型都是标准的两阶段架构,分工明确:

  1. 视觉编码器阶段:把输入的图像/视频帧转换成视觉token序列,相当于把图片"翻译"成大模型能看懂的语言token
  2. 语言推理阶段:把视觉token和文本prompt拼在一起,送入大语言模型生成回答

两阶段拆分的好处是可以分别优化、分别量化,视觉部分用FP16保精度,语言部分用W8A8省内存。

2.4 W8A8量化:端侧大模型的标配

W8A8是当前端侧大模型最主流的量化组合:权重用8bit整数存储,激活值也用8bit整数计算。相比FP16全精度模型,内存占用直接减少约一半,而推理质量损失极小,是大模型在端侧NPU上跑起来的核心技术。

本方案语言模型采用W8A8量化,视觉编码器保留FP16精度,平衡内存占用与视觉理解精度。

2.5 视频序列的稀疏采样推理

视频不能每一帧都送进大模型,算力和显存都扛不住。行业通用方案是均匀稀疏采样,隔几帧抽取一帧,转换成视觉token后送入模型,既保留时序信息,又控制计算量。

每个视觉token对应的内存占用远高于普通文本token,所以控制输入帧数是端侧视频推理的关键优化点。

三、整体架构设计思路

3.1 三层端侧推理架构

整体采用三层解耦设计,从硬件到应用逐层封装,每层职责清晰,可独立替换。

复制代码
┌──────────────────────────────────────────────────────────┐
│                  应用交互层                          │
│  命令行解析 / 图像加载 / 对话交互 / 结果输出      │
└──────────────────────┬───────────────────────────────┘
                       │
┌──────────────────────────────────────────────────────────┐
│                  模型运行时层                        │
│  语言模型运行时 / 视觉加速引擎 / KV缓存管理        │
└──────────────────────┬───────────────────────────────┘
                       │
┌──────────────────────────────────────────────────────────┐
│                  硬件加速层                          │
│              RK3588 NPU / 共享内存 / 图像预处理        │
└──────────────────────────────────────────────────────────┘
  • 硬件加速层:RK3588 NPU提供核心算力,共享内存做数据交互,OpenCV做图像预处理
  • 模型运行时层:核心计算层,负责语言推理调度、视觉编码计算、统一管理KV缓存
  • 应用交互层:负责命令行解析、图像读取、对话交互、流式输出,对接用户

3.2 双模式推理管线

根据输入图像数量自动切换工作模式:

  • 单图像模式:输入单张图片,视觉编码一次完成,进入对话模式,支持多轮问答
  • 视频序列模式:输入多张帧,稀疏采样后逐帧编码,拼接时序信息,做视频理解

3.3 内存规划

  • 语言模型:W8A8量化,约2.1GB内存
  • 视觉编码器:FP16精度,约0.8GB内存
  • KV缓存:最大16384token配置,约1GB内存
  • 图像缓冲:单张448×448约0.6MB

总内存占用约3GB左右,适配8GB以上内存的RK3588设备。

四、核心代码实现原理

4.1 核心接口封装

工程封装了统一的多模态推理类,向上提供极简接口,内部整合视觉编码与语言推理。

核心类定义(简化版):

cpp 复制代码
class VLLMEngine {
public:
    // 加载模型:视觉模型路径 + 语言模型路径,最大生成数,最大上下文
    bool LoadModel(const std::string& vlm_path, const std::string& llm_path,
                  int max_new_tokens, int max_context_len);
    
    // 加载单张图像进入上下文
    bool LoadImage(const cv::Mat& image);
    
    // 加载视频帧序列
    bool LoadVideoFrames(const std::vector<cv::Mat>& frames);
    
    // 发送提问,返回完整回答
    std::string Ask(const std::string& prompt);
    
    // 辅助控制
    void SetInfo(bool enable);   // 开关日志信息
    void SetSilence(bool enable); // 开关流式逐字输出
};

代码讲解:

  • 接口非常精简,应用层只需要调用加载模型、加载媒体、提问三个核心步骤
  • 内部自动处理视觉token拼接、KV缓存管理、推理生成
  • 流式输出由内部控制,可切换逐字输出还是一次性返回完整文本

4.2 主程序完整实现

主程序只有几十行代码,自动识别单图/视频模式,逻辑清晰易读。

完整主程序核心代码:

cpp 复制代码
#include "VLLMEngine.h"
#include <vector>

int main(int argc, char** argv)
{
    // 参数校验:视觉模型 + 语言模型 + 至少1张图片
    if (argc < 4) {
        std::cerr << "用法: " << argv[0] 
                  << " 视觉模型 语言模型 图片1 [图片2 图片3 ...]\n"; 
        return -1;
    }

    std::string vlm_model = argv[1];
    std::string llm_model = argv[2];

    VLLMEngine engine;
    engine.SetInfo(true);
    engine.SetSilence(false);

    // 加载模型:最大生成2048token,最大上下文16384token
    engine.LoadModel(vlm_model, llm_model, 2048, 16384);

    // 收集所有输入图像帧
    std::vector<cv::Mat> frames;
    for (int i = 3; i < argc; ++i) {
        cv::Mat frame = cv::imread(argv[i]);
        if (!frame.empty()) {
            frames.push_back(frame);
        } else {
            std::cerr << "警告:无法加载图片 " << argv[i] << "\n";
        }
    }

    if (frames.empty()) {
        std::cerr << "错误:没有有效图片加载。\n";
        return -1;
    }

    // 自动切换模式:单张→图像模式,多张→视频序列模式
    if (frames.size() == 1) {
        std::cout << "\n[信息] 加载单图像模式...\n";
        engine.LoadImage(frames[0]);
    } else {
        std::cout << "\n[信息] 加载视频序列模式 (" 
                  << frames.size() << " 帧)...\n";
        engine.LoadVideoFrames(frames);
    }

    // 交互式对话循环
    std::string input_str;
    std::string output_str;

    while (true) {
        printf("\n用户: ");
        std::getline(std::cin, input_str);
        if (input_str == "exit") break;

        // 提问并获取完整回答
        output_str = engine.Ask(input_str);
    }

    return 0;
}

代码逐段讲解:

  1. 参数解析:第一个参数是视觉编码器模型,第二个是大语言模型,后面跟一个或多个图片文件
  2. 初始化:创建引擎实例,开启运行日志,开启流式输出模式
  3. 模型加载:设置单次最大生成2048token,最大上下文16384token,适配长对话与长视频
  4. 图像收集:遍历所有图片参数,用OpenCV读取,自动跳过无效文件
  5. 模式自动切换:1张图走单图像模式,多张自动进入视频序列模式
  6. 对话循环:循环读取用户输入,调用Ask方法生成回答,输入exit退出程序

4.3 模型加载与内存配置

LoadModel是核心初始化函数,负责加载两个模型、分配KV缓存、初始化NPU运行时。

核心调用参数说明:

cpp 复制代码
engine.LoadModel(
    "视觉编码器模型路径",    // RKNN格式视觉编码器
    "语言模型路径",        // 专用格式语言模型
    2048,                 // 单次最大生成token数
    16384                 // 最大上下文总token数
);

参数详解:

  • max_new_tokens:单次推理最多生成多少token,控制回答长度,避免无限生成,同时控制峰值内存
  • max_context_len:KV缓存总大小,包含系统提示、视觉token、历史对话、生成回答。数值越大支持的对话越长,占用内存越多
  • 32GB内存的设备可以拉满16384,支持长视频序列;8/16GB设备建议设2048或4096

4.4 单图像模式实现

单图像模式下,图像只做一次编码,然后所有对话都基于这个图像特征。

核心实现逻辑:

cpp 复制代码
bool VLLMEngine::LoadImage(const cv::Mat& image) {
    // 1. 图像预处理:缩放到448×448,归一化,格式转换
    cv::Mat resized;
    cv::resize(image, resized, cv::Size(448, 448));
    
    // 2. 调用NPU视觉编码器,生成视觉token序列
    std::vector<float> vision_tokens = vision_infer(vlm_context_, resized);
    
    // 3. 视觉token插入到语言模型的输入前缀位置
    llm_context_.insert_vision_tokens(vision_tokens);
    
    return true;
}

讲解:图像统一预处理到448×448分辨率,匹配模型训练尺寸;视觉编码完全跑在NPU上;生成的视觉token拼接到prompt前面,送进大语言模型做推理。

4.5 视频序列模式实现

视频模式下,多帧稀疏采样后逐帧编码,拼接时序信息,保留时间先后关系。

核心实现逻辑:

cpp 复制代码
bool VLLMEngine::LoadVideoFrames(const std::vector<cv::Mat>& frames) {
    // 1. 稀疏采样:均匀抽取关键帧,默认最多8帧
    int step = std::max(1, (int)frames.size() / 8);
    std::vector<cv::Mat> sampled_frames;
    for (int i = 0; i < frames.size(); i += step) {
        sampled_frames.push_back(frames[i]);
    }

    // 2. 逐帧编码,生成多组视觉token
    std::vector<std::vector<float>> all_frame_tokens;
    for (auto& frame : sampled_frames) {
        cv::Mat resized;
        cv::resize(frame, resized, cv::Size(448, 448));
        all_frame_tokens.push_back(vision_infer(vlm_context_, resized));
    }

    // 3. 按顺序拼接所有帧的视觉token
    std::vector<float> video_tokens;
    for (size_t i = 0; i < all_frame_tokens.size(); ++i) {
        video_tokens.insert(video_tokens.end(), 
            all_frame_tokens[i].begin(), all_frame_tokens[i].end());
    }

    // 4. 插入到语言模型上下文
    llm_context_.insert_vision_tokens(video_tokens);
    return true;
}

讲解:

  • 稀疏采样避免帧数太多爆显存,默认最多8帧,平衡信息量与计算量
  • 逐帧编码后按时间顺序拼接,保留先后关系
  • 所有视觉token一次性插入上下文,后面对话都基于整个视频序列

4.6 对话推理与流式输出

Ask方法负责接收文本prompt,拼接上下文,自回归生成回答,支持流式逐字输出。

核心实现逻辑:

cpp 复制代码
std::string VLLMEngine::Ask(const std::string& prompt) {
    std::string full_answer;
    
    // 1. 文本分词,加入当前对话上下文
    llm_context_.append_text(prompt);
    
    // 2. 自回归生成,逐个token输出
    while (true) {
        int next_token = llm_context_.step_decode();
        
        // 遇到结束符或者达到最大长度则停止
        if (next_token == EOS_TOKEN) break;
        if (full_answer.size() >= max_new_tokens_) break;
        
        // token转成字符串
        std::string word = tokenizer_.decode(next_token);
        full_answer += word;
        
        // 非静默模式则逐字打印,流式输出
        if (!silence_) {
            printf("%s", word.c_str());
            fflush(stdout);
        }
    }
    
    return full_answer;
}

讲解:

  • 每步解码生成一个token,遇到结束符停止
  • 流式输出实时打印,不用等完整回答,交互体验更好
  • 内部自动维护KV缓存,多轮对话自动累积

五、环境配置与运行全教程

5.1 硬件环境

  • 核心板:RK3588核心板/开发板,8GB内存以上推荐
  • 系统:Linux系统(Debian/Ubuntu/Yocto等)
  • 存储:至少10GB空闲空间

5.2 依赖安装

基础系统依赖
cpp 复制代码
sudo apt-get update
sudo apt-get upgrade
sudo apt-get install cmake wget curl build-essential
OpenCV安装

用于图像读取与预处理:

cpp 复制代码
sudo apt-get install libopencv-dev
NPU运行时库安装

需要对应版本的大模型运行时库与NPU驱动,版本必须对应,否则会出现分词不匹配等错误。

将库文件与头文件安装到系统目录:

cpp 复制代码
cd library
sudo cp *.so /usr/local/lib
cd ../include
sudo cp *.h /usr/local/include
sudo ldconfig

注意:模型版本必须和运行时版本严格对应,不同版本的模型不能混用。

5.3 获取模型

模型分为视觉编码器和语言模型两个文件,W8A8量化语言模型+FP16视觉编码器。将下载好的两个模型文件放入models目录。

5.4 编译工程

cpp 复制代码
mkdir build
cd build
cmake ..
make -j4

编译完成后生成可执行文件。

5.5 运行推理

单图像模式
cpp 复制代码
./vlm ./models/视觉编码器.rknn ./models/语言模型.rkllm ./test.jpg

进入交互式对话,输入问题即可,比如:

复制代码
用户: 描述这张图片
用户: 这是哪里
用户: exit
视频序列模式

传入多张图片即可自动进入视频模式:

复制代码
./多模态vlm  ./models/视觉编码器.rknn ./models/语言模型.rkllm ./frame1.jpg ./frame2.jpg ./frame3.jpg

5.6 参数调整建议

根据设备内存调整上下文大小:

  • 32GB设备(推荐)2048, 16384,支持长视频与多轮对话
  • 16GB设备2048, 8192,平衡性能与内存
  • 8GB设备1024, 2048,基础可用

5.7 常见问题

  • 版本不匹配报错:检查运行时库版本与模型版本是否一致,必须严格对应
  • 内存不足崩溃:调小最大上下文参数,减少最大输入帧数
  • 图像加载失败:检查OpenCV是否安装,图片路径是否正确

六、落地用途与场景

6.1 智能安防监控

RK3588是安防设备的主流芯片,这套方案可以直接嵌入监控摄像头,本地实现图像理解、异常检测、行为识别,不需要回传云端,隐私性好、延迟低。

6.2 工业视觉检测

工业质检、设备巡检场景,嵌入式设备本地跑多模态模型,识别缺陷、读取仪表、判断异常,不用联网,适合工厂内网环境。

6.3 智能终端设备

智能平板、手持终端、教育机器人等设备,本地部署多模态能力,支持看图问答、绘本阅读、物体识别,离线也能用。

6.4 离线视频分析

离线视频内容分析、关键帧提取、内容检索,不需要云端API,批量处理视频内容,数据不出本地,适合保密场景。

6.5 嵌入式多模态工具

离线翻译、看图识物、辅助驾驶等嵌入式工具,低功耗NPU长时间运行,不需要高性能CPU和GPU。

If you need the complete source code, please add the WeChat number (c17865354792)

七、总结

这套基于RK3588 NPU的Qwen3.5-2B视觉语言模型方案,用两阶段架构、W8A8量化、NPU全链路加速,在消费级嵌入式芯片上实现了完整的多模态推理能力。

它最大的价值是提供了一套可直接落地的端侧多模态参考实现,从模型、运行时到应用代码完整打通,不需要重型框架,不需要云端依赖,真正可以部署到嵌入式设备里,是端侧多模态AI非常有价值的工程实践。

Welcome to follow WeChat official account【程序猿编码

相关推荐
刘马想放假2 小时前
RK3588 使用 rk-llama.cpp + RKNPU2 部署 Qwen3.5:从零开始的 NPU 本地大模型实战
人工智能·开源·llm
殷紫川2 小时前
ZCode 把整个 Git 仓库加密上传到了阿里云 OSS:一次客户端逆向的完整复盘
llm·aigc
一颗无畏豆儿3 小时前
关于常用AI工具和大模型的总结
ai·大模型·llm·ai工具
武子康3 小时前
Expert Parallel 深入解析:专家分得均匀,负载为什么仍不均
人工智能·llm·agent
烈风逍遥4 小时前
LLM 流式调用工具类 LlmSseHelper解析
llm
桃西西呀4 小时前
本地 RAG 问答 Agent:切片即建模,幻觉即责任
人工智能·llm·agent
XianMing的博客4 小时前
《Attention Is All You Need》学习记录(从零吃透版)
人工智能·大模型
韩曙亮5 小时前
【AI 大模型】各 AI 大厂 Agent 平台各等级订阅会员对比分析 ( 字节 TRAE、腾讯 Buddy、阿里 Qoder CN、百度 DuMate )
人工智能·ai·大模型·ai大模型·qoder·workbuddy·traecode
五仁火烧5 小时前
大模型开发: MCP
java·大模型·mcp