במדריך הזה נסביר איך לפרוס מודל שפה גדול (LLM) ולהשתמש בו באמצעות כמה מעבדי GPU ב-GKE כדי להסיק מסקנות בצורה יעילה וניתנת להרחבה. אתם יוצרים אשכול GKE שמשתמש בכמה יחידות GPU מסוג L4 ומכינים תשתית להפעלת אחד מהמודלים הבאים:
מספר ה-GPU הנדרש משתנה בהתאם לפורמט הנתונים של המודל. במדריך הזה, כל מודל משתמש בשני מעבדי GPU מסוג L4. מידע נוסף זמין במאמר בנושא חישוב מספר מעבדי ה-GPU.
המדריך הזה מיועד למהנדסי למידת מכונה (ML), למנהלי פלטפורמות ולמפעילים, ולמומחים בתחום הנתונים וה-AI שרוצים להשתמש ביכולות של Kubernetes לניהול קונטיינרים כדי להפעיל מודלים גדולים של שפה (LLM). מידע נוסף על תפקידים נפוצים ומשימות לדוגמה שמוזכרים בתוכן זמין במאמר תפקידים נפוצים של משתמשי GKE ומשימות. Google Cloud
לפני שקוראים את הדף הזה, חשוב לוודא שמכירים את הנושאים הבאים:
מטרות
במדריך הזה תלמדו:
- ליצור אשכול ומאגרי צמתים.
- הכנת עומס העבודה.
- פורסים את עומס העבודה.
- מנהלים אינטראקציה עם הממשק של מודל השפה הגדול.
לפני שמתחילים
לפני שמתחילים, חשוב לוודא שביצעתם את הפעולות הבאות:
- מפעילים את ממשק ה-API של Google Kubernetes Engine. הפעלת Google Kubernetes Engine API
- אם רוצים להשתמש ב-CLI של Google Cloud למשימה הזו, צריך להתקין ואז להפעיל את ה-CLI של gcloud. אם התקנתם בעבר את ה-CLI של gcloud, מריצים את הפקודה
gcloud components updateכדי לקבל את הגרסה העדכנית. יכול להיות שגרסאות קודמות של ה-CLI של gcloud לא יתמכו בהרצת הפקודות שמופיעות במסמך הזה.
יש מודלים עם דרישות נוספות. חשוב לוודא שאתם עומדים בדרישות הבאות:
- כדי לגשת למודלים מ-Hugging Face, צריך להשתמש בטוקן של HuggingFace.
- למודל Mixtral 8x7b – מאשרים את התנאים של מודל Mistral Mixtral.
- למודל Llama 3 70b – מוודאים שיש לכם רישיון פעיל לשימוש במודלים של Meta Llama.
הכנת הסביבה
במסוף Google Cloud , מפעילים מכונת Cloud Shell:
פתיחת Cloud Shellמגדירים את משתני הסביבה שמוגדרים כברירת מחדל:
gcloud config set project PROJECT_ID gcloud config set billing/quota_project PROJECT_ID export PROJECT_ID=$(gcloud config get project) export CONTROL_PLANE_LOCATION=us-central1מחליפים את PROJECT_ID במזהה הפרויקט ב- Google Cloud.
יצירת אשכול GKE ומאגר צמתים
אפשר להפעיל מודלים גדולים של שפה (LLM) במעבדי GPU באשכול GKE במצב Autopilot או במצב Standard. מומלץ להשתמש באשכול Autopilot כדי ליהנות מחוויית Kubernetes מנוהלת באופן מלא. כדי לבחור את מצב הפעולה של GKE שהכי מתאים לעומסי העבודה שלכם, אפשר לעיין במאמר בחירת מצב פעולה של GKE.
טייס אוטומטי
ב-Cloud Shell, מריצים את הפקודה הבאה:
gcloud container clusters create-auto l4-demo \ --project=${PROJECT_ID} \ --location=${CONTROL_PLANE_LOCATION} \ --release-channel=rapidGKE יוצר אשכול Autopilot עם צמתים של מעבד ו-GPU לפי בקשת עומסי העבודה שנפרסו.
מגדירים את
kubectlכדי לתקשר עם האשכול:gcloud container clusters get-credentials l4-demo --location=${CONTROL_PLANE_LOCATION}
רגילה
ב-Cloud Shell, מריצים את הפקודה הבאה כדי ליצור אשכול Standard שמשתמש באיחוד זהויות של עומסי עבודה ל-GKE:
, צריך לבדוק באילו אזורים כרטיסי ה-GPU מדגם L4 זמינים.gcloud container clusters create l4-demo \ --location ${CONTROL_PLANE_LOCATION} \ --workload-pool ${PROJECT_ID}.svc.id.goog \ --enable-image-streaming \ --node-locations=${CONTROL_PLANE_LOCATION}-a \ --workload-pool=${PROJECT_ID}.svc.id.goog \ --machine-type n2d-standard-4 \ --num-nodes 1 --min-nodes 1 --max-nodes 5 \ --release-channel=rapidיצירת האשכול עשויה להימשך כמה דקות.
מריצים את הפקודה הבאה כדי ליצור מאגר צמתים עבור האשכול:
gcloud container node-pools create g2-standard-24 --cluster l4-demo \ --location ${CONTROL_PLANE_LOCATION} \ --accelerator type=nvidia-l4,count=2,gpu-driver-version=latest \ --machine-type g2-standard-24 \ --enable-autoscaling --enable-image-streaming \ --num-nodes=0 --min-nodes=0 --max-nodes=3 \ --node-locations ${CONTROL_PLANE_LOCATION}-a,${CONTROL_PLANE_LOCATION}-c \ --spotGKE יוצר את המשאבים הבאים עבור ה-LLM:
- אשכול Standard ציבורי.
- מאגר צמתים עם
g2-standard-24סוג מכונה שהוקטן ל-0 צמתים. לא תחויבו על יחידות GPU עד שתפעילו Pods שמבקשים יחידות GPU. מאגר הצמתים הזה מספק מכונות וירטואליות מסוג Spot, שהמחיר שלהן נמוך יותר מהמחיר של מכונות וירטואליות רגילות של Compute Engine, ולא מובטחת זמינות שלהן. אפשר להסיר את הדגל--spotמהפקודה הזו, ואת בורר הצמתיםcloud.google.com/gke-spotבהגדרותtext-generation-inference.yamlכדי להשתמש במכונות וירטואליות לפי דרישה.
מגדירים את
kubectlכדי לתקשר עם האשכול:gcloud container clusters get-credentials l4-demo --location=${CONTROL_PLANE_LOCATION}
הכנת עומס העבודה
בקטע הזה מוסבר איך להגדיר את עומס העבודה בהתאם למודל שבו רוצים להשתמש. במדריך הזה נעשה שימוש בפריסות של Kubernetes כדי לפרוס את המודל. פריסה היא אובייקט Kubernetes API שמאפשר להריץ כמה עותקים של Pods שמפוזרים בין הצמתים באשכול.
Llama 3 70b
מגדירים את משתני הסביבה שמוגדרים כברירת מחדל:
export HF_TOKEN=HUGGING_FACE_TOKENמחליפים את
HUGGING_FACE_TOKENבאסימון HuggingFace.יוצרים סוד של Kubernetes עבור טוקן HuggingFace:
kubectl create secret generic l4-demo \ --from-literal=HUGGING_FACE_TOKEN=${HF_TOKEN} \ --dry-run=client -o yaml | kubectl apply -f -יוצרים את מניפסט הפריסה הבא
text-generation-inference.yaml:במניפסט הזה:
- הערך של
NUM_SHARDחייב להיות2כי המודל דורש שני מעבדי GPU מסוג NVIDIA L4. - הערך של
QUANTIZEמוגדר כ-bitsandbytes-nf4, כלומר המודל נטען ב-4 ביט במקום ב-32 ביט. כך אפשר להקטין את כמות זיכרון ה-GPU שנדרשת ב-GKE ולשפר את מהירות ההסקה. עם זאת, רמת הדיוק של המודל עלולה לרדת. במאמר חישוב מספר ה-GPU מוסבר איך לחשב את מספר ה-GPU שצריך לבקש.
- הערך של
החלת המניפסט:
kubectl apply -f text-generation-inference.yamlהפלט אמור להיראות כך:
deployment.apps/llm createdמאמתים את הסטטוס של המודל:
kubectl get deployהפלט אמור להיראות כך:
NAME READY UP-TO-DATE AVAILABLE AGE llm 1/1 1 1 20mצפייה ביומנים מהפריסה הפעילה:
kubectl logs -l app=llmהפלט אמור להיראות כך:
{"timestamp":"2024-03-09T05:08:14.751646Z","level":"INFO","message":"Warming up model","target":"text_generation_router","filename":"router/src/main.rs","line_number":291} {"timestamp":"2024-03-09T05:08:19.961136Z","level":"INFO","message":"Setting max batch total tokens to 133696","target":"text_generation_router","filename":"router/src/main.rs","line_number":328} {"timestamp":"2024-03-09T05:08:19.961164Z","level":"INFO","message":"Connected","target":"text_generation_router","filename":"router/src/main.rs","line_number":329} {"timestamp":"2024-03-09T05:08:19.961171Z","level":"WARN","message":"Invalid hostname, defaulting to 0.0.0.0","target":"text_generation_router","filename":"router/src/main.rs","line_number":343}
Mixtral 8x7b
מגדירים את משתני הסביבה שמוגדרים כברירת מחדל:
export HF_TOKEN=HUGGING_FACE_TOKENמחליפים את
HUGGING_FACE_TOKENבאסימון HuggingFace.יוצרים סוד של Kubernetes עבור טוקן HuggingFace:
kubectl create secret generic l4-demo \ --from-literal=HUGGING_FACE_TOKEN=${HF_TOKEN} \ --dry-run=client -o yaml | kubectl apply -f -יוצרים את מניפסט הפריסה הבא
text-generation-inference.yaml:במניפסט הזה:
- הערך של
NUM_SHARDחייב להיות2כי המודל דורש שני מעבדי GPU מסוג NVIDIA L4. - הערך של
QUANTIZEמוגדר כ-bitsandbytes-nf4, כלומר המודל נטען ב-4 ביט במקום ב-32 ביט. כך אפשר להקטין את כמות זיכרון ה-GPU שנדרשת ב-GKE ולשפר את מהירות ההסקה. עם זאת, יכול להיות שהפעולה הזו תפגע ברמת הדיוק של המודל. במאמר חישוב מספר ה-GPU מוסבר איך מחשבים את מספר ה-GPU שצריך לבקש.
- הערך של
החלת המניפסט:
kubectl apply -f text-generation-inference.yamlהפלט אמור להיראות כך:
deployment.apps/llm createdמאמתים את הסטטוס של המודל:
watch kubectl get deployכשהפריסה מוכנה, הפלט אמור להיראות כך:
NAME READY UP-TO-DATE AVAILABLE AGE llm 1/1 1 1 10mכדי לצאת מהשעון, מקלידים
CTRL + C.צפייה ביומנים מהפריסה הפעילה:
kubectl logs -l app=llmהפלט אמור להיראות כך:
{"timestamp":"2024-03-09T05:08:14.751646Z","level":"INFO","message":"Warming up model","target":"text_generation_router","filename":"router/src/main.rs","line_number":291} {"timestamp":"2024-03-09T05:08:19.961136Z","level":"INFO","message":"Setting max batch total tokens to 133696","target":"text_generation_router","filename":"router/src/main.rs","line_number":328} {"timestamp":"2024-03-09T05:08:19.961164Z","level":"INFO","message":"Connected","target":"text_generation_router","filename":"router/src/main.rs","line_number":329} {"timestamp":"2024-03-09T05:08:19.961171Z","level":"WARN","message":"Invalid hostname, defaulting to 0.0.0.0","target":"text_generation_router","filename":"router/src/main.rs","line_number":343}
Falcon 40b
יוצרים את מניפסט הפריסה הבא
text-generation-inference.yaml:במניפסט הזה:
- הערך של
NUM_SHARDחייב להיות2כי המודל דורש שני מעבדי GPU מסוג NVIDIA L4. - הערך של
QUANTIZEמוגדר כ-bitsandbytes-nf4, כלומר המודל נטען ב-4 ביט במקום ב-32 ביט. כך אפשר להקטין את כמות זיכרון ה-GPU שנדרשת ב-GKE ולשפר את מהירות ההסקה. עם זאת, רמת הדיוק של המודל עלולה לרדת. במאמר חישוב מספר ה-GPU מוסבר איך מחשבים את מספר ה-GPU שצריך לבקש.
- הערך של
החלת המניפסט:
kubectl apply -f text-generation-inference.yamlהפלט אמור להיראות כך:
deployment.apps/llm createdמאמתים את הסטטוס של המודל:
watch kubectl get deployכשהפריסה מוכנה, הפלט אמור להיראות כך:
NAME READY UP-TO-DATE AVAILABLE AGE llm 1/1 1 1 10mכדי לצאת מהשעון, מקלידים
CTRL + C.צפייה ביומנים מהפריסה הפעילה:
kubectl logs -l app=llmהפלט אמור להיראות כך:
{"timestamp":"2024-03-09T05:08:14.751646Z","level":"INFO","message":"Warming up model","target":"text_generation_router","filename":"router/src/main.rs","line_number":291} {"timestamp":"2024-03-09T05:08:19.961136Z","level":"INFO","message":"Setting max batch total tokens to 133696","target":"text_generation_router","filename":"router/src/main.rs","line_number":328} {"timestamp":"2024-03-09T05:08:19.961164Z","level":"INFO","message":"Connected","target":"text_generation_router","filename":"router/src/main.rs","line_number":329} {"timestamp":"2024-03-09T05:08:19.961171Z","level":"WARN","message":"Invalid hostname, defaulting to 0.0.0.0","target":"text_generation_router","filename":"router/src/main.rs","line_number":343}
יצירת שירות מסוג ClusterIP
חשיפת ה-Pods באופן פנימי בתוך האשכול כדי שאפליקציות אחרות יוכלו לגלות אותם ולגשת אליהם.
יוצרים את קובץ המניפסט
llm-service.yamlהבא:apiVersion: v1 kind: Service metadata: name: llm-service spec: selector: app: llm type: ClusterIP ports: - protocol: TCP port: 80 targetPort: 8080החלת המניפסט:
kubectl apply -f llm-service.yaml
פריסת ממשק צ'אט
משתמשים ב-Gradio כדי ליצור אפליקציית אינטרנט שמאפשרת אינטראקציה עם המודל. Gradio היא ספריית Python שיש לה wrapper של ChatInterface שיוצר ממשקי משתמש לצ'אטבוטים.
Llama 3 70b
יוצרים קובץ בשם
gradio.yaml:החלת המניפסט:
kubectl apply -f gradio.yamlמוצאים את כתובת ה-IP החיצונית של השירות:
kubectl get svcהפלט אמור להיראות כך:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE gradio-service LoadBalancer 10.24.29.197 34.172.115.35 80:30952/TCP 125mמעתיקים את כתובת ה-IP החיצונית מהעמודה
EXTERNAL-IP.אפשר להציג את ממשק המודל מדפדפן האינטרנט באמצעות כתובת ה-IP החיצונית עם היציאה שנחשפת:
http://EXTERNAL_IP
Mixtral 8x7b
יוצרים קובץ בשם
gradio.yaml:החלת המניפסט:
kubectl apply -f gradio.yamlמוצאים את כתובת ה-IP החיצונית של השירות:
kubectl get svcהפלט אמור להיראות כך:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE gradio-service LoadBalancer 10.24.29.197 34.172.115.35 80:30952/TCP 125mמעתיקים את כתובת ה-IP החיצונית מהעמודה
EXTERNAL-IP.אפשר לראות את ממשק המודל בדפדפן האינטרנט באמצעות כתובת ה-IP החיצונית עם היציאה שנחשפה:
http://EXTERNAL_IP
Falcon 40b
יוצרים קובץ בשם
gradio.yaml:החלת המניפסט:
kubectl apply -f gradio.yamlמוצאים את כתובת ה-IP החיצונית של השירות:
kubectl get svcהפלט אמור להיראות כך:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE gradio-service LoadBalancer 10.24.29.197 34.172.115.35 80:30952/TCP 125mמעתיקים את כתובת ה-IP החיצונית מהעמודה
EXTERNAL-IP.אפשר לראות את ממשק המודל בדפדפן האינטרנט באמצעות כתובת ה-IP החיצונית עם היציאה שנחשפה:
http://EXTERNAL_IP
חישוב מספר ה-GPU
מספר ה-GPU תלוי בערך של הדגל QUANTIZE. במדריך הזה, הערך של QUANTIZE מוגדר ל-bitsandbytes-nf4, כלומר המודל נטען ב-4 ביטים.
מודל עם 70 מיליארד פרמטרים ידרוש זיכרון GPU בנפח 40GB לפחות, ששווה ל-70 מיליארד כפול 4 ביט (70 מיליארד x 4 ביט= 35GB), וכולל 5GB של תקורה. במקרה כזה, ל-GPU יחיד מסוג L4 לא יהיה מספיק זיכרון. לכן, בדוגמאות במדריך הזה נעשה שימוש ב-שני GPU L4 עם זיכרון (2 x 24 = 48 GB). ההגדרה הזו מספיקה להרצת Falcon 40b או Llama 3 70b במעבדי GPU מסוג L4.
הסרת המשאבים
כדי לא לצבור חיובים לחשבון Google Cloud על המשאבים שבהם השתמשתם במדריך הזה, אתם יכולים למחוק את הפרויקט שמכיל את המשאבים או להשאיר את הפרויקט ולמחוק את המשאבים בנפרד.
מחיקת האשכול
כדי להימנע מחיובים בחשבון Google Cloud על המשאבים שיצרתם במדריך הזה, מוחקים את אשכול GKE:
gcloud container clusters delete l4-demo --location ${CONTROL_PLANE_LOCATION}