۱. مقدمه
نمای کلی
در این آزمایشگاه کد، یاد خواهید گرفت که چگونه یک مدل gemma3:4b را در یک محفظه کناری برای تابع Cloud Run میزبانی کنید. وقتی یک فایل در یک مخزن ذخیرهسازی ابری آپلود میشود، تابع Cloud Run را فعال میکند. این تابع محتویات فایل را برای خلاصهسازی به Gemma 3 در محفظه کناری ارسال میکند.
آنچه یاد خواهید گرفت
- چگونه با استفاده از یک تابع Cloud Run و یک LLM که در یک ماشین کناری با استفاده از GPU ها میزبانی شده است، استنتاج انجام دهیم؟
- نحوه استفاده از پیکربندی خروجی مستقیم VPC برای یک پردازنده گرافیکی Cloud Run برای آپلود و سرویسدهی سریعتر مدل
- نحوه استفاده از genkit برای ارتباط با مدل ollama میزبانی شده شما
۲. قبل از شروع
برای استفاده از ویژگی GPUها، باید برای یک منطقه پشتیبانیشده درخواست افزایش سهمیه دهید. سهمیه مورد نیاز nvidia_l4_gpu_allocation_no_zonal_redundancy است که تحت API Cloud Run Admin قرار دارد. در اینجا لینک مستقیم درخواست سهمیه آمده است.
۳. تنظیمات و الزامات
متغیرهای محیطی که در سراسر این آزمایشگاه کد استفاده خواهند شد را تنظیم کنید.
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 استفاده میشود، به عنوان حساب سرویس برای تریگر eventarc جهت فراخوانی تابع 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"
یک سطل (bucket) ایجاد کنید که میزبان مدل تنظیمشدهی دقیق شما باشد. این آزمایشگاه کد از یک سطل منطقهای استفاده میکند. شما میتوانید از یک سطل چند منطقهای نیز استفاده کنید.
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
و سطل اسناد.
gcloud storage buckets add-iam-policy-binding gs://$BUCKET_DOCS_NAME \
--member=serviceAccount:$SERVICE_ACCOUNT_ADDRESS \
--role=roles/storage.objectAdmin
یک مخزن رجیستری مصنوعات برای تصویر Ollama ایجاد کنید که در محفظه بار جانبی استفاده خواهد شد.
gcloud artifacts repositories create $AR_REPO \
--repository-format=docker \
--location=$REGION \
--description="codelab for CR function and gpu sidecar" \
--project=$PROJECT_ID
۴. مدل Gemma 3 را دانلود کنید
ابتدا، باید مدل Gemma 3 4b را از ollama دانلود کنید. میتوانید این کار را با نصب ollama و سپس اجرای مدل gemma3:4b به صورت محلی انجام دهید.
curl -fsSL https://ollama.com/install.sh | sh
ollama serve
اکنون در یک پنجره ترمینال جداگانه، دستور زیر را برای نمایش مدل اجرا کنید. اگر از Cloud Shell استفاده میکنید، میتوانید با کلیک روی نماد به علاوه در نوار منوی بالا سمت راست، یک پنجره ترمینال اضافی باز کنید.
ollama run gemma3:4b
وقتی اولاما اجرا شد، میتوانید از مدل چند سوال بپرسید، مثلاً
"why is the sky blue?"
وقتی چت کردن با ollama تمام شد، میتوانید با اجرای دستور زیر از چت خارج شوید.
/bye
سپس، در اولین پنجره ترمینال، دستور زیر را اجرا کنید تا سرویس ollama به صورت محلی متوقف شود.
# on Linux / Cloud Shell press Ctrl^C or equivalent for your shell
میتوانید محل دانلود مدلها توسط Ollama را بسته به سیستم عامل خود، اینجا پیدا کنید.
https://github.com/ollama/ollama/blob/main/docs/faq.md#where-are-models-stored
اگر از Cloud Workstations استفاده میکنید، میتوانید مدلهای ollama دانلود شده را در اینجا پیدا کنید /home/$USER/.ollama/models
تأیید کنید که مدلهای شما در اینجا میزبانی میشوند:
ls /home/$USER/.ollama/models
حالا مدل gemma3:4b را به سطل GCS خود منتقل کنید
gsutil cp -r /home/$USER/.ollama/models gs://$BUCKET_GEMMA_NAME
۵. تابع 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);
}
});
اکنون در دایرکتوری ریشه 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
}
}
۶. تابع را مستقر کنید
در این مرحله، با اجرای دستور زیر، تابع 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
۷. اتاقک کناری را ایجاد کنید
میتوانید اطلاعات بیشتری در مورد میزبانی Ollama در یک سرویس Cloud Run را در آدرس https://cloud.google.com/run/docs/tutorials/gpu-gemma-with-ollama کسب کنید.
به دایرکتوری مربوط به محفظه بار جانبی خود بروید:
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
۸. تابع را با sidecar بهروزرسانی کنید
برای افزودن یک sidecar به یک سرویس، کار یا تابع موجود، میتوانید فایل YAML را بهروزرسانی کنید تا sidecar را در خود جای دهد.
با اجرای دستور زیر، فایل YAML مربوط به تابع Cloud Run که به تازگی مستقر کردهاید را بازیابی کنید:
gcloud run services describe $FUNCTION_NAME --format=export > add-sidecar-service.yaml
حالا با بهروزرسانی YAML به صورت زیر، sidecar را به CRf اضافه کنید:
- قطعه کد 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
- دستور زیر را برای بهروزرسانی قطعه 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
در آخر، تریگر eventarc را برای تابع ایجاد کنید. این دستور آن را نیز به تابع اضافه میکند.
توجه: اگر یک سطل چند منطقهای ایجاد کردهاید، باید پارامتر --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
۹. عملکرد خود را آزمایش کنید
برای خلاصهسازی، یک فایل متنی ساده آپلود کنید. نمیدانید چه چیزی را خلاصه کنید؟ از Gemini بخواهید توضیحی سریع در حد ۱-۲ صفحه در مورد تاریخچه سگها به شما بدهد! سپس آن فایل متنی ساده را در باکت $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.
۱۰. عیبیابی
در اینجا چند اشتباه تایپی وجود دارد که ممکن است با آنها مواجه شوید:
- اگر با خطایی مبنی
PORT 8080 is in useمواجه شدید، مطمئن شوید که Dockerfile مربوط به Ollama sidecar شما از پورت ۱۱۴۳۴ استفاده میکند. همچنین در صورتی که چندین تصویر Ollama در مخزن AR خود دارید، مطمئن شوید که از تصویر sidecar صحیح استفاده میکنید. تابع Cloud Run روی پورت ۸۰۸۰ کار میکند و اگر از تصویر Ollama متفاوتی به عنوان sidecar استفاده کرده باشید که روی ۸۰۸۰ نیز کار میکند، با این خطا مواجه خواهید شد. - اگر با خطای
failed to build: (error ID: 7485c5b6): function.js does not existمواجه شدید، مطمئن شوید که فایلهای package.json و tsconfig.json شما در همان سطح دایرکتوری src قرار دارند. - اگر با خطای
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 خود تغییر دهید.