适用于 iOS 的 LLM 推断指南

借助 LLM Inference API,您可以完全在设备端为 iOS 应用运行大语言模型 (LLM),并用它来执行各种任务,例如生成文本、以自然语言形式检索信息以及对文档进行总结。该任务内置了对多个文本到文本大语言模型的支持,因此您可以将最新的设备端生成式 AI 模型应用于 iOS 应用。

您可以通过 MediaPipe Studio 演示了解此任务的实际运用。如需详细了解此任务的功能、模型和配置选项,请参阅概览

代码示例

MediaPipe Tasks 示例代码是适用于 iOS 的 LLM Inference API 应用的基本实现。您可以使用该应用作为基础来开发自己的 iOS 应用,也可以在修改现有应用时参考。LLM Inference API 示例代码托管在 GitHub 上。

下载代码

以下说明介绍了如何使用 git 命令行工具创建示例代码的本地副本。

如需下载示例代码,请执行以下操作:

  1. 使用以下命令克隆 Git 代码库:

    git clone https://github.com/google-ai-edge/mediapipe-samples
    
  2. (可选)将您的 Git 实例配置为使用稀疏签出,以便只有 LLM Inference API 示例应用的文件:

    cd mediapipe
    git sparse-checkout init --cone
    git sparse-checkout set examples/llm_inference/ios/
    

创建示例代码的本地版本后,您可以安装 MediaPipe 任务库,使用 Xcode 打开项目并运行应用。有关说明,请参阅 iOS 设置指南

设置

本部分介绍了设置开发环境和代码项目以使用 LLM Inference API 的关键步骤。如需了解有关为使用 MediaPipe 任务设置开发环境的一般信息(包括平台版本要求),请参阅 iOS 设置指南

依赖项

LLM Inference API 使用 MediaPipeTasksGenai 库,必须使用 CocoaPods 进行安装。该库与 Swift 和 Objective-C 应用兼容,不需要任何其他针对特定语言的设置。

如需了解如何在 macOS 上安装 CocoaPods,请参阅 CocoaPods 安装指南。 如需了解如何创建包含应用必要 Pod 的 Podfile,请参阅使用 CocoaPods

使用以下代码在 Podfile 中添加 MediaPipeTasksGenai pod:

target 'MyLlmInferenceApp' do
  use_frameworks!
  pod 'MediaPipeTasksGenAI'
  pod 'MediaPipeTasksGenAIC'
end

如果您的应用包含单元测试目标,请参阅 iOS 设置指南,详细了解如何设置 Podfile

模型

MediaPipe LLM Inference API 任务需要使用与此任务兼容的经过训练的模型。如需详细了解 LLM Inference API 可用的经过训练的模型,请参阅任务概览“模型”部分

下载模型

下载模型并使用 Xcode 将其添加到您的项目目录中。如需了解如何将文件添加到 Xcode 项目,请参阅管理 Xcode 项目中的文件和文件夹

下载 Gemma 2B

构建 iOS 应用时,请使用以下变体之一:

如需详细了解其他模型,请参阅任务概览“模型”部分

创建任务

您可以通过调用 LLM Inference API 任务之一来创建该任务。LlmInference(options:) 初始化程序用于设置配置选项的值。

如果您不需要使用自定义配置选项初始化的 LLM Inference API,则可以使用 LlmInference(modelPath:) 初始化程序使用默认选项创建 LLM Inference API。如需详细了解配置选项,请参阅配置概览

以下代码演示了如何构建和配置此任务。

import MediaPipeTasksGenai

let modelPath = Bundle.main.path(forResource: "model",
                                      ofType: "bin")

let options = LlmInferenceOptions()
options.baseOptions.modelPath = modelPath
options.maxTokens = 1000
options.topk = 40
options.temperature = 0.8
options.randomSeed = 101

let LlmInference = try LlmInference(options: options)

配置选项

此任务针对 iOS 应用提供以下配置选项:

选项名称 说明 值范围 默认值
modelPath 项目目录中存储模型的路径。 PATH N/A
maxTokens 模型处理的词元(输入词元 + 输出词元)的数量上限。 整数 512
topk 模型在生成时的每一步考虑的词元数。将预测限制为前 k 个概率最高的词元。设置 topk 时,您还必须为 randomSeed 设置一个值。 整数 40
temperature 生成期间引入的随机性。较高的温度可以使生成的文本更具创造性,而较低的温度会产生更可预测的生成。设置 temperature 时,您还必须为 randomSeed 设置一个值。 浮点数 0.8
randomSeed 在文本生成过程中使用的随机种子。 整数 0
loraPath 设备本地 LoRA 模型的绝对路径。注意:这仅与 GPU 模型兼容。 PATH N/A

准备数据

LLM Inference API 可处理文本数据。该任务会处理数据输入预处理,包括标记化和张量预处理。

所有预处理都在 generateResponse(inputText:) 函数中处理。无需事先对输入文本进行额外的预处理。

let inputPrompt = "Compose an email to remind Brett of lunch plans at noon on Saturday."

运行任务

如需运行 LLM Inference API,请使用 generateResponse(inputText:) 方法。LLM Inference API 会返回输入文本的可能类别。

let result = try LlmInference.generateResponse(inputText: inputPrompt)

如需流式传输响应,请使用 generateResponseAsync(inputText:) 方法。

let resultStream =  LlmInference.generateResponseAsync(inputText: inputPrompt)

do {
  for try await partialResult in resultStream {
    print("\(partialResult)")
  }
  print("Done")
}
catch {
  print("Response error: '\(error)")
}

处理和显示结果

LLM Inference API 会返回 LlmInferenceResult,其中包含生成的响应文本。

Here's a draft you can use:

Subject: Lunch on Saturday Reminder

Hi Brett,

Just a quick reminder about our lunch plans this Saturday at noon.
Let me know if that still works for you.

Looking forward to it!

Best,
[Your Name]

LoRA 模型自定义

Mediapipe LLM 推理 API 可以配置为支持针对大型语言模型的低秩自适应 (LoRA)。利用经微调的 LoRA 模型,开发者可以通过经济高效的训练过程来自定义 LLM 的行为。

LLM Inference API 的 LoRA 支持适用于 GPU 后端的 Gemma-2B 和 Phi-2 模型,LoRA 权重仅适用于注意力层。这一初始实现可用作未来开发的实验性 API,并计划在未来的更新中支持更多模型和各种类型的层。

准备 LoRA 模型

按照 HuggingFace 说明,使用受支持的模型类型(Gemma-2B 或 Phi-2)在您自己的数据集上训练微调后的 LoRA 模型。HuggingFace 上均以安全张量格式提供 Gemma-2B 和 Phi-2 模型。由于 LLM Inference API 仅支持注意力层上的 LoRA,因此请在创建 LoraConfig 时仅指定注意力层,如下所示:

# For Gemma-2B
from peft import LoraConfig
config = LoraConfig(
    r=LORA_RANK,
    target_modules=["q_proj", "v_proj", "k_proj", "o_proj"],
)

# For Phi-2
config = LoraConfig(
    r=LORA_RANK,
    target_modules=["q_proj", "v_proj", "k_proj", "dense"],
)

对于测试,HuggingFace 上提供适用于 LLM Inference API 且经过微调的可公开访问的 LoRA 模型。例如,对于 Gemma-2B,使用 monsterapi/gemma-2b-lora-maths-orca-200k,对于 Phi-2,使用 lole25/phi-2-sft-ultrachat-lora

使用准备好的数据集进行训练并保存模型后,您会获得一个 adapter_model.safetensors 文件,其中包含微调后的 LoRA 模型权重。safetensors 文件是在模型转换中使用的 LoRA 检查点。

接下来,您需要使用 MediaPipe Python 软件包将模型权重转换为 TensorFlow Lite FlatBuffer。ConversionConfig 应指定基本模型选项以及其他 LoRA 选项。请注意,由于 API 仅支持使用 GPU 进行 LoRA 推断,因此后端必须设置为 'gpu'

import mediapipe as mp
from mediapipe.tasks.python.genai import converter

config = converter.ConversionConfig(
  # Other params related to base model
  ...
  # Must use gpu backend for LoRA conversion
  backend='gpu',
  # LoRA related params
  lora_ckpt=LORA_CKPT,
  lora_rank=LORA_RANK,
  lora_output_tflite_file=LORA_OUTPUT_TFLITE_FILE,
)

converter.convert_checkpoint(config)

转换器将输出两个 TFLite 平面缓冲区文件,一个用于基本模型,另一个用于 LoRA 模型。

LoRA 模型推断

Web、Android 和 iOS LLM Inference API 已更新,以支持 LoRA 模型推断。Web 支持动态 LoRA,其可以在运行时切换不同的 LoRA 模型。Android 和 iOS 支持静态 LoRA,它会在任务的生命周期内使用相同的 LoRA 权重。

iOS 在初始化期间支持静态 LoRA。如需加载 LoRA 模型,用户需指定 LoRA 模型路径以及基本 LLM。

import MediaPipeTasksGenai

let modelPath = Bundle.main.path(forResource: "model",
                                      ofType: "bin")
let loraPath= Bundle.main.path(forResource: "lora_model",
                                      ofType: "bin")
let options = LlmInferenceOptions()
options.modelPath = modelPath
options.maxTokens = 1000
options.topk = 40
options.temperature = 0.8
options.randomSeed = 101
options.loraPath = loraPath

let LlmInference = try LlmInference(options: options)

如需使用 LoRA 运行 LLM 推断,请使用与基本模型相同的 generateResponse()generateResponseAsync() 方法。