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

# 快速入门

> 使用 Kotlin 运行 GenieX Android SDK 中的第一个模型。

本页将指导你在 Kotlin APP中运行第一个模型，然后再换用另一个模型。如需一个完整的参考应用——包含聊天 UI、模型选择器和 VLM 支持——请参阅[示例应用](https://github.com/qualcomm/ai-hub-apps/blob/release/geniex_chat_android/README.md)。

## **前置条件**

* 已将 SDK 添加到你的 Gradle 项目——参阅[安装](/cn/run/android/install)。
* 一台搭载 **骁龙 8 至尊版** 或 **骁龙 8 至尊版 Gen 5** 的手机。
* 在 `AndroidManifest.xml` 中声明 `INTERNET` 权限（SDK 会在首次使用时从 Hugging Face / Qualcomm AI Hub 拉取权重）。

## **运行你的第一个模型**

无论使用哪个模型，流程都是相同的：**初始化 SDK → 拉取权重 → 加载 → 生成**。下面是一个使用 `unsloth/Qwen3-0.6B-GGUF` 的最小端到端示例——这是一个小型的 Qwen3 0.6B 对话模型，可以在任何受支持的芯片组上运行。

<Steps>
  <Step title="Init the SDK">
    在应用启动时调用一次（幂等——可安全地放在 `Activity.onCreate` 中）：

    ```kotlin theme={"dark"}
    GenieXSdk.getInstance().init(context)
    ```
  </Step>

  <Step title="Pull the model">
    `pullFlow` 会流式推送进度事件。在 `Dispatchers.IO` 上的协程中运行：

    ```kotlin theme={"dark"}
    ModelManagerWrapper.pullFlow(
        ModelPullInput(
            model_name = "unsloth/Qwen3-0.6B-GGUF",
            precision  = "Q4_0",
            hub        = HubSource.HUGGINGFACE,
        )
    ).collect { event ->
        when (event) {
            is ModelManagerWrapper.PullEvent.Progress  -> /* update UI */
            ModelManagerWrapper.PullEvent.Completed    -> /* done */
            is ModelManagerWrapper.PullEvent.Error     -> /* show error */
        }
    }
    ```

    下载支持断点续传——在拉取过程中杀掉应用并重新运行，会从上次中断处继续。
  </Step>

  <Step title="Load the model">
    解析磁盘上的路径并构建一个 `LlmWrapper`：

    ```kotlin theme={"dark"}
    val paths = ModelManagerWrapper.getPaths("unsloth/Qwen3-0.6B-GGUF")
        ?: error("Model not downloaded")

    val llm = LlmWrapper.builder()
        .llmCreateInput(
            LlmCreateInput(
                model_name = paths.model_name,
                model_path = paths.model_path,
                config     = ModelConfig(nCtx = 4096),
                runtime_id  = "llama_cpp",
                compute_unit  = null,   // null → NPU on Snapdragon (recommended)
            )
        )
        .build()
        .getOrThrow()
    ```
  </Step>

  <Step title="Generate">
    应用 chat template，然后从流式 flow 中收集 token：

    ```kotlin theme={"dark"}
    val chat = arrayListOf(ChatMessage("user", "What is AI?"))
    val templated = llm.applyChatTemplate(chat.toTypedArray(), null, false).getOrThrow()

    llm.generateStreamFlow(
        templated.formattedText,
        GenerationConfig(maxTokens = 2048),
    ).collect { result ->
        when (result) {
            is LlmStreamResult.Token     -> print(result.text)
            is LlmStreamResult.Completed -> println("\nDone")
            is LlmStreamResult.Error     -> println("Error: ${result.throwable}")
        }
    }
    ```

    <Warning>
      始终将 `templated.formattedText`（经过 chat template 处理的 prompt）传入 `generateStreamFlow`，而 **不是** 原始用户文本。原生工作流期望接收一个已经过 template 处理的 prompt。
    </Warning>
  </Step>
</Steps>

## **切换模型**

切换模型主要就是更改 `model_name` 和 `runtime_id`。这里有两种运行环境：

* **`llama_cpp`** —— 运行任意 GGUF 模型。通过 `compute_unit` 支持 NPU / GPU / CPU 计算单元。
* **`qairt`**（Qualcomm AI Engine Direct）—— 运行 Qualcomm AI Hub 模型。仅支持 NPU，在 Android 上需要显式指定 `chipset`。

### 另一个 GGUF 模型 (llama.cpp)

只需更改 `model_name`（如果想要不同精度，再更改 `precision`）——其余流程完全相同：

```kotlin theme={"dark"}
ModelPullInput(
    model_name = "unsloth/Qwen3-VL-2B-Instruct-GGUF",
    precision  = "Q4_0",
    hub        = HubSource.HUGGINGFACE,
)
```

对于 VLM，还需将 `paths.mmproj_path` 传入 `VlmCreateInput`——参阅 [API 参考 → VLM](/cn/run/android/api-reference#vlm)。

### Qualcomm AI Hub 模型（通过 Qualcomm AI Engine Direct 使用 NPU）

Qualcomm AI Hub 模型会按芯片组预编译，且仅在 NPU 上运行。在 Android 上你 **必须** 传入 `chipset`：

```kotlin theme={"dark"}
ModelManagerWrapper.pullFlow(
    ModelPullInput(
        model_name = "ai-hub-models/Qwen3-4B-Instruct-2507",
        hub        = HubSource.AUTO,   // routes ai-hub-models/* to Qualcomm AI Hub
        chipset    = "SM8750",         // SM8750 = 8 Elite, SM8850 = 8 Elite Gen 5
    )
).collect { /* … */ }
```

然后在 `LlmCreateInput` 中切换为 `runtime_id = "qairt"`。受支持的 Qualcomm AI Hub 仓库参阅 [API 参考](/cn/run/android/api-reference#已支持模型)。

### 切换计算单元 (NPU / GPU / CPU)

仅适用于 `llama_cpp`——在 `LlmCreateInput` 上设置 `compute_unit`：

| `compute_unit`    | 计算单元                     |
| ----------------- | ------------------------ |
| `null` or `"npu"` | Hexagon NPU（骁龙上推荐）。      |
| `"gpu"`           | 通过 OpenCL 使用 Adreno GPU。 |
| `"cpu"`           | 纯 CPU。可在任意 ARM64 芯片组上运行。 |

Qualcomm AI Engine Direct 会忽略此设置——`cpu`/`gpu` 会带警告地被强制转换为 NPU。

## **使用本地模型**

如果权重已经在设备上——通过 `adb push` 侧载、打包进应用的 files 目录，或由其他工具生成——只需让模型管理器指向该目录，而不是某个 hub。设置 `hub = HubSource.LOCALFS`，并将 `local_path` 指向磁盘上的位置。`pullFlow` 会将其导入到 SDK 缓存中（不联网），之后 `getPaths` / `LlmWrapper` 的用法与下载的模型完全一致。

这里的 `model_name` 只是缓存键——任意 `org/repo` 风格的字符串都可以，常见约定是加上 `local/` 前缀。**运行时由导入的目录布局决定，而不是由你指定**：GGUF 目录导入为 `llama_cpp`，AI Hub 目录/zip 导入为 `qairt`。当你导入混合类型的模型时，请优先使用 `paths.runtime_id`（权威值），而不是硬编码 `runtime_id`。

### 本地 GGUF 模型 (llama.cpp)

`local_path` 是一个包含 `.gguf` 文件的目录。如果存在 `geniex.json` manifest 则会使用它，否则会根据文件名推断布局。对于 VLM，将 `mmproj-*.gguf` 放入同一目录即可。

```kotlin theme={"dark"}
ModelManagerWrapper.pullFlow(
    ModelPullInput(
        model_name = "local/qwen3-0.6b",
        hub        = HubSource.LOCALFS,
        local_path = "/data/local/tmp/qwen3-0.6b",   // 包含 *.gguf 的目录
    )
).collect { event ->
    when (event) {
        is ModelManagerWrapper.PullEvent.Progress  -> /* update UI */
        ModelManagerWrapper.PullEvent.Completed    -> /* imported */
        is ModelManagerWrapper.PullEvent.Error     -> /* show error */
    }
}
```

然后使用 `runtime_id = "llama_cpp"` 加载——与下载模型的流程完全相同：

```kotlin theme={"dark"}
val paths = ModelManagerWrapper.getPaths("local/qwen3-0.6b")
    ?: error("Model not imported")

val llm = LlmWrapper.builder()
    .llmCreateInput(
        LlmCreateInput(
            model_name = paths.model_name,
            model_path = paths.model_path,
            config     = ModelConfig(nCtx = 4096),
            runtime_id  = "llama_cpp",
            compute_unit  = null,   // null → 骁龙上使用 NPU（推荐）
        )
    )
    .build()
    .getOrThrow()
```

### 本地 Qualcomm AI Hub 模型 (qairt)

`local_path` 指向以下两者之一：已解压的 AI Hub 目录（一个 `metadata.json` 加上一个或多个 `.bin` 分片），或从 Qualcomm AI Hub 下载的 AI Hub `.zip`。插件会被强制设为 `qairt`，模态（LLM 还是 VLM）会从 `metadata.json` 中读取。无需 `chipset`——该 bundle 已经针对特定芯片组编译完成。

```kotlin theme={"dark"}
ModelManagerWrapper.pullFlow(
    ModelPullInput(
        model_name = "local/qwen3-4b-2507",
        hub        = HubSource.LOCALFS,
        local_path = "/data/local/tmp/Qwen3-4B-Instruct-2507",  // 已解压目录或 .zip
    )
).collect { /* Progress / Completed / Error */ }
```

然后使用 `runtime_id = "qairt"` 加载：

```kotlin theme={"dark"}
val paths = ModelManagerWrapper.getPaths("local/qwen3-4b-2507")
    ?: error("Model not imported")

val llm = LlmWrapper.builder()
    .llmCreateInput(
        LlmCreateInput(
            model_name = paths.model_name,
            model_path = paths.model_path,
            config     = ModelConfig(max_tokens = 2048, enable_thinking = false),
            runtime_id  = "qairt",
            compute_unit  = null,   // qairt 仅支持 NPU
        )
    )
    .build()
    .getOrThrow()
```

<Note>
  本地导入时你无需自己编写 `geniex.json`——模型管理器会在导入过程中于其缓存中生成一份。它从 `local_path` 读取的内容取决于布局：GGUF 目录需要一个 `*.gguf`（若存在 `geniex.json` 则会被采用，否则会根据文件名推断 manifest）；QAIRT 目录则通过 `metadata.json` + `.bin` 分片（或 `.zip`）来识别。对于 QAIRT，请按 Qualcomm AI Hub 提供的原样导入已解压的 bundle 或 `.zip`——一个只含零散 `.bin` 文件、缺少 `metadata.json` 的目录将无法被识别。
</Note>

## **使用示例应用**

[示例应用](https://github.com/qualcomm/ai-hub-apps/blob/release/geniex_chat_android/README.md)是一个完整连通的聊天客户端，构建在上述代码片段之上。当你构建自己的 UI 时，有几个值得借鉴的模式：

* **模型选择器 UI** —— 下拉菜单由 `app/src/main/assets/model_list.json` 驱动。每个条目固定了一个 `model_name`、`hub`，以及一个 `chipset`（对于 Qualcomm AI Engine Direct）。编辑此文件即可添加新模型而无需改动代码。
* **带进度的断点续传下载** —— 来自 `pullFlow` 的 `Progress` 事件携带每个文件的字节计数；示例将它们直接接入 `LinearProgressIndicator`。
* **运行环境感知的计算单元选择器** —— 当所选模型使用 Qualcomm AI Engine Direct 时，选择器会隐藏 GPU/CPU 选项。参阅 `LoadDialog.kt`。
* **VLM 图片选择器** —— 对于 VLM，示例会将绝对文件路径传入 `VlmContent("image", path)`。不要传入 content URI——原生侧会直接读取文件。

克隆 [`qualcomm/ai-hub-apps`](https://github.com/qualcomm/ai-hub-apps/blob/release/geniex_chat_android/README.md)，在 Android Studio 中打开并点击 **Run ▶**。

## **下一步**

<CardGroup cols={2}>
  <Card title="API 参考" href="/cn/run/android/api-reference" icon="book">
    Wrapper 类、运行环境 / 计算单元选择与数据结构。
  </Card>

  <Card title="平台与运行环境" href="/cn/get-started/platforms" icon="route">
    骁龙平台，以及何时选择 llama.cpp 或 Qualcomm AI Engine Direct。
  </Card>
</CardGroup>

<br />

<div class="feedback-wrapper">
  <span class="feedback-label">Was this page helpful?</span>

  <div class="feedback-toggle">
    <input type="radio" name="feedback" id="feedback-yes" class="feedback-input" />

    <label for="feedback-yes" class="feedback-button">
      <img src="https://mintlify.s3.us-west-1.amazonaws.com/qualcomm-0801e48b/Images/FeedBack/thumbs-up.svg" alt="Thumbs up" class="feedback-icon" noZoom />

      Yes
    </label>

    <input type="radio" name="feedback" id="feedback-no" class="feedback-input" />

    <label for="feedback-no" class="feedback-button">
      <img src="https://mintlify.s3.us-west-1.amazonaws.com/qualcomm-0801e48b/Images/FeedBack/thumbs-down.svg" alt="Thumbs down" class="feedback-icon" noZoom />

      No
    </label>
  </div>
</div>
