О практической работе
1. Введение
Обзор
В этой лаборатории кода вы узнаете, как разместить модель gemma3:4b в дополнительном модуле для функции Cloud Run. Когда файл загружается в корзину Cloud Storage, он запускает функцию Cloud Run. Функция отправит содержимое файла в Gemma 3 в коляске для обобщения.
Что вы узнаете
- Как сделать вывод с помощью функции Cloud Run и LLM, размещенного в коляске с использованием графических процессоров
- Как использовать выходную конфигурацию Direct VPC для графического процессора Cloud Run для более быстрой загрузки и обслуживания модели.
- Как использовать genkit для взаимодействия с вашей размещенной моделью олламы
2. Прежде чем начать
Чтобы использовать функцию графических процессоров, необходимо запросить увеличение квоты для поддерживаемого региона. Необходимая квота — 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, в качестве учетной записи службы для триггера 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"
Создайте корзину, в которой будет размещена ваша настроенная модель. В этой кодовой лаборатории используется региональный сегмент. Вы также можете использовать многорегиональную корзину.
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
4. Скачать модель Джемма 3
Сначала вам нужно загрузить модель Gemma 3 4b с сайта ollama. Вы можете сделать это, установив ollama, а затем локально запустив модель gemma3:4b.
curl -fsSL https://ollama.com/install.sh | sh
ollama serve
Теперь в отдельном окне терминала выполните следующую команду, чтобы спустить модель. Если вы используете Cloud Shell, вы можете открыть дополнительное окно терминала, щелкнув значок плюса в правой верхней строке меню.
ollama run gemma3:4b
После запуска ollama не стесняйтесь задавать модели несколько вопросов, например:
"why is the sky blue?"
Закончив общение с олламой, вы можете выйти из чата, запустив
/bye
Затем в первом окне терминала выполните следующую команду, чтобы прекратить локальное обслуживание олламы.
# 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
Если вы используете облачные рабочие станции, вы можете найти загруженные модели ollama здесь /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);
}
});
Теперь в корневом каталоге 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, выполнив следующую команду.
Примечание. Максимальное количество экземпляров должно быть установлено на число, меньшее или равное вашей квоте графического процессора.
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. Создайте коляску
Вы можете узнать больше о хостинге 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
8. Обновите функцию с помощью коляски
Чтобы добавить дополнительный компонент к существующей службе, заданию или функции, вы можете обновить файл YAML, включив в него дополнительный компонент.
Получите YAML для функции Cloud Run, которую вы только что развернули, выполнив:
gcloud run services describe $FUNCTION_NAME --format=export > add-sidecar-service.yaml
Теперь добавьте коляску в CRf, обновив YAML следующим образом:
- вставьте следующий фрагмент 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
##############################################
Теперь обновите функцию с помощью коляски, выполнив следующую команду.
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
9. Проверьте свою функцию
Загрузите обычный текстовый файл для обобщения. Не знаете, что подвести итог? Попросите Близнецов дать вам краткое описание истории собак на 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. Поиск неисправностей
Вот некоторые ошибки и опечатки, с которыми вы можете столкнуться:
- Если вы получаете сообщение об ошибке, указывающее, что
PORT 8080 is in use
, убедитесь, что ваш файл Dockerfile для вашего дополнительного устройства Ollama использует порт 11434. Также убедитесь, что вы используете правильный образ дополнительного устройства, если в вашем репозитории AR есть несколько изображений Ollama. Функция Cloud Run работает на порту 8080, и если вы использовали другой образ Ollama в качестве вспомогательного устройства, которое также обслуживается на порту 8080, вы столкнетесь с этой ошибкой. - Если вы получаете сообщение об ошибке
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 или на значение, меньшее или равное вашей квоте графического процессора.