نحوه میزبانی LLM در سایدکار برای عملکرد Cloud Run

نحوه میزبانی LLM در سایدکار برای عملکرد Cloud Run

درباره این codelab

subjectآخرین به‌روزرسانی: مارس ۲۷, ۲۰۲۵
account_circleنویسنده: یکی از کارمندان Google

1. مقدمه

در این کد لبه، شما یاد خواهید گرفت که چگونه یک مدل gemma3:4b را در یک سایدکار برای عملکرد Cloud Run میزبانی کنید. هنگامی که یک فایل در یک سطل ذخیره سازی ابری آپلود می شود، عملکرد Cloud Run را فعال می کند. تابع محتویات فایل را برای خلاصه سازی به Gemma 3 در sidecar ارسال می کند.

  • نحوه استنتاج با استفاده از تابع Cloud Run و LLM میزبانی شده در سایدکار با استفاده از پردازنده گرافیکی
  • نحوه استفاده از پیکربندی خروجی Direct VPC برای یک GPU Cloud Run برای آپلود و ارائه سریعتر مدل
  • نحوه استفاده از genkit برای رابط با مدل اوللامای میزبانی شده خود

2. قبل از شروع

برای استفاده از ویژگی GPU، باید درخواست افزایش سهمیه برای یک منطقه پشتیبانی شده کنید. سهمیه مورد نیاز nvidia_l4_gpu_allocation_no_zonal_redundancy است که تحت Cloud Run Admin API است. این لینک مستقیم برای درخواست سهمیه است.

3. راه اندازی و الزامات

متغیرهای محیطی را تنظیم کنید که در سراسر این کد لبه مورد استفاده قرار خواهند گرفت.

PROJECT_ID=<YOUR_PROJECT_ID>
REGION
=<YOUR_REGION>

AR_REPO
=codelab-crf-sidecar-gpu
FUNCTION_NAME
=crf-sidecar-gpu
BUCKET_GEMMA_NAME
=$PROJECT_ID-codelab-crf-sidecar-gpu-gemma3
BUCKET_DOCS_NAME
=$PROJECT_ID-codelab-crf-sidecar-gpu-docs
SERVICE_ACCOUNT
="crf-sidecar-gpu"
SERVICE_ACCOUNT_ADDRESS
=$SERVICE_ACCOUNT@$PROJECT_ID.iam.gserviceaccount.com
IMAGE_SIDECAR
=$REGION-docker.pkg.dev/$PROJECT_ID/$AR_REPO/ollama-gemma3

با اجرای این دستور اکانت سرویس ایجاد کنید:

gcloud iam service-accounts create $SERVICE_ACCOUNT \
 
--display-name="SA for codelab crf sidecar with gpu"

ما از همین حساب سرویس که به عنوان هویت تابع Cloud Run استفاده می شود، به عنوان حساب سرویس برای محرک eventtarc برای فراخوانی تابع Cloud Run استفاده می کنیم. در صورت تمایل می توانید SA متفاوتی برای Eventarc ایجاد کنید.

gcloud projects add-iam-policy-binding $PROJECT_ID \
   
--member=serviceAccount:$SERVICE_ACCOUNT_ADDRESS \
   
--role=roles/run.invoker

همچنین به حساب سرویس برای دریافت رویدادهای Eventarc دسترسی بدهید.

gcloud projects add-iam-policy-binding $PROJECT_ID \
   
--member="serviceAccount:$SERVICE_ACCOUNT_ADDRESS" \
   
--role="roles/eventarc.eventReceiver"

سطلی ایجاد کنید که میزبان مدل دقیق شما باشد. این کد لبه از یک سطل منطقه ای استفاده می کند. می توانید از یک سطل چند منطقه ای نیز استفاده کنید.

gsutil mb -l $REGION gs://$BUCKET_GEMMA_NAME

و سپس به SA دسترسی به سطل بدهید.

gcloud storage buckets add-iam-policy-binding gs://$BUCKET_GEMMA_NAME \
--member=serviceAccount:$SERVICE_ACCOUNT_ADDRESS \
--role=roles/storage.objectAdmin

اکنون یک سطل منطقه ای ایجاد کنید که اسنادی را که می خواهید به طور خلاصه ذخیره کنید. می‌توانید از یک سطل چند منطقه‌ای نیز استفاده کنید، مشروط بر اینکه ماشه Eventarc را بر اساس آن به‌روزرسانی کنید (در انتهای این کد لبه نشان داده شده است).

gsutil mb -l $REGION gs://$BUCKET_DOCS_NAME

و سپس به SA دسترسی به سطل Gemma 3 بدهید.

gcloud storage buckets add-iam-policy-binding gs://$BUCKET_GEMMA_NAME \
--member=serviceAccount:$SERVICE_ACCOUNT_ADDRESS \
--role=roles/storage.objectAdmin

و سطل Docs.

gcloud storage buckets add-iam-policy-binding gs://$BUCKET_DOCS_NAME \
--member=serviceAccount:$SERVICE_ACCOUNT_ADDRESS \
--role=roles/storage.objectAdmin

یک مخزن رجیستری مصنوع برای تصویر اوللاما ایجاد کنید که در سایدکار استفاده خواهد شد.

gcloud artifacts repositories create $AR_REPO \
   
--repository-format=docker \
   
--location=$REGION \
   
--description="codelab for CR function and gpu sidecar" \
   
--project=$PROJECT_ID

4. دانلود مدل جما 3

ابتدا می‌خواهید مدل Gemma 3 4b را از olama دانلود کنید. می توانید این کار را با نصب olama و سپس اجرای مدل gemma3:4b به صورت محلی انجام دهید.

curl -fsSL https://ollama.com/install.sh | sh
ollama serve

اکنون در یک پنجره ترمینال جداگانه، دستور زیر را اجرا کنید تا مدل پایین بیاید. اگر از Cloud Shell استفاده می‌کنید، می‌توانید یک پنجره ترمینال اضافی را با کلیک کردن روی نماد مثبت در نوار منوی بالا سمت راست باز کنید.

ollama run gemma3:4b

هنگامی که olama در حال اجرا است، به راحتی از مدل چند سوال بپرسید، به عنوان مثال

"why is the sky blue?"

پس از اتمام چت با olama، می توانید با اجرا از چت خارج شوید

/bye

سپس در اولین پنجره ترمینال دستور زیر را اجرا کنید تا سرویس olama به صورت محلی متوقف شود

# on Linux / Cloud Shell press Ctrl^C or equivalent for your shell

می‌توانید مکان‌هایی که Olama مدل‌ها را بسته به سیستم عامل خود دانلود می‌کند را در اینجا بیابید.

https://github.com/ollama/ollama/blob/main/docs/faq.md#where-are-models-stored

اگر از ایستگاه‌های کاری ابری استفاده می‌کنید، می‌توانید مدل‌های اوللاما را که از اینجا دانلود شده‌اند پیدا کنید /home/$USER/.ollama/models

تأیید کنید که مدل‌های شما در اینجا میزبانی می‌شوند:

ls /home/$USER/.ollama/models

اکنون مدل gemma3:4b را به سطل GCS خود منتقل کنید

gsutil cp -r /home/$USER/.ollama/models gs://$BUCKET_GEMMA_NAME

5. تابع Cloud Run را ایجاد کنید

یک پوشه ریشه برای کد منبع خود ایجاد کنید.

mkdir codelab-crf-sidecar-gpu &&
cd codelab
-crf-sidecar-gpu &&
mkdir cr
-function &&
mkdir ollama
-gemma3 &&
cd cr
-function

یک زیر پوشه به نام src ایجاد کنید. در داخل پوشه، فایلی به نام index.ts ایجاد کنید

mkdir src &&
touch src
/index.ts

index.ts را با کد زیر به روز کنید:

//import util from 'util';
import { cloudEvent, CloudEvent } from "@google-cloud/functions-framework";
import { StorageObjectData } from "@google/events/cloud/storage/v1/StorageObjectData";
import { Storage } from "@google-cloud/storage";

// Initialize the Cloud Storage client
const storage = new Storage();

import { genkit } from 'genkit';
import { ollama } from 'genkitx-ollama';

const ai = genkit({
   
plugins: [
       
ollama({
           
models: [
               
{
                   
name: 'gemma3:4b',
                   
type: 'generate', // type: 'chat' | 'generate' | undefined
               
},
           
],
           
serverAddress: 'http://127.0.0.1:11434', // default local address
       
}),
   
],
});


// Register a CloudEvent callback with the Functions Framework that will
// be triggered by Cloud Storage.

//functions.cloudEvent('helloGCS', await cloudEvent => {
cloudEvent("gcs-cloudevent", async (cloudevent: CloudEvent<StorageObjectData>) => {
   
console.log("---------------\nProcessing for ", cloudevent.subject, "\n---------------");

   
if (cloudevent.data) {

       
const data = cloudevent.data;

       
if (data && data.bucket && data.name) {
           
const bucketName = cloudevent.data.bucket;
           
const fileName = cloudevent.data.name;
           
const filePath = `${cloudevent.data.bucket}/${cloudevent.data.name}`;

           
console.log(`Attempting to download: ${filePath}`);

           
try {
               
// Get a reference to the bucket
               
const bucket = storage.bucket(bucketName!);

               
// Get a reference to the file
               
const file = bucket.file(fileName!);

               
// Download the file's contents
               
const [content] = await file.download();

               
// 'content' is a Buffer. Convert it to a string.
               
const fileContent = content.toString('utf8');

               
console.log(`Sending file to Gemma 3 for summarization`);
               
const { text } = await ai.generate({
                   
model: 'ollama/gemma3:4b',
                   
prompt: `Summarize the following document in just a few sentences ${fileContent}`,
               
});

               
console.log(text);

           
} catch (error: any) {

               
console.error('An error occurred:', error.message);
           
}
       
} else {
           
console.warn("CloudEvent bucket name is missing!", cloudevent);
       
}
   
} else {
       
console.warn("CloudEvent data is missing!", cloudevent);
   
}
});

اکنون در دایرکتوری root crf-sidecar-gpu یک فایل به نام package.json با محتویات زیر ایجاد کنید:

{
    "main": "lib/index.js",
    "name": "ingress-crf-genkit",
    "version": "1.0.0",
    "scripts": {
        "build": "tsc"
    },
    "keywords": [],
    "author": "",
    "license": "ISC",
    "description": "",
    "dependencies": {
        "@google-cloud/functions-framework": "^3.4.0",
        "@google-cloud/storage": "^7.0.0",
        "genkit": "^1.1.0",
        "genkitx-ollama": "^1.1.0",
        "@google/events": "^5.4.0"
    },
    "devDependencies": {
        "typescript": "^5.5.2"
    }
}

یک tsconfig.json نیز در سطح دایرکتوری ریشه با محتوای زیر ایجاد کنید:

{
 
"compileOnSave": true,
 
"include": [
   
"src"
 
],
 
"compilerOptions": {
   
"module": "commonjs",
   
"noImplicitReturns": true,
   
"outDir": "lib",
   
"sourceMap": true,
   
"strict": true,
   
"target": "es2017",
   
"skipLibCheck": true,
   
"esModuleInterop": true
 
}
}

6. تابع را مستقر کنید

در این مرحله، تابع Cloud Run را با اجرای دستور زیر اجرا می‌کنید.

توجه: حداکثر نمونه‌ها باید روی عددی کمتر یا مساوی سهمیه GPU شما تنظیم شوند.

gcloud beta run deploy $FUNCTION_NAME \
  --region $REGION \
  --function gcs-cloudevent \
  --base-image nodejs22 \
  --source . \
  --no-allow-unauthenticated \
  --max-instances 2 # this should be less than or equal to your GPU quota

7. چرخ کناری را ایجاد کنید

می‌توانید در https://cloud.google.com/run/docs/tutorials/gpu-gemma-with-ollama درباره میزبانی Ollama در یک سرویس Cloud Run اطلاعات بیشتری کسب کنید.

به دایرکتوری مربوط به ماشین کناری خود بروید:

cd ../ollama-gemma3

یک فایل Dockerfile با محتویات زیر ایجاد کنید:

FROM ollama/ollama:latest

# Listen on all interfaces, port 11434
ENV OLLAMA_HOST 0.0.0.0:11434

# Store model weight files in /models
ENV OLLAMA_MODELS /models

# Reduce logging verbosity
ENV OLLAMA_DEBUG false

# Never unload model weights from the GPU
ENV OLLAMA_KEEP_ALIVE -1

# Store the model weights in the container image
ENV MODEL gemma3:4b
RUN ollama serve & sleep 5 && ollama pull $MODEL

# Start Ollama
ENTRYPOINT ["ollama", "serve"]

تصویر را بسازید

gcloud builds submit \
   --tag $REGION-docker.pkg.dev/$PROJECT_ID/$AR_REPO/ollama-gemma3 \
   --machine-type e2-highcpu-32

8. عملکرد را با سایدکار به روز کنید

برای افزودن یک سایدکار به یک سرویس، کار یا عملکرد موجود، می‌توانید فایل YAML را به‌روزرسانی کنید تا شامل سایدکار باشد.

YAML را برای تابع Cloud Run که به تازگی با اجرای آن اجرا کرده اید، بازیابی کنید:

gcloud run services describe $FUNCTION_NAME --format=export > add-sidecar-service.yaml

اکنون با به‌روزرسانی YAML به صورت زیر، سایدکار را به CRf اضافه کنید:

  1. قطعه YAML زیر را مستقیماً بالای runtimeClassName: run.googleapis.com/linux-base-image-update خط. تصویر -image با آیتم کانتینر ورودی -image هماهنگ باشد
    - image: YOUR_IMAGE_SIDECAR:latest
        name
: gemma-sidecar
        env
:
       
- name: OLLAMA_FLASH_ATTENTION
          value
: '1'
        resources
:
          limits
:
            cpu
: 6000m
            nvidia
.com/gpu: '1'
            memory
: 16Gi
        volumeMounts
:
       
- name: gcs-1
          mountPath
: /root/.ollama
        startupProbe
:
          failureThreshold
: 2
          httpGet
:
            path
: /
            port: 11434
          initialDelaySeconds: 60
          periodSeconds: 60
          timeoutSeconds: 60
      nodeSelector:
        run.googleapis.com/
accelerator: nvidia-l4
      volumes
:
       
- csi:
            driver
: gcsfuse.run.googleapis.com
            volumeAttributes
:
              bucketName
: YOUR_BUCKET_GEMMA_NAME
          name
: gcs-1
  1. دستور زیر را برای به روز رسانی قطعه YAML با متغیرهای محیط خود اجرا کنید:
sed -i "s|YOUR_IMAGE_SIDECAR|$IMAGE_SIDECAR|; s|YOUR_BUCKET_GEMMA_NAME|$BUCKET_GEMMA_NAME|" add-sidecar-service.yaml

فایل YAML تکمیل شده شما باید چیزی شبیه به این باشد:

##############################################
# DO NOT COPY - For illustration purposes only
##############################################

apiVersion
: serving.knative.dev/v1
kind
: Service
metadata
:
  annotations
:    
    run
.googleapis.com/build-base-image: us-central1-docker.pkg.dev/serverless-runtimes/google-22/runtimes/nodejs22
    run
.googleapis.com/build-enable-automatic-updates: 'true'
    run
.googleapis.com/build-function-target: gcs-cloudevent
    run
.googleapis.com/build-id: f0122905-a556-4000-ace4-5c004a9f9ec6
    run
.googleapis.com/build-image-uri:<YOUR_IMAGE_CRF>
    run
.googleapis.com/build-name: <YOUR_BUILD_NAME>
    run
.googleapis.com/build-source-location: <YOUR_SOURCE_LOCATION>
    run
.googleapis.com/ingress: all
    run
.googleapis.com/ingress-status: all
    run
.googleapis.com/urls: '["<YOUR_CLOUD_RUN_FUNCTION_URLS"]'
  labels
:
    cloud
.googleapis.com/location: <YOUR_REGION>
  name
: <YOUR_FUNCTION_NAME>
 
namespace: '392295011265'
spec
:
 
template:
    metadata
:
      annotations
:
        autoscaling
.knative.dev/maxScale: '4'
        run
.googleapis.com/base-images: '{"":"us-central1-docker.pkg.dev/serverless-runtimes/google-22/runtimes/nodejs22"}'
        run
.googleapis.com/client-name: gcloud
        run
.googleapis.com/client-version: 514.0.0
        run
.googleapis.com/startup-cpu-boost: 'true'
      labels
:
        client
.knative.dev/nonce: hzhhrhheyd
        run
.googleapis.com/startupProbeType: Default
    spec
:
      containerConcurrency
: 80
      containers
:
     
- image: <YOUR_FUNCTION_IMAGE>
        ports
:
       
- containerPort: 8080
          name
: http1
        resources
:
          limits
:
            cpu
: 1000m
            memory
: 512Mi
        startupProbe
:
          failureThreshold
: 1
          periodSeconds
: 240
          tcpSocket
:
            port
: 8080
          timeoutSeconds
: 240
     
- image: <YOUR_SIDECAR_IMAGE>:latest
        name
: gemma-sidecar
        env
:
       
- name: OLLAMA_FLASH_ATTENTION
          value
: '1'
        resources
:
          limits
:
            cpu
: 6000m
            nvidia
.com/gpu: '1'
            memory
: 16Gi
        volumeMounts
:
       
- name: gcs-1
          mountPath
: /root/.ollama
        startupProbe
:
          failureThreshold
: 2
          httpGet
:
            path
: /
            port: 11434
          initialDelaySeconds: 60
          periodSeconds: 60
          timeoutSeconds: 60
      nodeSelector:
        run.googleapis.com/
accelerator: nvidia-l4
      volumes
:
       
- csi:
            driver
: gcsfuse.run.googleapis.com
            volumeAttributes
:
              bucketName
: <YOUR_BUCKET_NAME>
          name
: gcs-1
      runtimeClassName
: run.googleapis.com/linux-base-image-update
      serviceAccountName
: <YOUR_SA_ADDRESS>
      timeoutSeconds
: 300
  traffic
:
 
- latestRevision: true
    percent
: 100

##############################################
# DO NOT COPY - For illustration purposes only
##############################################

حالا با اجرای دستور زیر تابع را با sidecar به روز کنید.

gcloud run services replace add-sidecar-service.yaml

در نهایت، ماشه eventtarc را برای تابع ایجاد کنید. این دستور همچنین آن را به تابع اضافه می کند.

توجه: اگر یک سطل چند منطقه ای ایجاد کرده اید، می خواهید پارامتر --location تغییر دهید

gcloud eventarc triggers create my-crf-summary-trigger  \
    --location=$REGION \
    --destination-run-service=$FUNCTION_NAME  \
    --destination-run-region=$REGION \
    --event-filters="type=google.cloud.storage.object.v1.finalized" \
    --event-filters="bucket=$BUCKET_DOCS_NAME" \
    --service-account=$SERVICE_ACCOUNT_ADDRESS

9. عملکرد خود را تست کنید

یک فایل متنی ساده برای خلاصه سازی آپلود کنید. نمی دانید چه چیزی را خلاصه کنید؟ از Gemini بخواهید یک توضیح سریع 1-2 صفحه ای از تاریخچه سگ ها را ارائه دهد! سپس آن فایل متنی ساده را در سطل $BUCKET_DOCS_NAME خود برای مدل Gemma3:4b آپلود کنید تا خلاصه‌ای از گزارش‌های عملکرد بنویسید.

در گزارش‌ها، چیزی شبیه به زیر خواهید دید:

---------------
Processing for objects/dogs.txt
---------------
Attempting to download: <YOUR_PROJECT_ID>-codelab-crf-sidecar-gpu-docs/dogs.txt
Sending file to Gemma 3 for summarization
...
Here's a concise summary of the document "Humanity's Best Friend":
The dog's domestication, beginning roughly 20,000-40,000 years ago, represents a unique, deeply intertwined evolutionary partnership with humans, predating the domestication of any other animal
<
...>
solidifying their long-standing role as humanity's best friend.

10. عیب یابی

در اینجا برخی از خطاهای غلط املایی وجود دارد که ممکن است با آنها روبرو شوید:

  1. اگر خطایی دریافت کردید که PORT 8080 is in use ، مطمئن شوید که Dockerfile برای Ollama sidecar شما از پورت 11434 استفاده می کند. همچنین مطمئن شوید که در صورتی که چندین تصویر Ollama در مخزن AR خود دارید، از تصویر sidecar درست استفاده می کنید. عملکرد Cloud Run در پورت 8080 کار می کند، و اگر از تصویر Ollama دیگری به عنوان سایدکار که در 8080 نیز استفاده می شود استفاده کرده باشید، با این خطا مواجه خواهید شد.
  2. اگر خطای failed to build: (error ID: 7485c5b6): function.js does not exist ، مطمئن شوید که فایل های package.json و tsconfig.json شما در همان سطح دایرکتوری src هستند.
  3. اگر خطا دریافت کردید ERROR: (gcloud.run.services.replace) spec.template.spec.node_selector: Max instances must be set to 4 or fewer in order to set GPU requirements. ، در فایل YAML خود، autoscaling.knative.dev/maxScale: '100' را به 1 یا به چیزی کمتر یا مساوی سهمیه GPU خود تغییر دهید.