BGE-Base-Zh-V1.5 端侧使用教程

BGE 模型部署与运行指南 (QNN)

本项目基于 ai-engine-direct-helper (QAI_AppBuilder)
           https://github.com/quic/ai-engine-direct-helper.git

模型下载地址 (包含对应的上下文二进制文件)
           https://www.aidevhome.com/?id=51

QNN SDK (v2.41) 下载地址
           https://qpm.qualcomm.com/.../Qualcomm_AI_Runtime_SDK?version=2.41.0.251128

第一部分:Windows 平台推理指南


本部分介绍如何在 Windows 平台上使用 QNN SDK 进行模型推理。

1.1 环境准备

  1. 下载模型压缩包

  2. 进入目录:在终端中 cd 进入模型所在目录。

  3.  安装环境

    在已进入的模型目录中,请依次运行以下命令来安装相关的运行时依赖。建议先安装 QAI AppBuilder 的底层库,然后再安装其余的环境依赖。

    pip install qai_appbuilder-2.38.0-cp312-cp312-win_amd64.whl
    # 2. 再安装其他依赖
    pip install -r requirements.txt

1.2 执行推理

使用 python 运行推理命令。

>python inference.py
正在对 3 个文本编码...

[0]  '这是一段测试文本'
     vec[:6] = [-0.000327636138536036, -0.026442164555191994, -0.03566736727952957, -0.012925566174089909, -0.0035204824525862932, 0.003126997733488679]
     norm    = 1.000000
[1]  '今天天气不错'
     vec[:6] = [0.022236667573451996, -0.019486118108034134, -0.002200440037995577, 0.026454178616404533, -0.00762207992374897, 0.015892066061496735]
     norm    = 1.000000
[2]  '机器学习是人工智能的重要分支'
     vec[:6] = [0.00771187711507082, -0.046235859394073486, -0.02518308535218239, 0.05116862803697586, -0.005484460387378931, 0.0030166006181389093]
     norm    = 1.000000

=== Cosine 相似度矩阵 ===
  '这是一段测试文本' vs '今天天气不错' = 0.370892
  '这是一段测试文本' vs '机器学习是人工智' = 0.406855
  '今天天气不错' vs '机器学习是人工智' = 0.300794

第二部分:Android 平台推理指南

本部分介绍如何在 Android 设备(通过 ADB)上进行模型推理。

2.1 快速验证

2.1.1环境准备

  1. 上传依赖库:将 QNN SDK 2.41 中的 aarch64-android 库文件上传到设备(程序在2.41.0.251128\bin\aarch64-android)

    # 示例:将库文件复制到设备目录
    adb push libQnnHtp.so /data/local/tmp/bge_model/
    adb push libQnnSystem.so /data/local/tmp/bge_model/
    adb push libQnnHtpV73Skel.so /data/local/tmp/bge_model/
    # ... 以及其他必要文件
  2. 设置环境变量:进入 ADB shell 并设置库路径。

    cd /data/local/tmp/bge_model/
    export LD_LIBRARY_PATH=$PWD
    export ADSP_LIBRARY_PATH=$PWD
    chmod +x qnn-net-run

2.1.2执行推理

在 ADB Shell 中运行以下命令:

./qnn-net-run \
    --retrieve_context ./model.bin \
    --backend ./libQnnHtp.so \
    --input_list ./inputs/input_list.txt \
    --use_native_input_files \
    --config_file ./htp_backend.json

2.2 项目编译

注意: 整体的编译后端库流程请查看项目代码ai-engine-direct-helper-main\samples\android

2.2.1模型前处理和后处理

BgeProcessor.zip

import android.content.res.AssetManager;
import java.io.InputStream;
import java.util.Arrays;
// ...
try {
    // 1. 初始化 (加载词表)
    AssetManager assets = getAssets();
    InputStream vocabStream = assets.open("vocab.txt");
    BgeProcessor processor = new BgeProcessor(vocabStream);
    // 2. 前处理 (输入文本 -> 模型输入)
    String text = "这是一段测试文本";
    BgeProcessor.BgeInput input = processor.preprocess(text);
    // 打印结果验证 (Int数组可以直接传给 TFLite 或 QNN)
    // Log.d("BGE", "Input IDs: " + Arrays.toString(input.inputIds));
    // Log.d("BGE", "Attention Mask: " + Arrays.toString(input.attentionMask));
   
    // ---------------------------------------------------------
    // 这里执行你的模型推理 (TFLite / ONNX / QNN)
    // 假设 modelOutput 是推理得到的 float[] (大小通常是 768)
    // float[] modelOutput = runInference(input.inputIds, ...);
    // ---------------------------------------------------------
   
    // 模拟一个推理结果用于测试
    float[] mockOutput = new float[768];
    Arrays.fill(mockOutput, 0.1f);
    // 3. 后处理 (归一化)
    float[] finalEmbedding = processor.postprocess(mockOutput);
   
    // Log.d("BGE", "Normalized Embedding[0]: " + finalEmbedding[0]);
} catch (Exception e) {
    e.printStackTrace();
}

2.2.2模型调用推理

Java_com_example_DDColor_MainActivity_DDColor(...) {
    float* inputBuffer = (float*)env->GetDirectBufferAddress(j_inputBuffer);
    float* outputBuffer = (float*)env->GetDirectBufferAddress(j_outputBuffer);
    // 1. 指定后端 (例如:libQnnHtp.so 表示在DSP上运行)
    std::string backend_lib_path = libs_dir + "/libQnnHtp.so";
    std::string system_lib_path = libs_dir + "/libQnnSystem.so";
   
    // 2. 初始化模型
    libAppBuilder.ModelInitialize(MODEL_NAME, model_path, backend_lib_path, ...);
    // 3. 执行推理
    libAppBuilder.ModelInference(MODEL_NAME, ...);
    // 4. 拷贝结果
    memcpy(outputBuffer, outputBuffers.at(0), outputSize[0]);
   
    // ... 释放资源 ...
    return 0;
}