הצגת מודלים פתוחים של Gemma באמצעות מעבדי GPU ב-GKE עם Triton ו-TensorRT-LLM

במדריך הזה נדגים איך לפרוס ולהכניס לשימוש בסביבת הייצור מודל שפה גדול (LLM) של Gemma באמצעות GPUs ב-Google Kubernetes Engine ‏ (GKE) עם מחסנית הפרסום של NVIDIA Triton ו-TensorRT-LLM. ההסבר הזה מספק בסיס להבנה ולבדיקה של פריסת LLM מעשית להסקת מסקנות בסביבת Kubernetes מנוהלת. אתם פורסים קונטיינר שנבנה מראש עם Triton ו-TensorRT-LLM ב-GKE. בנוסף, מגדירים את GKE לטעינת המשקלים של Gemma 2B ו-7B.

המדריך הזה מיועד למהנדסי למידת מכונה (ML), למנהלי פלטפורמות ולמפעילים, ולמומחי נתונים ו-AI שרוצים להשתמש ביכולות של Kubernetes לניהול קונטיינרים כדי להפעיל מודלים גדולים של שפה (LLM) בחומרת GPU מסוג H100,‏ A100 ו-L4. מידע נוסף על תפקידים נפוצים ועל משימות לדוגמה שאנחנו מתייחסים אליהן בתוכן זמין במאמר תפקידים נפוצים של משתמשים ומשימות ב-GKE. Google Cloud

אם אתם צריכים פלטפורמת AI מנוהלת ומאוחדת כדי ליצור ולהכניס לשימוש בסביבת הייצור במהירות מודלים של למידת מכונה בצורה חסכונית, מומלץ לנסות את פתרון הפריסה שלנו Vertex AI.

לפני שקוראים את הדף הזה, חשוב לוודא שמכירים את הנושאים הבאים:

רקע

בקטע הזה מתוארות הטכנולוגיות העיקריות שמופיעות במדריך הזה.

‏Gemma

Gemma הוא קבוצה של מודלים קלים של בינה מלאכותית גנרטיבית (AI), שזמינים לשימוש חופשי ופורסמו ברישיון קוד פתוח. מודלים של AI זמינים להרצה באפליקציות, בחומרה, במכשירים ניידים או בשירותים מתארחים. אפשר להשתמש במודלים של Gemma ליצירת טקסט, אבל אפשר גם לכוונן את המודלים האלה למשימות מיוחדות.

מידע נוסף מופיע במאמרי העזרה בנושא Gemma.

יחידות GPU

מעבדי GPU מאפשרים להאיץ עומסי עבודה ספציפיים שפועלים בצמתים, כמו למידת מכונה ועיבוד נתונים. ‫GKE מספק מגוון אפשרויות של סוגי מכונות להגדרת צמתים, כולל סוגי מכונות עם מעבדי GPU של NVIDIA H100,‏ L4 ו-A100.

TensorRT-LLM

‫NVIDIA TensorRT-LLM‏ (TRT-LLM) היא ערכת כלים עם API בשפת Python להרכבת פתרונות אופטימליים להגדרת LLM ולבניית מנועי TensorRT שמבצעים היקש ביעילות ביחידות GPU של NVIDIA. ‫TensorRT-LLM כולל תכונות כמו:

  • הטמעה אופטימלית של טרנספורמר עם מיזוג שכבות, שמירת הפעלות במטמון, שימוש חוזר במאגר זיכרון ו-PagedAttention
  • הוספת מודעות לקבוצות בזמן אמת או באופן רציף כדי לשפר את קצב העברת הנתונים הכולל של הצגת המודעות
  • מקביליות טנסור ומקביליות צינורות להצגה מבוזרת בכמה יחידות GPU
  • קוונטיזציה (FP16, ‏ FP8, ‏ INT8)

מידע נוסף מופיע במאמרי העזרה בנושא TensorRT-LLM.

Triton

‫NVIDIA Triton Inference Server הוא שרת הסקה בקוד פתוח לאפליקציות AI/ML. ‫Triton תומך בהסקת מסקנות עם ביצועים גבוהים גם במעבדי GPU וגם במעבדי CPU של NVIDIA עם קצה עורפי שעבר אופטימיזציה, כולל TensorRT ו-TensorRT-LLM. ‫Triton כולל תכונות כמו:

  • הסקת מסקנות עם כמה מעבדי GPU וכמה צמתים
  • הרצה בו-זמנית של כמה מודלים
  • שילוב או שרשור של מודלים
  • איגוד סטטי, דינמי ורציף או איגוד של בקשות לחיזוי בזמן ההעברה

מידע נוסף מופיע במאמרי העזרה בנושא Triton.

מטרות

  1. מכינים את הסביבה עם אשכול GKE במצב Autopilot.
  2. פורסים קונטיינר עם Triton ו-TritonRT-LLM באשכול.
  3. משתמשים ב-Triton וב-TensorRT-LLM כדי להכניס לשימוש בסביבת הייצור את מודל Gemma 2B או 7B באמצעות curl.

לפני שמתחילים

  • נכנסים לחשבון Google Cloud . אם אתם משתמשים חדשים ב- Google Cloud, צרו חשבון כדי שתוכלו להעריך את הביצועים של המוצרים שלנו בתרחישים מהעולם האמיתי. לקוחות חדשים מקבלים בחינם גם קרדיט בשווי 300$ להרצה, לבדיקה ולפריסה של עומסי העבודה.
  • In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Roles required to select or create a project

    • Select a project: Selecting a project doesn't require a specific IAM role—you can select any project that you've been granted a role on.
    • Create a project: To create a project, you need the Project Creator role (roles/resourcemanager.projectCreator), which contains the resourcemanager.projects.create permission. Learn how to grant roles.

    Go to project selector

  • Verify that billing is enabled for your Google Cloud project.

  • Enable the required API.

    Roles required to enable APIs

    To enable APIs, you need the Service Usage Admin IAM role (roles/serviceusage.serviceUsageAdmin), which contains the serviceusage.services.enable permission. Learn how to grant roles.

    Enable the API

  • In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Roles required to select or create a project

    • Select a project: Selecting a project doesn't require a specific IAM role—you can select any project that you've been granted a role on.
    • Create a project: To create a project, you need the Project Creator role (roles/resourcemanager.projectCreator), which contains the resourcemanager.projects.create permission. Learn how to grant roles.

    Go to project selector

  • Verify that billing is enabled for your Google Cloud project.

  • Enable the required API.

    Roles required to enable APIs

    To enable APIs, you need the Service Usage Admin IAM role (roles/serviceusage.serviceUsageAdmin), which contains the serviceusage.services.enable permission. Learn how to grant roles.

    Enable the API

  • צריך לוודא שיש לכם בפרויקט את התפקיד או התפקידים הבאים: roles/container.admin, roles/iam.serviceAccountAdmin

    בדיקת התפקידים

    1. נכנסים לדף IAM במסוף Google Cloud .

      כניסה לדף IAM
    2. בוחרים את הפרויקט.
    3. בעמודה Principal (חשבון המשתמש), מוצאים את כל השורות שבהן מופיע השם שלכם או של קבוצה שאתם נכללים בה. כדי לברר באילו קבוצות אתם נכללים, פנו לאדמין.

    4. בודקים את העמודה Role בכל השורות שבהן מצוין או מופיע השם שלכם, כדי לראות אם רשימת התפקידים כוללת את התפקידים הנדרשים.

    מתן התפקידים

    1. נכנסים לדף IAM במסוף Google Cloud .

      כניסה לדף IAM
    2. בוחרים את הפרויקט.
    3. לוחצים על Grant access.
    4. בשדה New principals, מזינים את מזהה המשתמש. ‫ בדרך כלל מזהה המשתמש הוא כתובת האימייל של חשבון Google.

    5. לוחצים על Select a role ומחפשים את התפקיד.
    6. כדי לתת עוד תפקידים, לוחצים על Add another role ומוסיפים אותם.
    7. לוחצים על Save.

הכנת הסביבה

במדריך הזה משתמשים ב-Cloud Shell כדי לנהל משאבים שמתארחים ב-Google Cloud. ב-Cloud Shell מותקן מראש התוכנה שצריך למדריך הזה, כולל kubectl ו- gcloud CLI.

כדי להגדיר את הסביבה באמצעות Cloud Shell:

  1. ב Google Cloud מסוף, מפעילים סשן של Cloud Shell על ידי לחיצה על Activate Cloud Shell בGoogle Cloud מסוף.סמל ההפעלה של Cloud Shell תופעל סשן בחלונית התחתונה של Google Cloud המסוף.

  2. מגדירים את משתני הסביבה שמוגדרים כברירת מחדל:

    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=CONTROL_PLANE_LOCATION
    export CLUSTER_NAME=CLUSTER_NAME
    

    מחליפים את הערכים הבאים:

    • PROJECT_ID: מזהה הפרויקט ב- Google Cloud.
    • CONTROL_PLANE_LOCATION: האזור של Compute Engine במישור הבקרה של האשכול. האזור הזה צריך לתמוך בסוג המאיץ שבו רוצים להשתמש, לדוגמה, us-central1 ל-GPU מסוג L4.
    • CLUSTER_NAME: השם של האשכול.

גישה למודל

כדי לקבל גישה למודלים של Gemma, צריך להיכנס לפלטפורמת Kaggle ולקבל טוקן Kaggle API.

כדי להשתמש ב-Gemma, צריך לחתום על הסכם ההסכמה. פועלים לפי ההוראות הבאות:

  1. נכנסים אל דף ההסכמה לשימוש במודל באתר Kaggle.com.
  2. אם עדיין לא עשיתם זאת, מתחברים לחשבון Kaggle.
  3. לוחצים על בקשת גישה.
  4. בקטע Choose Account for Consent (בחירת חשבון להבעת הסכמה), בוחרים באפשרות Verify via Kaggle Account (אימות באמצעות חשבון Kaggle) כדי להשתמש בחשבון Kaggle להבעת הסכמה.
  5. מאשרים את התנאים וההגבלות של המודל.

יצירת אסימון גישה

כדי לגשת למודל דרך Kaggle, צריך טוקן Kaggle API. אם עדיין אין לכם טוקן, אתם יכולים ליצור טוקן חדש לפי השלבים הבאים:

  1. בדפדפן, עוברים אל ההגדרות של Kaggle.
  2. בקטע API, לוחצים על Create New Token (יצירת אסימון חדש).

מתבצעת הורדה של קובץ בשם kaggle.json.

העלאת טוקן הגישה ל-Cloud Shell

ב-Cloud Shell, מעלים את אסימון Kaggle API לפרויקט Google Cloud:

  1. ב-Cloud Shell, לוחצים על אפשרויות נוספות > העלאה.
  2. בוחרים באפשרות 'קובץ' ולוחצים על בחירת קבצים.
  3. פותחים את הקובץ kaggle.json.
  4. לוחצים על Upload.

יצירה והגדרה של Google Cloud משאבים

כדי ליצור את המשאבים הנדרשים, פועלים לפי ההוראות הבאות.

יצירת אשכול GKE ומאגר צמתים

אפשר להפעיל את Gemma במעבדים גרפיים באשכול GKE Autopilot או באשכול רגיל. מומלץ להשתמש באשכול Autopilot כדי ליהנות מחוויית Kubernetes מנוהלת באופן מלא. כדי לבחור את מצב הפעולה של GKE שהכי מתאים לעומסי העבודה שלכם, אפשר לעיין במאמר בחירת מצב פעולה של GKE.

טייס אוטומטי

ב-Cloud Shell, מריצים את הפקודה הבאה:

gcloud container clusters create-auto CLUSTER_NAME \
  --project=PROJECT_ID \
  --location=CONTROL_PLANE_LOCATION \
  --release-channel=rapid \
  --cluster-version=1.28

מחליפים את הערכים הבאים:

  • PROJECT_ID: מזהה הפרויקט ב- Google Cloud.
  • CONTROL_PLANE_LOCATION: האזור של Compute Engine במישור הבקרה של האשכול. האזור הזה צריך לתמוך בסוג המאיץ שבו רוצים להשתמש, לדוגמה, us-central1 ל-GPU מסוג L4.
  • CLUSTER_NAME: השם של האשכול.

‫GKE יוצר אשכול Autopilot עם צמתים של מעבד ו-GPU לפי הבקשה של עומסי העבודה שנפרסו.

רגילה

  1. ב-Cloud Shell, מריצים את הפקודה הבאה כדי ליצור אשכול Standard:

    gcloud container clusters create CLUSTER_NAME \
        --project=PROJECT_ID \
        --location=CONTROL_PLANE_LOCATION \
        --workload-pool=PROJECT_ID.svc.id.goog \
        --release-channel=rapid \
        --machine-type=e2-standard-4 \
        --num-nodes=1
    

    מחליפים את הערכים הבאים:

    • PROJECT_ID: מזהה הפרויקט ב- Google Cloud.
    • CONTROL_PLANE_LOCATION: האזור של Compute Engine במישור הבקרה של האשכול. האזור הזה צריך לתמוך בסוג המאיץ שבו רוצים להשתמש, לדוגמה, us-central1 ל-GPU מסוג L4.
    • CLUSTER_NAME: השם של האשכול.

    יצירת האשכול עשויה להימשך כמה דקות.

  2. מריצים את הפקודה הבאה כדי ליצור מאגר צמתים עבור האשכול:

    gcloud container node-pools create gpupool \
        --accelerator type=nvidia-l4,count=1,gpu-driver-version=latest \
        --project=PROJECT_ID \
        --location=CONTROL_PLANE_LOCATION \
        --cluster=CLUSTER_NAME \
        --machine-type=g2-standard-12 \
        --num-nodes=1
    

    ‫GKE יוצר מאגר צמתים יחיד שמכיל צומת GPU אחד מסוג L4.

יצירת Kubernetes Secret לפרטי הכניסה של Kaggle

במדריך הזה נשתמש בסוד של Kubernetes בשביל פרטי הכניסה של Kaggle.

ב-Cloud Shell, מבצעים את הפעולות הבאות:

  1. מגדירים את kubectl לתקשורת עם האשכול:

    gcloud container clusters get-credentials CLUSTER_NAME \
        --location=CONTROL_PLANE_LOCATION
    

    מחליפים את הערכים הבאים:

    • CONTROL_PLANE_LOCATION: האזור של Compute Engine במישור הבקרה של האשכול. האזור הזה צריך לתמוך בסוג המאיץ שבו רוצים להשתמש, לדוגמה, us-central1 ל-GPU מסוג L4.
    • CLUSTER_NAME: השם של האשכול.
  2. יוצרים סוד לאחסון פרטי הכניסה של Kaggle:

    kubectl create secret generic kaggle-secret \
        --from-file=kaggle.json \
        --dry-run=client -o yaml | kubectl apply -f -
    

יצירת משאב PersistentVolume לאחסון נקודות ביקורת

בקטע הזה, יוצרים PersistentVolume שמגובה על ידי דיסק אחסון מתמיד (persistent disk) כדי לאחסן את נקודות הבדיקה של המודל.

  1. יוצרים את קובץ המניפסט trtllm_checkpoint_pv.yaml הבא:

    apiVersion: v1
    kind: PersistentVolumeClaim
    metadata:
      name: model-data
    spec:
      accessModes:
      - ReadWriteOnce
      resources:
        requests:
          storage: 100G
  2. החלת המניפסט:

    kubectl apply -f trtllm_checkpoint_pv.yaml
    

הורדת קובצי המנוע של TensorRT-LLM עבור Gemma

בסעיף הזה, מריצים Kubernetes Job כדי לבצע את המשימות הבאות:

  • מורידים את קובצי המנוע של TensorRT-LLM ומאחסנים אותם ב-PersistentVolume שיצרתם קודם.
  • הכנת קובצי הגדרות לפריסת המודל בשרת Triton.

ב-Kubernetes, בקר משימות יוצר פוד אחד או יותר ועוזר לוודא שהם מבצעים משימה ספציפית בהצלחה.

התהליך הבא יכול להימשך כמה דקות.

Gemma 2B-it

מנוע TensorRT-LLM מבוסס על Gemma 2B-it (שעבר כוונון להנחיות) PyTorch checkpoint של Gemma באמצעות הפעלה של bfloat16, אורך רצף הקלט=2048, ואורך רצף הפלט=1024, עם יחידות GPU מסוג L4. אפשר לפרוס את המודל ב-GPU יחיד מסוג L4.

  1. יוצרים את קובץ המניפסט job-download-gemma-2b.yaml הבא:

    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: fetch-model-scripts
    data:
      fetch_model.sh: |-
        #!/usr/bin/bash -x
        pip install kaggle --break-system-packages && \
    
        MODEL_NAME=$(echo ${MODEL_PATH} | awk -F'/' '{print $2}') && \
        VARIATION_NAME=$(echo ${MODEL_PATH} | awk -F'/' '{print $4}') && \
        ACTIVATION_DTYPE=bfloat16 && \
    
        TOKENIZER_DIR=/data/trt_engine/${MODEL_NAME}/${VARIATION_NAME}/${ACTIVATION_DTYPE}/${WORLD_SIZE}-gpu/tokenizer.model && \
        ENGINE_PATH=/data/trt_engine/${MODEL_NAME}/${VARIATION_NAME}/${ACTIVATION_DTYPE}/${WORLD_SIZE}-gpu/ && \
        TRITON_MODEL_REPO=/data/triton/model_repository && \
    
        mkdir -p /data/${MODEL_NAME}_${VARIATION_NAME} && \
        mkdir -p ${ENGINE_PATH} && \
        mkdir -p ${TRITON_MODEL_REPO} && \
    
        kaggle models instances versions download ${MODEL_PATH} --untar -p /data/${MODEL_NAME}_${VARIATION_NAME} && \
        rm -f /data/${MODEL_NAME}_${VARIATION_NAME}/*.tar.gz && \
        find /data/${MODEL_NAME}_${VARIATION_NAME} -type f && \
        find /data/${MODEL_NAME}_${VARIATION_NAME} -type f | xargs -I '{}' mv '{}' ${ENGINE_PATH} && \
    
        # copying configuration files
        echo -e "\nCreating configuration files" && \
        cp -r /tensorrtllm_backend/all_models/inflight_batcher_llm/* ${TRITON_MODEL_REPO} && \
    
        # updating configuration files
        python3 /tensorrtllm_backend/tools/fill_template.py -i ${TRITON_MODEL_REPO}/preprocessing/config.pbtxt tokenizer_dir:${TOKENIZER_DIR},tokenizer_type:sp,triton_max_batch_size:64,preprocessing_instance_count:1 && \
        python3 /tensorrtllm_backend/tools/fill_template.py -i ${TRITON_MODEL_REPO}/postprocessing/config.pbtxt tokenizer_dir:${TOKENIZER_DIR},tokenizer_type:sp,triton_max_batch_size:64,postprocessing_instance_count:1 && \
        python3 /tensorrtllm_backend/tools/fill_template.py -i ${TRITON_MODEL_REPO}/tensorrt_llm_bls/config.pbtxt triton_max_batch_size:64,decoupled_mode:False,bls_instance_count:1,accumulate_tokens:False && \
        python3 /tensorrtllm_backend/tools/fill_template.py -i ${TRITON_MODEL_REPO}/ensemble/config.pbtxt triton_max_batch_size:64 && \
        python3 /tensorrtllm_backend/tools/fill_template.py -i ${TRITON_MODEL_REPO}/tensorrt_llm/config.pbtxt triton_max_batch_size:64,decoupled_mode:False,max_beam_width:1,engine_dir:${ENGINE_PATH},max_tokens_in_paged_kv_cache:2560,max_attention_window_size:2560,kv_cache_free_gpu_mem_fraction:0.5,exclude_input_in_output:True,enable_kv_cache_reuse:False,batching_strategy:inflight_batching,max_queue_delay_microseconds:600,batch_scheduler_policy:guaranteed_no_evict,enable_trt_overlap:False && \
    
        echo -e "\nCompleted extraction to ${ENGINE_PATH}"
    ---
    apiVersion: batch/v1
    kind: Job
    metadata:
      name: data-loader-gemma-2b
      labels:
        app: data-loader-gemma-2b
    spec:
      ttlSecondsAfterFinished: 120
      template:
        metadata:
          labels:
            app: data-loader-gemma-2b
        spec:
          restartPolicy: OnFailure
          containers:
          - name: gcloud
            image: us-docker.pkg.dev/google-samples/containers/gke/tritonserver:2.42.0
            command:
            - /scripts/fetch_model.sh
            env:
            - name: KAGGLE_CONFIG_DIR
              value: /kaggle
            - name: MODEL_PATH
              value: "google/gemma/tensorrtllm/2b-it/2"
            - name: WORLD_SIZE
              value: "1"
            volumeMounts:
            - mountPath: "/kaggle/"
              name: kaggle-credentials
              readOnly: true
            - mountPath: "/scripts/"
              name: scripts-volume
              readOnly: true
            - mountPath: "/data"
              name: data
          volumes:
          - name: kaggle-credentials
            secret:
              defaultMode: 0400
              secretName: kaggle-secret
          - name: scripts-volume
            configMap:
              defaultMode: 0700
              name: fetch-model-scripts
          - name: data
            persistentVolumeClaim:
              claimName: model-data
          tolerations:
          - key: "key"
            operator: "Exists"
            effect: "NoSchedule"
  2. החלת המניפסט:

    kubectl apply -f job-download-gemma-2b.yaml
    
  3. כדי לראות את היומנים של המשימה:

    kubectl logs -f job/data-loader-gemma-2b
    

    הפלט של היומנים אמור להיראות כך:

    ...
    Creating configuration files
    + echo -e '\n02-16-2024 04:07:45 Completed building TensortRT-LLM engine at /data/trt_engine/gemma/2b/bfloat16/1-gpu/'
    + echo -e '\nCreating configuration files'
    ...
    
  4. ממתינים לסיום העבודה:

    kubectl wait --for=condition=complete --timeout=900s job/data-loader-gemma-2b
    

    הפלט אמור להיראות כך:

    job.batch/data-loader-gemma-2b condition met
    
  5. מוודאים שהעבודה הושלמה בהצלחה (התהליך הזה עשוי להימשך כמה דקות):

    kubectl get job/data-loader-gemma-2b
    

    הפלט אמור להיראות כך:

    NAME             COMPLETIONS   DURATION   AGE
    data-loader-gemma-2b   1/1           ##s        #m##s
    

Gemma 7B-it

מנוע TensorRT-LLM מבוסס על Gemma 7B-it (הוראות מכוונות) PyTorch checkpoint של Gemma באמצעות הפעלה של bfloat16, אורך רצף הקלט=1024, ואורך רצף הפלט=512, עם יחידות GPU מסוג L4. אפשר לפרוס את המודל ב-GPU יחיד מסוג L4.

  1. יוצרים את קובץ המניפסט job-download-gemma-7b.yaml הבא:

    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: fetch-model-scripts
    data:
      fetch_model.sh: |-
        #!/usr/bin/bash -x
        pip install kaggle --break-system-packages && \
    
        MODEL_NAME=$(echo ${MODEL_PATH} | awk -F'/' '{print $2}') && \
        VARIATION_NAME=$(echo ${MODEL_PATH} | awk -F'/' '{print $4}') && \
        ACTIVATION_DTYPE=bfloat16 && \
    
        TOKENIZER_DIR=/data/trt_engine/${MODEL_NAME}/${VARIATION_NAME}/${ACTIVATION_DTYPE}/${WORLD_SIZE}-gpu/tokenizer.model && \
        ENGINE_PATH=/data/trt_engine/${MODEL_NAME}/${VARIATION_NAME}/${ACTIVATION_DTYPE}/${WORLD_SIZE}-gpu/ && \
        TRITON_MODEL_REPO=/data/triton/model_repository && \
    
        mkdir -p ${ENGINE_PATH} && \
        mkdir -p ${TRITON_MODEL_REPO} && \
    
        kaggle models instances versions download ${MODEL_PATH} --untar -p /data/${MODEL_NAME}_${VARIATION_NAME} && \
        rm -f /data/${MODEL_NAME}_${VARIATION_NAME}/*.tar.gz && \
        find /data/${MODEL_NAME}_${VARIATION_NAME} -type f && \
        find /data/${MODEL_NAME}_${VARIATION_NAME} -type f | xargs -I '{}' mv '{}' ${ENGINE_PATH} && \
    
        # copying configuration files
        echo -e "\nCreating configuration files" && \
        cp -r /tensorrtllm_backend/all_models/inflight_batcher_llm/* ${TRITON_MODEL_REPO} && \
    
        # updating configuration files
        python3 /tensorrtllm_backend/tools/fill_template.py -i ${TRITON_MODEL_REPO}/preprocessing/config.pbtxt tokenizer_dir:${TOKENIZER_DIR},tokenizer_type:sp,triton_max_batch_size:64,preprocessing_instance_count:1 && \
        python3 /tensorrtllm_backend/tools/fill_template.py -i ${TRITON_MODEL_REPO}/postprocessing/config.pbtxt tokenizer_dir:${TOKENIZER_DIR},tokenizer_type:sp,triton_max_batch_size:64,postprocessing_instance_count:1 && \
        python3 /tensorrtllm_backend/tools/fill_template.py -i ${TRITON_MODEL_REPO}/tensorrt_llm_bls/config.pbtxt triton_max_batch_size:64,decoupled_mode:False,bls_instance_count:1,accumulate_tokens:False && \
        python3 /tensorrtllm_backend/tools/fill_template.py -i ${TRITON_MODEL_REPO}/ensemble/config.pbtxt triton_max_batch_size:64 && \
        python3 /tensorrtllm_backend/tools/fill_template.py -i ${TRITON_MODEL_REPO}/tensorrt_llm/config.pbtxt triton_max_batch_size:64,decoupled_mode:False,max_beam_width:1,engine_dir:${ENGINE_PATH},max_tokens_in_paged_kv_cache:2560,max_attention_window_size:2560,kv_cache_free_gpu_mem_fraction:0.5,exclude_input_in_output:True,enable_kv_cache_reuse:False,batching_strategy:inflight_batching,max_queue_delay_microseconds:600,batch_scheduler_policy:guaranteed_no_evict,enable_trt_overlap:False && \
    
        echo -e "\nCompleted extraction to ${ENGINE_PATH}"
    ---
    apiVersion: batch/v1
    kind: Job
    metadata:
      name: data-loader-gemma-7b
      labels:
        app: data-loader-gemma-7b
    spec:
      ttlSecondsAfterFinished: 120
      template:
        metadata:
          labels:
            app: data-loader-gemma-7b
        spec:
          restartPolicy: OnFailure
          containers:
          - name: gcloud
            image: us-docker.pkg.dev/google-samples/containers/gke/tritonserver:2.42.0
            command:
            - /scripts/fetch_model.sh
            env:
            - name: KAGGLE_CONFIG_DIR
              value: /kaggle
            - name: MODEL_PATH
              value: "google/gemma/tensorrtllm/7b-it/2"
            - name: WORLD_SIZE
              value: "1"
            volumeMounts:
            - mountPath: "/kaggle/"
              name: kaggle-credentials
              readOnly: true
            - mountPath: "/scripts/"
              name: scripts-volume
              readOnly: true
            - mountPath: "/data"
              name: data
          volumes:
          - name: kaggle-credentials
            secret:
              defaultMode: 0400
              secretName: kaggle-secret
          - name: scripts-volume
            configMap:
              defaultMode: 0700
              name: fetch-model-scripts
          - name: data
            persistentVolumeClaim:
              claimName: model-data
          tolerations:
          - key: "key"
            operator: "Exists"
            effect: "NoSchedule"
  2. החלת המניפסט:

    kubectl apply -f job-download-gemma-7b.yaml
    
  3. כדי לראות את היומנים של המשימה:

    kubectl logs -f job/data-loader-gemma-7b
    

    הפלט של היומנים אמור להיראות כך:

    ...
    Creating configuration files
    + echo -e '\n02-16-2024 04:07:45 Completed building TensortRT-LLM engine at /data/trt_engine/gemma/7b/bfloat16/1-gpu/'
    + echo -e '\nCreating configuration files'
    ...
    
  4. ממתינים לסיום העבודה:

    kubectl wait --for=condition=complete --timeout=900s job/data-loader-gemma-7b
    

    הפלט אמור להיראות כך:

    job.batch/data-loader-gemma-7b condition met
    
  5. מוודאים שהעבודה הושלמה בהצלחה (התהליך הזה עשוי להימשך כמה דקות):

    kubectl get job/data-loader-gemma-7b
    

    הפלט אמור להיראות כך:

    NAME             COMPLETIONS   DURATION   AGE
    data-loader-gemma-7b   1/1           ##s        #m##s
    

לפני שממשיכים לקטע הבא, מוודאים שהעבודה הושלמה בהצלחה.

פריסת Triton

בקטע הזה פורסים קונטיינר שמשתמש ב-Triton עם TensorRT-LLM בק-אנד כדי להכניס לשימוש בסביבת הייצור את מודל Gemma שרוצים להשתמש בו.

  1. יוצרים את קובץ המניפסט deploy-triton-server.yaml הבא:

    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: launch-tritonserver
    data:
      entrypoint.sh: |-
        #!/usr/bin/bash -x
        # Launch Triton Inference server
    
        WORLD_SIZE=1
        TRITON_MODEL_REPO=/data/triton/model_repository
    
        python3 /tensorrtllm_backend/scripts/launch_triton_server.py \
          --world_size ${WORLD_SIZE} \
          --model_repo ${TRITON_MODEL_REPO}
    
        tail -f /dev/null
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: triton-gemma-deployment
      labels:
        app: gemma-server
        version: v1 
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: gemma-server 
          version: v1
      template:
        metadata:
          labels:
            app: gemma-server
            ai.gke.io/model: gemma
            ai.gke.io/inference-server: triton
            examples.ai.gke.io/source: user-guide
            version: v1
        spec:
          containers:
          - name: inference-server 
            image: us-docker.pkg.dev/google-samples/containers/gke/tritonserver:2.42.0
            imagePullPolicy: IfNotPresent
            resources:
              requests:
                ephemeral-storage: "40Gi"
                memory: "40Gi"
                nvidia.com/gpu: 1
              limits:
                ephemeral-storage: "40Gi"
                memory: "40Gi"
                nvidia.com/gpu: 1
            command:
            - /scripts/entrypoint.sh
            volumeMounts:
            - mountPath: "/scripts/"
              name: scripts-volume
              readOnly: true
            - mountPath: "/data"
              name: data
            ports:
              - containerPort: 8000
                name: http
              - containerPort: 8001
                name: grpc
              - containerPort: 8002
                name: metrics
            livenessProbe:
              failureThreshold: 60
              initialDelaySeconds: 600
              periodSeconds: 5
              httpGet:
                path: /v2/health/live
                port: http
            readinessProbe:
              failureThreshold: 60
              initialDelaySeconds: 600
              periodSeconds: 5
              httpGet:
                path: /v2/health/ready
                port: http
          securityContext:
            runAsUser: 1000
            fsGroup: 1000
          volumes:
          - name: scripts-volume
            configMap:
              defaultMode: 0700
              name: launch-tritonserver
          - name: data
            persistentVolumeClaim:
              claimName: model-data
          nodeSelector:
            cloud.google.com/gke-accelerator: nvidia-l4
          tolerations:
          - key: "key"
            operator: "Exists"
            effect: "NoSchedule"
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: triton-server
      labels:
        app: gemma-server 
    spec:
      type: ClusterIP
      ports:
        - port: 8000
          targetPort: http
          name: http-inference-server
        - port: 8001
          targetPort: grpc
          name: grpc-inference-server
        - port: 8002
          targetPort: metrics
          name: http-metrics
      selector:
        app: gemma-server
  2. החלת המניפסט:

    kubectl apply -f deploy-triton-server.yaml
    
  3. מחכים שהפריסה תהיה זמינה:

    kubectl wait --for=condition=Available --timeout=900s deployment/triton-gemma-deployment
    
  4. צפייה ביומנים מהמניפסט:

    kubectl logs -f -l app=gemma-server
    

    משאב הפריסה מפעיל את שרת Triton וטוען את נתוני המודל. התהליך הזה יכול להימשך כמה דקות (עד 20 דקות או יותר). הפלט אמור להיראות כך:

    I0216 03:24:57.387420 29 server.cc:676]
    +------------------+---------+--------+
    | Model            | Version | Status |
    +------------------+---------+--------+
    | ensemble         | 1       | READY  |
    | postprocessing   | 1       | READY  |
    | preprocessing    | 1       | READY  |
    | tensorrt_llm     | 1       | READY  |
    | tensorrt_llm_bls | 1       | READY  |
    +------------------+---------+--------+
    
    ....
    ....
    ....
    
    I0216 03:24:57.425104 29 grpc_server.cc:2519] Started GRPCInferenceService at 0.0.0.0:8001
    I0216 03:24:57.425418 29 http_server.cc:4623] Started HTTPService at 0.0.0.0:8000
    I0216 03:24:57.466646 29 http_server.cc:315] Started Metrics Service at 0.0.0.0:8002
    

פרסום המודל

בקטע הזה אתם מנהלים אינטראקציה עם המודל.

הגדרת העברה ליציאה אחרת

מריצים את הפקודה הבאה כדי להגדיר העברת נתונים (פורט פורוורדינג) למודל:

kubectl port-forward service/triton-server 8000:8000

הפלט אמור להיראות כך:

Forwarding from 127.0.0.1:8000 -> 8000
Forwarding from [::1]:8000 -> 8000
Handling connection for 8000

אינטראקציה עם המודל באמצעות curl

בקטע הזה מוסבר איך לבצע בדיקת עשן בסיסית כדי לוודא שהמודל שהותאם להוראות נפרס. כדי לפשט את הדברים, בקטע הזה מתוארת גישת הבדיקה רק באמצעות מודל מכוונן עם 2 מיליארד פרמטרים.

בסשן חדש של מסוף, משתמשים ב-curl כדי לשוחח עם המודל:

USER_PROMPT="I'm new to coding. If you could only recommend one programming language to start with, what would it be and why?"

curl -X POST localhost:8000/v2/models/ensemble/generate \
  -H "Content-Type: application/json" \
  -d @- <<EOF
{
    "text_input": "<start_of_turn>user\n${USER_PROMPT}<end_of_turn>\n",
    "temperature": 0.9,
    "max_tokens": 128
}
EOF

בדוגמה הבאה אפשר לראות את התשובה של המודל:

{
  "context_logits": 0,
  "cum_log_probs": 0,
  "generation_logits": 0,
  "model_name": "ensemble",
  "model_version": "1",
  "output_log_probs": [0.0,0.0,...],
  "sequence_end": false,
  "sequence_id": 0,
  "sequence_start": false,
  "text_output":"Python.\n\nPython is an excellent choice for beginners due to its simplicity, readability, and extensive documentation. Its syntax is close to natural language, making it easier for beginners to understand and write code. Python also has a vast collection of libraries and tools that make it versatile for various projects. Additionally, Python's dynamic nature allows for easier learning and experimentation, making it a perfect choice for newcomers to get started.Here are some specific reasons why Python is a good choice for beginners:\n\n- Simple and Easy to Read: Python's syntax is designed to be close to natural language, making it easier for"
}

פתרון בעיות

הסרת המשאבים

כדי להימנע מחיובים בחשבון Google Cloud בגלל השימוש במשאבים שנעשה במסגרת המדריך הזה, אפשר למחוק את הפרויקט שמכיל את המשאבים, או להשאיר את הפרויקט ולמחוק את המשאבים בנפרד.

מחיקת המשאבים שנפרסו

כדי להימנע מחיובים בחשבון Google Cloud על המשאבים שיצרתם במדריך הזה, מריצים את הפקודה הבאה:

gcloud container clusters delete CLUSTER_NAME \
    --location=CONTROL_PLANE_LOCATION

המאמרים הבאים