Informationen zu diesem Codelab
1. Einführung
Übersicht
In diesem Codelab erfahren Sie, wie Sie ein gemma3:4b-Modell in einem Sidecar für eine Cloud Run-Funktion hosten. Wenn eine Datei in einen Cloud Storage-Bucket hochgeladen wird, wird die Cloud Run-Funktion ausgelöst. Die Funktion sendet den Inhalt der Datei zur Zusammenfassung an Gemma 3 im Sidecar.
Aufgaben in diesem Lab
- Inferenzen mit einer Cloud Run-Funktion und einem LLM ausführen, das in einem Sidecar mit GPUs gehostet wird
- Direct VPC-Ausgangskonfiguration für eine Cloud Run-GPU verwenden, um das Modell schneller hochzuladen und bereitzustellen
- Genkit zum Interagieren mit Ihrem gehosteten Ollama-Modell verwenden
2. Hinweis
Wenn Sie die GPU-Funktion verwenden möchten, müssen Sie eine Kontingenterhöhung für eine unterstützte Region beantragen. Das erforderliche Kontingent ist „nvidia_l4_gpu_allocation_no_zonal_redundancy“ und wird über die Cloud Run Admin API verwaltet. Hier finden Sie den direkten Link zum Anfordern eines Kontingents.
3. Einrichtung und Anforderungen
Legen Sie Umgebungsvariablen fest, die in diesem Codelab verwendet werden.
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
Erstellen Sie das Dienstkonto mit dem folgenden Befehl:
gcloud iam service-accounts create $SERVICE_ACCOUNT \
--display-name="SA for codelab crf sidecar with gpu"
Wir verwenden dasselbe Dienstkonto, das als Identität der Cloud Run-Funktion verwendet wird, als Dienstkonto für den Eventarc-Trigger, um die Cloud Run-Funktion aufzurufen. Sie können auch eine andere Service-Ansicht für Eventarc erstellen.
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member=serviceAccount:$SERVICE_ACCOUNT_ADDRESS \
--role=roles/run.invoker
Gewähren Sie dem Dienstkonto außerdem Zugriff auf das Empfangen von Eventarc-Ereignissen.
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:$SERVICE_ACCOUNT_ADDRESS" \
--role="roles/eventarc.eventReceiver"
Erstellen Sie einen Bucket, in dem das optimierte Modell gehostet wird. In diesem Codelab wird ein regionaler Bucket verwendet. Sie können auch einen multiregionalen Bucket verwenden.
gsutil mb -l $REGION gs://$BUCKET_GEMMA_NAME
Gewähren Sie der SA dann Zugriff auf den Bucket.
gcloud storage buckets add-iam-policy-binding gs://$BUCKET_GEMMA_NAME \
--member=serviceAccount:$SERVICE_ACCOUNT_ADDRESS \
--role=roles/storage.objectAdmin
Erstellen Sie nun einen regionalen Bucket, in dem die Dokumente gespeichert werden, die Sie zusammenfassen möchten. Sie können auch einen multiregionalen Bucket verwenden, sofern Sie den Eventarc-Trigger entsprechend aktualisieren (siehe Ende dieses Codelabs).
gsutil mb -l $REGION gs://$BUCKET_DOCS_NAME
Gewähren Sie der SA dann Zugriff auf den Gemma 3-Bucket.
gcloud storage buckets add-iam-policy-binding gs://$BUCKET_GEMMA_NAME \
--member=serviceAccount:$SERVICE_ACCOUNT_ADDRESS \
--role=roles/storage.objectAdmin
und den Docs-Bucket.
gcloud storage buckets add-iam-policy-binding gs://$BUCKET_DOCS_NAME \
--member=serviceAccount:$SERVICE_ACCOUNT_ADDRESS \
--role=roles/storage.objectAdmin
Erstellen Sie ein Artifact Registry-Repository für das Ollama-Image, das im Sidecar verwendet wird.
gcloud artifacts repositories create $AR_REPO \
--repository-format=docker \
--location=$REGION \
--description="codelab for CR function and gpu sidecar" \
--project=$PROJECT_ID
4. Gemma 3-Modell herunterladen
Laden Sie zuerst das Gemma 3 4b-Modell von ollama herunter. Dazu müssen Sie ollama installieren und das Modell „gemma3:4b“ lokal ausführen.
curl -fsSL https://ollama.com/install.sh | sh
ollama serve
Führen Sie nun in einem separaten Terminalfenster den folgenden Befehl aus, um das Modell herunterzuladen. Wenn Sie Cloud Shell verwenden, können Sie ein zusätzliches Terminalfenster öffnen, indem Sie oben rechts in der Menüleiste auf das Pluszeichen klicken.
ollama run gemma3:4b
Sobald ollama läuft, können Sie dem Modell Fragen stellen, z.B.:
"why is the sky blue?"
Wenn Sie mit dem Chatten mit ollama fertig sind, können Sie den Chat beenden, indem Sie
/bye
Führen Sie dann im ersten Terminalfenster den folgenden Befehl aus, um das lokale Bereitstellen von ollama zu beenden:
# on Linux / Cloud Shell press Ctrl^C or equivalent for your shell
Hier finden Sie Informationen dazu, wo Ollama die Modelle je nach Betriebssystem herunterlädt.
https://github.com/ollama/ollama/blob/main/docs/faq.md#where-are-models-stored
Wenn Sie Cloud Workstations verwenden, finden Sie die heruntergeladenen Ollama-Modelle hier: /home/$USER/.ollama/models
Prüfen Sie, ob Ihre Modelle hier gehostet werden:
ls /home/$USER/.ollama/models
Verschieben Sie das Modell „gemma3:4b“ jetzt in Ihren GCS-Bucket.
gsutil cp -r /home/$USER/.ollama/models gs://$BUCKET_GEMMA_NAME
5. Cloud Run-Funktion erstellen
Erstellen Sie einen Stammordner für Ihren Quellcode.
mkdir codelab-crf-sidecar-gpu &&
cd codelab-crf-sidecar-gpu &&
mkdir cr-function &&
mkdir ollama-gemma3 &&
cd cr-function
Erstellen Sie einen Unterordner mit dem Namen „src“. Erstellen Sie im Ordner eine Datei mit dem Namen „index.ts“.
mkdir src &&
touch src/index.ts
Aktualisieren Sie index.ts mit dem folgenden Code:
//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);
}
});
Erstellen Sie nun im Stammverzeichnis crf-sidecar-gpu
eine Datei namens package.json
mit folgendem Inhalt:
{
"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"
}
}
Erstellen Sie auch auf Stammverzeichnisebene eine tsconfig.json
mit folgendem Inhalt:
{
"compileOnSave": true,
"include": [
"src"
],
"compilerOptions": {
"module": "commonjs",
"noImplicitReturns": true,
"outDir": "lib",
"sourceMap": true,
"strict": true,
"target": "es2017",
"skipLibCheck": true,
"esModuleInterop": true
}
}
6. Funktion implementieren
In diesem Schritt stellen Sie die Cloud Run-Funktion bereit, indem Sie den folgenden Befehl ausführen.
Hinweis: Die maximale Anzahl von Instanzen sollte kleiner oder gleich Ihrem GPU-Kontingent sein.
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. Sidecar erstellen
Weitere Informationen zum Hosten von Ollama in einem Cloud Run-Dienst finden Sie unter https://cloud.google.com/run/docs/tutorials/gpu-gemma-with-ollama.
Wechseln Sie in das Verzeichnis für Ihren Sidecar:
cd ../ollama-gemma3
Erstellen Sie eine Dockerfile
-Datei mit folgendem Inhalt:
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"]
Image erstellen
gcloud builds submit \
--tag $REGION-docker.pkg.dev/$PROJECT_ID/$AR_REPO/ollama-gemma3 \
--machine-type e2-highcpu-32
8. Funktion mit Sidecar aktualisieren
Wenn Sie einem vorhandenen Dienst, Job oder einer vorhandenen Funktion einen Sidecar hinzufügen möchten, können Sie die YAML-Datei aktualisieren, damit sie den Sidecar enthält.
Rufen Sie die YAML-Datei für die gerade bereitgestellte Cloud Run-Funktion ab:
gcloud run services describe $FUNCTION_NAME --format=export > add-sidecar-service.yaml
Fügen Sie nun den Sidecar dem CRf hinzu, indem Sie die YAML-Datei so aktualisieren:
- Fügen Sie das folgende YAML-Fragment direkt über die Zeile
runtimeClassName: run.googleapis.com/linux-base-image-update
ein. Der-image
sollte mit dem Ingress-Containerelement-image
übereinstimmen.
- 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
- Führen Sie den folgenden Befehl aus, um das YAML-Fragment mit Ihren Umgebungsvariablen zu aktualisieren:
sed -i "s|YOUR_IMAGE_SIDECAR|$IMAGE_SIDECAR|; s|YOUR_BUCKET_GEMMA_NAME|$BUCKET_GEMMA_NAME|" add-sidecar-service.yaml
Ihre fertige YAML-Datei sollte in etwa so aussehen:
##############################################
# 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
##############################################
Aktualisieren Sie die Funktion jetzt mit dem Sidecar, indem Sie den folgenden Befehl ausführen.
gcloud run services replace add-sidecar-service.yaml
Erstellen Sie abschließend den Eventarc-Trigger für die Funktion. Mit diesem Befehl wird er auch der Funktion hinzugefügt.
Hinweis: Wenn Sie einen Bucket mit mehreren Regionen erstellt haben, müssen Sie den Parameter --location
ändern.
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. Funktion testen
Laden Sie eine Nur-Textdatei für die Zusammenfassung hoch. Sie wissen nicht, was Sie zusammenfassen sollen? Bitten Sie Gemini um eine kurze Beschreibung der Geschichte von Hunden auf einer bis zwei Seiten. Laden Sie diese Textdatei dann in Ihren $BUCKET_DOCS_NAME
-Bucket für das Gemma3:4b-Modell hoch, um eine Zusammenfassung in die Funktionsprotokolle zu schreiben.
In den Protokollen wird in etwa Folgendes angezeigt:
---------------
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. Fehlerbehebung
Hier sind einige Fehler, die bei Tippfehlern auftreten können:
- Wenn Sie die Fehlermeldung
PORT 8080 is in use
erhalten, prüfen Sie, ob im Dockerfile für Ihr Ollama-Sidecar der Port 11434 verwendet wird. Achten Sie außerdem darauf, dass Sie das richtige Sidecar-Image verwenden, falls Sie mehrere Ollama-Images in Ihrem AR-Repository haben. Die Cloud Run-Funktion wird über Port 8080 bereitgestellt. Wenn Sie ein anderes Ollama-Image als Sidecar verwendet haben, das ebenfalls über 8080 bereitgestellt wird, tritt dieser Fehler auf. - Wenn der Fehler
failed to build: (error ID: 7485c5b6): function.js does not exist
angezeigt wird, prüfen Sie, ob sich die Dateien „package.json“ und „tsconfig.json“ auf derselben Ebene wie das Verzeichnis „src“ befinden. - Wenn Sie den Fehler
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.
erhalten, ändern Sie in Ihrer YAML-Dateiautoscaling.knative.dev/maxScale: '100'
in „1“ oder in einen Wert, der kleiner oder gleich Ihrem GPU-Kontingent ist.