> ## Documentation Index
> Fetch the complete documentation index at: https://dragonwingdocs.qualcomm.com/llms.txt
> Use this file to discover all available pages before exploring further.

# 使用 Qualcomm Generative AI (GenAI) 推理扩展 (Genie) 运行 GenAI 模型

> 使用 Genie 框架和 CLI 工具在 Qualcomm Dragonwing 物联网平台上运行大语言模型 (LLM) 和多模态模型。

Genie 是一个高层框架,用于在 Qualcomm 平台上运行 GenAI 模型,如 LLM、视觉
Transformer 和多模态模型。它屏蔽了管理多种二进制文件的复杂性,并在异构计算单元
(CPU、GPU、NPU)之间协调执行,提供低延迟、高能效以及简单的用户体验。

<img src="https://mintlify.s3.us-west-1.amazonaws.com/qualcomm-prod/zh/AI-Developer-Workflow-Ubuntu/_images/genie-arch.png" alt="用于在 Qualcomm 平台上运行 GenAI 模型的 Genie 框架架构" />

以下 JSON 配置、Genie 工具和 C API 是在设备端准备、执行和管理 GenAI 模型的核心
组件。

| 组件        | 用途                                  |                          |                                                                                                            |                   |                         |                                      |                                                                                                                             |
| --------- | ----------------------------------- | ------------------------ | ---------------------------------------------------------------------------------------------------------- | ----------------- | ----------------------- | ------------------------------------ | --------------------------------------------------------------------------------------------------------------------------- |
| JSON 配置   | 主要功能:                               | 指定后端选择(CPU 或 NPU)。       | 配置模型路径、分词器设置和内存分配。                                                                                         | 管理多轮对话的会话参数。示例字段: | `backend`:"CPU" 或 "NPU" | `model_bundle_path`:Genie 模型二进制文件的路径 | `max_tokens`:token 生成上限。更多信息请参见 [Qualcomm AI Engine Direct](https://docs.qualcomm.com/doc/80-63442-10/topic/index_QNN.html) |
| Genie 工具  | 用于模型执行和性能分析的命令行工具。常用工具:             | `genie-t2t-run`:文本到文本推理。 | `genie-profile`:性能分析。更多信息请参见 [Qualcomm AI Runtime (QAIRT) SDK](https://docs.qualcomm.com/doc/80-63442-10)。 |                   |                         |                                      |                                                                                                                             |
| Genie API | 提供以编程方式将 Genie 集成到 GenAI 应用中的入口。特性: | 对话 API:支持多轮对话工作流。        | Token 生成 API:处理 LLM 的增量 token 流式输出。优势:                                                                     | 支持自定义应用逻辑。        | 对推理会话提供细粒度控制。集成:        | 与 QAIRT SDK 协同进行后端执行。                | 同时支持 CPU 和 NPU 目标。更多信息请参见 [QAIRT](https://docs.qualcomm.com/doc/80-63442-10)                                                |

## 使用 Genie 运行 LLM

在使用 [AI Hub](../topic/genai-prepare-ai-hub) 或
[Jupyter notebooks](../topic/genai-prepare-jupyter) 准备并优化好您的大语言模型
(LLM) 后,Genie 提供了一种在 Qualcomm 平台上高效执行它的方式。

### 前置条件

在使用 Genie 运行语言模型之前,确认满足以下前置条件。

* 模型包已针对正确的后端(CPU 或 NPU)导出并准备就绪,并包含
  AI Engine Direct (QNN) 二进制文件、分词器文件和配置文件。
* QAIRT 已安装在目标设备上,并且 Genie 工具和库作为 SDK 的一部分可用。
* 目标硬件为具备充足内存(足以复制并执行模型二进制文件的 RAM 和存储)的 Qualcomm 平台。

下图展示了使用 Genie 通过 `genie-t2t-run` 运行 LLM 所需的输入。

<img src="https://mintlify.s3.us-west-1.amazonaws.com/qualcomm-prod/zh/AI-Developer-Workflow-Ubuntu/_images/genie-t2t-execution.png" alt="使用 genie-t2t-run 运行 LLM 所需的输入" />

`genie-t2t-run` 工具是一个用于在给定 LLM 网络上执行文本到文本推理的测试应用。它以
文本形式接收用户 prompt,并以文本形式输出结果。它提供了一个开箱即用的命令行界面
(CLI),可通过 CPU、GPU 和 Hexagon Tensor Processor (HTP) 后端在受支持的 Qualcomm
设备上运行 LLM 推理。Genie 使用预优化的模型资源将多二进制 LLM 执行简化为单个任务。

以下代码片段展示了一个示例 `genie-t2t-run` 命令。

```
genie-t2t-run -c genie_config.json -p "Tell me about Qualcomm" 
```

下图展示了 `genie-t2t-run` 命令的调用流程。

<img src="https://mintlify.s3.us-west-1.amazonaws.com/qualcomm-prod/zh/AI-Developer-Workflow-Ubuntu/_images/genie-t2t-call-flow.png" alt="genie-t2t-run 命令的调用流程" />

以下步骤详述了如何将 LLM 相关文件推送到目标设备,并使用 Genie 运行 LLM 模型。
在执行 `genie-t2t-run` 之前,您需要将模型准备阶段生成的 genie-bundle 复制到目标设备。

<Steps>
  <Step title="使用目标设备的 IP 地址连接设备">
    在主机上:

    ```shell theme={null}
    ssh ubuntu@<IP_ADDRESS_OF_TARGET_DEVICE>
    ```
  </Step>

  <Step title="创建目录以存放模型文件">
    在目标设备上,通过上一步的 SSH 会话执行:

    ```shell theme={null}
    mkdir -p /tmp
    ```
  </Step>

  <Step title="推送运行模型所需的库和二进制文件">
    在主机上:

    ```shell theme={null}
    scp ${QNN_SDK_ROOT}/bin/aarch64-oe-linux-gcc11.2/genie-t2t-run ubuntu@<TARGET_IP>:/tmp/
    ```

    ```shell theme={null}
    scp ${QNN_SDK_ROOT}/lib/aarch64-oe-linux-gcc11.2/libGenie.so ubuntu@<TARGET_IP>:/tmp/
    ```

    ```shell theme={null}
    scp ${QNN_SDK_ROOT}/lib/aarch64-oe-linux-gcc11.2/libQnnHtp.so ubuntu@<TARGET_IP>:/tmp/
    ```

    ```shell theme={null}
    scp ${QNN_SDK_ROOT}/lib/aarch64-oe-linux-gcc11.2/libQnnSystem.so ubuntu@<TARGET_IP>:/tmp/
    ```

    ```shell theme={null}
    scp ${QNN_SDK_ROOT}/lib/aarch64-oe-linux-gcc11.2/libQnnHtpPrepare.so ubuntu@<TARGET_IP>:/tmp/
    ```

    ```shell theme={null}
    scp ${QNN_SDK_ROOT}/lib/aarch64-oe-linux-gcc11.2/libQnnHtpNetRunExtensions.so ubuntu@<TARGET_IP>:/tmp/
    ```

    <Note>
      在下面的命令中,请将 `<ARCHITECTURE>` 替换为 DSP Hexagon 架构库的版本号。

      | 设备                             | 架构   |
      | ------------------------------ | ---- |
      | IQ-8275                        | `75` |
      | IQ-9075/QCS9100                | `73` |
      | Qualcomm Dragonwing™ RB3 Gen 2 | `68` |

      对于其他硬件的 Hexagon 架构,请查看此[页面](https://docs.qualcomm.com/nav/home/QNN_general_overview.html?product=924033590759186372#supported-snapdragon-devices)。
    </Note>

    ```shell theme={null}
    scp ${QNN_SDK_ROOT}/lib/aarch64-oe-linux-gcc11.2/libQnnHtpV<ARCHITECTURE>Stub.so ubuntu@<TARGET_IP>:/tmp/
    ```

    ```shell theme={null}
    scp ${QNN_SDK_ROOT}/lib/hexagon-v<ARCHITECTURE>/unsigned/libQnnHtpV<ARCHITECTURE>Skel.so ubuntu@<TARGET_IP>:/tmp/
    ```
  </Step>

  <Step title="推送模型二进制文件和配置文件">
    在主机上:

    ```shell theme={null}
    scp <path to htp_backend_ext_config.json> ubuntu@<TARGET_IP>:/tmp/
    ```

    ```shell theme={null}
    scp <path to genie_config.json> ubuntu@<TARGET_IP>:/tmp/
    ```

    ```shell theme={null}
    scp <path to tokenizer.json> ubuntu@<TARGET_IP>:/tmp/
    ```

    ```shell theme={null}
    scp <path to model bin files> ubuntu@<TARGET_IP>:/tmp/
    ```
  </Step>

  <Step title="运行模型">
    在目标设备上:

    ```shell theme={null}
    export LD_LIBRARY_PATH=/tmp/
    ```

    ```shell theme={null}
    export PATH=$LD_LIBRARY_PATH:$PATH
    ```

    ```shell theme={null}
    cd $LD_LIBRARY_PATH
    ```

    ```shell theme={null}
    ./genie-t2t-run -c <path to genie_config.json> -p "What's the most popular cookie in the world?"
    ```
  </Step>
</Steps>

<Note>
  通过
  [JSON 配置文件](https://docs.qualcomm.com/doc/80-63442-10/topic/json.html#genie-dialog-json-config-string)
  中的 `backend::type` 参数选择运行时。

  | 参数              | 后端   | 描述                                                                                        |
  | --------------- | ---- | ----------------------------------------------------------------------------------------- |
  | `backend::type` | 所有后端 | 使用的引擎:QNN HTP 后端:`QnnHtp`;QNN AI transformer 后端:`QnnGenAiTransformer`;QNN GPU 后端:`QnnGpu` |
</Note>

<Note>
  针对不同模型的 Genie 示例配置可通过
  [AI Hub](https://github.com/qualcomm/ai-hub-apps/tree/main/tutorials/llm_on_genie/configs/genie)
  获取。
</Note>

## 使用 Genie 运行多模态模型

要使用 Genie 运行多模态模型,请使用 GenAI 教程(可在 Qualcomm Package Manager 中
获取)生成模型,然后用 Genie 工具运行它们。

Genie 的多模态执行通过 Genie 管道完成。

* Genie 节点 API:用于创建独立的模块。每个节点的创建都需要一份独立的 JSON 配置,
  类似于对话配置。

  * `text-encoder`
  * `image-encoder`
  * `text-generator`

* Genie 管道 API:用于连接节点并简化执行流程。Genie 管道会管理内部的数据类型转换、
  重量化和拼接操作。

<img src="https://mintlify.s3.us-west-1.amazonaws.com/qualcomm-prod/zh/AI-Developer-Workflow-Ubuntu/_images/genie-multimodal.png" alt="用于多模态模型执行的 Genie 管道,包含文本和图像编码器节点" />

### Genie 管道各阶段

<Steps>
  <Step title="创建节点">
    <Steps>
      <Step title="创建节点配置">
        节点 JSON 配置随节点类型而变化。更多信息请参见 [node JSON](https://docs.qualcomm.com/doc/80-63442-10/topic/node_json.html)

        ```
        Genie_Status_t GenieNodeConfig_createFromJson(const char* str, 
                                                      GenieNodeConfig_Handle_t* configHandle);
        ```
      </Step>

      <Step title="创建节点">
        ```
        Genie_Status_t GenieNode_create(const GenieNodeConfig_Handle_t nodeConfigHandle, 
                                        GenieNode_Handle_t* nodeHandle);
        ```
      </Step>
    </Steps>
  </Step>

  <Step title="构建管道">
    <Steps>
      <Step title="从节点配置创建管道">
        ```
        Genie_Status_t GeniePipelineConfig_createFromJson(const char* str, 
                                                          GeniePipelineConfig_Handle_t* configHandle);
        ```
      </Step>

      <Step title="向管道添加节点">
        ```
        Genie_Status_t GeniePipeline_create(const GeniePipelineConfig_Handle_t configHandle, 
                                            GeniePipeline_Handle_t* pipelineHandle);
        ```
      </Step>

      <Step title="连接节点">
        * 每种节点类型都有一组预定义的 IO 名称。这些名称定义在 `GenieNode.h` 中。

          例如,文本生成器节点有两种可能输入之一和一个输出:

          * 输入:`GENIE_NODE_TEXT_GENERATOR_TEXT_INPUT`
          * 输入:`GENIE_NODE_TEXT_GENERATOR_EMBEDDING_INPUT`
          * 输出:`GENIE_NODE_TEXT_GENERATOR_TEXT_OUTPUT`

        * Genie 管道 connect API 定义从一个生产者节点输出到一个消费者节点输入的一条
          连接。例如:

        ```
        GeniePipeline_connect(pipelineHandle, 
                              lutEncoder, 
                              GENIE_NODE_TEXT_ENCODER_EMBEDDING_OUTPUT,
                              textGenerator,
                              GENIE_NODE_TEXT_GENERATOR_EMBEDDING_INPUT)
        ```
      </Step>
    </Steps>
  </Step>

  <Step title="运行管道">
    <Steps>
      <Step title="为输入节点设置数据">
        ```
        Genie_Status_t GenieNode_setData(const GenieNode_Handle_t nodeHandle, 
                                         const GenieNode_IOName_t nodeIOName, 
                                         const void* data, 
                                         const size_t dataSize, 
                                         const char* dataConfig);
        ```

        * 使用预定义的 IO 名称(与 connect API 中相同)
        * IO 名称隐式定义了数据类型
      </Step>

      <Step title="运行管道">
        ```
        Genie_Status_t GeniePipeline_execute(const GeniePipeline_Handle_t pipelineHandle, 
                                             void* userData);
        ```

        * 注册到输出节点的回调将返回结果。
      </Step>
    </Steps>
  </Step>
</Steps>

## Genie API

Genie API 是在 Qualcomm 设备上运行 LLM 管道的高层接口。它将分词器、引擎(QNN 后端)、
KV 缓存管理、解码和采样封装为对话和 token 生成流程,并将设备端执行委托给带有 HTP/NPU
和 CPU 后端的 QAIRT。

下图展示了 Genie API 内部处理的高层功能。您可以使用 Genie C API 根据 LLM 应用的需要
配置每个组件。

<img src="https://mintlify.s3.us-west-1.amazonaws.com/qualcomm-prod/zh/AI-Developer-Workflow-Ubuntu/_images/genie-dialog.png" alt="Genie API 内部处理的高层功能" />

Genie API 包含以下组件。完整的函数定义和头文件级别的细节请参见
[Genie API 文档](https://docs.qualcomm.com/doc/80-63442-10/topic/library.html)

* `GeniePipeline`:通过将分词器、引擎、采样器和其他节点链接为可运行管道,统一编排
  整个推理工作流。它管理文本生成或 embedding 任务的数据流和执行顺序。
* `GenieNode`:代表管道中的一个处理单元(分词器、引擎)。节点封装了具体功能,可用于
  构建自定义推理图。
* `GenieDialog`:面向对话任务的高层抽象。它通过 JSON 配置将分词器、模型、后端和采样器
  连接起来,并提供 token 生成和 embedding 的 API。
* `GenieEmbedding`:处理检索增强生成 (RAG) 或语义搜索的 embedding 查询。使用已加载的
  模型将输入文本转换为稠密向量表示。
* `GenieProfile`:存储配置和运行时参数,如后端选择、采样策略和性能设置。配置文件允许
  在不同的推理设置之间快速切换。
* `GenieSampler`:实现解码策略(例如贪心、top-k 或 top-p 采样),将模型 logits 转换为
  输出 token。支持推测解码 (SPD)、自推测解码 (SSD) 和前瞻解码 (LADE) 等高级加速技术。
* `GenieEngine`:在所选后端(HTP、GenAI transformer 或 CPU)上执行模型前向计算。
  它管理图执行、内存分配和硬件加速。
* `GenieTokenizer`:在推理过程中将文本转换为 token ID,再将 token ID 转换回文本。
  它支持模型特定的词表,并可为多轮对话高效地进行编解码。

下图展示了在端到端 LLM 聊天机器人应用中 Genie API 的一个示例调用流程。

<img src="https://mintlify.s3.us-west-1.amazonaws.com/qualcomm-prod/zh/AI-Developer-Workflow-Ubuntu/_images/genie-chatbot-call-flow.png" alt="Genie API 在聊天机器人应用中的调用流程" />
