סקירה כללית
במדריך הזה נסביר איך להכניס לשימוש בסביבת הייצור מודלים המתקדמים ביותר (SOTA) של שפה גדולה (LLM) כמו DeepSeek-R1 671B או Llama 3.1 405B בתוכנת Distributed Cloud רק עבור Bare Metal באמצעות מעבדים גרפיים (GPU) בכמה צמתים.
במדריך הזה נדגים איך להשתמש בטכנולוגיות ניידות בקוד פתוח, ב-Kubernetes, ב-vLLM וב-API LeaderWorkerSet (LWS) כדי לפרוס ולפרסם עומסי עבודה של AI/ML באשכולות Bare Metal. Google Distributed Cloud מרחיב את GKE לשימוש בסביבה מקומית, תוך מתן היתרונות של שליטה מפורטת, יכולת הרחבה, עמידות, ניידות וחסכוניות של GKE.
רקע
בקטע הזה מתוארות הטכנולוגיות העיקריות שבהן נעשה שימוש במדריך הזה, כולל שני מודלים גדולים של שפה (LLM) שמשמשים כדוגמאות במדריך הזה: DeepSeek-R1 ו-Llama 3.1 405B.
DeepSeek-R1
DeepSeek-R1 הוא מודל שפה גדול (LLM) עם 671 מיליארד פרמטרים של DeepSeek. הוא מיועד להסקת מסקנות לוגיות, לחשיבה מתמטית ולפתרון בעיות בזמן אמת במשימות שונות שמבוססות על טקסט. Google Distributed Cloud מטפל בדרישות החישוב של DeepSeek-R1, ותומך ביכולות שלו באמצעות משאבים ניתנים להרחבה, מחשוב מבוזר ורשת יעילה.
מידע נוסף זמין במאמרי העזרה של DeepSeek.
Llama 3.1 405B
Llama 3.1 405B הוא מודל שפה גדול (LLM) של מטא שנועד לביצוע מגוון רחב של משימות עיבוד שפה טבעית (NLP), כולל יצירת טקסט, תרגום ומענה לשאלות. Google Distributed Cloud מציע תשתית חזקה שנדרשת כדי לתמוך בצרכים של אימון מבוזר והפעלת מודלים בקנה מידה כזה.
מידע נוסף זמין במאמרי העזרה בנושא Llama.
שירות Kubernetes מנוהל של Google Distributed Cloud
Google Distributed Cloud מציע מגוון רחב של שירותים, כולל תוכנת Distributed Cloud ל-Bare Metal בלבד, שמתאימה לפריסה ולניהול של עומסי עבודה של AI/ML במרכז הנתונים שלכם. Google Distributed Cloud הוא שירות מנוהל של Kubernetes שמפשט את הפריסה, ההתאמה לעומס והניהול של אפליקציות בקונטיינרים. Google Distributed Cloud מספק את התשתית הנדרשת, כולל משאבים ניתנים להרחבה, מחשוב מבוזר ורשת יעילה, כדי לעמוד בדרישות החישוב של מודלי שפה גדולים.
מידע נוסף על מושגי מפתח ב-Kubernetes זמין במאמר תחילת הלימוד של Kubernetes. מידע נוסף על Google Distributed Cloud ועל האופן שבו הוא עוזר לכם להרחיב, לבצע אוטומציה ולנהל את Kubernetes זמין במאמר סקירה כללית של תוכנת Distributed Cloud ל-Bare Metal בלבד.
יחידות GPU
מעבדים גרפיים (GPU) מאפשרים להאיץ עומסי עבודה ספציפיים, כמו למידת מכונה ועיבוד נתונים. Google Distributed Cloud תומך בצמתים שמצוידים במעבדי GPU חזקים כאלה, ומאפשר לכם להגדיר את האשכול לביצועים אופטימליים במשימות של למידת מכונה ועיבוד נתונים. Google Distributed Cloud מספק מגוון אפשרויות של סוגי מכונות להגדרת צמתים, כולל סוגי מכונות עם מעבדי GPU של NVIDIA H100, L4 ו-A100.
מידע נוסף זמין במאמרים התקנה או הסרה של NVIDIA GPU Operator או הגדרה ושימוש ב-GPU של NVIDIA.
LeaderWorkerSet (LWS)
LeaderWorkerSet (LWS) הוא API לפריסת Kubernetes שמטפל בדפוסי פריסה נפוצים של עומסי עבודה של הסקת מסקנות מרובת צמתים של AI/ML. הצגה משרתים מרובים מסתמכת על כמה תרמילים (Pods), שכל אחד מהם יכול לפעול על צומת אחר, כדי לטפל בעומס העבודה של ההסקה המבוזרת. LWS מאפשרת להתייחס לכמה Pods כאל קבוצה, וכך מפשטת את הניהול של מודלים מבוזרים.
vLLM והצגה במספר מארחים
כשמציגים מודלים גדולים של שפה (LLM) שדורשים הרבה משאבי מחשוב, מומלץ להשתמש ב-vLLM ולהריץ את עומסי העבודה ביחידות GPU.
vLLM הוא פריימוורק קוד פתוח עם אופטימיזציה גבוהה להצגת מודלים גדולים של שפה (LLM). הוא יכול לשפר את קצב העברת הנתונים (throughput) של הצגת המודלים ביחידות GPU, עם תכונות כמו:
הטמעה אופטימלית של טרנספורמר עם PagedAttention
צירוף מתמשך של בקשות (batching) כדי לשפר את קצב העברת הנתונים הכולל של הצגת המודעות
הצגת מודלים מבוזרת בכמה מעבדי GPU
במקרים של מודלי LLM שדורשים הרבה משאבי מחשוב ולא יכולים להיכנס לצומת GPU יחיד, אפשר להשתמש בכמה צמתי GPU כדי להפעיל את המודל. vLLM תומך בהפעלת עומסי עבודה בכמה מעבדי GPU באמצעות שתי אסטרטגיות:
מקביליות טנסור מפצלת את הכפלות המטריצות בשכבת הטרנספורמציה בין כמה מעבדי GPU. עם זאת, האסטרטגיה הזו דורשת רשת מהירה בגלל התקשורת שנדרשת בין יחידות ה-GPU, ולכן היא פחות מתאימה להרצת עומסי עבודה בצמתים.
Pipeline parallelism מפצל את המודל לפי שכבה, או אנכית. האסטרטגיה הזו לא דורשת תקשורת מתמדת בין מעבדי GPU, ולכן היא עדיפה כשמריצים מודלים על פני צמתים.
אפשר להשתמש בשתי האסטרטגיות בהצגת מודעות בכמה צמתים. לדוגמה, כשמשתמשים בשני צמתים עם שמונה יחידות GPU מסוג H100 בכל אחד מהם, אפשר להשתמש בשתי האסטרטגיות:
מקביליות דו-כיוונית בצינורות (pipeline) כדי לפצל את המודל בין שני הצמתים
מקביליות טנסור שמונה-כיוונית כדי לפצל את המודל בין שמונת מעבדי ה-GPU בכל צומת
מידע נוסף מופיע במאמרי העזרה בנושא vLLM.
מטרות
מכינים את הסביבה עם אשכול Google Distributed Cloud במצב Autopilot או במצב רגיל.
פריסת vLLM בכמה צמתים באשכול.
משתמשים ב-vLLM כדי להפעיל את המודל באמצעות
curl.
לפני שמתחילים
- מוודאים שיש לכם אשכול Bare Metal פעיל עם לפחות מאגר צמתים אחד של צמתים לעובדים, שכולל שני צמתים לעובדים, שכל אחד מהם מוגדר עם שמונה יחידות GPU של NVIDIA H100 80 GB.
- אם עדיין אין לכם חשבון Hugging Face, אתם צריכים ליצור חשבון.
גישה למודל
אפשר להשתמש במודלים Llama 3.1 405B או DeepSeek-R1.
DeepSeek-R1
יצירת אסימון גישה
אם עדיין אין לכם טוקן, יוצרים טוקן חדש של Hugging Face:
לוחצים על הפרופיל שלך > הגדרות > טוקנים של גישה.
לוחצים על New Token (טוקן חדש).
מציינים שם לבחירתכם ותפקיד ברמה של
Readלפחות.לוחצים על יצירת אסימון.
Llama 3.1 405B
יצירת אסימון גישה
אם עדיין אין לכם טוקן, יוצרים טוקן חדש של Hugging Face:
לוחצים על הפרופיל שלך > הגדרות > טוקנים של גישה.
לוחצים על New Token (טוקן חדש).
מציינים שם לבחירתכם ותפקיד ברמה של
Readלפחות.לוחצים על יצירת אסימון.
הכנת הסביבה
כדי להגדיר את הסביבה:
מגדירים את הפרמטרים הבאים בתחנת העבודה של האדמין:
gcloud config set project PROJECT_ID export PROJECT_ID=$(gcloud config get project) export HF_TOKEN=HUGGING_FACE_TOKEN export IMAGE_NAME= gcr.io/PROJECT_ID/vllm-multihost/vllm-multihost:latestמחליפים את הערכים הבאים:
PROJECT_ID: מזהה הפרויקט שמשויך לאשכול.
HUGGING_FACE_TOKEN: הטוקן של Hugging Face שנוצר מהקטע הקודם קבלת גישה למודל.
יצירת סוד של Kubernetes לפרטי הכניסה של Hugging Face
יוצרים סוד ב-Kubernetes שמכיל את הטוקן של Hugging Face באמצעות הפקודה הבאה:
kubectl create secret generic hf-secret \
--kubeconfig KUBECONFIG \
--from-literal=hf_api_token=${HF_TOKEN} \
--dry-run=client -o yaml | kubectl apply -f -
מחליפים את KUBECONFIG בנתיב של קובץ ה-kubeconfig של האשכול שבו רוצים לארח את מודל ה-LLM.
התקנת LeaderWorkerSet
כדי להתקין את LWS, מריצים את הפקודה הבאה:
kubectl apply --server-side \
--kubeconfig KUBECONFIG \
-f https://github.com/kubernetes-sigs/lws/releases/latest/download/manifests.yaml
מריצים את הפקודה הבאה כדי לוודא שהבקר LeaderWorkerSet פועל במרחב השמות lws-system:
kubectl get pod -n lws-system --kubeconfig KUBECONFIG
הפלט אמור להיראות כך:
NAME READY STATUS RESTARTS AGE
lws-controller-manager-5c4ff67cbd-9jsfc 2/2 Running 0 6d23h
פריסת שרת מודלים של vLLM
כדי לפרוס את שרת מודל vLLM, פועלים לפי השלבים הבאים:
יוצרים ומחילים את קובץ המניפסט, בהתאם למודל ה-LLM שרוצים לפרוס.
DeepSeek-R1
יוצרים מניפסט YAML,
vllm-deepseek-r1-A3.yaml, לשרת של מודל vLLM:apiVersion: leaderworkerset.x-k8s.io/v1 kind: LeaderWorkerSet metadata: name: vllm spec: replicas: 1 leaderWorkerTemplate: size: 2 restartPolicy: RecreateGroupOnPodRestart leaderTemplate: metadata: labels: role: leader spec: nodeSelector: cloud.google.com/gke-accelerator: nvidia-h100-80gb containers: - name: vllm-leader image: vllm/vllm-openai:v0.8.5 env: - name: HUGGING_FACE_HUB_TOKEN valueFrom: secretKeyRef: name: hf-secret key: hf_api_token command: - sh - -c - "bash /vllm-workspace/examples/online_serving/multi-node-serving.sh leader --ray_cluster_size=$(LWS_GROUP_SIZE); python3 -m vllm.entrypoints.openai.api_server --port 8080 --model deepseek-ai/DeepSeek-R1 --tensor-parallel-size 8 --pipeline-parallel-size 2 --trust-remote-code --max-model-len 4096" resources: limits: nvidia.com/gpu: "8" ports: - containerPort: 8080 readinessProbe: tcpSocket: port: 8080 initialDelaySeconds: 15 periodSeconds: 10 volumeMounts: - mountPath: /dev/shm name: dshm volumes: - name: dshm emptyDir: medium: Memory sizeLimit: 15Gi workerTemplate: spec: containers: - name: vllm-worker image: vllm/vllm-openai:v0.8.5 command: - sh - -c - "bash /vllm-workspace/examples/online_serving/multi-node-serving.sh worker --ray_address=$(LWS_LEADER_ADDRESS)" resources: limits: nvidia.com/gpu: "8" env: - name: HUGGING_FACE_HUB_TOKEN valueFrom: secretKeyRef: name: hf-secret key: hf_api_token volumeMounts: - mountPath: /dev/shm name: dshm volumes: - name: dshm emptyDir: medium: Memory sizeLimit: 15Gi --- apiVersion: v1 kind: Service metadata: name: vllm-leader spec: ports: - name: http port: 8080 protocol: TCP targetPort: 8080 selector: leaderworkerset.sigs.k8s.io/name: vllm role: leader type: ClusterIPמריצים את הפקודה הבאה כדי להחיל את המניפסט:
kubectl apply -f vllm-deepseek-r1-A3.yaml \ --kubeconfig KUBECONFIG
Llama 3.1 405B
יוצרים מניפסט YAML,
vllm-llama3-405b-A3.yaml, לשרת של מודל vLLM:apiVersion: leaderworkerset.x-k8s.io/v1 kind: LeaderWorkerSet metadata: name: vllm spec: replicas: 1 leaderWorkerTemplate: size: 2 restartPolicy: RecreateGroupOnPodRestart leaderTemplate: metadata: labels: role: leader spec: nodeSelector: cloud.google.com/gke-accelerator: nvidia-h100-80gb containers: - name: vllm-leader image: vllm/vllm-openai:v0.8.5 env: - name: HUGGING_FACE_HUB_TOKEN valueFrom: secretKeyRef: name: hf-secret key: hf_api_token command: - sh - -c - "bash /vllm-workspace/examples/online_serving/multi-node-serving.sh leader --ray_cluster_size=$(LWS_GROUP_SIZE); python3 -m vllm.entrypoints.openai.api_server --port 8080 --model meta-llama/Meta-Llama-3.1-405B-Instruct --tensor-parallel-size 8 --pipeline-parallel-size 2" resources: limits: nvidia.com/gpu: "8" ports: - containerPort: 8080 readinessProbe: tcpSocket: port: 8080 initialDelaySeconds: 15 periodSeconds: 10 volumeMounts: - mountPath: /dev/shm name: dshm volumes: - name: dshm emptyDir: medium: Memory sizeLimit: 15Gi workerTemplate: spec: containers: - name: vllm-worker image: vllm/vllm-openai:v0.8.5 command: - sh - -c - "bash /vllm-workspace/examples/online_serving/multi-node-serving.sh worker --ray_address=$(LWS_LEADER_ADDRESS)" resources: limits: nvidia.com/gpu: "8" env: - name: HUGGING_FACE_HUB_TOKEN valueFrom: secretKeyRef: name: hf-secret key: hf_api_token volumeMounts: - mountPath: /dev/shm name: dshm volumes: - name: dshm emptyDir: medium: Memory sizeLimit: 15Gi --- apiVersion: v1 kind: Service metadata: name: vllm-leader spec: ports: - name: http port: 8080 protocol: TCP targetPort: 8080 selector: leaderworkerset.sigs.k8s.io/name: vllm role: leader type: ClusterIPמריצים את הפקודה הבאה כדי להחיל את המניפסט:
kubectl apply -f vllm-llama3-405b-A3.yaml \ --kubeconfig KUBECONFIG
כדי לראות את היומנים משרת המודל הפועל, מריצים את הפקודה הבאה:
kubectl logs vllm-0 -c vllm-leader \ --kubeconfig KUBECONFIGהפלט אמור להיראות כך:
INFO 08-09 21:01:34 api_server.py:297] Route: /detokenize, Methods: POST INFO 08-09 21:01:34 api_server.py:297] Route: /v1/models, Methods: GET INFO 08-09 21:01:34 api_server.py:297] Route: /version, Methods: GET INFO 08-09 21:01:34 api_server.py:297] Route: /v1/chat/completions, Methods: POST INFO 08-09 21:01:34 api_server.py:297] Route: /v1/completions, Methods: POST INFO 08-09 21:01:34 api_server.py:297] Route: /v1/embeddings, Methods: POST INFO: Started server process [7428] INFO: Waiting for application startup. INFO: Application startup complete. INFO: Uvicorn running on http://0.0.0.0:8080 (Press CTRL+C to quit)
פרסום המודל
מגדירים העברה ליציאה אחרת למודל על ידי הרצת הפקודה הבאה:
kubectl port-forward svc/vllm-leader 8080:8080 \
--kubeconfig KUBECONFIG
אינטראקציה עם המודל באמצעות curl
כדי לקיים אינטראקציה עם המודל באמצעות curl, פועלים לפי ההוראות הבאות:
DeepSeek-R1
במסוף חדש, שולחים בקשה לשרת:
curl http://localhost:8080/v1/completions \
-H "Content-Type: application/json" \
-d '{
"model": "deepseek-ai/DeepSeek-R1",
"prompt": "I have four boxes. I put the red box on the bottom and put the blue box on top. Then I put the yellow box on top the blue. Then I take the blue box out and put it on top. And finally I put the green box on the top. Give me the final order of the boxes from bottom to top. Show your reasoning but be brief",
"max_tokens": 1024,
"temperature": 0
}'
הפלט אמור להיראות כך:
{
"id": "cmpl-f2222b5589d947419f59f6e9fe24c5bd",
"object": "text_completion",
"created": 1738269669,
"model": "deepseek-ai/DeepSeek-R1",
"choices": [
{
"index": 0,
"text": ".\n\nOkay, let's see. The user has four boxes and is moving them around. Let me try to visualize each step. \n\nFirst, the red box is placed on the bottom. So the stack starts with red. Then the blue box is put on top of red. Now the order is red (bottom), blue. Next, the yellow box is added on top of blue. So now it's red, blue, yellow. \n\nThen the user takes the blue box out. Wait, blue is in the middle. If they remove blue, the stack would be red and yellow. But where do they put the blue box? The instruction says to put it on top. So after removing blue, the stack is red, yellow. Then blue is placed on top, making it red, yellow, blue. \n\nFinally, the green box is added on the top. So the final order should be red (bottom), yellow, blue, green. Let me double-check each step to make sure I didn't mix up any steps. Starting with red, then blue, then yellow. Remove blue from the middle, so yellow is now on top of red. Then place blue on top of that, so red, yellow, blue. Then green on top. Yes, that seems right. The key step is removing the blue box from the middle, which leaves yellow on red, then blue goes back on top, followed by green. So the final order from bottom to top is red, yellow, blue, green.\n\n**Final Answer**\nThe final order from bottom to top is \\boxed{red}, \\boxed{yellow}, \\boxed{blue}, \\boxed{green}.\n</think>\n\n1. Start with the red box at the bottom.\n2. Place the blue box on top of the red box. Order: red (bottom), blue.\n3. Place the yellow box on top of the blue box. Order: red, blue, yellow.\n4. Remove the blue box (from the middle) and place it on top. Order: red, yellow, blue.\n5. Place the green box on top. Final order: red, yellow, blue, green.\n\n\\boxed{red}, \\boxed{yellow}, \\boxed{blue}, \\boxed{green}",
"logprobs": null,
"finish_reason": "stop",
"stop_reason": null,
"prompt_logprobs": null
}
],
"usage": {
"prompt_tokens": 76,
"total_tokens": 544,
"completion_tokens": 468,
"prompt_tokens_details": null
}
}
Llama 3.1 405B
במסוף חדש, שולחים בקשה לשרת:
curl http://localhost:8080/v1/completions \
-H "Content-Type: application/json" \
-d '{
"model": "meta-llama/Meta-Llama-3.1-405B-Instruct",
"prompt": "San Francisco is a",
"max_tokens": 7,
"temperature": 0
}'
הפלט אמור להיראות כך:
{"id":"cmpl-0a2310f30ac3454aa7f2c5bb6a292e6c",
"object":"text_completion","created":1723238375,"model":"meta-llama/Meta-Llama-3.1-405B-Instruct","choices":[{"index":0,"text":" top destination for foodies, with","logprobs":null,"finish_reason":"length","stop_reason":null}],"usage":{"prompt_tokens":5,"total_tokens":12,"completion_tokens":7}}
המאמרים הבאים
- מידע נוסף על מעבדי GPU ב-Google Distributed Cloud
- אפשר לעיין במאגר GitHub ובמסמכי העזרה של vLLM.
- עיון במאגר GitHub של LWS