Przewodnik po wnioskowaniu LLM na Androida

Interfejs LLM Inference API pozwala uruchamiać duże modele językowe (LLM) w pełni na urządzeniu dla aplikacji na Androida. Pozwala to 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 Androida.

To zadanie obsługuje Gemma 2B, część rodziny lekkich, najnowocześniejszych otwartych modeli stworzonych na podstawie tych samych badań i technologii, które są używane do tworzenia modeli Gemini. Obsługuje też te modele zewnętrzne: Phi-2, Falcon-RW-1B i StableLM-3B, a także wszystkie modele wyeksportowane przez AI Edge.

Więcej informacji o możliwościach, modelach i opcjach konfiguracji tego zadania znajdziesz w sekcji Omówienie.

Przykładowy kod

W tym przewodniku omawiamy przykład podstawowej aplikacji do generowania tekstu na Androida. Możesz użyć aplikacji jako punktu wyjścia dla własnej aplikacji na Androida lub odwołać się do niej podczas modyfikowania istniejącej aplikacji. Przykładowy kod jest hostowany 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/android
    

Po utworzeniu lokalnej wersji przykładowego kodu możesz zaimportować projekt do Android Studio i uruchomić aplikację. Instrukcje znajdziesz w przewodniku konfiguracji na Androida.

Konfiguracja

W tej sekcji znajdziesz najważniejsze kroki konfigurowania środowiska programistycznego i tworzenia kodu projektów pod kątem korzystania 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 na Androida.

Zależności

Interfejs LLM Inference API używa biblioteki com.google.mediapipe:tasks-genai. Dodaj tę zależność do pliku build.gradle aplikacji na Androida:

dependencies {
    implementation 'com.google.mediapipe:tasks-genai:0.10.14'
}

Model

MediaPipe LLM Inference API wymaga wytrenowanego modelu językowego (tekst na tekst), który jest zgodny z tym zadaniem. Po pobraniu modelu zainstaluj wymagane zależności i wypchnij model na urządzenie z Androidem. Jeśli używasz modelu innego niż Gemma, musisz go przekonwertować na format zgodny z MediaPipe.

Więcej informacji o dostępnych wytrenowanych modelach dla LLM Inference API znajdziesz w sekcji poświęconej modelom w omówieniem zadania.

Pobierz model

Zanim zainicjujesz interfejs LLM Inference API, pobierz jeden z obsługiwanych modeli i zapisz plik w katalogu projektu:

  • Gemma 2B: część rodziny lekkich, najnowocześniejszych otwartych modeli stworzonych na podstawie tych samych badań i technologii, które są używane do tworzenia modeli Gemini. Sprawdza się w różnych zadaniach związanych z generowaniem tekstu, takich jak odpowiadanie na pytania, streszczanie i rozumowanie.
  • Phi-2 model transformera z 2, 7 miliarda parametrów, najlepiej dopasowany do formatu pytań i odpowiedzi, czatu i kodu.
  • Falcon-RW-1B: model z tylko dekoderem przyczynowym z 1 miliardem parametrów wytrenowany na 350 mld tokenów RefinedWeb.
  • StableLM-3B: model językowy z samym dekoderem parametrów obejmujący 3 miliardy parametrów, wytrenowany na 1 biliona tokenów różnorodnych zbiorów danych w języku angielskim i kodu.

Możesz też użyć modeli zmapowanych i wyeksportowanych za pomocą AI Edge Troch.

Zalecamy korzystanie z interfejsu Gemma 2B, który jest dostępny w modelach Kaggle i jest w formacie zgodnym z interfejsem LLM Inference API. Jeśli używasz innego LLM, musisz przekonwertować model na format zgodny z MediaPipe. Więcej informacji o Gemma 2B znajdziesz na stronie Gemma. Więcej informacji o innych dostępnych modelach znajdziesz w sekcji na temat modeli przeglądu zadania.

Konwertuj model na format MediaPipe

Konwersja modelu natywnego

Jeśli korzystasz z zewnętrznego modelu LLM (Phi-2, Falcon lub StableLM) albo wersji Gemma innej niż Kaggle, użyj naszych skryptów konwersji, aby sformatować model tak, aby był zgodny z MediaPipe.

Proces konwersji modelu wymaga pakietu MediaPipe PyPI. Skrypt konwersji jest dostępny we wszystkich pakietach MediaPipe po 0.10.11.

Zainstaluj i zaimportuj zależności:

$ python3 -m pip install mediapipe

Użyj biblioteki genai.converter, aby przekonwertować model:

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

config = converter.ConversionConfig(
  input_ckpt=INPUT_CKPT,
  ckpt_format=CKPT_FORMAT,
  model_type=MODEL_TYPE,
  backend=BACKEND,
  output_dir=OUTPUT_DIR,
  combine_file_only=False,
  vocab_model_file=VOCAB_MODEL_FILE,
  output_tflite_file=OUTPUT_TFLITE_FILE,
)

converter.convert_checkpoint(config)

Aby przekonwertować model LoRA, obiekt 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.

Parametr Opis Akceptowane wartości
input_ckpt Ścieżka do pliku model.safetensors lub pytorch.bin. Pamiętaj, że czasami format zabezpieczeń modelu jest podzielony na kilka plików, np. model-00001-of-00003.safetensors i model-00001-of-00003.safetensors. Możesz określić wzorzec pliku, np. model*.safetensors. PATH
ckpt_format Format pliku modelu. {"safetensors", "pytorch"}
model_type Przekonwertowany LLM. {"PHI_2", "FALCON_RW_1B", "STABLELM_4E1T_3B", "GEMMA_2B"}
backend Procesor (przedstawiciel) używany do uruchomienia modelu. {"cpu", "gpu"}
output_dir Ścieżka do katalogu wyjściowego, w którym są hostowane pliki wag w poszczególnych warstwach. PATH
output_tflite_file Ścieżka do pliku wyjściowego. Na przykład „model_cpu.bin” lub „model_gpu.bin”. Ten plik jest zgodny tylko z interfejsem LLM Inference API i nie może być używany jako ogólny plik „tflite”. PATH
vocab_model_file Ścieżka do katalogu, w którym są zapisane pliki tokenizer.json i tokenizer_config.json. W przypadku aplikacji Gemma wskaż pojedynczy plik tokenizer.model. PATH
lora_ckpt Ścieżka do pliku klpt sejfów LoRA, w którym jest przechowywana waga adaptera LoRA. PATH
lora_rank Liczba całkowita określająca pozycję ckpt LoRA. Wymagane do przekonwertowania wag lora. Jeśli ich nie podasz, konwerter zakłada, że nie ma wag LoRA. Uwaga: tylko backend GPU obsługuje LoRA. Liczba całkowita
lora_output_tflite_file Wyjściowa nazwa pliku tflite wag LoRA. PATH

Konwersja modelu AI Edge

Jeśli używasz LLM zmapowanego na model TFLite za pomocą AI Edge, utwórz pakiet zadań za pomocą naszego skryptu tworzenia pakietów. Proces grupowania obejmuje zmapowany model dodatkowymi metadanymi (np. parametry tokenizatora) potrzebne do pełnego wnioskowania.

Proces grupowania modeli wymaga pakietu MediaPipe PyPI. Skrypt konwersji jest dostępny we wszystkich pakietach MediaPipe po 0.10.14.

Zainstaluj i zaimportuj zależności:

$ python3 -m pip install mediapipe

Użyj biblioteki genai.bundler, aby połączyć model:

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

config = bundler.BundleConfig(
    tflite_model=TFLITE_MODEL,
    tokenizer_model=TOKENIZER_MODEL,
    start_token=START_TOKEN,
    stop_tokens=STOP_TOKENS,
    output_filename=OUTPUT_FILENAME,
    enable_bytes_to_unicode_mapping=ENABLE_BYTES_TO_UNICODE_MAPPING,
)
bundler.create_bundle(config)
Parametr Opis Akceptowane wartości
tflite_model Ścieżka do AI Edge wyeksportowanego z modelu TFLite. PATH
tokenizer_model Ścieżka do modelu tokenizatora SentencePiece. PATH
start_token Token początkowy konkretnego modelu. Token początkowy musi być obecny w podanym modelu tokenizatora. CIĄG ZNAKÓW
stop_tokens Tokeny zatrzymania dla konkretnego modelu. Tokeny zatrzymania muszą być obecne w podanym modelu tokenizatora. LISTA[STRING]
output_filename Nazwa wyjściowego pliku pakietu zadań. PATH

Przekaż model na urządzenie

Przekaż zawartość folderu output_path na urządzenie z Androidem.

$ adb shell rm -r /data/local/tmp/llm/ # Remove any previously loaded models
$ adb shell mkdir -p /data/local/tmp/llm/
$ adb push output_path /data/local/tmp/llm/model_version.bin

Tworzenie zadania

MediaPipe LLM Inference API używa funkcji createFromOptions() do konfigurowania zadania. Funkcja createFromOptions() akceptuje wartości opcji konfiguracji. Więcej informacji o opcjach konfiguracji znajdziesz w artykule Opcje konfiguracji.

Ten kod inicjuje zadanie przy użyciu podstawowych opcji konfiguracji:

// Set the configuration options for the LLM Inference task
val options = LlmInferenceOptions.builder()
        .setModelPATH('/data/local/.../')
        .setMaxTokens(1000)
        .setTopK(40)
        .setTemperature(0.8)
        .setRandomSeed(101)
        .build()

// Create an instance of the LLM Inference task
llmInference = LlmInference.createFromOptions(context, options)

Opcje konfiguracji

Aby skonfigurować aplikację na Androida, użyj tych opcji konfiguracji:

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
resultListener Konfiguruje detektor wyników, aby asynchronicznie otrzymywać wyniki. Ma zastosowanie tylko w przypadku korzystania z metody generowania asynchronicznego. Nie dotyczy Nie dotyczy
errorListener Ustawia opcjonalny detektor błędów. Nie dotyczy Nie dotyczy

Przygotuj dane

Interfejs LLM Inference API akceptuje te dane wejściowe:

  • prompt (ciąg znaków): pytanie lub prompt.
val inputPrompt = "Compose an email to remind Brett of lunch plans at noon on Saturday."

Uruchamianie zadania

Metoda generateResponse() pozwala wygenerować odpowiedź tekstową na tekst wejściowy podany w poprzedniej sekcji (inputPrompt). Generuje to pojedynczą odpowiedź.

val result = llmInference.generateResponse(inputPrompt)
logger.atInfo().log("result: $result")

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

val options = LlmInference.LlmInferenceOptions.builder()
  ...
  .setResultListener { partialResult, done ->
    logger.atInfo().log("partial result: $partialResult")
  }
  .build()

llmInference.generateResponseAsync(inputPrompt)

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.

Android obsługuje statyczną lokację LoRA podczas inicjowania. Aby wczytać model LoRA, użytkownicy muszą podać ścieżkę modelu LoRA oraz podstawowy model LLM.

// Set the configuration options for the LLM Inference task
val options = LlmInferenceOptions.builder()
        .setModelPath('<path to base model>')
        .setMaxTokens(1000)
        .setTopK(40)
        .setTemperature(0.8)
        .setRandomSeed(101)
        .setLoraPath('<path to LoRA model>')
        .build()

// Create an instance of the LLM Inference task
llmInference = LlmInference.createFromOptions(context, options)

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