一区二区三区三上|欧美在线视频五区|国产午夜无码在线观看视频|亚洲国产裸体网站|无码成年人影视|亚洲AV亚洲AV|成人开心激情五月|欧美性爱内射视频|超碰人人干人人上|一区二区无码三区亚洲人区久久精品

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

基于RK3576開(kāi)發(fā)板的RKLLM大模型部署教程

ljx2016 ? 來(lái)源:ljx2016 ? 作者:ljx2016 ? 2025-05-16 17:48 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

1. RKLLM簡(jiǎn)介

1.1 RKLLM工具鏈介紹

1.1.1 RKLLM-Toolkit功能介紹

RKLLM-Toolkit 是為用戶提供在計(jì)算機(jī)上進(jìn)行大語(yǔ)言模型的量化、轉(zhuǎn)換的開(kāi)發(fā)套件。通過(guò)該 工具提供的 Python 接口可以便捷地完成以下功能:

(1)模型轉(zhuǎn)換:支持將 Hugging Face 和 GGUF 格式的大語(yǔ)言模型(Large Language Model, LLM) 轉(zhuǎn)換為 RKLLM 模型,目前支持的模型包括 LLaMA, Qwen, Qwen2, Phi-2, Phi-3, ChatGLM3, Gemma, Gemma2, InternLM2, MiniCPM 和 MiniCPM3,轉(zhuǎn)換后的 RKLLM 模型能夠在 Rockchip NPU 平臺(tái)上加載使用。

(2)量化功能:支持將浮點(diǎn)模型量化為定點(diǎn)模型,目前支持的量化類型包括 w4a16 、wa4a16分組量化(支持的分組數(shù)為32,64,128)、w8a8、w8a8分組量化(支持的分組數(shù)為128,256,512)。

1.1.2 RKLLM Runtime功能介紹

RKLLM Runtime 主 要 負(fù) 責(zé) 加 載 RKLLM-Toolkit 轉(zhuǎn)換得到的 RKLLM 模型,并在RK3576/RK3588 板端通過(guò)調(diào)用 NPU 驅(qū)動(dòng)在 Rockchip NPU 上實(shí)現(xiàn) RKLLM 模型的推理。在推理 RKLLM 模型時(shí),用戶可以自行定義 RKLLM 模型的推理參數(shù)設(shè)置,定義不同的文本生成方式, 并通過(guò)預(yù)先定義的回調(diào)函數(shù)不斷獲得模型的推理結(jié)果。

1.2 RKLLM開(kāi)發(fā)流程介紹

(1)模型轉(zhuǎn)換:

在這一階段,用戶提供的 Hugging Face 格式的大語(yǔ)言模型將會(huì)被轉(zhuǎn)換為 RKLLM 格式,以便在 Rockchip NPU 平臺(tái)上進(jìn)行高效的推理。這一步驟包括:

獲取原始模型:1、開(kāi)源的 Hugging Face 格式的大語(yǔ)言模型;2、自行訓(xùn)練得到的大語(yǔ) 言模型,要求模型保存的結(jié)構(gòu)與 Hugging Face 平臺(tái)上的模型結(jié)構(gòu)一致;3、GGUF 模型,目前 僅支持 q4_0 和 fp16 類型模型;

模型加載:通過(guò) rkllm.load_huggingface()函數(shù)加載 huggingface 格式模型,通過(guò)rkllm.load_gguf()函數(shù)加載 GGUF 模型;

模型量化配置:通過(guò) rkllm.build() 函數(shù)構(gòu)建 RKLLM 模型,在構(gòu)建過(guò)程中可選擇是否進(jìn)行模型量化來(lái)提高模型部署在硬件上的性能,以及選擇不同的優(yōu)化等級(jí)和量化類型。

模型導(dǎo)出:通過(guò) rkllm.export_rkllm() 函數(shù)將 RKLLM 模型導(dǎo)出為一個(gè).rkllm 格式文件, 用于后續(xù)的部署。

(2)板端部署運(yùn)行:

這個(gè)階段涵蓋了模型的實(shí)際部署和運(yùn)行。它通常包括以下步驟:

模型初始化:加載 RKLLM 模型到 Rockchip NPU 平臺(tái),進(jìn)行相應(yīng)的模型參數(shù)設(shè)置來(lái)定義所需的文本生成方式,并提前定義用于接受實(shí)時(shí)推理結(jié)果的回調(diào)函數(shù),進(jìn)行推理前準(zhǔn)備。

模型推理:執(zhí)行推理操作,將輸入數(shù)據(jù)傳遞給模型并運(yùn)行模型推理,用戶可以通過(guò)預(yù)先定義的回調(diào)函數(shù)不斷獲取推理結(jié)果。

模型釋放:在完成推理流程后,釋放模型資源,以便其他任務(wù)繼續(xù)使用 NPU 的計(jì)算資源。以上這兩個(gè)步驟構(gòu)成了完整的 RKLLM 開(kāi)發(fā)流程,確保大語(yǔ)言模型能夠成功轉(zhuǎn)換、調(diào)試,并 最終在 Rockchip NPU 上實(shí)現(xiàn)高效部署。

1.3 資料下載

模型文件、模型轉(zhuǎn)換與部署代碼的百度網(wǎng)盤(pán)下載鏈接(比較大,可以選擇來(lái)下載):https://pan.baidu.com/s/13CHxaF-Cyp4tYxXpksD8LA?pwd=1234 (提取碼:1234 )

wKgZPGgnCjGAIL_TAADtWKbX22Q856.jpg

1.4 開(kāi)發(fā)環(huán)境搭建

1.4.1 RKLLM-Toolkit安裝

本節(jié)主要說(shuō)明如何通過(guò) pip 方式來(lái)安裝 RKLLM-Toolkit,用戶可以參考以下的具體流程說(shuō)明完成 RKLLM-Toolkit 工具鏈的安裝。

工具安裝包鏈接: https://pan.baidu.com/s/1y5ZN5sl4e3HJI5d9Imt4pg?pwd=1234(提取碼: 1234)。

1.4.1.1 安裝miniforge3工具

為防止系統(tǒng)對(duì)多個(gè)不同版本的 Python 環(huán)境的需求,建議使用 miniforge3 管理 Python 環(huán)境。 檢查是否安裝 miniforge3 和 conda 版本信息,若已安裝則可省略此小節(jié)步驟。

下載 miniforge3 安裝包:

wget -c https://mirrors.bfsu.edu.cn/github-release/conda-forge/miniforge/LatestRelease/Miniforge3-Linux-x86_64.sh

安裝miniforge3:

chmod 777 Miniforge3-Linux-x86_64.sh
bash Miniforge3-Linux-x86_64.sh

1.4.1.2 創(chuàng)建 RKLLM-Toolkit Conda 環(huán)境

進(jìn)入 Conda base 環(huán)境:

source ~/miniforge3/bin/activate

創(chuàng)建一個(gè) Python3.8 版本(建議版本)名為 RKLLM-Toolkit 的 Conda 環(huán)境:

conda create -n RKLLM-Toolkit python=3.8

進(jìn)入 RKLLM-Toolkit Conda 環(huán)境:

conda activate RKLLM-Toolkit
wKgZO2gnCjKARQIdAACXY3o2Z0Q020.jpg

1.4.1.3 安裝RKLLM-Toolkit

在 RKLLM-Toolkit Conda 環(huán)境下使用 pip 工具直接安裝所提供的工具鏈 whl 包,在安裝過(guò)程 中,安裝工具會(huì)自動(dòng)下載 RKLLM-Toolkit 工具所需要的相關(guān)依賴包。

pip3 install nvidia_cublas_cu12-12.1.3.1-py3-none-manylinux1_x86_64.whl
pip3 install torch-2.1.0-cp38-cp38-manylinux1_x86_64.whl
pip3 install rkllm_toolkit-1.1.4-cp38-cp38-linux_x86_64.whl

若在安裝的過(guò)程中,某些文件安裝很慢,可以登錄python官網(wǎng)單獨(dú)下載:

https://pypi.org/

執(zhí)行以下命令沒(méi)有報(bào)錯(cuò),則安裝成功。

wKgZPGgnCjKATZhoAAC1cFw6a18184.jpg

1.5 AI模型轉(zhuǎn)換

本章主要說(shuō)明如何實(shí)現(xiàn)Hugging Face格式的大語(yǔ)言模型(Large Language Model, LLM)

如何轉(zhuǎn)換為RKLLM模型,目前支持的模型包括 LLaMA, Qwen, Qwen2, Phi-2, Phi-3, ChatGLM3, Gemma, InternLM2 和 MiniCPM。

1.5.1 模型下載

本節(jié)提供兩種大模型文件,Hugging face的原始模型和轉(zhuǎn)換完成的NPU模型。

wKgZO2gnCjKAWdngAAAoj3h83vY035.jpg

下載鏈接: https://pan.baidu.com/s/14BDYQBOMTTK7jtsSa8evHw?pwd=1234 (提取碼: 1234)。

1.5.2 模型轉(zhuǎn)換

下載完成后模型和腳本放到同一個(gè)目錄:

wKgZPGgnCjOAHVSpAACUwY5ccWk362.jpg

在RKLLM-Toolkit環(huán)境,執(zhí)行以下指令進(jìn)行模型轉(zhuǎn)換:

wKgZO2gnCjSAaeHIAAFeaWzxJwo542.jpg

至此模型轉(zhuǎn)換成功,生成Qwen.rkllm NPU化的大模型文件:

wKgZPGgnCjWAKHBKAACZRcc7UbE872.jpg

test.py轉(zhuǎn)換腳本如下所示, 用于轉(zhuǎn)換Qwen-1_8B-Chat模型:

from rkllm.api import RKLLM
from datasets import load_dataset
from transformers import AutoTokenizer
from tqdm import tqdm
import torch
from torch import nn
import os
# os.environ['CUDA_VISIBLE_DEVICES']='1'

'''
https://huggingface.co/Qwen/Qwen-1_8B-Chat
從上面網(wǎng)址中下載Qwen模型
'''

modelpath = '/home/developer/RKLLM-Toolkit/Qwen-1_8B-Chat'
# modelpath = "./path/to/Qwen-1.8B-F16.gguf"
llm = RKLLM()

# Load model
# Use 'export CUDA_VISIBLE_DEVICES=2' to specify GPU device
# options ['cpu', 'cuda']
ret = llm.load_huggingface(model=modelpath, model_lora = None, device='cpu')
# ret = llm.load_gguf(model = modelpath)
if ret != 0:
    print('Load model failed!')
    exit(ret)

# Build model
dataset = "./data_quant.json"
# Json file format, please note to add prompt in the input,like this:
# [{"input":"Human: 你好!nAssistant: ", "target": "你好!我是人工智能助手KK!"},...]

qparams = None
# qparams = 'gdq.qparams' # Use extra_qparams
ret = llm.build(do_quantization=True, optimization_level=1, quantized_dtype='w4a16',
                quantized_algorithm='normal', target_platform='rk3576', num_npu_core=2, extra_qparams=qparams, dataset=None)

if ret != 0:
    print('Build model failed!')
    exit(ret)

# Evaluate Accuracy
def eval_wikitext(llm):
    seqlen = 512
    tokenizer = AutoTokenizer.from_pretrained(
        modelpath, trust_remote_code=True)
    # Dataset download link:
    # https://huggingface.co/datasets/Salesforce/wikitext/tree/main/wikitext-2-raw-v1
    testenc = load_dataset(
        "parquet", data_files='./wikitext/wikitext-2-raw-1/test-00000-of-00001.parquet', split='train')
    testenc = tokenizer("nn".join(
        testenc['text']), return_tensors="pt").input_ids
    nsamples = testenc.numel() // seqlen
    nlls = []
    for i in tqdm(range(nsamples), desc="eval_wikitext: "):
        batch = testenc[:, (i * seqlen): ((i + 1) * seqlen)]
        inputs = {"input_ids": batch}
        lm_logits = llm.get_logits(inputs)
        if lm_logits is None:
            print("get logits failed!")
            return
        shift_logits = lm_logits[:, :-1, :]
        shift_labels = batch[:, 1:].to(lm_logits.device)
        loss_fct = nn.CrossEntropyLoss().to(lm_logits.device)
        loss = loss_fct(
            shift_logits.view(-1, shift_logits.size(-1)), shift_labels.view(-1))
        neg_log_likelihood = loss.float() * seqlen
        nlls.append(neg_log_likelihood)
    ppl = torch.exp(torch.stack(nlls).sum() / (nsamples * seqlen))
    print(f'wikitext-2-raw-1-test ppl: {round(ppl.item(), 2)}')

# eval_wikitext(llm)


# Chat with model
messages = "<|im_start|?>system You are a helpful assistant.<|im_end|?><|im_start|?>user你好!n<|im_end|?><|im_start|?>assistant"
kwargs = {"max_length": 128, "top_k": 1, "top_p": 0.8,
          "temperature": 0.8, "do_sample": True, "repetition_penalty": 1.1}
# print(llm.chat_model(messages, kwargs))


# Export rkllm model
ret = llm.export_rkllm("./Qwen_w4a16.rkllm")
if ret != 0:
    print('Export model failed!')
    exit(ret)

1.6 模型轉(zhuǎn)換API說(shuō)明

1.6.1 RKLLM 初始化

在這一部分,用戶需要先初始化 RKLLM 對(duì)象,這是整個(gè)工作流的第一步。在示例代碼中使用 RKLLM()構(gòu)造函數(shù)來(lái)初始化 RKLLM 對(duì)象:

rkllm = RKLLM()

1.6.2 模型加載

在 RKLLM 初始化完成后,用戶需要調(diào)用 rkllm.load_huggingface()函數(shù)來(lái)傳入模型的具體路徑,RKLLM-Toolkit 即可根據(jù)對(duì)應(yīng)路徑順利加載 Hugging Face 或 GGUF 格式的大語(yǔ)言模型,從而順利完成后續(xù)的轉(zhuǎn)換、量化操作,具體的函數(shù)定義如下:

表 1 load_huggingface 函數(shù)接口說(shuō)明

函數(shù)名 load_huggingface
描述 用于加載開(kāi)源的 Hugging Face 格式的大語(yǔ)言模型。
參數(shù) model: LLM 模型的文件路徑,用于加載模型進(jìn)行后續(xù)的轉(zhuǎn)換、量化;
model_lora: lora 權(quán)重的文件路徑,轉(zhuǎn)換時(shí) model 必須指向相應(yīng)的 base model 路徑;
返回值 0 表示模型加載正常;-1 表示模型加載失?。?/td>

示例代碼如下:

ret = rkllm.load_huggingface(
   model = './huggingface_model_dir', 
   model_lora = './huggingface_lora_model_dir'
   )
if ret != 0:
   print('Load model failed!')

表 2 load_gguf 函數(shù)接口說(shuō)明

函數(shù)名 load_gguf
描述 用于加載開(kāi)源的 GGUF 格式的大語(yǔ)言模型,所支持的數(shù)值類型為 q4_0 和 fp16 兩種,gguf 格式的 lora 模型也可以通過(guò)此接口加載轉(zhuǎn)換為 rkllm 模型。
參數(shù) model: GGUF 模型文件路徑;
返回值 0 表示模型加載正常;-1 表示模型加載失??;

示例代碼如下:

ret = rkllm.load_gguf(model = './model-Q4_0.gguf')
if ret != 0:
   print('Load model failed!')

1.6.3 RKLLM 模型的量化構(gòu)建

用戶在通過(guò) rkllm.load_huggingface()函數(shù)完成原始模型的加載后,下一步就是通過(guò) rkllm.build()函數(shù)實(shí)現(xiàn)對(duì) RKLLM 模型的構(gòu)建。構(gòu)建模型時(shí),用戶可以選擇是否進(jìn)行量化,量化有助于減小模型的大小和提高在 Rockchip NPU 上的推理性能。rkllm.build()函數(shù)的具體定義如下:

表 3 build 函數(shù)接口說(shuō)明

函數(shù)名 build
描述 用于構(gòu)建得到 RKLLM 模型,并在轉(zhuǎn)換過(guò)程中定義具體的量化操作。
參數(shù) do_quantization: 該參數(shù)控制是否對(duì)模型進(jìn)行量化操作,建議設(shè)置為 True;
optimization_level: 該參數(shù)用于設(shè)置是否進(jìn)行量化精度優(yōu)化,可選擇的設(shè)置為{0,1},0 表示不做任何優(yōu)化,1 表示進(jìn)行精度優(yōu)化,精度優(yōu)化可能造成模型推理性能下降;
quantized_dtype: 該參數(shù)用于設(shè)置量化的具體類型,目前支持的量化類型包括“ w4a16 ” , “ w4a16_g32 ” , “ w4a16_g64 ” , “ w4a16_g128 ” , “ w8a8 ” ,“w8a8_g128”,“w8a8_g256”,“w8a8_g512”,“w4a16”表示對(duì)權(quán)重進(jìn)行 4bit 量化而對(duì)激活值不進(jìn)行量化;“w4a16_g64”表示對(duì)權(quán)重進(jìn)行 4bit 分組量化(groupsize=64)而對(duì)激活值不進(jìn)行量化;“w8a8”表示對(duì)權(quán)重和激活值均進(jìn)行 8bit 量化;“w8a8_g128”表示對(duì)權(quán)重和激活值均進(jìn)行 8bit 分組量化(group size=128);目前rk3576 平臺(tái)支持“w4a16”,“w4a16_g32”,“w4a16_g64”,“w4a16_g128”和“w8a8”五種量化類型,rk3588 支持“w8a8”,“w8a8_g128”,“w8a8_g256”,“ w8a8_g512 ” 四種量化類型; GGUF 模型的 q4_0 對(duì)應(yīng)的量化類型為“w4a16_g32”;注意group size 應(yīng)能被線性層的輸出維度整除,否則會(huì)量化失??!
quantized_algorithm: 量化精度優(yōu)化算法, 可選擇的設(shè)置包括“normal”或“gdq”,所有量化類型均可選擇 normal,而 gdq 算法只支持 w4a16 及 w4a16 分組量化,且 gdq
對(duì)算力要求高,必須使用 GPU 進(jìn)行加速運(yùn)算;
num_npu_core: 模型推理需要使用的 npu 核心數(shù),“rk3576”可選項(xiàng)為[1,2],“rk3588”可選項(xiàng)為[1,2,3];
extra_qparams: 使用 gdq 算法會(huì)生成 gdq.qparams 量化權(quán)重緩存文件,將此參數(shù)設(shè)置為 gdq.qparams 路徑,可以重復(fù)進(jìn)行模型導(dǎo)出;
dataset: 用于量化校正數(shù)據(jù)集,格式為 json,內(nèi)容示例如下,input 為問(wèn)題,需要加上提示詞,target 為回答,多條數(shù)據(jù)以{}字典形式保存在列表中:[{"input":"今天天氣怎么樣?","target":"今天天氣晴。"},....]
hybrid_rate: 分組和不分組混合量化比率(∈[0,1)),當(dāng)量化類型為 w4a16/w8a8 時(shí),會(huì)按比率分別混合 w4a16 分組/w8a8 分組類型來(lái)提高精度,當(dāng)量化類型為 w4a16分組/w8a8 分組類型時(shí),會(huì)按比率分別混合 w4a16/w8a8 類型來(lái)提高推理性能,當(dāng)hybrid_rate 值為 0 時(shí),不進(jìn)行混合量化;
target_platform: 模型運(yùn)行的硬件平臺(tái), 可選擇的設(shè)置包括“rk3576”或“rk3588”;
返回值 0 表示模型轉(zhuǎn)換、量化正常;-1 表示模型轉(zhuǎn)換失敗;

示例代碼如下:

ret = rkllm.build(
       do_quantization=True,
       optimization_level=1,
       quantized_dtype='w8a8',
       quantized_algorithm="normal",
       num_npu_core=3,
       extra_qparams=None,
       dataset="quant_data.json",
       hybrid_rate=0,
       target_platform='rk3588')
if ret != 0:
   print('Build model failed!')

1.6.4 導(dǎo)出 RKLLM 模型

用戶在通過(guò) rkllm.build()函數(shù)構(gòu)建了 RKLLM 模型后,可以通過(guò) rkllm.export_rkllm()函數(shù)將RKNN 模型保存為一個(gè).rkllm 文件,以便后續(xù)模型的部署。rkllm.export_rkllm()函數(shù)的具體參數(shù)定義如下:

表 4 export_rkllm 函數(shù)接口說(shuō)明

函數(shù)名 export_rkllm
描述 用于保存轉(zhuǎn)換、量化后的 RKLLM 模型,用于后續(xù)的推理調(diào)用。
參數(shù) export_path: 導(dǎo)出 RKLLM 模型文件的保存路徑,lora 模型會(huì)自動(dòng)保存為帶_lora 后綴的 rkllm 模型;
返回值 0 表示模型成功導(dǎo)出保存;-1 表示模型導(dǎo)出失敗;

示例代碼如下:

ret = rkllm.export_rkllm(export_path = './model.rkllm')
if ret != 0:
   print('Export model failed!')

1.6.5 仿真精度評(píng)估

用戶在通過(guò) rkllm.build()函數(shù)構(gòu)建了 RKLLM 模型后,可以通過(guò) rkllm.get_logits()函數(shù)在 PC端進(jìn)行仿真精度評(píng)估,rkllm.get_logits()函數(shù)的具體參數(shù)定義如下:

函數(shù)名 get_logits
函數(shù)名 用于 PC 端仿真精度評(píng)估。
參數(shù) inputs: 仿真輸入格式與 huggingface 模型推理一樣,示例如下:{“input_ids":"","top_k":1,...}
返回值 返回模型推理出的 logits 值;

使用此函數(shù)進(jìn)行 wikitext 數(shù)據(jù)集 ppl 測(cè)試示例代碼如下:

ef eval_wikitext(llm):
  seqlen = 512
  tokenizer = AutoTokenizer.from_pretrained(
     modelpath,
     trust_remote_code=True
     )
  #Dataset download link: 
  #https://huggingface.co/datasets/Salesforce/wikitext/tree/main/wiki
text-2-raw-v1
   testenc = load_dataset("parquet", data_files='./wikitext/wikitext-
2-raw-1/test-00000-of-00001.parquet', split='train')
   testenc = tokenizer(
      "nn".join(testenc['text']), 
      return_tensors="pt").input_ids
 nsamples = testenc.numel() // seqlen
 nlls = []
 for i in tqdm(range(nsamples), desc="eval_wikitext: "):
    batch = testenc[:, (i * seqlen): ((i + 1) * seqlen)]
    inputs = {"input_ids": batch}
    lm_logits = llm.get_logits(inputs)
    if lm_logits is None:
       print("get logits failed!")
       return 
    shift_logits = lm_logits[:, :-1, :]
    shift_labels = batch[:, 1:].to(lm_logits.device)
    loss_fct = nn.CrossEntropyLoss().to(lm_logits.device)
    loss = loss_fct(shift_logits.view(-1, shift_logits.size(-1)), 
shift_labels.view(-1))
    neg_log_likelihood = loss.float() * seqlen
    nlls.append(neg_log_likelihood)
   ppl = torch.exp(torch.stack(nlls).sum() / (nsamples * seqlen))
   print(f'wikitext-2-raw-1-test ppl: {round(ppl.item(), 2)}')

1.6.6 仿真模型推理

用戶在通過(guò) rkllm.build()函數(shù)構(gòu)建了 RKLLM 模型后,可以通過(guò) rkllm.chat_model()函數(shù)在 PC端進(jìn)行仿真推理,rkllm.chat_model()函數(shù)的具體參數(shù)定義如下:

函數(shù)名 chat_model
描述 用于 PC 端仿真模型推理。
參數(shù) messages: 文本輸入,需要加上相應(yīng)提示詞
args: 推理配置參數(shù),比如 topk 等采樣策略參數(shù)
返回值 返回模型推理結(jié)果;

示例代碼如下:

args ={
   "max_length":128,
   "top_k":1,
   "temperature":0.8,
   "do_sample":True,
   "repetition_penalty":1.1
   }
mesg = "Human: 今天天氣怎么樣?nAssistant:"
print(llm.chat_model(mesg, args))

以上的這些操作涵蓋了 RKLLM-Toolkit 模型轉(zhuǎn)換、量化的全部步驟,根據(jù)不同的需求和應(yīng)用場(chǎng)景,用戶可以選擇不同的配置選項(xiàng)和量化方式進(jìn)行自定義設(shè)置,方便后續(xù)進(jìn)行部署。

1.7 AI模型部署

本章主要說(shuō)明RKLLM格式的通義千問(wèn)NPU大模型如何運(yùn)行在EASY-EAI-Orin-Nano硬件上。

wKgZO2gnCjaAHKz7AAQs3ECnN8w985.jpg

1.7.1 快速上手

1.7.1.1 源碼下載以及例程編譯

本節(jié)提供轉(zhuǎn)換成功的通義千問(wèn)大模型文Qwen_w4a16.rkllm及對(duì)應(yīng)的C/C++程序部署代碼。

wKgZO2gnCjeANa7cAAAieXduLLE099.jpg

下載鏈接:https://pan.baidu.com/s/19GZ_UjsA-IjA9zf10ZZ93w?pwd=1234(提取碼: 1234)。

然后把例程【復(fù)制粘貼】到nfs掛載目錄中。(不清楚目錄如何構(gòu)建的,可以參考《入門(mén)指南/開(kāi)發(fā)環(huán)境準(zhǔn)備/nfs服務(wù)搭建與掛載》)。特別注意:源碼目錄和模型最好cp到板子上,如/userdata,否則在nfs目錄執(zhí)行大模型會(huì)導(dǎo)致模型初始化過(guò)慢。

wKgZPGgnCjeAIiPhAACT-gIoKVU267.jpg

進(jìn)入到開(kāi)發(fā)板對(duì)應(yīng)的例程目錄執(zhí)行編譯操作,具體命令如下所示:

cd /userdata/rkllm-demo
./build.sh
wKgZO2gnCjiAeRrSAAEq2xOrQbo624.jpg

1.7.1.2 例程運(yùn)行及效果

進(jìn)入例程的rkllm-demo/rkllm-demo_release目錄,執(zhí)行下方命令,運(yùn)行示例程序:

cd rkllm-demo_release/
ulimit -HSn 102400 
./rkllm-demo Qwen_w4a16.rkllm 256 512
wKgZPGgnCjmAAHByAAH-7OQ_UFY458.jpg

至此可以進(jìn)行對(duì)話測(cè)試了,試著輸入“如何制作PCB板?”。回答如下所示:

wKgZO2gnCjqAKcz9AAH8rsurcwg429.jpg

1.7.2 RKLLM算法例程

例程目錄為rkllm-demo/src/main.cpp,操作流程如下。

wKgZPGgnCjuADvNjAAB3aGFJohk241.jpg

具體代碼如下所示:

#include 
#include 
#include 
#include "rkllm.h"
#include 
#include 
#include 
#include 

#define PROMPT_TEXT_PREFIX "<|im_start|?>system You are a helpful assistant. <|im_end|?> <|im_start|?>user"
#define PROMPT_TEXT_POSTFIX "<|im_end|?><|im_start|?>assistant"


using namespace std;
LLMHandle llmHandle = nullptr;

void exit_handler(int signal)
{
    if (llmHandle != nullptr)
    {
        {
            cout last_hidden_layer.embd_size != 0 && result->last_hidden_layer.num_tokens != 0) {
            int data_size = result->last_hidden_layer.embd_size * result->last_hidden_layer.num_tokens * sizeof(float);
            printf("ndata_size:%d",data_size);
            std::ofstream outFile("last_hidden_layer.bin", std::ios::binary);
            if (outFile.is_open()) {
                outFile.write(reinterpret_cast(result->last_hidden_layer.hidden_states), data_size);
                outFile.close();
                std::cout text);
    }
}

int main(int argc, char **argv)
{
    if (argc < 4) {
        std::cerr  pre_input;
    pre_input.push_back("把下面的現(xiàn)代文翻譯成文言文: 到了春風(fēng)和煦,陽(yáng)光明媚的時(shí)候,湖面平靜,沒(méi)有驚濤駭浪,天色湖光相連,一片碧綠,廣闊無(wú)際;沙洲上的鷗鳥(niǎo),時(shí)而飛翔,時(shí)而停歇,美麗的魚(yú)游來(lái)游去,岸上與小洲上的花草,青翠欲滴。");
    pre_input.push_back("以詠梅為題目,幫我寫(xiě)一首古詩(shī),要求包含梅花、白雪等元素。");
    pre_input.push_back("上聯(lián): 江邊慣看千帆過(guò)");
    pre_input.push_back("把這句話翻譯成中文: Knowledge can be acquired from many sources. These include books, teachers and practical experience, and each has its own advantages. The knowledge we gain from books and formal education enables us to learn about things that we have no opportunity to experience in daily life. We can also develop our analytical skills and learn how to view and interpret the world around us in different ways. Furthermore, we can learn from the past by reading books. In this way, we won't repeat the mistakes of others and can build on their achievements.");
    pre_input.push_back("把這句話翻譯成英文: RK3588是新一代高端處理器,具有高算力、低功耗、超強(qiáng)多媒體、豐富數(shù)據(jù)接口等特點(diǎn)");
    cout 

1.8 模型部署API說(shuō)明

1.8.1 回調(diào)函數(shù)定義

回調(diào)函數(shù)是用于接收模型實(shí)時(shí)輸出的結(jié)果。在初始化 RKLLM 時(shí)回調(diào)函數(shù)會(huì)被綁定,在模型推理過(guò)程中不斷將結(jié)果輸出至回調(diào)函數(shù)中,并且每次回調(diào)只返回一個(gè) token。

示例代碼如下,該回調(diào)函數(shù)將輸出結(jié)果實(shí)時(shí)地打印輸出到終端中:

void callback(RKLLMResult* result, void* userdata, LLMCallState state)
{
   if(state == LLM_RUN_NORMAL){
      printf("%s", result->text);
      for (int i=0; inum; i++) {
          printf("token_id: %d logprob: %f", result->tokens[i].id, 
          result->tokens[i].logprob);
      }
   }
   if (state == LLM_RUN_FINISH) {
      printf("finishn");
   } else if (state == LLM_RUN_ERROR){
      printf("run errorn");
   }
}

(1)LLMCallState 是一個(gè)狀態(tài)標(biāo)志,其具體定義如下:

表 1 LLMCallState 狀態(tài)標(biāo)志說(shuō)明

枚舉定義 LLMCallState
描述 用于表示當(dāng)前 RKLLM 的運(yùn)行狀態(tài)。
枚舉值 0, LLM_RUN_NORMAL, 表示 RKLLM 模型當(dāng)前正在推理中;
1, LLM_RUN_FINISH, 表示 RKLLM 模型已完成當(dāng)前輸入的全部推理;
2, LLM_RUN_WAITING, 表示當(dāng)前 RKLLM 解碼出的字符不是完整 UTF8 編碼,需等待與下一次解碼拼接;
3, LLM_RUN_ERROR, 表示 RKLLM 模型推理出現(xiàn)錯(cuò)誤;

用戶在回調(diào)函數(shù)的設(shè)計(jì)過(guò)程中,可以根據(jù) LLMCallState 的不同狀態(tài)設(shè)置不同的后處理行為;
(2)RKLLMResult 是返回值結(jié)構(gòu)體,其具體定義如下:

表 2 RKLLMResult 返回值結(jié)構(gòu)體說(shuō)明

結(jié)構(gòu)體定義 RKLLMResult
描述 用于返回當(dāng)前推理生成結(jié)果。
字段 0, text, 表示當(dāng)前推理生成的文本內(nèi)容;
1, token_id, 表示當(dāng)前推理生成的 token id;

1.8.2 參數(shù)結(jié)構(gòu)體 RKLLMParam 定義

結(jié)構(gòu)體 RKLLMParam 用于描述、定義 RKLLM 的詳細(xì)信息,具體的定義如下:

表 2 RKLLMParam 結(jié)構(gòu)體參數(shù)說(shuō)明

結(jié)構(gòu)體定義 RKLLMParam
描述 用于定義 RKLLM 模型的各項(xiàng)細(xì)節(jié)參數(shù)。
字段 const char* model_path: 模型文件的存放路徑;
int32_t max_context_len: 設(shè)置推理時(shí)的最大上下文長(zhǎng)度;
int32_t max_new_tokens: 用于設(shè)置模型推理時(shí)生成 token 的數(shù)量上限;
int32_t top_k: top-k 采樣是一種文本生成方法,它僅從模型預(yù)測(cè)概率最高的 k個(gè) token 中選擇下一個(gè) token。該方法有助于降低生成低概率或無(wú)意義 token 的風(fēng)險(xiǎn)。更高的值(如 100)將考慮更多的 token 選擇,導(dǎo)致文本更加多樣化;而更低的值(如 10)將聚焦于最可能的 token,生成更加保守的文本。默認(rèn)值為40;
float top_p: top-p 采樣,也被稱為核心采樣,是另一種文本生成方法,從累計(jì)概率至少為 p 的一組 token 中選擇下一個(gè) token。這種方法通過(guò)考慮 token 的概率和采樣的 token 數(shù)量在多樣性和質(zhì)量之間提供平衡。更高的值(如 0.95)使得生成的文本更加多樣化;而更低的值(如 0.5)將生成更加保守的文本。默認(rèn)值為 0.9;
float temperature: 控制生成文本隨機(jī)性的超參數(shù),它通過(guò)調(diào)整模型輸出token的概率分布來(lái)發(fā)揮作用;更高的溫度(如 1.5)會(huì)使輸出更加隨機(jī)和創(chuàng)造性,當(dāng)溫度較高時(shí),模型在選擇下一個(gè) token 時(shí)會(huì)考慮更多可能性較低的選項(xiàng),從而產(chǎn)生更多樣和意想不到的輸出;更低的溫度(例 0.5)會(huì)使輸出更加集中、保守,較低的溫度意味著模型在生成文本時(shí)更傾向于選擇概率高的 token,從而導(dǎo)致更一致、更可預(yù)測(cè)的輸出;溫度為 0 的極端情況下,模型總是選擇最有可能的下一個(gè) token,這會(huì)導(dǎo)致每次運(yùn)行時(shí)輸出完全相同;為了確保隨機(jī)性和確定性之間的平衡,使輸出既不過(guò)于單一和可預(yù)測(cè),也不過(guò)于隨機(jī)和雜亂,默認(rèn)值為 0.8;
float repeat_penalty: 控制生成文本中 token 序列重復(fù)的情況,幫助防止模型生成重復(fù)或單調(diào)的文本。更高的值(例如 1.5)將更強(qiáng)烈地懲罰重復(fù),而較低的值(例如 0.9)則更為寬容。默認(rèn)值為 1.1;
float frequency_penalty: 單詞/短語(yǔ)重復(fù)度懲罰因子,減少總體上使用頻率較高的單詞/短語(yǔ)的概率,增加使用頻率較低的單詞/短語(yǔ)的可能性,這可能會(huì)使生成的文本更加多樣化,但也可能導(dǎo)致生成的文本難以理解或不符合預(yù)期。設(shè)置范圍為[-2.0, 2.0],默認(rèn)為 0;
int32_t mirostat: 在文本生成過(guò)程中主動(dòng)維持生成文本的質(zhì)量在期望的范圍內(nèi)的算法,它旨在在連貫性和多樣性之間找到平衡,避免因過(guò)度重復(fù)(無(wú)聊陷阱)或不連貫(混亂陷阱)導(dǎo)致的低質(zhì)量輸出;取值空間為{0, 1, 2}, 0 表示不啟動(dòng)該算法,1 表示使用 mirostat 算法,2 則表示使用 mirostat2.0 算法;
float mirostat_tau: 選項(xiàng)設(shè)置 mirostat 的目標(biāo)熵,代表生成文本的期望困惑度。調(diào)整目標(biāo)熵可以控制生成文本中連貫性與多樣性的平衡。較低的值將導(dǎo)致文本更加集中和連貫,而較高的值將導(dǎo)致文本更加多樣化,可能連貫性較差。默認(rèn)值是 5.0;
float mirostat_eta: 選項(xiàng)設(shè)置 mirostat 的學(xué)習(xí)率,學(xué)習(xí)率影響算法對(duì)生成文本反饋的響應(yīng)速度。較低的學(xué)習(xí)率將導(dǎo)致調(diào)整速度較慢,而較高的學(xué)習(xí)率將使算法更加靈敏。默認(rèn)值是 0.1;
bool skip_special_token: 是否跳過(guò)特殊 token 不輸出,例如結(jié)束符號(hào)等;
bool is_async: 是否使用異步模式;
const char* img_start: 選項(xiàng)設(shè)置多模態(tài)輸入圖像編碼的起始標(biāo)志符,在多模態(tài)輸入模式下需要配置;
const char* img_end: 選項(xiàng)設(shè)置多模態(tài)輸入圖像編碼的終止標(biāo)志符,在多模態(tài)輸入模式下需要配置;
const char* img_content: 選項(xiàng)設(shè)置多模態(tài)輸入圖像編碼的內(nèi)容標(biāo)志符,在多模態(tài)輸入模式下需要配置;

在實(shí)際的代碼構(gòu)建中,RKLLMParam 需要調(diào)用 rkllm_createDefaultParam()函數(shù)來(lái)初始化定義,并根據(jù)需求設(shè)置相應(yīng)的模型參數(shù)。示例代碼如下:

RKLLMParam param = rkllm_createDefaultParam();
param.model_path = "model.rkllm";
param.top_k = 1;
param.max_new_tokens = 256;
param.max_context_len = 512;

1.8.3 輸入結(jié)構(gòu)體定義

為適應(yīng)不同的輸入數(shù)據(jù),定義了 RKLLMInput 輸入結(jié)構(gòu)體,目前可接受文本、圖片和文本、Token id 以及編碼向量四種形式的輸入,具體的定義如下:

表 3 RKLLMInput 結(jié)構(gòu)體參數(shù)說(shuō)明

結(jié)構(gòu)體定義 RKLLMInput
描述 用于接收不同形式的輸入數(shù)據(jù)。
字段 RKLLMInputType input_type: 輸入模式;
union: 用于存儲(chǔ)不同的輸入數(shù)據(jù)類型,具體包含以下幾種形式:
- const char* prompt_input: 文本提示輸入,用于傳遞自然語(yǔ)言文本;
- RKLLMEmbedInput embed_input: 嵌入向量輸入,表示已處理的特征向量;
- RKLLMTokenInput token_input: Token 輸入,用于傳遞 Token 序列;
- RKLLMMultiModelInput multimodal_input: 多模態(tài)輸入,可傳遞多模態(tài)數(shù)據(jù),如圖片和文本的聯(lián)合輸入。

表 4 RKLLMInputType 輸入類型說(shuō)明

枚舉定義 RKLLMInputType
描述 用于表示輸入數(shù)據(jù)類型。
枚舉值 0, RKLLM_INPUT_PROMPT, 表示輸入數(shù)據(jù)是純文本;
1, RKLLM_INPUT_TOKEN, 表示輸入數(shù)據(jù)是 Token id;
2, RKLLM_INPUT_EMBED, 表示輸入數(shù)據(jù)是編碼向量;
3, RKLLM_INPUT_MULTIMODAL, 表示輸入數(shù)據(jù)是圖片和文本;

當(dāng)輸入數(shù)據(jù)是純文本時(shí),使用 input_data 直接輸入;當(dāng)輸入數(shù)據(jù)是 Token id、編碼向量以及圖片 和 文 本 時(shí) , RKLLMInput 需 要 搭 配 RKLLMTokenInput, RKLLMEmbedInput 以 及RKLLMMultiModelInput 三個(gè)輸入結(jié)構(gòu)體使用,具體的介紹如下:

(1)RKLLMTokenInput 是接收 Token id 的輸入結(jié)構(gòu)體,具體的定義如下:

表 5 RKLLMTokenInput 結(jié)構(gòu)體參數(shù)說(shuō)明

結(jié)構(gòu)體定義 RKLLMTokenInput
描述 用于接收 Token id 數(shù)據(jù)。
字段 int32_t* input_ids: 輸入 token ids 的內(nèi)存指針;
size_t n_tokens: 輸入數(shù)據(jù)的 token 數(shù)量;

(2)RKLLMEmbedInput 是接收編碼向量的輸入結(jié)構(gòu)體,具體的定義如下:

表 6 RKLLMEmbedInput 結(jié)構(gòu)體參數(shù)說(shuō)明

結(jié)構(gòu)體定義 RKLLMEmbedInput
描述 用于接收 Embedding 數(shù)據(jù)。
字段 float* embed: 輸入 token embedding 的內(nèi)存指針;
size_t n_tokens: 輸入數(shù)據(jù)的 token 數(shù)量;

(3)RKLLMMultiModelInput 是接收?qǐng)D片和文本的輸入結(jié)構(gòu)體,具體的定義如下:

表 7 RKLLMMultiModelInput 結(jié)構(gòu)體參數(shù)說(shuō)明

結(jié)構(gòu)體定義 RKLLMMultiModelInput
描述 用于接收?qǐng)D片和文本多模態(tài)數(shù)據(jù)。
字段 char* prompt: 輸入文本的內(nèi)存指針;
float* image_embed: 輸入圖片 embedding 的內(nèi)存指針;
size_t n_image_tokens: 輸入圖片 embedding 的 token 數(shù)量;

純文本輸入示例代碼如下:

// 提前定義 prompt 前后的文本預(yù)設(shè)值
#define PROMPT_TEXT_PREFIX "<|im_start|?>system You are a helpful 
assistant. <|im_end|?> <|im_start|?>user"
#define PROMPT_TEXT_POSTFIX "<|im_end|?><|im_start|?>assistant"

// 定義輸入的 prompt 并完成前后 prompt 的拼接
string input_str = "把這句話翻譯成英文:RK3588 是新一代高端處理器,具有高算力、
低功耗、超強(qiáng)多媒體、豐富數(shù)據(jù)接口等特點(diǎn)";
input_str = PROMPT_TEXT_PREFIX + input_str + PROMPT_TEXT_POSTFIX;

RKLLMInput rkllm_input;
rkllm_input.input_data = (char*)input_str.c_str();
rkllm_input.input_type = RKLLM_INPUT_PROMPT;

// 初始化 infer 參數(shù)結(jié)構(gòu)體
RKLLMInferParam rkllm_infer_params;
memset(&rkllm_infer_params, 0, sizeof(RKLLMInferParam)); // 將所有內(nèi)容初
始化為 0
rkllm_infer_params.mode = RKLLM_INFER_GENERATE;

圖片和文本多模態(tài)輸入示例代碼如下,注意多模態(tài)輸入的 prompt 中需要加入占位符用于標(biāo)示圖像編碼插入的位置:

// 提前定義 prompt 前后的文本預(yù)設(shè)值
#define PROMPT_TEXT_PREFIX "<|im_start|?>system You are a helpful 
assistant. <|im_end|?> <|im_start|?>user"
#define PROMPT_TEXT_POSTFIX "<|im_end|?><|im_start|?>assistant"

RKLLMInput rkllm_input;

// 定義輸入的 prompt 并完成前后 prompt 的拼接
string input_str = "Please describe the image shortly.";
input_str = PROMPT_TEXT_PREFIX + input_str + PROMPT_TEXT_POSTFIX;
rkllm_input.multimodal_input.prompt = (char*)input_str.c_str();

rkllm_input.multimodal_input.n_image_tokens = 256;
int rkllm_input_len = multimodal_input.n_image_tokens * 3072;
rkllm_input.multimodal_input.image_embed = (float 
*)malloc(rkllm_input_len * sizeof(float));
FILE *file;
file = fopen("models/image_embed.bin", "rb");
fread(rkllm_input.multimodal_input.image_embed, sizeof(float), 
rkllm_input_len, file);
fclose(file);

rkllm_input.input_type = RKLLM_INPUT_MULTIMODAL;

// 初始化 infer 參數(shù)結(jié)構(gòu)體
RKLLMInferParam rkllm_infer_params;
memset(&rkllm_infer_params, 0, sizeof(RKLLMInferParam)); // 將所有內(nèi)容初
始化為 0
rkllm_infer_params.mode = RKLLM_INFER_GENERATE;

RKLLM 支持不同的推理模式,定義了 RKLLMInferParam 結(jié)構(gòu)體,目前可支持在推理過(guò)程與預(yù)加載的 LoRA 模型聯(lián)合推理,或保存 Prompt Cache 用于后續(xù)推理加速,具體的定義如下:

表 8 RKLLMInferParam 結(jié)構(gòu)體參數(shù)說(shuō)明

結(jié)構(gòu)體定義 RKLLMInferParam
描述 用于定義不同的推理模式。
字段 RKLLMInferMode mode: 推理模式,當(dāng)前僅支持 RKLLM_INFER_GENERATE 模式;
RKLLMLoraParam* lora_params: 推理時(shí)使用的 LoRA 的參數(shù)配置,用于在加載多個(gè) LoRA 時(shí)選擇需要推理的 LoRA,若無(wú)需加載 LoRA 則設(shè)為 NULL 即可;
RKLLMPromptCacheParam* prompt_cache_params: 推理時(shí)使用Prompt Cache的參數(shù)配置,若無(wú)需生成 Prompt Cache 則設(shè)為 NULL 即可;

表 9 RKLLMLoraParam 結(jié)構(gòu)體參數(shù)說(shuō)明

結(jié)構(gòu)體定義 RKLLMLoraParam
描述 用于定義推理時(shí)使用 LoRA 的參數(shù);
字段 const char* lora_adapter_name: 推理時(shí)使用的 LoRA 名稱

表 10 RKLLMInferParam 結(jié)構(gòu)體參數(shù)說(shuō)明

結(jié)構(gòu)體定義 RKLLMPromptCacheParam
描述 用于定義推理時(shí)使用 Prompt Cache 的參數(shù);
字段 int save_prompt_cache: 是否在推理時(shí)保存 Prompt Cache, 1 為需要, 0 為不需要;
const char* prompt_cache_path: Prompt Cache 保存路徑, 若未設(shè)置則默認(rèn)保存到"./prompt_cache.bin"中;

使用 InferRaram 的示例如下:

// 1. 初始化并設(shè)置 LoRA 參數(shù)(如果需要使用 LoRA)
RKLLMLoraParam lora_params;
lora_params.lora_adapter_name = "test"; // 指定用于推理的 lora 名稱
// 2. 初始化并設(shè)置 Prompt Cache 參數(shù)(如果需要使用 prompt cache)
RKLLMPromptCacheParam prompt_cache_params;
prompt_cache_params.save_prompt_cache = true; // 是否保存 prompt cache
prompt_cache_params.prompt_cache_path = "./prompt_cache.bin"; // 若需要
保存 prompt cache, 指定 cache 文件路徑
rkllm_infer_params.mode = RKLLM_INFER_GENERATE;
rkllm_infer_params.lora_params = &lora_params;
rkllm_infer_params.prompt_cache_params = &prompt_cache_params;

1.8.4 初始化模型

在進(jìn)行模型的初始化之前,需要提前定義 LLMHandle 句柄,該句柄用于模型的初始化、推理和資源釋放過(guò)程。注意,正確的模型推理流程需要統(tǒng)一這 3 個(gè)流程中的 LLMHandle 句柄對(duì)象。在模型推理前,用戶需要通過(guò) rkllm_init()函數(shù)完成模型的初始化,具體函數(shù)的定義如下:

表 11 rkllm_init 函數(shù)接口說(shuō)明

函數(shù)名 rkllm_init
描述 用于初始化 RKLLM 模型的具體參數(shù)及相關(guān)推理設(shè)置。
參數(shù) LLMHandle* handle: 將模型注冊(cè)到相應(yīng)句柄中,用于后續(xù)推理、釋放調(diào)用;
RKLLMParam* param: 模型定義的參數(shù)結(jié)構(gòu)體;
LLMResultCallback callback: 用于接受處理模型實(shí)時(shí)輸出的回調(diào)函數(shù);
返回值 0 表示初始化流程正常;-1 表示初始化失??;

示例代碼如下:

LLMHandle llmHandle = nullptr;
rkllm_init(&llmHandle, ?m, callback);

1.8.5 模型推理

用戶在完成 RKLLM 模型的初始化流程后,即可通過(guò) rkllm_run()函數(shù)進(jìn)行模型推理,并可以通過(guò)初始化時(shí)預(yù)先定義的回調(diào)函數(shù)對(duì)實(shí)時(shí)推理結(jié)果進(jìn)行處理;rkllm_run()的具體函數(shù)定義如下:

表 12 rkllm_run 函數(shù)接口說(shuō)明

函數(shù)名 rkllm_run
描述 調(diào)用完成初始化的 RKLLM 模型進(jìn)行結(jié)果推理;
參數(shù) LLMHandle handle: 模型初始化注冊(cè)的目標(biāo)句柄;
RKLLMInput* rkllm_input: 模型推理的輸入數(shù)據(jù);
RKLLMInferParam* rkllm_infer_params: 模型推理過(guò)程中的參數(shù)傳遞;
void* userdata: 用戶自定義的函數(shù)指針,默認(rèn)設(shè)置為 NULL 即可;
返回值 0 表示模型推理正常運(yùn)行;-1 表示調(diào)用模型推理失??;

模型推理的示例代碼如下:

#define PROMPT_TEXT_PREFIX "<|im_start|?>system You are a helpful 
assistant. <|im_end|?> <|im_start|?>user"
#define PROMPT_TEXT_POSTFIX "<|im_end|?><|im_start|?>assistant"

string input_str = "把這句話翻譯成英文:RK3588 是新一代高端處理器,具有高算力、
低功耗、超強(qiáng)多媒體、豐富數(shù)據(jù)接口等特點(diǎn)";
input_str = PROMPT_TEXT_PREFIX + input_str + PROMPT_TEXT_POSTFIX;

// 初始化 infer 參數(shù)結(jié)構(gòu)體
RKLLMInferParam rkllm_infer_params;
memset(&rkllm_infer_params, 0, sizeof(RKLLMInferParam));
rkllm_infer_params.mode = RKLLM_INFER_GENERATE;
// 1. 初始化并設(shè)置 LoRA 參數(shù)(如果需要使用 LoRA)
RKLLMLoraParam lora_params;
lora_params.lora_adapter_name = "test"; // 指定用于推理的 lora 名稱
// 2. 初始化并設(shè)置 Prompt Cache 參數(shù)(如果需要使用 prompt cache)
RKLLMPromptCacheParam prompt_cache_params;
prompt_cache_params.save_prompt_cache = true; // 是否保存 prompt cache
prompt_cache_params.prompt_cache_path = "./prompt_cache.bin";

rkllm_infer_params.mode = RKLLM_INFER_GENERATE;
// rkllm_infer_params.lora_params = &lora_params;
// rkllm_infer_params.prompt_cache_params = &prompt_cache_params;
rkllm_infer_params.lora_params = NULL;
rkllm_infer_params.prompt_cache_params = NULL;

RKLLMInput rkllm_input;
rkllm_input.input_type = RKLLM_INPUT_PROMPT;
rkllm_input.prompt_input = (char *)text.c_str();

rkllm_run(llmHandle, &rkllm_input, &rkllm_infer_params, NULL);

1.8.6 模型中斷

在進(jìn)行模型推理時(shí),用戶可以調(diào)用 rkllm_abort()函數(shù)中斷推理進(jìn)程,具體的函數(shù)定義如下:

表 13 rkllm_ abort 函數(shù)接口說(shuō)明

函數(shù)名 rkllm_ abort
描述 用于中斷 RKLLM 模型推理進(jìn)程。
參數(shù) LLMHandle handle: 模型初始化注冊(cè)的目標(biāo)句柄;
返回值 0 表示 RKLLM 模型中斷成功;-1 表示模型中斷失?。?/td>

示例代碼如下:

// 其中 llmHandle 為模型初始化時(shí)傳入的句柄
rkllm_abort(llmHandle);

1.8.7 釋放模型資源

在完成全部的模型推理調(diào)用后,用戶需要調(diào)用 rkllm_destroy()函數(shù)進(jìn)行 RKLLM 模型的銷毀,并釋放所申請(qǐng)的 CPU、NPU 計(jì)算資源,以供其他進(jìn)程、模型的調(diào)用。具體的函數(shù)定義如下:

表 14 rkllm_ destroy 函數(shù)接口說(shuō)明

函數(shù)名 rkllm_ destroy
描述 用于銷毀 RKLLM 模型并釋放所有計(jì)算資源。
參數(shù) LLMHandle handle: 模型初始化注冊(cè)的目標(biāo)句柄;
返回值 0 表示 RKLLM 模型正常銷毀、釋放;-1 表示模型釋放失?。?/td>

示例代碼如下:

// 其中 llmHandle 為模型初始化時(shí)傳入的句柄
rkllm_destroy(llmHandle);

1.8.8 LoRA 模型加載

RKLLM 支持在推理基礎(chǔ)模型的同時(shí)推理 LoRA 模型,可以在調(diào)用 rkllm_run 接口前通過(guò)rkllm_load_lora 接口加載 LoRA 模型。RKLLM 支持加載多個(gè) LoRA 模型,每調(diào)用一次rkllm_load_lora 可加載一個(gè) LoRA 模型。具體的函數(shù)定義如下:

表 15 rkllm_load_lora 函數(shù)接口說(shuō)明

函數(shù)名 rkllm_load_lora
描述 用于加載 LoRA 模型。
參數(shù) LLMHandle handle: 模型初始化注冊(cè)的目標(biāo)句柄;
RKLLMLoraAdapter* lora_adapter: 加載 LoRA 模型時(shí)的參數(shù)配置;
返回值 0 表示 LoRA 模型正常加載;-1 表示模型加載失??;

表 16 RKLLMLoraAdapter 結(jié)構(gòu)體參數(shù)說(shuō)明

結(jié)構(gòu)體定義 RKLLMLoraAdapter
描述 用于配置加載 LoRA 時(shí)的參數(shù)。
字段 const char* lora_adapter_path: 待加載 LoRA 模型的路徑;
const char* lora_adapter_name: 待加載 LoRA 模型的名稱, 由用戶自定義, 用于后續(xù)推理時(shí)選擇指定 LoRA;
float scale: LoRA 模型在推理過(guò)程中對(duì)基礎(chǔ)模型參數(shù)進(jìn)行調(diào)整的幅度;

加載 LoRA 的示例代碼如下:

RKLLMLoraAdapter lora_adapter;
memset(&lora_adapter, 0, sizeof(RKLLMLoraAdapter));
lora_adapter.lora_adapter_path = "lora.rkllm";
lora_adapter.lora_adapter_name = "lora_name";
lora_adapter.scale = 1.0;
ret = rkllm_load_lora(llmHandle, &lora_adapter);
if (ret != 0) {
   printf("nload lora failedn");
}

1.8.9 Prompt Cache 加載

RKLLM 支持加載預(yù)生成的 Prompt Cache 文件,以此加速模型 Prefill 階段的推理。具體的函數(shù)定義如下:

表 17 rkllm_load_prompt_cache 函數(shù)接口說(shuō)明

函數(shù)名 rkllm_load_prompt_cache
描述 用于加載 Prompt Cache。
參數(shù) LLMHandle handle: 模型初始化注冊(cè)的目標(biāo)句柄,可見(jiàn) 4. 初始化模型;
const char* prompt_cache_path: 待加載 Prompt Cache 文件的路徑;
返回值 0 表示 Prompt Cache 模型正常加載;-1 表示模型加載失??;

表 18 rkllm_release_prompt_cache 函數(shù)接口說(shuō)明

函數(shù)名 rkllm_release_prompt_cache
描述 用于釋放 Prompt Cache。
參數(shù) LLMHandle handle: 模型初始化注冊(cè)的目標(biāo)句柄,可見(jiàn) 4. 初始化模型;
返回值 0 表示 Prompt Cache 模型正常釋放;-1 表示模型釋放失??;

加載 Prompt Cache 的示例代碼如下:

rkllm_load_prompt_cache(llmHandle, "./prompt_cache.bin");
if (ret != 0) {
printf("nload Prompt Cache failedn");
}

審核編輯 黃宇

聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 開(kāi)發(fā)板
    +關(guān)注

    關(guān)注

    25

    文章

    5620

    瀏覽量

    103503
  • python
    +關(guān)注

    關(guān)注

    56

    文章

    4825

    瀏覽量

    86444
  • 大模型
    +關(guān)注

    關(guān)注

    2

    文章

    3085

    瀏覽量

    3963
  • rk3576
    +關(guān)注

    關(guān)注

    1

    文章

    162

    瀏覽量

    645
收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評(píng)論

    相關(guān)推薦
    熱點(diǎn)推薦

    基于RK3576開(kāi)發(fā)板的人臉識(shí)別算法

    RK3576開(kāi)發(fā)板展示人臉識(shí)別算法例程和API說(shuō)明
    的頭像 發(fā)表于 05-07 16:48 ?1882次閱讀
    基于<b class='flag-5'>RK3576</b><b class='flag-5'>開(kāi)發(fā)板</b>的人臉識(shí)別算法

    基于RK3576開(kāi)發(fā)板的RTC使用說(shuō)明

    文章主要展示RK3576開(kāi)發(fā)板的RTC信息和快速上手例程
    的頭像 發(fā)表于 05-07 15:04 ?735次閱讀
    基于<b class='flag-5'>RK3576</b><b class='flag-5'>開(kāi)發(fā)板</b>的RTC使用說(shuō)明

    基于RK3576開(kāi)發(fā)板的PWN使用說(shuō)明

    RK3576開(kāi)發(fā)板使用PWN教程及Demo
    的頭像 發(fā)表于 05-07 14:07 ?1226次閱讀
    基于<b class='flag-5'>RK3576</b><b class='flag-5'>開(kāi)發(fā)板</b>的PWN使用說(shuō)明

    基于RK3576開(kāi)發(fā)板的TF卡槽使用說(shuō)明

    RK3576開(kāi)發(fā)板使用TF卡槽
    的頭像 發(fā)表于 05-07 09:24 ?663次閱讀
    基于<b class='flag-5'>RK3576</b><b class='flag-5'>開(kāi)發(fā)板</b>的TF卡槽使用說(shuō)明

    基于RK3576開(kāi)發(fā)板的PCIE固態(tài)硬盤(pán)使用說(shuō)明

    RK3576開(kāi)發(fā)板的PICE固態(tài)硬盤(pán)使用方法
    的頭像 發(fā)表于 05-06 17:33 ?1290次閱讀
    基于<b class='flag-5'>RK3576</b><b class='flag-5'>開(kāi)發(fā)板</b>的PCIE固態(tài)硬盤(pán)使用說(shuō)明

    基于RK3576開(kāi)發(fā)板的WDT看門(mén)狗使用說(shuō)明

    RK3576開(kāi)發(fā)板的WDT使用說(shuō)明
    的頭像 發(fā)表于 05-06 17:15 ?564次閱讀
    基于<b class='flag-5'>RK3576</b><b class='flag-5'>開(kāi)發(fā)板</b>的WDT看門(mén)狗使用說(shuō)明

    基于RK3576開(kāi)發(fā)板的HDMI-OUT使用說(shuō)明

    RK3576開(kāi)發(fā)板的HDMI-OUT使用說(shuō)明
    的頭像 發(fā)表于 05-06 16:48 ?262次閱讀
    基于<b class='flag-5'>RK3576</b><b class='flag-5'>開(kāi)發(fā)板</b>的HDMI-OUT使用說(shuō)明

    基于RK3576開(kāi)發(fā)板的MIPI-DSI使用

    MIPI DSI接口是由MIPI聯(lián)盟下的Display工作組指定的DSI(Display Serial Interface)的接口標(biāo)準(zhǔn)。rk3576開(kāi)發(fā)板使用mipi-dsi教程
    的頭像 發(fā)表于 05-06 16:11 ?302次閱讀
    基于<b class='flag-5'>RK3576</b><b class='flag-5'>開(kāi)發(fā)板</b>的MIPI-DSI使用

    米爾RK3576開(kāi)發(fā)板評(píng)測(cè)】+ RKLLM-Toolkit 環(huán)境安裝

    3588和RK3576,詳情可在《RKLLM SDK User Guide》查找。 為了使用 RKNPU,用戶需要首先在計(jì)算機(jī)上運(yùn)行 RKLLM-Toolkit 工具,將訓(xùn)練好的模型轉(zhuǎn)
    發(fā)表于 02-22 09:41

    迅為RK3576開(kāi)發(fā)板Android?多屏顯示

    迅為RK3576開(kāi)發(fā)板Android?多屏顯示
    的頭像 發(fā)表于 01-16 16:58 ?932次閱讀
    迅為<b class='flag-5'>RK3576</b><b class='flag-5'>開(kāi)發(fā)板</b>Android?多屏顯示

    迅為RK3576開(kāi)發(fā)板核心與底板接口硬件介紹

    迅為RK3576開(kāi)發(fā)板核心與底板接口硬件介紹
    的頭像 發(fā)表于 01-14 15:15 ?1400次閱讀
    迅為<b class='flag-5'>RK3576</b><b class='flag-5'>開(kāi)發(fā)板</b>核心<b class='flag-5'>板</b>與底板接口硬件介紹

    敬請(qǐng)期待 | 迅為RK3576開(kāi)發(fā)板即將發(fā)布

    敬請(qǐng)期待 | 迅為RK3576開(kāi)發(fā)板即將發(fā)布
    的頭像 發(fā)表于 11-22 15:13 ?591次閱讀
    敬請(qǐng)期待 | 迅為<b class='flag-5'>RK3576</b><b class='flag-5'>開(kāi)發(fā)板</b>即將發(fā)布

    米爾RK3576開(kāi)發(fā)板特惠活動(dòng)!

    近日,米爾電子發(fā)布基于瑞芯微RK3576核心開(kāi)發(fā)板,RK3576作為國(guó)產(chǎn)熱門(mén)處理器,其高性能數(shù)據(jù)處理能力、領(lǐng)先的AI智能分析、強(qiáng)大的擴(kuò)展性與兼容性受到廣大
    的頭像 發(fā)表于 11-12 01:00 ?789次閱讀
    米爾<b class='flag-5'>RK3576</b><b class='flag-5'>開(kāi)發(fā)板</b>特惠活動(dòng)!

    新品體驗(yàn) | RK3576開(kāi)發(fā)板

    RK3399、RK3566、RK3568、RK3588、RK3576等型號(hào)的核心與評(píng)估
    的頭像 發(fā)表于 11-01 08:08 ?1855次閱讀
    新品體驗(yàn) | <b class='flag-5'>RK3576</b><b class='flag-5'>開(kāi)發(fā)板</b>

    【飛凌嵌入式OK3576-C開(kāi)發(fā)板體驗(yàn)】rkllm模型量化構(gòu)建

    和Android下RKLLM Runtime 的全部文件: lib/librkllmrt.so: 適用于 RK3576/RK3588 端進(jìn)行模型
    發(fā)表于 08-27 22:50