מדריך להסקת מודלים של LLM ל-iOS

בעזרת LLM Inference API אפשר להריץ מודלים גדולים של שפה (LLM) לגמרי במכשיר באפליקציות ל-iOS. אפשר להשתמש בהם כדי לבצע מגוון רחב של משימות, כמו יצירת טקסט, אחזור מידע בפורמט שפה טבעית (LLM) וסיכום מסמכים. המשימה כוללת תמיכה מובנית במספר מודלים של שפה גדול (LLM) של טקסט לטקסט, כדי שתוכלו להחיל את המודלים העדכניים ביותר של בינה מלאכותית גנרטיבית במכשיר על האפליקציות ל-iOS.

ניתן לראות את המשימה הזו בפעולה בהדגמה של MediaPipe Studio. למידע נוסף על היכולות, המודלים ואפשרויות ההגדרה של המשימה הזו, קראו את הסקירה הכללית.

קוד לדוגמה

הקוד לדוגמה של משימות MediaPipe הוא יישום בסיסי של אפליקציית LLM Inference API ל-iOS. אפשר להשתמש באפליקציה כנקודת התחלה לאפליקציה שלכם ל-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. במדריך ההגדרה ל-iOS תוכלו לקרוא מידע כללי על הגדרת סביבת הפיתוח לשימוש במשימות MediaPipe, כולל הדרישות לגרסת הפלטפורמה.

יחסי תלות

ב-LLM Inference API נעשה שימוש בספריית MediaPipeTasksGenai, וצריך להתקין אותה באמצעות CocoaPods. הספרייה תואמת לאפליקציות של Swift וגם לאפליקציות Objective-C, ואין צורך בהגדרות נוספות ספציפיות לשפה.

תוכלו למצוא הוראות להתקנת CocoaPods ב-macOS במדריך ההתקנה של CocoaPods. לשימוש ב-CocoaPods תוכלו למצוא הוראות ליצירת Podfile עם הרפידות הנדרשות לאפליקציה.

מוסיפים את הרכיב MediaPipeTasksGenai בתוך Podfile באמצעות הקוד הבא:

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, צריך להשתמש באחת מהווריאציות הבאות:

  • gemma-2b-it-cpu-int4: מודל 4 ביט של Gemma עם תאימות למעבד (CPU).
  • gemma-2b-it-gpu-int4: מודל 4 ביט של Gemma עם תאימות ל-GPU.
  • לפיד של AI Edge ממופה מודלים שתואמים לדרישות הזיכרון של iOS.

למידע נוסף על מודלים אחרים, קראו את הקטע על מודלים בסקירה הכללית על משימות.

יצירת המשימה

אפשר ליצור את משימת ה-LLM Inference API על ידי קריאה לאחד מהמפעילים שלה. המאתחל LlmInference(options:) מגדיר ערכים לאפשרויות התצורה.

אם אין לכם צורך ב-LLM Inference API שמופעל עם אפשרויות הגדרה מותאמות אישית, אפשר להשתמש במאתחל LlmInference(modelPath:) כדי ליצור API של LLM Inference עם אפשרויות ברירת המחדל. מידע נוסף על אפשרויות ההגדרה זמין במאמר סקירה כללית בנושא הגדרות.

הקוד הבא מדגים איך ליצור ולהגדיר את המשימה הזו.

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 לא רלוונטי
maxTokens מספר האסימונים המקסימלי (אסימוני קלט + אסימוני פלט) שהמודל מטפל בהם. מספר שלם 512
topk מספר האסימונים שהמודל לוקח בחשבון בכל שלב של היצירה. מגביל את החיזויים ל-k האסימונים בעלי הסבירות הגבוהה ביותר. כשמגדירים את topk, צריך להגדיר גם ערך עבור randomSeed. מספר שלם 40
temperature כמות הרנדומיזציה שהוכנסה במהלך היצירה. טמפרטורה גבוהה יותר מובילה ליצירתיות רבה יותר בטקסט שנוצר, וטמפרטורה נמוכה יוצרת יצירה צפויה יותר. כשמגדירים את temperature, צריך להגדיר גם ערך עבור randomSeed. Float 0.8
randomSeed המקור האקראי שנעשה בו שימוש במהלך יצירת הטקסט. מספר שלם 0
loraPath הנתיב המוחלט למודל LoRA באופן מקומי במכשיר. הערה: האפשרות הזו תואמת רק לדגמים של GPU. PATH לא רלוונטי

הכנת הנתונים

LLM Inference API פועל עם נתוני טקסט. המשימה מטפלת בעיבוד מראש של קלט הנתונים, כולל המרה לאסימונים ועיבוד מראש של tensor.

כל העיבודים מראש מטופלים בפונקציה generateResponse(inputText:). אין צורך בעיבוד מראש נוסף של טקסט הקלט לפני כן.

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

מריצים את המשימה.

כדי להריץ את LLM Inference API, משתמשים ב-method 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

אפשר להגדיר את ה-API להסקת ה-LLM של Mediapipe כך שיתמוך באדפטציה נמוכה (LoRA) במודלים גדולים של שפה (LLM). מפתחים יכולים להשתמש במודלים משופרים של LoRA כדי להתאים אישית את ההתנהגות של מודלים גדולים של שפה, באמצעות תהליך אימון חסכוני.

התמיכה של LoRA ב-LLM Inference API פועלת במודלים מסוג Gemma-2B ו-Pi-2 בקצה העורפי של ה-GPU, עם משקלי LoRA שרלוונטיים לשכבות תשומת לב בלבד. ההטמעה הראשונית הזו משמשת כ-API ניסיוני לפיתוחים עתידיים, עם תוכניות לתמוך במודלים נוספים ובסוגים שונים של שכבות בעדכונים הקרובים.

הכנת מודלים של LoRA

פועלים לפי ההוראות ב-HugingFace כדי לאמן מודל LoRA שעבר כוונון עדין במערך נתונים משלכם עם סוגי מודלים נתמכים, Gemma-2B או Phi-2. הדגמים Gemma-2B ו-Pi-2 זמינים ב-HugingFace בפורמט Safetensors. מכיוון ש-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"],
)

לצורך בדיקה, יש מודלים של LoRA שזמינים לציבור הרחב, שמותאמים ל-LLM Inference API, שזמינים ב-HugingFace. לדוגמה: monsterapi/gemma-2b-lora-maths-orca-200k עבור Gemma-2B, ו-lole25/phi-2-sft-ultrachat-lora עבור Phi-2.

אחרי אימון על מערך הנתונים המוכן ושמירת המודל, מתקבל קובץ adapter_model.safetensors שמכיל את המשקלים המדויקים של מודל LoRA. קובץ Safetensors הוא נקודת הביקורת של LoRA שמשמשת בהמרת המודל.

בשלב הבא, צריך להמיר את משקלי המודל ל-TensorFlow Lite Flatbuffer באמצעות חבילת MediaPipe Python. השדה ConversionConfig צריך לציין את האפשרויות של הדגם הבסיסי וכן אפשרויות נוספות של LoRA. שימו לב: ה-API תומך רק בהסקה של LoRA עם GPU, ולכן הקצה העורפי צריך להיות מוגדר ל-'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

ה-LLM Inference API של האינטרנט, ה-Android ו-iOS מתעדכנות כדי לתמוך בהסקה של מודל LoRA. האינטרנט תומך ב-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)

כדי להריץ הסקת LLM באמצעות LoRA, משתמשים באותן שיטות מסוג generateResponse() או generateResponseAsync() כמו המודל הבסיסי.