Przewodnik po wnioskowaniu LLM dla iOS

Interfejs LLM Inference API pozwala uruchamiać duże modele językowe (LLM) w pełni na urządzeniu dla aplikacji na iOS. Pozwala on wykonywać wiele zadań, takich jak generowanie tekstu, pobieranie informacji w formie języka naturalnego i podsumowywanie dokumentów. To zadanie ma wbudowaną obsługę wielu dużych modeli językowych obsługujących tekst na tekst, dzięki czemu możesz stosować najnowsze modele generatywnej AI działające na urządzeniu w swoich aplikacjach na iOS.

Możesz zobaczyć, jak to wygląda w praktyce, w prezentacji MediaPipe Studio. Więcej informacji o możliwościach, modelach i opcjach konfiguracji tego zadania znajdziesz w sekcji Omówienie.

Przykładowy kod

Przykładowy kod MediaPipe Tasks to podstawowa implementacja aplikacji LLM Inference API na iOS. Możesz użyć aplikacji jako punktu wyjścia dla własnej aplikacji na iOS lub skorzystać z niej podczas modyfikowania istniejącej aplikacji. Przykładowy kod interfejsu LLM Inference API znajduje się na GitHub.

Pobieranie kodu

Z instrukcji poniżej dowiesz się, jak utworzyć lokalną kopię przykładowego kodu za pomocą narzędzia wiersza poleceń git.

Aby pobrać przykładowy kod:

  1. Sklonuj repozytorium git za pomocą tego polecenia:

    git clone https://github.com/google-ai-edge/mediapipe-samples
    
  2. Opcjonalnie skonfiguruj instancję git tak, aby używała rozproszonego procesu płatności, aby mieć tylko pliki dla przykładowej aplikacji interfejsu LLM Inference API:

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

Po utworzeniu lokalnej wersji przykładowego kodu możesz zainstalować bibliotekę zadań MediaPipe, otworzyć projekt za pomocą Xcode i uruchomić aplikację. Instrukcje znajdziesz w przewodniku po konfiguracji na iOS.

Konfiguracja

W tej sekcji znajdziesz opis kluczowych kroków, które należy wykonać, aby skonfigurować środowisko programistyczne i kodować projekty, które mają korzystać z interfejsu LLM Inference API. Ogólne informacje o konfigurowaniu środowiska programistycznego na potrzeby zadań MediaPipe, w tym o wymaganiach dotyczących wersji platformy, znajdziesz w przewodniku konfiguracji dla iOS.

Zależności

Interfejs LLM Inference API używa biblioteki MediaPipeTasksGenai, którą należy zainstalować za pomocą CocoaPods. Biblioteka jest zgodna z aplikacjami Swift i Objective-C i nie wymaga dodatkowej konfiguracji pod kątem określonego języka.

Instrukcje instalowania CocoaPods w systemie macOS znajdziesz w przewodniku instalacji CocoaPods. Instrukcje tworzenia Podfile z podami niezbędnymi do działania aplikacji znajdziesz w artykule Korzystanie z CocoaPods.

Dodaj pod MediaPipeTasksGenai w tabeli Podfile, używając tego kodu:

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

Jeśli aplikacja zawiera cele testu jednostkowego, dodatkowe informacje o konfigurowaniu Podfile znajdziesz w przewodniku konfiguracji na iOS.

Model

Zadanie MediaPipe LLM Inference API wymaga wytrenowanego modelu, który jest zgodny z tym zadaniem. Więcej informacji o dostępnych wytrenowanych modelach dla interfejsu LLM Inference API znajdziesz w sekcji poświęconej modelom – omówieniem zadania.

Pobierz model

Pobierz model i dodaj go do katalogu projektu za pomocą Xcode. Instrukcje dodawania plików do projektu Xcode znajdziesz w artykule Zarządzanie plikami i folderami w projekcie Xcode.

Pobierz Gemma 2B

Podczas tworzenia aplikacji na iOS użyj jednego z tych wariantów:

  • gemma-2b-it-cpu-int4: 4-bitowy model Gemma zgodny z procesorem.
  • gemma-2b-it-gpu-int4: 4-bitowy model Gemma zgodny z GPU.
  • Modele zmapowane przez AI Edge Torch, które są zgodne z wymaganiami dotyczącymi pamięci iOS.

Więcej informacji o innych modelach znajdziesz w sekcji na temat modeli przeglądu zadań.

Tworzenie zadania

Możesz utworzyć zadanie interfejsu LLM Inference API, wywołując jeden z jego inicjatorów. Inicjator LlmInference(options:) ustawia wartości opcji konfiguracji.

Jeśli nie potrzebujesz interfejsu LLM Inference API zainicjowanego z niestandardowymi opcjami konfiguracji, możesz użyć inicjatora LlmInference(modelPath:), aby utworzyć interfejs LLM Inference API z opcjami domyślnymi. Więcej informacji o opcjach konfiguracji znajdziesz w artykule Omówienie konfiguracji.

Poniższy kod pokazuje, jak skompilować i skonfigurować to zadanie.

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)

Opcje konfiguracji

To zadanie ma te opcje konfiguracji w przypadku aplikacji na iOS:

Nazwa opcji Opis Zakres wartości Wartość domyślna
modelPath Ścieżka do miejsca, w którym model jest przechowywany w katalogu projektu. PATH Nie dotyczy
maxTokens Maksymalna liczba tokenów (tokeny wejściowe + tokeny wyjściowe) obsługiwanych przez model. Liczba całkowita 512
topk Liczba tokenów uwzględnianych przez model na każdym etapie generowania. Ogranicza prognozy do k najbardziej prawdopodobnych tokenów. Przy ustawieniu topk musisz też ustawić wartość randomSeed. Liczba całkowita 40
temperature Ilość losowości wprowadzonej podczas generowania. Wyższa temperatura zwiększa kreatywność w generowaniu tekstu, a niższa – bardziej przewidywalny generowanie tekstu. Przy ustawieniu temperature musisz też ustawić wartość randomSeed. Liczba zmiennoprzecinkowa 0,8
randomSeed Losowy materiał wyjściowy używany podczas generowania tekstu. Liczba całkowita 0
loraPath Ścieżka bezwzględna do modelu LoRA lokalnie na urządzeniu. Uwaga: ta funkcja jest zgodna tylko z modelami GPU. PATH Nie dotyczy

Przygotuj dane

Interfejs LLM Inference API obsługuje dane tekstowe. To zadanie obsługuje wstępne przetwarzanie danych wejściowych, w tym tokenizację i wstępne przetwarzanie tensorów.

Przetwarzanie wstępne jest realizowane w ramach funkcji generateResponse(inputText:). Nie ma potrzeby wcześniejszego wstępnego przetwarzania tekstu wejściowego.

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

Uruchamianie zadania

Aby uruchomić interfejs LLM Inference API, użyj metody generateResponse(inputText:). Interfejs LLM Inference API zwraca możliwe kategorie tekstu wejściowego.

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

Aby przesłać odpowiedź strumieniowo, użyj metody generateResponseAsync(inputText:).

let resultStream =  LlmInference.generateResponseAsync(inputText: inputPrompt)

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

Obsługa i wyświetlanie wyników

Interfejs LLM Inference API zwraca wartość LlmInferenceResult, która zawiera wygenerowany tekst odpowiedzi.

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]

Dostosowanie modelu LoRA

Interfejs Mediapipe LLM inference API można skonfigurować tak, aby obsługiwał adaptację niskiego rankingu (LoRA) w przypadku dużych modeli językowych. Dzięki dostrojonym modelom LoRA deweloperzy mogą dostosowywać działanie modeli LLM przy użyciu ekonomicznego procesu trenowania.

Obsługa LoRA interfejsu LLM Inference API działa w przypadku modeli Gemma-2B oraz Phi-2 w backendzie GPU, przy czym wagi LoRA mają zastosowanie tylko do warstw uwagi. Ta wstępna implementacja służy jako eksperymentalny interfejs API na potrzeby przyszłych prac, a w kolejnych aktualizacjach planujemy obsługiwać więcej modeli i różne typy warstw.

Przygotuj modele LoRA

Wykonaj instrukcje w HugingFace, aby wytrenować dostrojony model LoRA na własnym zbiorze danych z obsługiwanymi typami modeli: Gemma-2B lub Phi-2. Modele Gemma-2B i Phi-2 są dostępne w HuggingFace w formacie Safetensors. Interfejs LLM Inference API obsługuje tylko LoRA w warstwach uwagi, dlatego podczas tworzenia obiektu LoraConfig określ tylko warstwy uwagi:

# 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"],
)

Do testowania dostępne są publicznie dostępne dostrojone modele LoRA pasujące do interfejsu LLM Inference API w usłudze HuggingFace. Na przykład monsterapi/gemma-2b-lora-maths-orca-200k dla Gemma-2B i lole25/phi-2-sft-ultrachat-lora dla Phi-2.

Po wytrenowaniu na przygotowanym zbiorze danych i zapisaniu modelu otrzymasz plik adapter_model.safetensors zawierający dostrojone wagi modelu LoRA. Plik Safetensors to punkt kontrolny LoRA używany w konwersji modelu.

W kolejnym kroku musisz przekonwertować wagi modelu na TensorFlow Lite Flatbuffer przy użyciu pakietu MediaPipe Python. Element ConversionConfig powinien określać opcje modelu podstawowego oraz dodatkowe opcje LoRA. Zwróć uwagę, że interfejs API obsługuje wnioskowanie LoRA tylko z GPU, więc backend musi być ustawiony na '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)

Konwerter wygeneruje 2 pliki płaskie TFLite, jeden dla modelu podstawowego, a drugi dla modelu LoRA.

wnioskowanie z modelu LoRA,

Interfejs Web, Android i iOS LLM Inference API został zaktualizowany, aby obsługiwać wnioskowanie na podstawie modelu LoRA. Internet obsługuje dynamiczne modele LoRA, które mogą przełączać różne modele LoRA w czasie działania. Android i iOS obsługują statyczną wartość LoRA, która korzysta z tych samych wag przez cały okres wykonywania zadania.

iOS obsługuje statyczną lokację LoRA podczas inicjowania. Aby wczytać model LoRA, użytkownicy muszą podać ścieżkę modelu LoRA oraz podstawowy model 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)

Aby uruchomić wnioskowanie z LLM z użyciem LoRA, użyj tych samych metod generateResponse() lub generateResponseAsync() co w modelu podstawowym.