### Installation Rules for Executables and Libraries
Source: https://github.com/airockchip/rknn-llm/blob/main/examples/multimodal_model_demo/deploy/CMakeLists.txt
Configures the installation prefix based on the source directory and target system architecture. It then installs the built executables ('imgenc', demo executable) and runtime libraries ('librknnrt.so', 'librkllmrt.so') to their respective destinations.
```cmake
# Install the executable file to the specified directory
set(CMAKE_INSTALL_PREFIX ${CMAKE_SOURCE_DIR}/install/demo_${CMAKE_SYSTEM_NAME}_${TARGET_LIB_ARCH})
install(TARGETS imgenc ${PROJECT_NAME} DESTINATION ./)
install(PROGRAMS ${LIBRKNNRT} ${LIBRKLLMRT} DESTINATION lib)
install(PROGRAMS ../data/demo.jpg DESTINATION ./)
```
--------------------------------
### RKLLMClient Quick Start for Function Calling
Source: https://github.com/airockchip/rknn-llm/blob/main/examples/rkllm_server_demo/README.md
Demonstrates using RKLLMClient for function calling. This involves parsing tool calls, executing them, and synthesizing a final answer.
```python
from chat_api_flask import RKLLMClient, TOOLS, parse_tool_calls, execute_tool_calls
client = RKLLMClient(base_url="http://x.x.x.x:8080")
messages = [
{"role": "system", "content": "You are Qwen, created by Alibaba Cloud. You are a helpful assistant.\nCurrent Date: 2024-09-30"},
{"role": "user", "content": "What's the temperature in San Francisco now? How about tomorrow?"},
]
# Step 1: Model returns which tools to call and with what arguments
resp = client.chat(messages=messages, tools=TOOLS, stream=False)
tool_calls = parse_tool_calls(resp["choices"][0]["message"]["content"])
# Step 2: Execute tool calls and append results to messages
assistant_msg, tool_msgs = execute_tool_calls(tool_calls)
messages.append(assistant_msg)
messages.extend(tool_msgs)
# Step 3: Model synthesizes the final answer from tool results
resp = client.chat(messages=messages, tools=None, stream=False)
print("A:", resp["choices"][0]["message"]["content"])
```
--------------------------------
### Compile and Build C++ Demo
Source: https://github.com/airockchip/rknn-llm/blob/main/examples/multimodal_model_demo/README.md
Scripts to compile the C++ example code for Linux and Android. Ensure the cross-compiler path is correctly set. This generates an executable demo in the deploy directory.
```bash
cd deploy
# for linux
./build-linux.sh
# for android
./build-android.sh
# push install dir to device
adb push ./install/demo_Linux_aarch64 /data
# push model file to device
adb push qwen2-vl-vision_rk3588.rknn /data/models
adb push qwen2-vl-llm_rk3588.rkllm /data/models
```
--------------------------------
### LLM Demo Interaction Example
Source: https://github.com/airockchip/rknn-llm/blob/main/examples/rkllm_api_demo/README.md
Example of interacting with the LLM demo by providing a question number or custom input.
```text
user:
```
example 1 (DeepSeek-R1-Distill-Qwen-1.5B_W8A8_RK3588.rkllm)
```
user: 0
现有一笼子,里面有鸡和兔子若干只,数一数,共有头14个,腿38条,求鸡和兔子各有多少只?
robot:
首先,设鸡的数量为x,兔子的数量为y。
根据题目中的条件,我们知道:
1. 鸡和兔子的总数是14,因此有方程:
x + y = 14
2. 鸡有两条腿,兔子有四条腿,总腿数是38,所以有另一个方程:
2x + 4y = 38
接下来,通过代入法或消元法来解这两个方程。假设我们用代入法:
从第一个方程中,可以得到:
x = 14 - y
将这个表达式代入第二个方程:
2(14 - y) + 4y = 38
展开计算后得到:
28 - 2y + 4y = 38
合并同类项:
2y = 10
解得:
y = 5
然后,将y的值代入x = 14 - y中:
x = 14 - 5 = 9
因此,鸡有9只,兔子有5只。
要解决这个问题,我们可以设鸡的数量为 \( x \),兔子的数量为 \( y \)。根据题目给出的条件:
1. **头的总数**:每只鸡和兔子都有一个头,所以:
\[
x + y = 14
\]
2. **腿的总数**:鸡有两条腿,兔子有四条腿,总腿数为38条,因此:
\[
2x + 4y = 38
\]
接下来,我们可以通过解这两个方程来找到 \( x \) 和 \( y \) 的值。
**步骤一:简化第二个方程**
将第二个方程两边同时除以2:
\[
x + 2y = 19
\]
现在,我们有两个方程:
\[
\begin{cases}
x + y = 14 \\
x + 2y = 19
\end{cases}
\]
**步骤二:消元法**
用第二个方程减去第一个方程:
\[
(x + 2y) - (x + y) = 19 - 14 \\
y = 5
\]
**步骤三:代入求 \( x \)**
将 \( y = 5 \) 代入第一个方程:
\[
x + 5 = 14 \\
x = 14 - 5 \\
x = 9
\]
因此,鸡的数量是 **9只**,兔子的数量是 **5只**。
**最终答案:**
鸡有 \(\boxed{9}\) 只,兔子有 \(\boxed{5}\) 只。
```
example 2 (DeepSeek-R1-Distill-Qwen-1.5B_W8A8_RK3588.rkllm)
```
user: 1
有28位小朋友排成一行,从左边开始数第10位是学豆,从右边开始数他是第几位?
robot:
首先,总共有28位小朋友。
从左边开始数,第10位是学豆的位置。
因此,从右边开始数,学豆的位置是从右边数的第(28 - 10 + 1) = 第19位。
**解答:**
我们有28位小朋友排成一行。题目要求确定从右边开始数时,第10位是学豆的位置。
**步骤如下:**
1. **总人数**:共有28位小朋友。
2. **左边数的顺序**:从左边开始数,第10位是学豆。
3. **右边数的计算**:
- 从右边数时,第1位对应左边数的第28位。
- 因此,第n位在左边对应的是第(28 - n + 1)位在右边。
4. **具体计算**:
\[
第10位在左边 = 第(28 - 10 + 1) = 第19位在右边
\]
**最终答案:**
\boxed{19}
```
```
--------------------------------
### InternVL3 Image Token Configuration Example
Source: https://github.com/airockchip/rknn-llm/blob/main/README.md
This Python code snippet shows how to define image start, end, and context tokens within the chat function for the InternVL3 model.
```python
def chat(self, tokenizer, pixel_values, question, generation_config, history=None, return_history=False,
num_patches_list=None, IMG_START_TOKEN='
', IMG_END_TOKEN='', IMG_CONTEXT_TOKEN='',
verbose=False):
```
--------------------------------
### Compile and Build C++ Demo
Source: https://github.com/airockchip/rknn-llm/blob/main/examples/rkllm_api_demo/Readme.md
Scripts to compile the C++ LLM demo for Linux or Android. After compilation, the install directory will contain executables and libraries.
```bash
cd deploy
# for linux
./build-linux.sh
# for android
./build-android.sh
```
--------------------------------
### Example 1: Chicken and Rabbit Problem
Source: https://github.com/airockchip/rknn-llm/blob/main/examples/rkllm_api_demo/Readme.md
Solves a classic word problem involving chickens and rabbits with a given number of heads and legs. This example demonstrates basic arithmetic and algebraic equation solving.
```python
user:
```
example 1 (DeepSeek-R1-Distill-Qwen-1.5B_W8A8_RK3588.rkllm)
```
user: 0
现有一笼子,里面有鸡和兔子若干只,数一数,共有头14个,腿38条,求鸡和兔子各有多少只?
robot:
首先,设鸡的数量为x,兔子的数量为y。
根据题目中的条件,我们知道:
1. 鸡和兔子的总数是14,因此有方程:
x + y = 14
2. 鸡有两条腿,兔子有四条腿,总腿数是38,所以有另一个方程:
2x + 4y = 38
接下来,通过代入法或消元法来解这两个方程。假设我们用代入法:
从第一个方程中,可以得到:
x = 14 - y
将这个表达式代入第二个方程:
2(14 - y) + 4y = 38
展开计算后得到:
28 - 2y + 4y = 38
合并同类项:
2y = 10
解得:
y = 5
然后,将y的值代入x = 14 - y中:
x = 14 - 5 = 9
因此,鸡有9只,兔子有5只。
要解决这个问题,我们可以设鸡的数量为 \( x \),兔子的数量为 \( y \)。根据题目给出的条件:
1. **头的总数**:每只鸡和兔子都有一个头,所以:
[ \nx + y = 14 \n]
2. **腿的总数**:鸡有两条腿,兔子有四条腿,总腿数为38条,因此:
[ \n2x + 4y = 38 \n]
接下来,我们可以通过解这两个方程来找到 \( x \) 和 \( y \) 的值。
**步骤一:简化第二个方程**
将第二个方程两边同时除以2:
[ \nx + 2y = 19 \n]
现在,我们有两个方程:
[ \n\begin{cases}
x + y = 14 \\
x + 2y = 19
\end{cases}
]
**步骤二:消元法**
用第二个方程减去第一个方程:
[ \n(x + 2y) - (x + y) = 19 - 14 \\
y = 5
]
**步骤三:代入求 \( x \)**
将 \( y = 5 \) 代入第一个方程:
[ \nx + 5 = 14 \\
x = 14 - 5 \\
x = 9
]
因此,鸡的数量是 **9只**,兔子的数量是 **5只**。
**最终答案:**
鸡有 \(\boxed{9}\) 只,兔子有 \(\boxed{5}\) 只。
```
--------------------------------
### Basic CMake Project Setup
Source: https://github.com/airockchip/rknn-llm/blob/main/examples/multimodal_model_demo/deploy/CMakeLists.txt
Sets the minimum CMake version, project name, and defines C++ compiler flags for the project. It also includes conditional link options for specific CMake versions and Linux systems.
```cmake
cmake_minimum_required(VERSION 3.15.1)
project(demo)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wl,--allow-shlib-undefined")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wl,--allow-shlib-undefined")
if(${CMAKE_VERSION} VERSION_GREATER "3.15.0" AND CMAKE_SYSTEM_NAME STREQUAL "Linux")
add_link_options("-Wl,-Bsymbolic")
endif()
```
--------------------------------
### RKLLMClient Quick Start for Regular Chat
Source: https://github.com/airockchip/rknn-llm/blob/main/examples/rkllm_server_demo/README.md
Use the RKLLMClient wrapper for simple chat interactions. Supports both non-streaming and streaming responses.
```python
from chat_api_flask import RKLLMClient
client = RKLLMClient(base_url="http://x.x.x.x:8080")
# Non-streaming
reply = client.chat_simple("Hello, introduce yourself please.")
print(reply)
# Streaming
for chunk in client.chat(messages=[{"role": "user", "content": "Hello"}], stream=True):
print(chunk["content"], end="", flush=True)
```
--------------------------------
### CMakeLists.txt Configuration for RKLLM API Demo
Source: https://github.com/airockchip/rknn-llm/blob/main/examples/rkllm_api_demo/deploy/CMakeLists.txt
This snippet shows the main CMakeLists.txt file for the RKLLM API demo. It sets up the project, C++ standard, determines the target architecture based on the system, and configures build and installation paths.
```cmake
cmake_minimum_required(VERSION 3.10)
project(rkllm_demo)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
if (CMAKE_SYSTEM_NAME STREQUAL "Android")
set (TARGET_LIB_ARCH ${CMAKE_ANDROID_ARCH_ABI})
else()
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
set (TARGET_LIB_ARCH aarch64)
else()
set (TARGET_LIB_ARCH armhf)
endif()
if (CMAKE_C_COMPILER MATCHES "uclibc")
set (TARGET_LIB_ARCH ${TARGET_LIB_ARCH}_uclibc)
endif()
endif()
set(SOURCE_FILES_1 src/llm_demo.cpp)
add_executable(llm_demo ${SOURCE_FILES_1})
set(RKLLM_API_PATH "${CMAKE_SOURCE_DIR}/../../../rkllm-runtime/${CMAKE_SYSTEM_NAME}/librkllm_api")
include_directories(${RKLLM_API_PATH}/include)
if(CMAKE_SYSTEM_NAME STREQUAL "Android")
set(RKLLM_RT_LIB ${RKLLM_API_PATH}/${CMAKE_ANDROID_ARCH_ABI}/librkllmrt.so)
find_package(OpenMP REQUIRED)
target_link_libraries(llm_demo ${RKLLM_RT_LIB} log OpenMP::OpenMP_CXX)
elseif(CMAKE_SYSTEM_NAME STREQUAL "Linux")
set(RKLLM_RT_LIB ${RKLLM_API_PATH}/${CMAKE_SYSTEM_PROCESSOR}/librkllmrt.so)
target_link_libraries(llm_demo ${RKLLM_RT_LIB})
endif()
# Install the executable file to the specified directory
set(CMAKE_INSTALL_PREFIX ${CMAKE_SOURCE_DIR}/install/demo_${CMAKE_SYSTEM_NAME}_${TARGET_LIB_ARCH})
install(TARGETS llm_demo DESTINATION ./)
install(PROGRAMS ${RKLLM_RT_LIB} DESTINATION lib)
```
--------------------------------
### Convert Qwen3-VL Vision Model to ONNX and RKNN
Source: https://github.com/airockchip/rknn-llm/blob/main/examples/multimodal_model_demo/README.md
Steps to convert the Qwen3-VL vision model. This involves installing a specific transformers version, exporting to ONNX format, and then converting the ONNX model to RKNN format.
```bash
1、pip install transformers==4.57.0
2、python export_vision.py --path=/path/to/Qwen3-VL --model_name=qwen3-vl --height=448 --width=448
3、python export_vision_rknn.py --path=./onnx/qwen3-vl_vision.onnx --model_name=qwen3-vl --height=448 --width=448
```
--------------------------------
### Set Build CUDA Extension to 0 for Python 3.12
Source: https://github.com/airockchip/rknn-llm/blob/main/README.md
Before installing the RKLLM package in a Python 3.12 environment, set the BUILD_CUDA_EXT environment variable to 0.
```bash
export BUILD_CUDA_EXT=0
```
--------------------------------
### Example 2: Positional Counting Problem
Source: https://github.com/airockchip/rknn-llm/blob/main/examples/rkllm_api_demo/Readme.md
Determines the position of an individual from the right end of a line, given their position from the left end and the total number of people. This demonstrates basic counting and positional logic.
```python
example 2 (DeepSeek-R1-Distill-Qwen-1.5B_W8A8_RK3588.rkllm)
```
user: 1
有28位小朋友排成一行,从左边开始数第10位是学豆,从右边开始数他是第几位?
robot:
首先,总共有28位小朋友。
从左边开始数,第10位是学豆的位置。
因此,从右边开始数,学豆的位置是从右边数的第(28 - 10 + 1) = 第19位。
**解答:**
我们有28位小朋友排成一行。题目要求确定从右边开始数时,第10位是学豆的位置。
**步骤如下:**
1. **总人数**:共有28位小朋友。
2. **左边数的顺序**:从左边开始数,第10位是学豆。
3. **右边数的计算**:
- 从右边数时,第1位对应左边数的第28位。
- 因此,第n位在左边对应的是第(28 - n + 1)位在右边。
4. **具体计算**:
[ \n第10位在左边 = 第(28 - 10 + 1) = 第19位在右边
]
**最终答案:**
\boxed{19}
```
--------------------------------
### Run Demo with Qwen3-VL Model
Source: https://github.com/airockchip/rknn-llm/blob/main/README.md
Execute the demo with the Qwen3-VL model, specifying image path, RKNN encoder model, RKLLM language model, and tokenization parameters.
```bash
./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|>"
```
--------------------------------
### Deploy and Run C++ Demo
Source: https://github.com/airockchip/rknn-llm/blob/main/examples/rkllm_api_demo/Readme.md
Commands to push the compiled demo to a device, set environment variables, and run the LLM inference executable. Adjust model path and memory parameters as needed.
```bash
adb push install/demo_Linux_aarch64 /data
# push model file to device
adb push DeepSeek-R1-Distill-Qwen-1.5B.rkllm /data/demo_Linux_aarch64
# push the appropriate fixed-frequency script to the device
adb push ../../../scripts/fix_freq_rk3588.sh /data/demo_Linux_aarch64
adb shell
cd /data/demo_Linux_aarch64
# export lib path
export LD_LIBRARY_PATH=./lib
# Execute the fixed-frequency script
sh fix_freq_rk3588.sh
# Set the logging level for performance analysis
export RKLLM_LOG_LEVEL=1
./llm_demo /path/to/your/rkllm/model 2048 4096
```
--------------------------------
### Second Call: Get Final Answer
Source: https://github.com/airockchip/rknn-llm/blob/main/examples/rkllm_server_demo/README.md
Send the updated messages, including the tool execution results, back to the RKLLM server to get the final answer from the model.
```python
data["messages"] = messages
resp = session.post(server_url, json=data, headers=headers)
print("A:", resp.json()["choices"][0]["message"]["content"])
# Example output:
# A: The current temperature in San Francisco is 26.1°C.
# Tomorrow, the temperature is expected to be 25.9°C.
```
--------------------------------
### Run Demo with Qwen2.5-VL Model
Source: https://github.com/airockchip/rknn-llm/blob/main/README.md
Execute the demo with the Qwen2.5-VL model, specifying image path, RKNN encoder model, RKLLM language model, and tokenization parameters.
```bash
./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|>"
```
--------------------------------
### Run Demo with Qwen3.5 Model
Source: https://github.com/airockchip/rknn-llm/blob/main/README.md
Execute the demo with the Qwen3.5 model, specifying image path, RKNN encoder model, RKLLM language model, and tokenization parameters.
```bash
./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|>"
```
--------------------------------
### Run C++ LLM Demo
Source: https://github.com/airockchip/rknn-llm/blob/main/examples/rkllm_api_demo/README.md
Execute the compiled LLM demo on the device. Set environment variables for library paths and logging, then run the demo with the model path and context/generation lengths.
```bash
adb shell
cd /data/demo_Linux_aarch64
# export lib path
export LD_LIBRARY_PATH=./lib
# Execute the fixed-frequency script
sh fix_freq_rk3588.sh
# Set the logging level for performance analysis
export RKLLM_LOG_LEVEL=1
./llm_demo /path/to/your/rkllm/model 2048 4096
```
--------------------------------
### Run Demo with InternVL3 Model
Source: https://github.com/airockchip/rknn-llm/blob/main/README.md
Execute the demo with the InternVL3 model, specifying image path, RKNN encoder model, RKLLM language model, and specific image token placeholders.
```bash
./demo demo.jpg ./internvl3-1b_vision_fp16_rk3588.rknn ./internvl3-1b_w8a8_rk3588.rkllm 2048 4096 3 rk3588 "
" "" ""
```
--------------------------------
### Push Demo and Model Files to Device
Source: https://github.com/airockchip/rknn-llm/blob/main/README.md
Use adb to push the demo executable and model files to the device's /data directory. Ensure you have the necessary model files and the demo executable.
```bash
adb push ./demo_Linux_aarch64 /data
adb push model.rkllm /data/demo_Linux_aarch64
adb push model.rknn /data/demo_Linux_aarch64
```
--------------------------------
### Run Interactive Chat Demo
Source: https://github.com/airockchip/rknn-llm/blob/main/examples/rkllm_server_demo/README.md
Launches the built-in interactive chat demo for the server. Replace with the actual IP address.
```bash
# Interactive chat (Demo 1)
python chat_api_flask.py --server http://:8080
# Disable streaming
python chat_api_flask.py --server http://:8080 --no-stream
```
--------------------------------
### Set Up Environment Variables on Device
Source: https://github.com/airockchip/rknn-llm/blob/main/README.md
Connect to the device via adb shell, navigate to the demo directory, and set the LD_LIBRARY_PATH environment variable to include the local lib directory.
```bash
adb shell
cd /data/demo_Linux_aarch64
export LD_LIBRARY_PATH=./lib
```
--------------------------------
### First Call: Model Returns Tool Invocation Instructions
Source: https://github.com/airockchip/rknn-llm/blob/main/examples/rkllm_server_demo/README.md
Send an initial request to the RKLLM server with user messages and tool definitions. The model will respond with instructions to call specific tools.
```python
messages = [
{"role": "system", "content": "You are Qwen, created by Alibaba Cloud. You are a helpful assistant.\nCurrent Date: 2024-09-30"},
{"role": "user", "content": "What's the temperature in San Francisco now? How about tomorrow?"},
]
data = {
"model": "rkllm",
"messages": messages,
"stream": False,
"tools": TOOLS,
}
resp = session.post(server_url, json=data, headers=headers)
server_answer = resp.json()["choices"][0]["message"]["content"]
# Example model output:
#
# {"name": "get_current_temperature", "arguments": {"location": "San Francisco"}}
#
#
# {"name": "get_temperature_date", "arguments": {"location": "San Francisco", "date": "2024-10-01"}}
#
```
--------------------------------
### Build Gradio Server for RKLLM
Source: https://github.com/airockchip/rknn-llm/blob/main/examples/rkllm_server_demo/README.md
Builds and deploys the Gradio server for a web UI. Ensure the model path and platform are correctly specified.
```bash
# Usage: ./build_rkllm_server_gradio.sh --workshop [Working Path] --model_path [Absolute Path of RKLLM Model on Board] --platform [Target Platform: rk3588/rk3576] [--lora_model_path [Lora Model Path]] [--prompt_cache_path [Prompt Cache File Path]] [--adb_device [ADB Device Serial]]
./build_rkllm_server_gradio.sh --workshop /userdata --model_path /userdata/model.rkllm --platform rk3588 --adb_device 1234567890abcdef
```
--------------------------------
### Compile and Build C++ Demo
Source: https://github.com/airockchip/rknn-llm/blob/main/examples/rkllm_api_demo/README.md
Scripts to compile the C++ LLM demo for Linux or Android. After compilation, push the necessary files to the target device.
```bash
cd deploy
# for linux
./build-linux.sh
# for android
./build-android.sh
# push install dir to device
adb push install/demo_Linux_aarch64 /data
# push model file to device
adb push DeepSeek-R1-Distill-Qwen-1.5B.rkllm /data/demo_Linux_aarch64
# push the appropriate fixed-frequency script to the device
adb push ../../../scripts/fix_freq_rk3588.sh /data/demo_Linux_aarch4
```
--------------------------------
### Convert DeepSeekOCR Vision Model to ONNX and RKNN
Source: https://github.com/airockchip/rknn-llm/blob/main/examples/multimodal_model_demo/README.md
Steps to convert the DeepSeekOCR vision model. This involves installing a specific ONNX version, exporting to ONNX format, and then converting the ONNX model to RKNN format. Note the requirement to set 'antialias' to False for F.interpolate calls in deepencoder.py.
```bash
1、pip install onnx==1.18.0
2、python export_vision.py --path=/path/to/DeepSeek-OCR --model_name=deepseekocr --height=448 --width=448
3、python export_vision_rknn.py --path=./onnx/deepseekocr_vision.onnx --model_name=deepseekocr --height=448 --width=448
```
--------------------------------
### Run HuggingFace Multimodal Model Demo
Source: https://github.com/airockchip/rknn-llm/blob/main/examples/multimodal_model_demo/README.md
Execute the inference script for the Qwen2-VL demo. Ensure the model path in 'infer.py' is correctly set before running.
```bash
cd examples/Qwen2-VL_Demo
python infer.py
# expect results:
["The image depicts an astronaut in a white spacesuit, reclining on a green chair with his feet up. He is holding a green beer bottle in his right hand. The astronaut is on a moon-like surface, with the Earth visible in the background. The scene is set against a backdrop of stars and the moon's surface, creating a surreal and whimsical atmosphere."]
```
--------------------------------
### Main Demo Executable Build and Linking
Source: https://github.com/airockchip/rknn-llm/blob/main/examples/multimodal_model_demo/deploy/CMakeLists.txt
Builds the main demo executable, linking against OpenCV, rknn runtime, and rkllm runtime libraries. It includes platform-specific linking for Android (adding the 'log' library).
```cmake
# demo
add_executable(${PROJECT_NAME} src/image_enc.cc src/main.cpp)
if(CMAKE_SYSTEM_NAME STREQUAL "Android")
target_link_libraries(${PROJECT_NAME} PRIVATE ${OpenCV_LIBS} ${LIBRKNNRT} ${LIBRKLLMRT} log)
else()
target_link_libraries(${PROJECT_NAME} PRIVATE ${OpenCV_LIBS} ${LIBRKNNRT} ${LIBRKLLMRT})
endif()
```
--------------------------------
### Run C++ Demo on Board
Source: https://github.com/airockchip/rknn-llm/blob/main/examples/multimodal_model_demo/README.md
Commands to run the compiled C++ demo on the target board. This includes setting the library path, linking models, and executing the image encoder and the main multimodal demo.
```bash
adb shell
cd /data/demo_Linux_aarch64
# export lib path
export LD_LIBRARY_PATH=./lib
# soft link models dir
ln -s /data/models .
# run imgenc
./imgenc models/qwen2-vl-vision_rk3588.rknn demo.jpg 3
# run demo(Multimodal Example)
./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|>"
```
--------------------------------
### Run Demo with DeepSeekOCR Model
Source: https://github.com/airockchip/rknn-llm/blob/main/README.md
Execute the demo with the DeepSeekOCR model, specifying image path, RKNN encoder model, RKLLM language model, and specific padding token.
```bash
./demo demo.jpg ./deepseekocr_vision_rk3588.rknn ./deepseekocr_w8a8_rk3588.rkllm 2048 4096 3 rk3588 "" "" "<|▁pad▁|>"
```
--------------------------------
### Run Function Calling Demo
Source: https://github.com/airockchip/rknn-llm/blob/main/examples/rkllm_server_demo/README.md
Launches the built-in interactive demo for function calling (Demo 2). Replace with the actual IP address.
```bash
python chat_api_flask.py --server http://:8080 --demo 2
```
--------------------------------
### Build Flask Server for RKLLM
Source: https://github.com/airockchip/rknn-llm/blob/main/examples/rkllm_server_demo/README.md
Builds and deploys the Flask server for an OpenAI-compatible API. Ensure the model path and platform are correctly specified.
```bash
# Usage: ./build_rkllm_server_flask.sh --workshop [Working Path] --model_path [Absolute Path of RKLLM Model on Board] --platform [Target Platform: rk3588/rk3576] [--lora_model_path [Lora Model Path]] [--prompt_cache_path [Prompt Cache File Path]] [--adb_device [ADB Device Serial]]
./build_rkllm_server_flask.sh --workshop /userdata --model_path /userdata/model.rkllm --platform rk3588 --adb_device 1234567890abcdef
```
--------------------------------
### RKLLM Runtime Path and Include Directories
Source: https://github.com/airockchip/rknn-llm/blob/main/examples/multimodal_model_demo/deploy/CMakeLists.txt
Defines the path to the rkllm runtime library and its include directories. It also finds the OpenMP package, which might be required by the rkllm runtime.
```cmake
# rkllm runtime
set(RKLLM_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../../../rkllm-runtime)
set(LIBRKLLMRT ${RKLLM_PATH}/${CMAKE_SYSTEM_NAME}/librkllm_api/${TARGET_LIB_ARCH}/librkllmrt.so)
set(LIBRKLLMRT_INCLUDES ${RKLLM_PATH}/${CMAKE_SYSTEM_NAME}/librkllm_api/include)
find_package(OpenMP REQUIRED)
include_directories(${LIBRKLLMRT_INCLUDES})
```
--------------------------------
### Generate Input Embeds for RKLLM Quantization
Source: https://github.com/airockchip/rknn-llm/blob/main/examples/multimodal_model_demo/README.md
Create input embeddings for quantizing an RKLLM model using a specified model path and type. This step is required before exporting the RKLLM model.
```bash
python data/make_input_embeds_for_quantize.py --path /path/to/Qwen2-VL-model --model_type qwen2vl
```
--------------------------------
### RKNN Runtime Path and Include Directories
Source: https://github.com/airockchip/rknn-llm/blob/main/examples/multimodal_model_demo/deploy/CMakeLists.txt
Defines the path to the rknn runtime library and its include directories. This allows the project to link against the rknnrt.so library.
```cmake
# rknn runtime
set(RKNN_PATH ${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/librknnrt)
set(LIBRKNNRT ${RKNN_PATH}/${CMAKE_SYSTEM_NAME}/librknn_api/${TARGET_LIB_ARCH}/librknnrt.so)
set(LIBRKNNRT_INCLUDES ${RKNN_PATH}/${CMAKE_SYSTEM_NAME}/librknn_api/include)
```
--------------------------------
### Convert Qwen2-VL Vision Component to ONNX
Source: https://github.com/airockchip/rknn-llm/blob/main/examples/multimodal_model_demo/README.md
Export the Vision + Projector component of a Qwen2-VL model to ONNX format. The first run generates necessary embeddings with 'step' set to 1, and the second run exports the ONNX model with 'step' set to 0. Ensure 'use_flash_attn' is false in config.json if float32 is required.
```bash
# First time to generate cu_seqlens and rotary_pos_emb, need to set 'step' to 1
python export/export_vision_qwen2.py --step 1 --path /path/to/Qwen2-VL-model --batch 1 --height 392 --width 392
# Second time to export onnx model, need to set 'step' to any number except 1
python export/export_vision_qwen2.py --step 0 --path /path/to/Qwen2-VL-model --savepath /path/to/save/qwen2-vl-vision.onnx --batch 1 --height 392 --width 392
```
--------------------------------
### Convert Qwen2-VL Vision Component to RKNN
Source: https://github.com/airockchip/rknn-llm/blob/main/examples/multimodal_model_demo/README.md
Convert an exported ONNX vision model to an RKNN model using rknn-toolkit2. Specify the path to the ONNX model and the target platform.
```bash
python export/export_vision_rknn.py --path /path/to/save/qwen2-vl-vision.onnx --target-platform rk3588
```
--------------------------------
### Export RKLLM Model
Source: https://github.com/airockchip/rknn-llm/blob/main/examples/rkllm_api_demo/Readme.md
Commands to generate quantization data and export the RKLLM model. Ensure you are in the 'export' directory and have the fp16 model available.
```bash
cd export
python generate_data_quant.py -m /path/to/DeepSeek-R1-Distill-Qwen-1.5B
python export_rkllm.py
```
--------------------------------
### Define Tool Descriptions (OpenAI Function Calling Format)
Source: https://github.com/airockchip/rknn-llm/blob/main/examples/rkllm_server_demo/README.md
Define the tools available to the model using the OpenAI Function Calling specification. This includes the function name, description, and parameter schema.
```python
TOOLS = [
{
"type": "function",
"function": {
"name": "get_current_temperature",
"description": "Get current temperature at a location.",
"parameters": {
"type": "object",
"properties": {
"location": {"type": "string", "description": "City, State, Country"},
"unit": {"type": "string", "enum": ["celsius", "fahrenheit"]},
},
"required": ["location"],
},
},
},
{
"type": "function",
"function": {
"name": "get_temperature_date",
"description": "Get temperature at a location and date.",
"parameters": {
"type": "object",
"properties": {
"location": {"type": "string", "description": "City, State, Country"},
"date": {"type": "string", "description": "YYYY-MM-DD"},
"unit": {"type": "string", "enum": ["celsius", "fahrenheit"]},
},
"required": ["location", "date"],
},
},
},
]
```
--------------------------------
### OpenCV Configuration and Find Package
Source: https://github.com/airockchip/rknn-llm/blob/main/examples/multimodal_model_demo/deploy/CMakeLists.txt
Sets the OpenCV directory based on the system name (Linux or Android) and then finds the OpenCV package. This is required for using OpenCV functionalities in the project.
```cmake
# opencv
if (CMAKE_SYSTEM_NAME MATCHES "Linux")
set(OpenCV_DIR ${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/opencv/opencv-linux-aarch64/share/OpenCV)
elseif(CMAKE_SYSTEM_NAME MATCHES "Android")
set(OpenCV_DIR ${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/opencv/OpenCV-android-sdk/sdk/native/jni/abi-${CMAKE_ANDROID_ARCH_ABI})
endif()
find_package(OpenCV REQUIRED)
```
--------------------------------
### Regular Chat - Manual HTTP Calls
Source: https://github.com/airockchip/rknn-llm/blob/main/examples/rkllm_server_demo/README.md
Manually construct and send HTTP requests to the chat completions endpoint for more control over the interaction. This includes setting up the server URL, creating a session, building the request body, sending the request, and parsing the response for both streaming and non-streaming modes.
```python
# 1) Set the server URL
server_url = "http://x.x.x.x:8080/v1/chat/completions"
# 2) Create a session
import requests
session = requests.Session()
session.keep_alive = False
adapter = requests.adapters.HTTPAdapter(max_retries=3)
session.mount("https://", adapter)
session.mount("http://", adapter)
# 3) Build the request body
data = {
"model": "rkllm", # Model identifier (customizable)
"messages": [
{"role": "user", "content": "Hello"}
],
"stream": False, # True = streaming, False = non-streaming
"temperature": 0.8, # Sampling temperature (default: 0.8)
"top_p": 0.9, # Nucleus sampling threshold (default: 0.9)
"top_k": 1, # Top-k sampling (default: 1)
"max_tokens": 4096, # Max tokens to generate (default: 4096)
"repeat_penalty": 1.1, # Repeat penalty (default: 1.1)
"frequency_penalty": 0.0, # Frequency penalty (default: 0.0)
"presence_penalty": 0.0, # Presence penalty (default: 0.0)
"enable_thinking": False, # Enable deep thinking mode
}
# 4) Send the request
headers = {"Content-Type": "application/json", "Authorization": "not_required"}
resp = session.post(server_url, json=data, headers=headers, stream=data["stream"])
# 5) Parse the response
import json
# Non-streaming
if resp.status_code == 200:
result = resp.json()
print("A:", result["choices"][0]["message"]["content"])
else:
print("Error:", resp.text)
# Streaming (SSE)
if resp.status_code == 200:
for line in resp.iter_lines(decode_unicode=True):
if line.startswith("data: ") and line[6:].strip() != "[DONE]":
chunk = json.loads(line[6:])
delta = chunk["choices"][0].get("delta", {})
if delta.get("content"):
print(delta["content"], end="", flush=True)
```
--------------------------------
### Manual HTTP Call: Create Requests Session
Source: https://github.com/airockchip/rknn-llm/blob/main/examples/rkllm_server_demo/README.md
Initializes a requests session with keep-alive disabled and retries configured for robustness.
```python
import requests
session = requests.Session()
session.keep_alive = False
adapter = requests.adapters.HTTPAdapter(max_retries=3)
session.mount("https://", adapter)
session.mount("http://", adapter)
```
--------------------------------
### Model Conversion Requirements
Source: https://github.com/airockchip/rknn-llm/blob/main/examples/rkllm_api_demo/Readme.md
Specifies the necessary toolkit and runtime versions for RKLLM model conversion. Ensure Python version is 3.8 or higher.
```bash
rkllm-toolkit==1.2.x
rkllm-runtime==1.2.x
python >=3.8
```
--------------------------------
### Export RKLLM Model
Source: https://github.com/airockchip/rknn-llm/blob/main/examples/multimodal_model_demo/README.md
Export the LLM component to an RKLLM model. This command specifies the model path, target platform, number of NPU cores, quantized data type, device, and save path.
```bash
python export/export_rkllm.py --path /path/to/Qwen2-VL-model --target-platform rk3588 --num_npu_core 3 --quantized_dtype w8a8 --device cpu --savepath /path/to/save/qwen2-vl-llm_rk3588.rkllm
```
--------------------------------
### Image Encoder Executable Build
Source: https://github.com/airockchip/rknn-llm/blob/main/examples/multimodal_model_demo/deploy/CMakeLists.txt
Compiles the image encoder source files into an executable named 'imgenc'. It includes necessary header directories and links against OpenCV and the rknn runtime library.
```cmake
# imgenc
include_directories(src/image_enc.h ${LIBRKNNRT_INCLUDES})
add_executable(imgenc src/image_enc.cc src/img_encoder.cpp)
target_link_libraries(imgenc PRIVATE ${OpenCV_LIBS} ${LIBRKNNRT})
```