Cloud Run işlevi için yan tarafta LLM barındırma

Cloud Run işlevi için yan tarafta LLM barındırma

Bu codelab hakkında

subjectSon güncelleme Mar 27, 2025
account_circleBir Google çalışanı tarafından yazılmıştır

1. Giriş

Bu codelab'de, bir Cloud Run işlevi için gemma3:4b modelini bir yan araçta nasıl barındıracağınızı öğreneceksiniz. Bir Cloud Storage paketine dosya yüklendiğinde Cloud Run işlevi tetiklenir. İşlev, özetlenmesi için dosyanın içeriğini yan taraftaki Gemma 3'e gönderir.

  • GPU'ları kullanarak bir Cloud Run işlevi ve yardımcı araçta barındırılan bir LLM kullanarak çıkarım yapma
  • Modelin daha hızlı yüklenmesi ve sunulması için Cloud Run GPU'da doğrudan VPC çıkış yapılandırmasını kullanma
  • Barındırılan ollama modelinizle arayüz oluşturmak için genkit'i kullanma

2. Başlamadan önce

GPU'lar özelliğini kullanmak için desteklenen bir bölge için kota artışı isteğinde bulunmanız gerekir. Gerekli kota, Cloud Run Admin API kapsamındaki nvidia_l4_gpu_allocation_no_zonal_redundancy'dir. Kota isteğinde bulunmaya yönelik doğrudan bağlantıyı burada bulabilirsiniz.

3. Kurulum ve Gereksinimler

Bu codelab boyunca kullanılacak ortam değişkenlerini ayarlayın.

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

Aşağıdaki komutu çalıştırarak hizmet hesabını oluşturun:

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

Cloud Run işlevinin kimliği olarak kullanılan bu hizmet hesabını, Cloud Run işlevini çağırmak için eventarc tetikleyicisinin hizmet hesabı olarak da kullanırız. Dilerseniz Eventarc için farklı bir SA oluşturabilirsiniz.

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

Ayrıca, hizmet hesabına Eventarc etkinliklerini alma izni verin.

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

İnce ayarlanmış modelinizi barındıracak bir paket oluşturun. Bu codelab'de bölgesel bir paket kullanılır. Çok bölgeli bir paket de kullanabilirsiniz.

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

Ardından SA'ya pakete erişim izni verin.

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

Ardından, özetlenmesini istediğiniz dokümanları depolayacak bölgesel bir paket oluşturun. Eventarc tetikleyicisini uygun şekilde güncellemeniz (bu kod laboratuvarının sonunda gösterilmiştir) koşuluyla çok bölgeli bir paket de kullanabilirsiniz.

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

Ardından, SA'ya Gemma 3 paketine erişim izni verin.

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

ve Dokümanlar paketi.

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

Yan tarafta kullanılacak Ollama resmi için bir Artifact Registry deposu oluşturun

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 modelini indirme

Öncelikle, ollama'dan Gemma 3 4b modelini indirmeniz gerekir. Bunu, ollama'yı yükleyip gemma3:4b modelini yerel olarak çalıştırarak yapabilirsiniz.

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

Ardından, ayrı bir terminal penceresinde modeli indirmek için aşağıdaki komutu çalıştırın. Cloud Shell kullanıyorsanız sağ üst menü çubuğundaki artı simgesini tıklayarak ek bir terminal penceresi açabilirsiniz.

ollama run gemma3:4b

Ollama çalıştıktan sonra modele soru sorabilirsiniz. Örneğin:

"why is the sky blue?"

Olla ile sohbetinizi tamamladığınızda

/bye

Ardından, ilk terminal penceresinde, ollama'yı yerel olarak yayınlamayı durdurmak için aşağıdaki komutu çalıştırın

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

Ollama'nın, işletim sisteminize bağlı olarak modelleri indirdiği yeri burada bulabilirsiniz.

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

Cloud Workstations kullanıyorsanız indirilen ollama modellerini burada bulabilirsiniz /home/$USER/.ollama/models

Modellerinizin burada barındırıldığını onaylayın:

ls /home/$USER/.ollama/models

Ardından gemma3:4b modelini GCS paketinize taşıyın.

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

5. Cloud Run işlevini oluşturma

Kaynak kodunuz için bir kök klasör oluşturun.

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

src adlı bir alt klasör oluşturun. Klasörün içinde index.ts adlı bir dosya oluşturun.

mkdir src &&
touch src
/index.ts

index.ts dosyasını aşağıdaki kodla güncelleyin:

//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);
   
}
});

Ardından, crf-sidecar-gpu kök dizininde aşağıdaki içeriğe sahip package.json adlı bir dosya oluşturun:

{
    "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"
    }
}

Kök dizin düzeyinde de aşağıdaki içerikleri içeren bir tsconfig.json oluşturun:

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

6. İşlevi dağıtma

Bu adımda, aşağıdaki komutu çalıştırarak Cloud Run işlevini dağıtacaksınız.

Not: max_instances, GPU kotanızdan az veya bu kotaya eşit bir sayıya ayarlanmalıdır.

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. Yan araç oluşturma

Ollama'yı bir Cloud Run hizmetinde barındırma hakkında daha fazla bilgiyi https://cloud.google.com/run/docs/tutorials/gpu-gemma-with-ollama adresinde bulabilirsiniz.

Yan aracınızın dizinine gidin:

cd ../ollama-gemma3

Aşağıdaki içerikleri içeren bir Dockerfile dosyası oluşturun:

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"]

Görüntüyü oluşturma

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

8. İşlevi yan araçla güncelleme

Mevcut bir hizmete, işe veya işleve yardımcı dosya eklemek için YAML dosyasını yardımcı dosyayı içerecek şekilde güncelleyebilirsiniz.

Aşağıdaki komutu çalıştırarak dağıttığınız Cloud Run işlevinin YAML dosyasını alın:

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

Ardından, YAML'i aşağıdaki gibi güncelleyerek yardımcı dosyayı CRf'ye ekleyin:

  1. doğrudan runtimeClassName: run.googleapis.com/linux-base-image-update satırının üzerine aşağıdaki YAML parçasını ekleyin. -image, giriş kapsayıcı öğesi -image ile hizalanmalıdır.
    - 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 parçasını ortam değişkenlerinizle güncellemek için aşağıdaki komutu çalıştırın:
sed -i "s|YOUR_IMAGE_SIDECAR|$IMAGE_SIDECAR|; s|YOUR_BUCKET_GEMMA_NAME|$BUCKET_GEMMA_NAME|" add-sidecar-service.yaml

Tamamlanmış YAML dosyanız şöyle görünmelidir:

##############################################
# 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
##############################################

Ardından, aşağıdaki komutu çalıştırarak işlevi yan araçla güncelleyin.

gcloud run services replace add-sidecar-service.yaml

Son olarak, işlev için eventarc tetikleyicisini oluşturun. Bu komut, değişkeni işleve de ekler.

Not: Çok bölgeli bir paket oluşturduysanız --location parametresini değiştirmeniz gerekir.

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. İşlevinizi test etme

Özetlemek için düz metin dosyası yükleyin. Neleri özetleyeceğinizi bilmiyor musunuz? Gemini'den köpeklerin tarihiyle ilgili 1-2 sayfalık kısa bir açıklama isteyebilirsiniz. Ardından, işlev günlüklerine özet yazmak için bu düz metin dosyasını Gemma3:4b modeli için $BUCKET_DOCS_NAME paketinize yükleyin.

Günlüklerde aşağıdakine benzer bir ifade görürsünüz:

---------------
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. Sorun giderme

Karşılaşabileceğiniz bazı yazım hataları aşağıda verilmiştir:

  1. PORT 8080 is in use hatası alırsanız Ollama yardımcı aracınızın Dockerfile dosyasında 11434 bağlantı noktasının kullanıldığından emin olun. Ayrıca, AR deponuzda birden fazla Ollama resmi varsa doğru yan araç resmini kullandığınızdan emin olun. Cloud Run işlevi 8080 numaralı bağlantı noktasında yayınlanır. Yan araç olarak 8080 numaralı bağlantı noktasında da yayınlanan farklı bir Ollama resmi kullandıysanız bu hatayla karşılaşırsınız.
  2. failed to build: (error ID: 7485c5b6): function.js does not exist hatası alırsanız package.json ve tsconfig.json dosyalarınızın src dizini ile aynı düzeyde olduğundan emin olun.
  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. hatası alırsanız YAML dosyanızda autoscaling.knative.dev/maxScale: '100' değerini 1 veya GPU kotanızdan az veya eşit bir değere değiştirin.