RKNN-LLM 软件栈深度解析:RKLLM 模型转换量化与瑞芯微 NPU 端侧 LLM 部署实战

  • 大模型
  • 本地部署
  • 推理引擎
  • 模型量化
  • 嵌入式

【免费下载链接】rknn-llm

项目地址: https://gitcode.com/gh_mirrors/rk/rknn-llm
点击查看 免费下载

RKLLM 软件栈(RKNN-LLM)是瑞芯微(Rockchip)面向 AI 芯片推出的端侧大语言模型(LLM)部署方案,覆盖从 PC 端模型转换量化到开发板端 C/C++ API 推理的完整链路。本文以当前开源仓库 README.md 为主线,结合 rkllm.h、llm_demo.cpp、main.cpp 等源码与配置,系统讲解架构组成、支持范围、多模态快速上手、模型转换量化、C API 编程接口与性能测试方法,帮助开发者快速将 LLM 部署到 RK3588、RK3576、RK3562、RV1126B 等平台。

一、RKLLM 软件栈整体架构

RKLLM 软件栈由三个层次组成,帮助用户将 AI 模型快速部署到瑞芯微芯片上,整体框架如下图所示:

RKLLM 软件栈框架图:从 HuggingFace 开源模型经 RKLLM Toolkit 转换,再到 RKLLM Runtime API 与 RKNPU 驱动硬件加速

  • RKLLM-Toolkit:运行在 PC 上的软件开发工具包(SDK),负责把训练好的模型转换为 RKLLM 格式,并完成量化。用户先在电脑上完成转换,再把生成的 .rkllm 模型部署到开发板上。
  • RKLLM Runtime:面向瑞芯微 NPU 平台的 C/C++ 编程接口,负责加载 RKLLM 模型并加速 LLM 应用落地,对应仓库中的 rkllm-runtime 目录。
  • RKNPU 内核驱动:负责与 NPU 硬件交互的底层驱动,已在瑞芯微内核代码中开源,对应仓库中的 rknpu-driver 目录。

从源码结构看,整个部署链路是「PC 端转换 → 板端推理」两段式:转换阶段使用 rkllm-toolkit 目录下提供的 Python 包(whl 文件)与 examples/rkllm_api_demo/export/export_rkllm.py 等脚本;推理阶段使用 rkllm-runtime 目录下的 librkllmrt.so 动态库与 rkllm.h 头文件。

二、支持平台与支持模型

2.1 支持平台

RKLLM 软件栈支持以下四类瑞芯微平台:

平台说明
RK3588 Series高性能旗舰,常见于多模态与大模型应用
RK3576 Series中高端平台
RK3562 Series中低功耗平台
RV1126B Series轻量级平台(性能测试中可见 w4a16/w8a8 量化配置)

从 main.cpp 可以看到,板端程序会按平台区分 base_domain_id:rv1126b、rk3562 使用 0,rk3588、rk3576 使用 1,这也印证了不同平台的 NPU 域配置差异。

2.2 支持模型

README 中列出的已验证模型覆盖了主流开源 LLM 与多模态模型:

  • LLM 系列:LLAMA、TinyLLAMA、Qwen2/Qwen2.5/Qwen3/Qwen3.5、Phi2/Phi3、ChatGLM3-6B、Gemma2/Gemma3/Gemma3n/Gemma4、InternLM2、MiniCPM3/MiniCPM4、TeleChat2、DeepSeek-R1-Distill、RWKV7、SmolLM3 等。
  • 多模态系列:Qwen2-VL/Qwen3-VL、MiniCPM-V-2_6、Janus-Pro-1B、InternVL2-1B/InternVL3-1B、DeepSeekOCR 等。

RWKV7 模型转换仅支持 Python 3.12,需使用 requirements_rwkv7.txt 搭建 pip 环境(见 rkllm-toolkit/packages/requirements_rwkv7.txt)。多模态 demo 使用的开源模型可参考 examples/multimodal_model_demo/README.md。

三、快速开始:多模态视觉模型本地部署

README 推荐的快速体验路径是运行多模态视觉模型示例:该 demo 完全在本地设备上运行,视觉部分使用 RKNN,语言部分使用 RKLLM,可以上传自己的图片并提问,所有处理均在本地完成,数据不会离开设备。

3.1 下载与推送

  1. 从 rkllm_model_zoo 下载预转换模型与 demo 可执行文件(位于 quickstart 目录),取件码 rkllm。
  2. 通过 adb 将 demo 与模型文件推送到设备:
adb push ./demo_Linux_aarch64 /data
adb push model.rkllm /data/demo_Linux_aarch64
adb push model.rknn /data/demo_Linux_aarch64
  1. 进入 demo 目录并设置环境变量:
adb shell
cd /data/demo_Linux_aarch64
export LD_LIBRARY_PATH=./lib

3.2 运行 demo

demo 的命令行参数格式为:

Usage: ./demo image_path encoder_model_path llm_model_path max_new_tokens max_context_len rknn_core_num platform [img_start] [img_end] [img_content]

不同模型对应的运行命令示例(RK3588 平台,w8a8 量化模型):

# for Qwen2.5-VL
./demo demo.jpg ./qwen2_5_vl_3b_vision_rk3588.rknn ./qwen2.5-vl-3b-w8a8_level1_rk3588.rkllm 2048 4096 3 rk3588 "<|vision_start|>" "<|vision_end|>" "<|image_pad|>"

# for Qwen3-VL
./demo demo.jpg ./qwen3-vl-2b_vision_rk3588.rknn ./qwen3-vl-2b-instruct_w8a8_rk3588.rkllm 2048 4096 3 rk3588 "<|vision_start|>" "<|vision_end|>" "<|image_pad|>"

# for Qwen3.5
./demo demo.jpg ./Qwen3.5-0.8B_vision_rk3588.rknn ./Qwen3.5-0.8B_w8a8_rk3588.rkllm 2048 4096 3 rk3588 "<|vision_start|>" "<|vision_end|>" "<|image_pad|>"

# for InternVL3
./demo demo.jpg ./internvl3-1b_vision_fp16_rk3588.rknn ./internvl3-1b_w8a8_rk3588.rkllm 2048 4096 3 rk3588 "<img>" "</img>" "<IMG_CONTEXT>"

# for DeepSeekOCR
./demo demo.jpg ./deepseekocr_vision_rk3588.rknn ./deepseekocr_w8a8_rk3588.rkllm 2048 4096 3 rk3588 "" "" "<|▁pad▁|>"

参数说明:

  • max_new_tokens 与 max_context_len:分别控制单次生成的最大 token 数与上下文窗口长度。注意 max_context_len 必须大于 text-token-num + image-token-num + max_new_tokens,否则会因上下文不足而报错。
  • rknn_core_num:指定使用的 NPU 核心数,示例中为 3。
  • platform:可选 rk3588 | rk3576 | rk3562 | rv1126b,用于决定 base_domain_id。
  • [img_start]、[img_end]、[img_content]:图片占位标记,需在模型的配置文件(如 modeling_internvl_chat.py)中确认。例如 InternVL3 的 chat 接口默认值即为 IMG_START_TOKEN='<img>'、IMG_END_TOKEN='</img>'、IMG_CONTEXT_TOKEN='<IMG_CONTEXT>'。若缺省,main.cpp 会使用 Qwen 系列的默认值(<|vision_start|>、<|vision_end|>、<|image_pad|>)并打印警告,提醒用户按模型定制。

四、模型转换与量化:从 HuggingFace 到 RKLLM

4.1 RKLLM-Toolkit 安装与环境

  • 支持的 Python 版本:3.9 / 3.10 / 3.11 / 3.12,对应 rkllm-toolkit/packages 目录下的 rkllm_toolkit-1.3.0-cp{39,310,311,312}-*.whl。
  • 在 Python 3.12 环境安装前需先执行:
export BUILD_CUDA_EXT=0

4.2 纯文本 LLM 的转换量化流程

以 examples/rkllm_api_demo/export/export_rkllm.py 为例(该示例转换 DeepSeek-R1-Distill-Qwen-1.5B),流程分为三步:

第一步:生成量化校准数据。 量化 RKLLM 模型需要校准数据,demo 采用 fp16 模型生成结果作为量化校准数据:

cd export
python generate_data_quant.py -m /path/to/DeepSeek-R1-Distill-Qwen-1.5B

generate_data_quant.py 会使用 transformers 加载模型,对内置的多条中英文问答样本执行 model.generate,将结果整理为 data_quant.json,格式为:

[{"input": "Human: 你好!\nAssistant: ", "target": "你好!我是人工智能助手KK!"}, ...]

其中 input 必须带上提示词前缀。该脚本支持通过 --apply_chat_template(默认 True)套用 chat 模板、--max_new_tokens(默认 128)、--temperature(默认 0.6)、--repetition_penalty(默认 1.1)等参数控制生成行为。

第二步:加载并构建 RKLLM 模型。 核心代码如下:

from rkllm.api import RKLLM

llm = RKLLM()
# device 可选 ['cpu', 'cuda'];dtype 可选 ['float32', 'float16', 'bfloat16']
# 使用 float16/bfloat16 可显著降低内存占用,但精度略低于 float32
ret = llm.load_huggingface(model=modelpath, model_lora=None, device='cuda', dtype="float32",
                            custom_config=None, load_weight=True)
# 也支持 ret = llm.load_gguf(model = modelpath)

ret = llm.build(do_quantization=True, optimization_level=optimization_level,
                quantized_dtype=quantized_dtype, quantized_algorithm=quantized_algorithm,
                target_platform=target_platform, num_npu_core=num_npu_core,
                extra_qparams=qparams, dataset=dataset, hybrid_rate=0, max_context=4096)

关键配置项与取值:

配置项示例值说明
devicecpu / cuda加载权重时的计算设备,可用 export CUDA_VISIBLE_DEVICES=0 指定 GPU
dtypefloat32 / float16 / bfloat16权重加载精度,低精度更省内存但精度略降
target_platformRK3588 等目标 NPU 平台
optimization_level1(示例)优化级别;性能测试中要求设置为 0 以获得优化后的运行性能
quantized_dtypeW8A8 / W4A16 / W4A16_G128 等量化位宽组合
quantized_algorithmnormal / grq量化算法。w8a8 系列推荐 normal 算法,w4a16 系列推荐 grq 算法
num_npu_core3使用的 NPU 核心数
extra_qparamsNone附加量化参数(qparams),为 None 时使用默认
dataset./data_quant.json量化校准数据集
hybrid_rate0混合量化比例
max_context4096上下文长度

第三步:导出 RKLLM 模型:

ret = llm.export_rkllm(f"./{os.path.basename(modelpath)}_{quantized_dtype}_{target_platform}.rkllm")

产物即板端推理使用的 .rkllm 文件;已转换好的模型也可直接从 rkllm_model_zoo 下载。

4.3 多模态模型的转换

多模态模型需要把「视觉编码器(Vision)+ Projector」用 rknn-toolkit2 导出为 RKNN 模型,把 LLM 部分用 rkllm-toolkit 导出为 RKLLM 模型,详细步骤见 examples/multimodal_model_demo/README.md:

  1. 依赖版本:rkllm-toolkit>=1.3.0、rknn-toolkit2>=2.3.2(pip install rknn-toolkit2)。
  2. Qwen2-VL 使用 export/export_vision_qwen2.py 导出 ONNX:首次运行 --step 1 生成 cu_seqlens 与 rotary_pos_emb,第二次 --step 0 导出 ONNX;若修改 batch/height/width,必须重新生成这两个中间量。Qwen2.5-VL、Qwen3-VL、MiniCPM-V-2_6、SmolVLM、DeepSeekOCR、Qwen3.5、InternVL3 则使用 export/export_vision.py。
  3. 用 export/export_vision_rknn.py 配合 rknn-toolkit2 将 ONNX 转换为 RKNN(如 --target-platform rk3588)。
  4. LLM 部分:先用 data/make_input_embeds_for_quantize.py 基于 data/datasets.json(MMBench_DEV_EN 的 20 条图文样本)生成 data/inputs.json,再执行 export/export_rkllm.py 导出 RKLLM 模型。

注意:DeepSeekOCR 视觉模型转 ONNX 时,需将 deepencoder.py 中所有 F.interpolate 的 antialias 设为 False;转换 DeepSeekOCR 的 LLM 时需用 export/modeling_deepseekv2.py 替换原文件(因该模型仅支持旧版 transformers)。

五、RKLLM Runtime C API 详解

RKLLM Runtime 提供 C/C++ 接口,核心头文件为 rkllm-runtime/Linux/librkllm_api/include/rkllm.h(Android 侧位于 rkllm-runtime/Android/librkllm_api/include/rkllm.h),运行时库为各架构下的 librkllmrt.so。

5.1 核心 API 函数

API功能
rkllm_createDefaultParam()创建带默认值的 RKLLMParam
rkllm_init()初始化 LLM,传入参数与回调结构
rkllm_run() / rkllm_run_async()同步 / 异步执行推理
rkllm_abort() / rkllm_is_running()中止任务 / 查询是否在运行
rkllm_clear_kv_cache()按范围或整体清空 KV 缓存(可保留系统提示)
rkllm_get_kv_cache_size()获取各 batch 的 KV 缓存大小
rkllm_set_chat_template()自定义 system prompt、前缀与后缀模板
rkllm_set_function_tools()配置 function calling 工具集与工具响应标记
rkllm_load_lora() / rkllm_load_prompt_cache()加载 LoRA 适配器 / Prompt 缓存
rkllm_set_cross_attn_params()设置解码器交叉注意力参数
rkllm_destroy()释放 LLM 实例

5.2 关键数据结构

  • RKLLMParam:模型路径、max_context_len、max_new_tokens、采样参数(top_k/top_p/temperature/repeat_penalty/frequency_penalty/presence_penalty/mirostat 系列)、skip_special_token、ignore_eos_token(是否忽略 EOS token,v1.3.0 新增)、is_async,以及扩展参数 extend_param(base_domain_id、embed_flash(是否从 flash 查询词嵌入)、enabled_cpus_num、enabled_cpus_mask、n_batch(>1 启用 batch 推理)、use_cross_attn)。
  • RKLLMInput:联合体输入,按 input_type 区分四种输入:RKLLM_INPUT_PROMPT(文本提示)、RKLLM_INPUT_TOKEN(token 序列)、RKLLM_INPUT_EMBED(嵌入向量)、RKLLM_INPUT_MULTIMODAL(多模态,含 image/video 的 embed、token 数与起止标记)。role 字段标记 "user" 或 "tool",enable_thinking 控制 Qwen3 模型的思考模式。
  • RKLLMInferParam:推理参数,含 mode(RKLLM_INFER_GENERATE / RKLLM_INFER_GET_LAST_HIDDEN_LAYER / RKLLM_INFER_GET_LOGITS)、lora_params、prompt_cache_params、sampling_params(设置后覆盖初始化时的采样参数)、keep_history(是否保留上下文)与 max_new_tokens(覆盖初始化值,≤0 使用初始值,v1.3.0 新增)。
  • RKLLMCallback:result_callback 接收 RKLLMResult(含 text、token_id、last_hidden_layer、logits、perf),通过 LLMCallState(RKLLM_RUN_NORMAL/WAITING/FINISH/ERROR)区分状态。回调返回值语义:返回 0 继续正常推理;返回 1 暂停推理(可修改/注入内容后调用 rkllm_run 恢复);返回 2 释放当前输出缓冲(在 GET_LAST_HIDDEN_LAYER / GET_LOGITS 模式下大词表会占用大量内存,应及时释放)。此外还支持 tokenizer_callback 与 embed_callback(模型缺少内建 tokenizer / embedding 层时必需,v1.3.0 新增)。
  • RKLLMPerfStat:prefill_time_ms、prefill_tokens、generate_time_ms、generate_tokens、memory_usage_mb(VmHWM),用于日志输出性能与内存占用。

5.3 最小初始化与采样配置示例

参考 llm_demo.cpp:

RKLLMParam param = rkllm_createDefaultParam();
param.model_path = argv[1];
param.top_k = 1;
param.top_p = 0.95;
param.temperature = 0.8;
param.repeat_penalty = 1.1;
param.frequency_penalty = 0.0;
param.presence_penalty = 0.0;
param.max_new_tokens = std::atoi(argv[2]);
param.max_context_len = std::atoi(argv[3]);
param.skip_special_token = true;
param.extend_param.base_domain_id = 0;
param.extend_param.embed_flash = 1;

RKLLMCallback rkllm_callback = {};
rkllm_callback.result_callback = callback;
int ret = rkllm_init(&llmHandle, &param, &rkllm_callback);

六、板端 C++ Demo 实战

6.1 纯文本 API Demo(rkllm_api_demo)

examples/rkllm_api_demo/README.md 演示部署 DeepSeek-R1-Distill-Qwen-1.5B:

cd deploy
./build-linux.sh        # 或 ./build-android.sh(替换交叉编译器路径)
adb push install/demo_Linux_aarch64 /data
adb push DeepSeek-R1-Distill-Qwen-1.5B.rkllm /data/demo_Linux_aarch64
adb push ../../../scripts/fix_freq_rk3588.sh /data/demo_Linux_aarch64

板端运行:

adb shell
cd /data/demo_Linux_aarch64
export LD_LIBRARY_PATH=./lib
sh fix_freq_rk3588.sh        # 设置固定频率
export RKLLM_LOG_LEVEL=1     # 输出推理性能与内存日志
./llm_demo /path/to/your/rkllm/model 2048 4096

demo 启动后会打印 rkllm init start → rkllm init success,然后进入交互式问答。用户可输入预设题目序号或自定义文本,输入 exit 退出、clear 调用 rkllm_clear_kv_cache 清空 KV 缓存(见 llm_demo.cpp)。示例输出展示了 DeepSeek-R1 的 <think> 推理过程,例如鸡兔同笼问题可正确得到"鸡 9 只、兔 5 只"。

6.2 多模态 C++ Demo(multimodal_model_demo)

examples/multimodal_model_demo/deploy 演示"图像输入 → 图像特征 → 多模态推理"的完整流程,编译后生成 imgenc、llm、demo 可执行文件与 lib 目录。运行方式:

adb shell
cd /data/demo_Linux_aarch64
export LD_LIBRARY_PATH=./lib
ln -s /data/models .
./imgenc models/qwen2-vl-vision_rk3588.rknn demo.jpg 3
./demo demo.jpg models/qwen2-vl-vision_rk3588.rknn models/qwen2-vl-llm_rk3588.rkllm 2048 4096 3 rk3588 "<|vision_start|>" "<|vision_end|>" "<|image_pad|>"

从 main.cpp 可以看到图像预处理细节:读取 BGR 图像后转为 RGB,调用 expand2square 将图像扩展为正方形并以 (127.5,127.5,127.5) 背景填充,再按 RKNN 模型输入尺寸线性缩放;run_imgenc 在 NPU 上完成视觉编码并输出 img_vec.bin(含图像特征)。输入含 <image> 标记时构造 RKLLM_INPUT_MULTIMODAL 输入,否则走纯文本 RKLLM_INPUT_PROMPT 路径。示例问答:

user: <image>What is in the image?
robot: The image depicts an astronaut on the moon, enjoying a beer. The background shows the Earth and stars, creating a surreal and futuristic scene.

6.3 API Server Demo

如需通过 HTTP 接口提供服务,可参考 examples/rkllm_server_demo,其提供 flask 与 gradio 两种服务器实现(flask_server.py、gradio_server.py)及对应构建脚本,v1.3.0 起进一步提升了与 OpenAI API 接口的兼容性。

七、性能测试方法

README 给出了标准的性能测试四步法:

  1. 设置固定频率:在目标平台运行 scripts 目录下的频率设置脚本,如 fix_freq_rk3588.sh、fix_freq_rk3576.sh、fix_freq_rk3562.sh、fix_freq_rv1126b.sh。benchmark 数据均基于各平台最大 CPU/NPU 频率采集。
  2. 开启性能日志:在设备上执行 export RKLLM_LOG_LEVEL=1,输出模型推理性能与内存占用(对应 RKLLMPerfStat 中的 prefill/generate 时间与 VmHWM 内存)。
  3. 测量 CPU 占用:运行 eval_perf_watch_cpu.sh。
  4. 测量 NPU 占用:运行 eval_perf_watch_npu.sh。

各平台常见模型的 TTFT、Tokens/s、内存占用数据可参考 benchmark.md,其中包含 RK3588、RK3576、RK3562、RV1126B 四平台的纯文本 LLM 数据表,以及 Qwen2-VL-2B、Qwen2.5-VL-3B、MiniCPM-V-2_6、SmolVLM-256M、Qwen3-VL-2B、DeepSeekOCR-3B、Qwen3.5-0.8B 等模型的多模态分阶段数据(img-encoder 推理时间 / Prefill / Decode tokens/s)。例如 RK3588 平台 Qwen2-0.5B(w8a8、seqlen 128、new_tokens 64)TTFT 约 145.90 ms、41.58 tokens/s;RK3576 平台同配置下 w4a16 与 w8a8 的 Tokens/s 分别为 32.56 与 21.73。测试前提请以 benchmark.md 说明为准:所有模型转换时 optimization_level 需设为 0,且图像编码器使用 FP16、全部 NPU 核心。

八、安装与运行注意事项

  • Python 版本:RKLLM-Toolkit 支持 Python 3.9 ~ 3.12;Python 3.12 环境安装前需 export BUILD_CUDA_EXT=0。
  • libomp.so 缺失:部分平台可能报 libomp.so 找不到,需在对应交叉编译工具链中找到该库,放置到板端 lib 目录(与 librkllmrt.so 同级)。
  • RWKV 模型:转换仅支持 Python 3.12,使用 requirements_rwkv7.txt 配置 pip 环境。
  • 板端运行:务必 export LD_LIBRARY_PATH=./lib;多模态场景 max_context_len 必须大于文本 token 数 + 图像 token 数 + max_new_tokens。
  • 最新版本:仓库当前标注版本为 v1.3.0,历史版本变更见 CHANGELOG.md。

九、v1.3.0 关键更新

当前仓库对应的 v1.3.0 版本(详见 CHANGELOG.md 与 README 的 CHANGELOG 小节)主要更新包括:

  • 新增 Qwen3.5、Gemma4、SmolLM3 模型支持。
  • 优化多模态输入接口与缓存复用策略。
  • 支持多个 EOS token ID,新增 ignore_eos_token 参数。
  • 优化 32 位系统性能。
  • 新增 tokenizer 与 embedding 回调(对应 RKLLMCallback 中的 tokenizer_callback / embed_callback)。
  • 优化 RK3576 平台部分模型的长上下文解码性能。
  • 优化 embedding 输入数据的量化方法。
  • 修复 RV1126B 平台内存统计与 RK3588 平台部分模型推理数值溢出问题。
  • 提升 rkllm_server_demo 与 OpenAI API 接口的兼容性。
  • 支持在 RKLLMInferParam 中覆盖 max_new_tokens 与采样参数。

十、延伸:RKNN-Toolkit2 与更多模型

如需部署 RKLLM 之外的更多 AI 模型,瑞芯微提供了 RKNN-Toolkit2 SDK,README 将其作为补充方案单独列出。当前仓库的 examples/multimodal_model_demo/export 目录即同时包含 RKNN 视觉模型导出脚本(export_vision.py、export_vision_rknn.py)与 RKLLM 导出脚本(export_rkllm.py),体现了"视觉走 RKNN、语言走 RKLLM"的典型多模态部署组合。

总结

RKNN-LLM 软件栈以"PC 端 RKLLM-Toolkit 转换量化 + 板端 RKLLM Runtime C API 推理 + RKNPU 驱动硬件加速"的三层架构,覆盖了从文本 LLM 到多模态视觉模型在瑞芯微四大平台的完整部署路径。本文结合 README 与仓库源码,从快速体验、模型转换、API 编程、板端实战到性能测试给出了可复现的操作流程;建议读者进一步阅读 benchmark.md 选择合适模型与量化配置,并参考 examples 下的三个 demo 工程动手实践。

  • 大模型
  • 本地部署
  • 推理引擎
  • 模型量化
  • 嵌入式

【免费下载链接】rknn-llm

项目地址: https://gitcode.com/gh_mirrors/rk/rknn-llm
点击查看 免费下载

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值