Thông tin về lớp học lập trình này
1. Giới thiệu
Tổng quan
Trong lớp học lập trình này, bạn sẽ tìm hiểu cách lưu trữ mô hình gemma3:4b trong một sidecar cho một hàm Cloud Run. Khi một tệp được tải lên bộ chứa trên Google Cloud Storage, tệp đó sẽ kích hoạt hàm Cloud Run. Hàm này sẽ gửi nội dung của tệp đến Gemma 3 trong sidecar để tóm tắt.
Kiến thức bạn sẽ học được
- Cách dự đoán bằng cách sử dụng hàm Cloud Run và LLM được lưu trữ trong một sidecar bằng GPU
- Cách sử dụng cấu hình đầu ra VPC trực tiếp cho GPU Cloud Run để tải lên và phân phát mô hình nhanh hơn
- Cách sử dụng genkit để giao tiếp với mô hình ollama được lưu trữ
2. Trước khi bắt đầu
Để sử dụng tính năng GPU, bạn phải yêu cầu tăng hạn mức cho một khu vực được hỗ trợ. Hạn mức cần thiết là nvidia_l4_gpu_allocation_no_zonal_redundancy, thuộc Cloud Run Admin API. Dưới đây là đường liên kết trực tiếp để yêu cầu hạn mức.
3. Cách thiết lập và các yêu cầu
Thiết lập các biến môi trường sẽ được sử dụng trong suốt lớp học lập trình này.
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
Tạo tài khoản dịch vụ bằng cách chạy lệnh sau:
gcloud iam service-accounts create $SERVICE_ACCOUNT \
--display-name="SA for codelab crf sidecar with gpu"
Chúng ta sẽ sử dụng chính tài khoản dịch vụ này làm danh tính của hàm Cloud Run làm tài khoản dịch vụ cho trình kích hoạt eventarc để gọi hàm Cloud Run. Bạn có thể tạo một SA khác cho Eventarc nếu muốn.
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member=serviceAccount:$SERVICE_ACCOUNT_ADDRESS \
--role=roles/run.invoker
Ngoài ra, hãy cấp cho tài khoản dịch vụ quyền nhận các sự kiện Eventarc.
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:$SERVICE_ACCOUNT_ADDRESS" \
--role="roles/eventarc.eventReceiver"
Tạo một bộ chứa sẽ lưu trữ mô hình được tinh chỉnh của bạn. Lớp học lập trình này sử dụng một bộ chứa theo khu vực. Bạn cũng có thể sử dụng bộ chứa nhiều khu vực.
gsutil mb -l $REGION gs://$BUCKET_GEMMA_NAME
Sau đó, cấp cho SA quyền truy cập vào bộ chứa.
gcloud storage buckets add-iam-policy-binding gs://$BUCKET_GEMMA_NAME \
--member=serviceAccount:$SERVICE_ACCOUNT_ADDRESS \
--role=roles/storage.objectAdmin
Bây giờ, hãy tạo một bộ chứa theo khu vực để lưu trữ các tài liệu bạn muốn tóm tắt. Bạn cũng có thể sử dụng bộ chứa nhiều khu vực, miễn là bạn cập nhật trình kích hoạt Eventarc cho phù hợp (hiển thị ở cuối lớp học lập trình này).
gsutil mb -l $REGION gs://$BUCKET_DOCS_NAME
Sau đó, cấp cho SA quyền truy cập vào bộ chứa Gemma 3.
gcloud storage buckets add-iam-policy-binding gs://$BUCKET_GEMMA_NAME \
--member=serviceAccount:$SERVICE_ACCOUNT_ADDRESS \
--role=roles/storage.objectAdmin
và bộ chứa Tài liệu.
gcloud storage buckets add-iam-policy-binding gs://$BUCKET_DOCS_NAME \
--member=serviceAccount:$SERVICE_ACCOUNT_ADDRESS \
--role=roles/storage.objectAdmin
Tạo kho lưu trữ đăng ký cấu phần phần mềm cho hình ảnh Ollama sẽ được sử dụng trong sidecar
gcloud artifacts repositories create $AR_REPO \
--repository-format=docker \
--location=$REGION \
--description="codelab for CR function and gpu sidecar" \
--project=$PROJECT_ID
4. Tải mô hình Gemma 3 xuống
Trước tiên, bạn cần tải mô hình Gemma 3 4b xuống từ ollama. Bạn có thể thực hiện việc này bằng cách cài đặt ollama rồi chạy mô hình gemma3:4b trên máy.
curl -fsSL https://ollama.com/install.sh | sh
ollama serve
Bây giờ, trong một cửa sổ dòng lệnh riêng, hãy chạy lệnh sau để tải mô hình xuống. Nếu đang sử dụng Cloud Shell, bạn có thể mở thêm một cửa sổ dòng lệnh bằng cách nhấp vào biểu tượng dấu cộng ở thanh trình đơn trên cùng bên phải.
ollama run gemma3:4b
Sau khi ollama chạy, bạn có thể hỏi mô hình một số câu hỏi, ví dụ:
"why is the sky blue?"
Sau khi trò chuyện xong với ollama, bạn có thể thoát khỏi cuộc trò chuyện bằng cách chạy
/bye
Sau đó, trong cửa sổ dòng lệnh đầu tiên, hãy chạy lệnh sau để ngừng phân phát ollama cục bộ
# on Linux / Cloud Shell press Ctrl^C or equivalent for your shell
Bạn có thể tìm thấy nơi Ollama tải các mô hình xuống tuỳ thuộc vào hệ điều hành của bạn tại đây.
https://github.com/ollama/ollama/blob/main/docs/faq.md#where-are-models-stored
Nếu đang sử dụng Máy trạm trên đám mây, bạn có thể tìm thấy các mô hình ollama đã tải xuống tại đây /home/$USER/.ollama/models
Xác nhận rằng các mô hình của bạn được lưu trữ tại đây:
ls /home/$USER/.ollama/models
giờ hãy chuyển mô hình gemma3:4b sang bộ chứa GCS
gsutil cp -r /home/$USER/.ollama/models gs://$BUCKET_GEMMA_NAME
5. Tạo hàm Cloud Run
Tạo thư mục gốc cho mã nguồn.
mkdir codelab-crf-sidecar-gpu &&
cd codelab-crf-sidecar-gpu &&
mkdir cr-function &&
mkdir ollama-gemma3 &&
cd cr-function
Tạo một thư mục con có tên là src. Bên trong thư mục, hãy tạo một tệp có tên index.ts
mkdir src &&
touch src/index.ts
Cập nhật index.ts bằng mã sau:
//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);
}
});
Bây giờ, trong thư mục gốc crf-sidecar-gpu
, hãy tạo một tệp có tên package.json
với nội dung sau:
{
"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"
}
}
Tạo một tsconfig.json
cũng ở cấp thư mục gốc với nội dung sau:
{
"compileOnSave": true,
"include": [
"src"
],
"compilerOptions": {
"module": "commonjs",
"noImplicitReturns": true,
"outDir": "lib",
"sourceMap": true,
"strict": true,
"target": "es2017",
"skipLibCheck": true,
"esModuleInterop": true
}
}
6. Triển khai hàm
Ở bước này, bạn sẽ triển khai hàm Cloud Run bằng cách chạy lệnh sau.
Lưu ý: bạn nên đặt số lượng thực thể tối đa thành một số nhỏ hơn hoặc bằng hạn mức 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. Tạo sidecar
Bạn có thể tìm hiểu thêm về cách lưu trữ Ollama trong dịch vụ Cloud Run tại https://cloud.google.com/run/docs/tutorials/gpu-gemma-with-ollama
Chuyển vào thư mục cho xe bên:
cd ../ollama-gemma3
Tạo tệp Dockerfile
có nội dung sau:
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"]
Tạo hình ảnh
gcloud builds submit \
--tag $REGION-docker.pkg.dev/$PROJECT_ID/$AR_REPO/ollama-gemma3 \
--machine-type e2-highcpu-32
8. Cập nhật hàm bằng sidecar
Để thêm một tệp trợ giúp vào một dịch vụ, công việc hoặc hàm hiện có, bạn có thể cập nhật tệp YAML để chứa tệp trợ giúp đó.
Truy xuất tệp YAML cho hàm Cloud Run mà bạn vừa triển khai bằng cách chạy:
gcloud run services describe $FUNCTION_NAME --format=export > add-sidecar-service.yaml
Bây giờ, hãy thêm sidecar vào CRf bằng cách cập nhật tệp YAML như sau:
- chèn mảnh YAML sau ngay phía trên dòng
runtimeClassName: run.googleapis.com/linux-base-image-update
.-image
phải khớp với mục vùng chứa truy cập-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
- Chạy lệnh sau để cập nhật mảnh YAML bằng các biến môi trường:
sed -i "s|YOUR_IMAGE_SIDECAR|$IMAGE_SIDECAR|; s|YOUR_BUCKET_GEMMA_NAME|$BUCKET_GEMMA_NAME|" add-sidecar-service.yaml
Tệp YAML hoàn chỉnh sẽ có dạng như sau:
##############################################
# 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
##############################################
Bây giờ, hãy cập nhật hàm bằng sidecar bằng cách chạy lệnh sau.
gcloud run services replace add-sidecar-service.yaml
Cuối cùng, hãy tạo điều kiện kích hoạt eventarc cho hàm. Lệnh này cũng thêm biến đó vào hàm.
Lưu ý: nếu đã tạo một bộ chứa nhiều khu vực, bạn nên thay đổi thông số --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. Kiểm thử hàm
Tải tệp văn bản thuần tuý lên để tóm tắt. Bạn không biết nên tóm tắt nội dung nào? Yêu cầu Gemini cung cấp nội dung mô tả nhanh từ 1 đến 2 trang về lịch sử của loài chó! Sau đó, hãy tải tệp văn bản thuần tuý đó lên bộ chứa $BUCKET_DOCS_NAME
để mô hình Gemma3:4b ghi nội dung tóm tắt vào nhật ký hàm.
Trong nhật ký, bạn sẽ thấy nội dung tương tự như sau:
---------------
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. Khắc phục sự cố
Dưới đây là một số lỗi chính tả mà bạn có thể gặp phải:
- Nếu bạn gặp lỗi
PORT 8080 is in use
, hãy đảm bảo tệp Dockerfile cho xe bên Ollama của bạn đang sử dụng cổng 11434. Ngoài ra, hãy đảm bảo bạn đang sử dụng đúng hình ảnh xe bên trong trường hợp bạn có nhiều hình ảnh Ollama trong kho lưu trữ AR. Hàm Cloud Run phân phát trên cổng 8080 và nếu bạn đã sử dụng một hình ảnh Ollama khác làm xe bên cũng phân phát trên 8080, thì bạn sẽ gặp lỗi này. - Nếu bạn gặp lỗi
failed to build: (error ID: 7485c5b6): function.js does not exist
, hãy đảm bảo rằng các tệp package.json và tsconfig.json nằm ở cùng cấp với thư mục src. - Nếu bạn gặp lỗi
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.
, trong tệp YAML, hãy thay đổiautoscaling.knative.dev/maxScale: '100'
thành 1 hoặc thành một giá trị nhỏ hơn hoặc bằng hạn mức GPU của bạn.