AlloyDB Omni и EmbeddingGemma с Gemma 4 в Kubernetes

1. Введение

В этой практической работе вы узнаете, как развернуть AlloyDB Omni в Google Kubernetes Engine (GKE) и использовать ее с открытыми моделями, такими как EmbeddingGemma и Gemma 4, для встраиваний и прогнозов. Запуск базы данных и моделей в одном кластере снижает задержку сети и позволяет избежать зависимостей от сторонних сервисов. Это также помогает соблюдать требования к соответствию и месту хранения данных, поскольку ваши данные никогда не покидают вашу среду.

Схема архитектуры AlloyDB Omni и EmbeddingGemma в GKE

Требования

  • Базовое представление о Google Cloud и консоли Google Cloud.
  • Базовые знания о Kubernetes и GKE.
  • Знание интерфейса командной строки и Google Cloud Shell.

Что вы узнаете

  • Как развернуть AlloyDB Omni в кластере GKE.
  • Как подключиться к AlloyDB Omni
  • Как загрузить данные в AlloyDB Omni
  • Как развернуть ИИ-модели (эмбеддинг и LLM) в GKE.
  • Как зарегистрировать ИИ-модели в AlloyDB Omni
  • Как генерировать эмбеддинги для семантического поиска
  • Как выполнять запросы семантического поиска в AlloyDB Omni
  • Как создавать и использовать векторные индексы в AlloyDB Omni

Что вам понадобится

  • Аккаунт и проект Google Cloud.
  • браузер, например Chrome;

2. Настройка и требования

Настройка проекта

  1. Войдите в консоль Google Cloud. Если у вас нет аккаунта Gmail или Google Workspace, создайте его. Используйте личный аккаунт вместо рабочего или учебного.
  1. Создайте новый проект или выберите существующий. В заголовке консоли Google Cloud нажмите Выбрать проект, а затем – Новый проект.

Диалоговое окно выбора проекта в консоли Google Cloud

В окне Выбор проекта нажмите Новый проект, чтобы открыть диалоговое окно создания проекта.

Диалоговое окно создания проекта

В диалоговом окне введите название проекта и выберите организацию или местоположение.

Поля ввода сведений о проекте

  • Название проекта – это отображаемое название для участников проекта. Название проекта не используется API Google, и его можно изменить в любой момент.
  • Идентификатор проекта уникален для всех проектов Google Cloud и неизменен (его нельзя изменить после настройки). Консоль Google Cloud автоматически сгенерирует уникальный идентификатор, или вы можете указать собственный. В этой практической работе идентификатор проекта обозначается плейсхолдером .
  • Номер проекта – это третий идентификатор, который используется некоторыми API. Подробную информацию можно найти в документации по Resource Manager.

Включить оплату

Если вы настроили оплату с помощью бонусов Google Cloud, пропустите этот шаг.

Чтобы настроить личный платежный аккаунт, включите оплату в консоли Google Cloud.

  • Для выполнения этой практической работы требуются ресурсы Google Cloud стоимостью менее 5 долларов США.
  • Чтобы избежать дополнительных расходов, удалите ресурсы, следуя инструкциям в конце этой лабораторной работы.
  • Новые пользователи могут воспользоваться бесплатной пробной версией с бонусом в размере 300 долларов США.

Запустить Cloud Shell

В этой практической работе вы будете использовать Google Cloud Shell – среду командной строки, работающую в облаке.

В консоли Google Cloud нажмите на значок Активировать Cloud Shell на панели инструментов в правом верхнем углу.

Кнопка "Активировать Cloud Shell"

Вы также можете нажать G, а затем S или открыть Google Cloud Shell напрямую.

После подключения в Cloud Shell появится командная строка:

Скриншот терминала Google Cloud Shell

Cloud Shell включает постоянное хранилище и инструменты разработки. Все шаги этой практической работы можно выполнить в браузере.

3. Как включить API

Чтобы использовать Google Kubernetes Engine (GKE) для развертывания AlloyDB Omni и моделей, включите API Compute Engine и GKE в облачном проекте Google Cloud.

В Cloud Shell проверьте, настроен ли идентификатор проекта:

PROJECT_ID=$(gcloud config get-value project)
echo $PROJECT_ID

Если идентификатор проекта не задан, настройте его:

export PROJECT_ID=<YOUR_PROJECT_ID>
gcloud config set project $PROJECT_ID

Включите необходимые API:

gcloud services enable compute.googleapis.com
gcloud services enable container.googleapis.com

Ожидаемый результат:

student@cloudshell:~ (test-project-001-402417)$ PROJECT_ID=test-project-001-402417
student@cloudshell:~ (test-project-001-402417)$ gcloud config set project test-project-001-402417
Updated property [core/project].
student@cloudshell:~ (test-project-001-402417)$ gcloud services enable compute.googleapis.com
gcloud services enable container.googleapis.com
Operation "operations/acat.p2-4470404856-1f44ebd8-894e-4356-bea7-b84165a57442" finished successfully.

Подробную информацию о каждом включенном API можно найти в документации.

4. Как развернуть AlloyDB Omni в GKE

Чтобы развернуть AlloyDB Omni в GKE, подготовьте кластер Kubernetes в соответствии с требованиями оператора AlloyDB Omni.

Создайте кластер GKE

Разверните кластер GKE в режиме Autopilot, чтобы запустить AlloyDB Omni, оператор и контейнеры мониторинга. Режим Autopilot упрощает развертывание: все ресурсы для оператора AlloyDB Omni, кластера и других компонентов будут назначены автоматически.

Выберите регион, в котором вы развертываете ресурсы. Выберите регион, который находится ближе всего к вашему местоположению:

export LOCATION=<your region>

Задайте переменные среды для развертывания:

export PROJECT_ID=$(gcloud config get-value project)
export CLUSTER_NAME=alloydb-ai-gke

Создайте кластер GKE в режиме Autopilot:

gcloud container clusters create-auto ${CLUSTER_NAME} \
  --project=${PROJECT_ID} \
  --region=${LOCATION}

Ожидаемый результат в консоли:

student@cloudshell:~ (test-project-001-402417)$ export PROJECT_ID=$(gcloud config get project)
export CLUSTER_NAME=alloydb-ai-gke
Your active configuration is: [test-project-001-402417]
student@cloudshell:~ (test-project-001-402417)$ gcloud container clusters create-auto ${CLUSTER_NAME} \
>   --project=${PROJECT_ID} \
>   --region=${LOCATION}
Creating cluster alloydb-ai-gke in us-east4... Cluster is being health-checked.
..⠹
Creating cluster alloydb-ai-gke in us-east4... Cluster is being health-checked
(Kubernetes Control Plane is healthy)...done.
Created [https://container.googleapis.com/v1/projects/gleb-genai-002/zones/us-east4/clusters/alloydb-ai-gke].
To inspect the contents of your cluster, go to: https://console.cloud.google.com/kubernetes/workload_/gcloud/us-east4/alloydb-ai-gke?project=gleb-genai-002
kubeconfig entry generated for alloydb-ai-gke.
NAME            LOCATION  MASTER_VERSION      MASTER_IP      MACHINE_TYPE   NODE_VERSION        NUM_NODES  STATUS   STACK_TYPE
alloydb-ai-gke  us-east4  1.36.4-gke.1391002  34.145.214.51  ek-standard-8  1.36.4-gke.1391002  3          RUNNING  IPV4

Подготовка кластера

Установите необходимые компоненты, например cert-manager, контроллер сертификатов для Kubernetes. Подробные сведения можно найти в документации по установке cert-manager.

В Cloud Shell есть инструмент командной строки Kubernetes kubectl и helm. Получите учетные данные кластера с помощью gcloud:

gcloud container clusters get-credentials ${CLUSTER_NAME} --region=${LOCATION}

Установите cert-manager с помощью helm:

helm install \
  cert-manager oci://quay.io/jetstack/charts/cert-manager \
  --version v1.21.2 \
  --namespace cert-manager \
  --create-namespace \
  --set featureGates="ServerSideApply=true" \
  --set global.leaderElection.namespace=cert-manager \
  --set "extraArgs={--certificate-request-minimum-backoff-duration=15s,--certificate-request-maximum-backoff-duration=5m}" \
  --set crds.enabled=true

Ожидаемый вывод в консоли (отредактированный):

student@cloudshell:~$ elm install \
>   cert-manager oci://quay.io/jetstack/charts/cert-manager \
>   --version v1.21.2 \
>   --namespace cert-manager \
>   --create-namespace \
>  --set featureGates="ServerSideApply=true" \
>  --set global.leaderElection.namespace=cert-manager \
>  --set "extraArgs={--certificate-request-minimum-backoff-duration=15s,--certificate-request-maximum-backoff-duration=5m}" \
>   --set crds.enabled=true
Pulled: quay.io/jetstack/charts/cert-manager:v1.21.2
Digest: sha256:634dce9c13b56677a2c05e2ab76c312d0be2664022d5dd05815da67e1fd5f610
I1016 12:25:06.128464   30644 warnings.go:107] "Warning: autopilot-default-resources-mutator:Autopilot updated Deployment cert-manager/cert-manager-cainjector: defaulted unspecified 'cpu' resource for containers [cert-manager-cainjector] (see http://g.co/gke/autopilot-defaults)."
I1016 12:25:06.129972   30644 warnings.go:107] "Warning: autopilot-default-resources-mutator:Autopilot updated Deployment cert-manager/cert-manager: defaulted unspecified 'cpu' resource for containers [cert-manager-controller] (see http://g.co/gke/autopilot-defaults)."
I1016 12:25:06.134580   30644 warnings.go:107] "Warning: autopilot-default-resources-mutator:Autopilot updated Deployment cert-manager/cert-manager-webhook: defaulted unspecified 'cpu' resource for containers [cert-manager-webhook] (see http://g.co/gke/autopilot-defaults)."
I1016 12:25:06.250590   30644 warnings.go:107] "Warning: AdmissionWebhookController: mutated namespaceselector of the webhooks to enforce GKE Autopilot policies."
I1016 12:25:09.758249   30644 warnings.go:107] "Warning: autopilot-default-resources-mutator:Autopilot updated Job cert-manager/cert-manager-startupapicheck: defaulted unspecified 'cpu' resource for containers [cert-manager-startupapicheck] (see http://g.co/gke/autopilot-defaults)."
NAME: cert-manager
LAST DEPLOYED: Fri Oct 16 12:24:57 2026
NAMESPACE: cert-manager
STATUS: deployed
REVISION: 1
DESCRIPTION: Install complete
TEST SUITE: None
NOTES:
cert-manager v1.21.2 has been deployed successfully!

Установите оператор AlloyDB Omni

Установите оператор AlloyDB Omni с помощью Helm.

Скачайте и установите диаграмму оператора AlloyDB Omni:

helm install alloydbomni-operator oci://gcr.io/alloydb-omni/alloydbomni-operator \
--version 1.9.0 \
--create-namespace \
--namespace alloydb-omni-system \
$(helm install --help | grep -q -- '--rollback-on-failure' && echo '--rollback-on-failure' || echo '--atomic') \
--timeout 5m

Ожидаемый вывод в консоли (отредактированный):

student@cloudshell:~$ helm install alloydbomni-operator oci://gcr.io/alloydb-omni/alloydbomni-operator \
> --version 1.9.0 \
> --create-namespace \
> --namespace alloydb-omni-system \
> $(helm install --help | grep -q -- '--rollback-on-failure' && echo '--rollback-on-failure' || echo '--atomic') \
> --timeout 5m

Pulled: gcr.io/alloydb-omni/alloydbomni-operator:1.9.0
Digest: sha256:4f6cc3f0c1fbe003ab7d0119afee516e5c67ec950cd2909b418e5a3f6f09d1f6
I1016 12:28:50.088533   30982 warnings.go:107] "Warning: autopilot-default-resources-mutator:Autopilot updated Deployment alloydb-omni-system/fleet-controller-manager: adjusted 'cpu' resource to meet requirements for containers [fleet-manager] (see http://g.co/gke/autopilot-defaults)."
I1016 12:28:50.092917   30982 warnings.go:107] "Warning: autopilot-default-resources-mutator:Autopilot updated Deployment alloydb-omni-system/local-controller-manager: adjusted 'cpu' resource to meet requirements for containers [local-manager] (see http://g.co/gke/autopilot-defaults)."
I1016 12:28:50.229717   30982 warnings.go:107] "Warning: AdmissionWebhookController: mutated namespaceselector of the webhooks to enforce GKE Autopilot policies."
I1016 12:28:50.238578   30982 warnings.go:107] "Warning: AdmissionWebhookController: mutated namespaceselector of the webhooks to enforce GKE Autopilot policies."
NAME: alloydbomni-operator
LAST DEPLOYED: Fri Oct 16 12:28:45 2026
NAMESPACE: alloydb-omni-system
STATUS: deployed
REVISION: 1
DESCRIPTION: Install complete
TEST SUITE: None

Разверните кластер базы данных.

В следующем манифесте настраивается кластер базы данных с включенным googleMLExtension и внутренним балансировщиком нагрузки:

cat << 'EOF' > my-omni.yaml
apiVersion: v1
kind: Secret
metadata:
  name: db-pw-my-omni
type: Opaque
data:
  my-omni: "VmVyeVN0cm9uZ1Bhc3N3b3Jk"
---
apiVersion: alloydbomni.dbadmin.goog/v1
kind: DBCluster
metadata:
  name: my-omni
spec:
  databaseVersion: "18.4.0"
  primarySpec:
    adminUser:
      passwordRef:
        name: db-pw-my-omni
    features:
      googleMLExtension:
        enabled: true
    resources:
      cpu: 1
      memory: 8Gi
      disks:
      - name: DataDisk
        size: 20Gi
    dbLoadBalancerOptions:
      annotations:
        networking.gke.io/load-balancer-type: "internal"
  allowExternalIncomingTraffic: true
EOF

Секретное значение пароля – это представление VeryStrongPassword в кодировке Base64. В рабочих средах для управления паролями используйте Google Secret Manager. Подробную информацию можно найти в документации Secret Manager.

Манифест сохраняется как my-omni.yaml. В Cloud Shell нажмите Открыть редактор в правом верхнем углу окна терминала и прочитайте файл.

Открыть редактор в Cloud Shell

Прочитав манифест my-omni.yaml, нажмите Открыть терминал, чтобы вернуться в командную строку.

Открыть терминал в Cloud Shell

Примените манифест my-omni.yaml:

kubectl apply -f my-omni.yaml

Ожидаемый результат в консоли:

secret/db-pw-my-omni created
dbcluster.alloydbomni.dbadmin.goog/my-omni created

Проверьте статус кластера my-omni:

kubectl get dbclusters.alloydbomni.dbadmin.goog my-omni -n default

Во время развертывания кластер базы данных проходит через этапы настройки, пока не достигнет состояния DBClusterReady.

Ожидаемый результат в консоли:

$ kubectl get dbclusters.alloydbomni.dbadmin.goog my-omni -n default
NAME      PRIMARYENDPOINT   PRIMARYPHASE   DBCLUSTERPHASE   HAREADYSTATUS   HAREADYREASON
my-omni   10.131.0.33        Ready          DBClusterReady

При желании вы можете отслеживать развертывание кластера с помощью команды kubectl log:

kubectl logs -l alloydbomni.internal.dbadmin.goog/dbcluster=my-omni --all-containers -f

Подключиться к AlloyDB Omni

Когда кластер будет готов, подключитесь к модулю базы данных с помощью клиента PostgreSQL (psql). Пароль – VeryStrongPassword, как указано в my-omni.yaml:

DB_CLUSTER_NAME=my-omni
DB_CLUSTER_NAMESPACE=default
DBPOD=`kubectl get pod --selector=alloydbomni.internal.dbadmin.goog/dbcluster=$DB_CLUSTER_NAME,alloydbomni.internal.dbadmin.goog/task-type=database -n $DB_CLUSTER_NAMESPACE -o jsonpath='{.items[0].metadata.name}'`
kubectl exec -ti $DBPOD -n $DB_CLUSTER_NAMESPACE -c database -- psql -h localhost -U postgres

Пример выходных данных консоли:

DB_CLUSTER_NAME=my-omni
DB_CLUSTER_NAMESPACE=default
DBPOD=`kubectl get pod --selector=alloydbomni.internal.dbadmin.goog/dbcluster=$DB_CLUSTER_NAME,alloydbomni.internal.dbadmin.goog/task-type=database -n $DB_CLUSTER_NAMESPACE -o jsonpath='{.items[0].metadata.name}'`
kubectl exec -ti $DBPOD -n $DB_CLUSTER_NAMESPACE -c database -- psql -h localhost -U postgres
Password for user postgres:
psql (18.4)
SSL connection (protocol: TLSv1.3, cipher: TLS_AES_128_GCM_SHA256, compression: off, ALPN: postgresql)
Type "help" for help.

postgres=#

Выйдите из сеанса psql, введя \q и нажав Enter:

postgres=# \q

5. Развертывание модели EmbeddingGemma в GKE

Чтобы протестировать интеграцию AlloyDB Omni AI с локальными моделями, разверните модель встраивания в кластере GKE. В этом руководстве используется модель Google EmbeddingGemma.

Как получить токен Hugging Face

В этом руководстве развертывается модель EmbeddingGemma из Hugging Face. Чтобы получить доступ к весам модели, сгенерируйте токен доступа Hugging Face:

  1. Войдите в аккаунт Hugging Face или создайте его.
  2. Перейдите в раздел Your Profile (Ваш профиль) > Access Tokens (Токены доступа).
  3. Нажмите Создать токен.
  4. Введите название токена и выберите роль Read (Чтение).
  5. Нажмите Создать токен и скопируйте сгенерированное значение токена.
  6. Примите условия использования модели на странице EmbeddingGemma, если вы ещё этого не сделали.

Создайте секрет Kubernetes, содержащий ваш токен Hugging Face, в Cloud Shell (замените плейсхолдер токена своим токеном):

export HF_TOKEN=<YOUR_HUGGING_FACE_TOKEN>
kubectl create secret generic hf-secret \
  --from-literal=hf_api_token=$HF_TOKEN \
  --dry-run=client -o yaml | kubectl apply -f -

Подготовка манифеста развертывания

Чтобы развернуть модель, используйте пакет контейнеров Text Embeddings Inference (TEI) от Hugging Face. Подробную информацию можно найти в документации Hugging Face по GKE TEI.

Клонируйте хранилище развертывания из GitHub:

git clone https://github.com/huggingface/Google-Cloud-Containers

Проверьте и измените манифест конфигурации ЦП:

edit Google-Cloud-Containers/examples/gke/tei-deployment/cpu-config/deployment.yaml

Обновленный манифест для развертывания ЦП:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: tei-deployment
spec:
  replicas: 1
  selector:
    matchLabels:
      app: tei-server
  template:
    metadata:
      labels:
        app: tei-server
        hf.co/model: Google--embeddinggemma-300m
        hf.co/task: text-embeddings
    spec:
      containers:
        - name: tei-container
          image: ghcr.io/huggingface/text-embeddings-inference:cpu-latest
          resources:
            requests:
              cpu: "6"
              memory: "24Gi"
            limits:
              cpu: "6"
              memory: "24Gi"
          env:
            - name: MODEL_ID
              value: google/embeddinggemma-300m
            - name: NUM_SHARD
              value: "1"
            - name: PORT
              value: "8080"
            - name: HF_TOKEN
              valueFrom:
                secretKeyRef:
                  name: hf-secret
                  key: hf_api_token
          volumeMounts:
            - mountPath: /tmp
              name: tmp
      volumes:
        - name: tmp
          emptyDir: {}
      nodeSelector:
        cloud.google.com/machine-family: "c3"

Сохраните изменения, нажав ctrl+s, и вернитесь в терминал.

Развертывание модели

Примените манифест, чтобы развернуть сервер TEI:

kubectl apply -f Google-Cloud-Containers/examples/gke/tei-deployment/cpu-config

Отслеживайте развертывание, пока оно не будет готово:

printf "Waiting for model to load..."; until kubectl logs -l app=tei-server --tail=50 2>/dev/null | grep -q "Ready"; do printf "."; sleep 3; done; printf '\n\033[1;32m========================================\n[SUCCESS] Model is loaded and ready!\nYou can now proceed to the next step.\n========================================\033[0m\n'

Проверьте сервис Kubernetes tei-service:

kubectl get service tei-service

Ожидаемый результат:

student@cloudshell$ kubectl get service tei-service
NAME          TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
tei-service   ClusterIP   34.118.233.48   <none>        8080/TCP   10m

Сервис CLUSTER-IP обрабатывает запросы внутри компании по адресу http://34.118.233.48:8080/embed.

Протестируйте конечную точку модели локально с помощью kubectl port-forward:

kubectl port-forward service/tei-service 8080:8080

Откройте вторую вкладку Cloud Shell, нажав + в верхней части терминала.

Добавить вкладку Cloud Shell

На новой вкладке протестируйте создание эмбеддингов с помощью curl:

curl http://localhost:8080/embed \
  -X POST \
  -d '{"inputs":"Test"}' \
  -H 'Content-Type: application/json'

Ожидаемый результат (массив векторов):

curl http://localhost:8080/embed \
>     -X POST \
>     -d '{"inputs":"Test"}' \
>     -H 'Content-Type: application/json'
[[-0.018975832,0.0071419072,0.06347208,0.022992613,0.014205903
...
-0.03677433,0.01636146,0.06731572]]

Остановите переадресацию портов на первой вкладке, нажав ctrl+c.

6. Зарегистрируйте модель встраивания в AlloyDB Omni

Чтобы использовать развернутую модель из AlloyDB Omni, создайте базу данных, определите функции преобразования и зарегистрируйте конечную точку модели.

Создайте клиентскую ВМ и базу данных

Создайте экземпляр виртуальной машины Compute Engine в той же сети VPC, чтобы использовать его в качестве клиентского хоста перехода:

Схема сетевой архитектуры, на которой показаны клиентская виртуальная машина и AlloyDB Omni

В Cloud Shell создайте клиентскую ВМ:

export ZONE=${LOCATION}-a
gcloud compute instances create instance-1 \
  --zone=$ZONE

Получите IP-адрес конечной точки AlloyDB Omni:

echo "INSTANCE_IP=$(kubectl get dbclusters.alloydbomni.dbadmin.goog my-omni -n default -o jsonpath='{.status.primary.endpoint}')"

Ожидаемый результат:

INSTANCE_IP=10.128.0.33

Значение INSTANCE_IP – это IP-адрес внутреннего балансировщика нагрузки для кластера AlloyDB Omni. В нашем примере это 10.131.0.33.

Подключитесь к экземпляру виртуальной машины по SSH:

gcloud compute ssh instance-1 --zone=$ZONE

В сеансе SSH на instance-1 установите клиент PostgreSQL:

sudo apt-get update && sudo apt-get install --yes postgresql-client 

Экспортируйте IP-адрес балансировщика нагрузки AlloyDB Omni (замените на свой IP-адрес PRIMARYENDPOINT):

export INSTANCE_IP=10.131.0.33

Подключитесь к AlloyDB Omni с помощью psql (пароль – VeryStrongPassword):

psql "host=$INSTANCE_IP user=postgres sslmode=require"

В сеансе psql создайте базу данных demo:

CREATE DATABASE demo;

Переключитесь на базу данных demo:

\c demo

Как создать функцию преобразования

Для пользовательских конечных точек встраивания требуются функции преобразования входных и выходных данных, чтобы адаптировать форматы данных между AlloyDB Omni и API модели.

Создайте функцию преобразования входных данных:

CREATE OR REPLACE FUNCTION tei_text_input_transform(model_id VARCHAR(100), input_text TEXT)
RETURNS JSON
LANGUAGE plpgsql
AS $$
DECLARE
  transformed_input JSON;
BEGIN
  SELECT json_build_object('inputs', input_text, 'truncate', true)::JSON INTO transformed_input;
  RETURN transformed_input;
END;
$$;

Ожидаемый результат:

demo=# CREATE OR REPLACE FUNCTION tei_text_input_transform(model_id VARCHAR(100), input_text TEXT)
RETURNS JSON
LANGUAGE plpgsql
AS $$
DECLARE
  transformed_input JSON;
BEGIN
  SELECT json_build_object('inputs', input_text, 'truncate', true)::JSON INTO transformed_input;
  RETURN transformed_input;
END;
$$;
CREATE FUNCTION
demo=#

Создайте функцию преобразования выходных данных, чтобы проанализировать ответ массива векторов:

CREATE OR REPLACE FUNCTION tei_text_output_transform(model_id VARCHAR(100), response_json JSON)
RETURNS REAL[]
LANGUAGE plpgsql
AS $$
DECLARE
  transformed_output REAL[];
BEGIN
  SELECT ARRAY(SELECT json_array_elements_text(response_json->0)) INTO transformed_output;
  RETURN transformed_output;
END;
$$;

Ожидаемый результат:

demo=# CREATE OR REPLACE FUNCTION tei_text_output_transform(model_id VARCHAR(100), response_json JSON)
RETURNS REAL[]
LANGUAGE plpgsql
AS $$
DECLARE
  transformed_output REAL[];
BEGIN
  SELECT ARRAY(SELECT json_array_elements_text(response_json->0)) INTO transformed_output;
  RETURN transformed_output;
END;
$$;
CREATE FUNCTION
demo=#

Зарегистрируйте модель

Зарегистрируйте модель в AlloyDB Omni с помощью процедуры google_ml.create_model. Укажите http://tei-service:8080/embed в качестве model_request_url, чтобы направлять запросы в сервис кластера Kubernetes:

CALL
  google_ml.create_model(
    model_id => 'embeddinggemma',
    model_request_url => 'http://tei-service:8080/embed',
    model_provider => 'custom',
    model_type => 'text_embedding',
    model_in_transform_fn => 'tei_text_input_transform',
    model_out_transform_fn => 'tei_text_output_transform');

Ожидаемый результат:

demo=# CALL
  google_ml.create_model(
    model_id => 'embeddinggemma',
    model_request_url => 'http://tei-service:8080/embed',
    model_provider => 'custom',
    model_type => 'text_embedding',
    model_in_transform_fn => 'tei_text_input_transform',
    model_out_transform_fn => 'tei_text_output_transform');
CALL
demo=#

Протестируйте зарегистрированную модель с помощью примера SQL-запроса:

SELECT google_ml.embedding('embeddinggemma', 'What is AlloyDB Omni?');

Функция возвращает представление массива действительных чисел, сгенерированное локальной моделью EmbeddingGemma, работающей в GKE.

Нажмите q, чтобы вернуться к запросу сеанса psql.

Выйдите из сеанса psql:

\q

7. Протестируйте модель на выборке данных

Загрузить пример данных

В этом руководстве для демонстрации векторного поиска по сходству используется набор данных Cymbal Retail. Вы будете использовать Google Cloud SDK и клиент PostgreSQL для импорта данных в AlloyDB Omni.

В сеансе SSH на instance-1 подключитесь к демонстрационной базе данных и включите расширение vector:

psql "host=$INSTANCE_IP user=postgres sslmode=require dbname=demo"

В сеансе psql:

CREATE EXTENSION IF NOT EXISTS vector;

Выйдите из сеанса psql:

\q

Скачайте и примените схему, чтобы создать таблицы в базе данных demo:

gcloud storage cat gs://cloud-training/gcc/gcc-tech-004/cymbal_demo_schema.sql |psql "host=$INSTANCE_IP user=postgres dbname=demo"

Ожидаемый результат:

student@cloudshell:~$ gcloud storage cat gs://cloud-training/gcc/gcc-tech-004/cymbal_demo_schema.sql |psql "host=$INSTANCE_IP user=postgres dbname=demo"
Password for user postgres:
SET
SET
SET
SET
SET
 set_config
------------

(1 row)

SET
SET
SET
SET
SET
SET
CREATE TABLE
ALTER TABLE
CREATE TABLE
ALTER TABLE
CREATE TABLE
ALTER TABLE
CREATE TABLE
ALTER TABLE
CREATE SEQUENCE
ALTER TABLE
ALTER SEQUENCE
ALTER TABLE
ALTER TABLE
ALTER TABLE
student@cloudshell:~$

Проверьте созданные таблицы:

psql "host=$INSTANCE_IP user=postgres dbname=demo" -c "\dt+"

Ожидаемый результат:

student@cloudshell:~$ psql "host=$INSTANCE_IP user=postgres dbname=demo" -c "\dt+"
Password for user postgres: 
                                           List of relations
 Schema |       Name       | Type  |  Owner   | Persistence | Access method |    Size    | Description 
--------+------------------+-------+----------+-------------+---------------+------------+-------------
 public | cymbal_embedding | table | postgres | permanent   | heap          | 8192 bytes | 
 public | cymbal_inventory | table | postgres | permanent   | heap          | 8192 bytes | 
 public | cymbal_products  | table | postgres | permanent   | heap          | 8192 bytes | 
 public | cymbal_stores    | table | postgres | permanent   | heap          | 8192 bytes | 
(4 rows)

Загрузите данные в таблицу cymbal_products:

gcloud storage cat gs://cloud-training/gcc/gcc-tech-004/cymbal_products.csv |psql "host=$INSTANCE_IP user=postgres dbname=demo" -c "\copy cymbal_products from stdin csv header"

Ожидаемый результат:

student@cloudshell:~$ gcloud storage cat gs://cloud-training/gcc/gcc-tech-004/cymbal_products.csv |psql "host=$INSTANCE_IP user=postgres dbname=demo" -c "\copy cymbal_products from stdin csv header"
COPY 941
student@cloudshell:~$ 

Ниже приведен пример нескольких строк из таблицы cymbal_products.

psql "host=$INSTANCE_IP user=postgres dbname=demo" -c "SELECT uniq_id,left(product_name,30),left(product_description,50),sale_price FROM cymbal_products limit 3"

Ожидаемый результат:

student@cloudshell:~$ psql "host=$INSTANCE_IP user=postgres dbname=demo" -c "SELECT uniq_id,left(product_name,30),left(product_description,50),sale_price FROM cymbal_products limit 3"
Password for user postgres: 
             uniq_id              |              left              |                        left                        | sale_price 
----------------------------------+--------------------------------+----------------------------------------------------+------------
 a73d5f754f225ecb9fdc64232a57bc37 | Laundry Tub Strainer Cup       |   Laundry tub strainer cup Chrome For 1-.50, drain |      11.74
 41b8993891aa7d39352f092ace8f3a86 | LED Starry Star Night Light La |  LED Starry Star Night Light Laser Projector 3D Oc |      46.97
 ed4a5c1b02990a1bebec908d416fe801 | Surya Horizon HRZ-1060 Area Ru |  The 100% polypropylene construction of the Surya  |       77.4
(3 rows)
student@cloudshell:~$ 

Загрузите данные в таблицу cymbal_inventory:

gcloud storage cat gs://cloud-training/gcc/gcc-tech-004/cymbal_inventory.csv |psql "host=$INSTANCE_IP user=postgres dbname=demo" -c "\copy cymbal_inventory from stdin csv header"

Ожидаемый результат:

student@cloudshell:~$ gcloud storage cat gs://cloud-training/gcc/gcc-tech-004/cymbal_inventory.csv |psql "host=$INSTANCE_IP user=postgres dbname=demo" -c "\copy cymbal_inventory from stdin csv header"
Password for user postgres: 
COPY 263861
student@cloudshell:~$ 

Ниже приведен пример нескольких строк из таблицы cymbal_inventory.

psql "host=$INSTANCE_IP user=postgres dbname=demo" -c "SELECT * FROM cymbal_inventory LIMIT 3"

Вывод:

student@cloudshell:~$ psql "host=$INSTANCE_IP user=postgres dbname=demo" -c "SELECT * FROM cymbal_inventory LIMIT 3"
Password for user postgres: 
 store_id |             uniq_id              | inventory 
----------+----------------------------------+-----------
     1583 | adc4964a6138d1148b1d98c557546695 |         5
     1490 | adc4964a6138d1148b1d98c557546695 |         4
     1492 | adc4964a6138d1148b1d98c557546695 |         3
(3 rows)
student@cloudshell:~$ 

Загрузите данные в таблицу cymbal_stores:

gcloud storage cat gs://cloud-training/gcc/gcc-tech-004/cymbal_stores.csv |psql "host=$INSTANCE_IP user=postgres dbname=demo" -c "\copy cymbal_stores from stdin csv header"

Ожидаемый результат в консоли:

student@cloudshell:~$ gcloud storage cat gs://cloud-training/gcc/gcc-tech-004/cymbal_stores.csv |psql "host=$INSTANCE_IP user=postgres dbname=demo" -c "\copy cymbal_stores from stdin csv header"
Password for user postgres: 
COPY 4654
student@cloudshell:~$

Ниже приведен пример нескольких строк из таблицы cymbal_stores.

psql "host=$INSTANCE_IP user=postgres dbname=demo" -c "SELECT store_id, name, zip_code FROM cymbal_stores limit 3"

Вывод:

student@cloudshell:~$ psql "host=$INSTANCE_IP user=postgres dbname=demo" -c "SELECT store_id, name, zip_code FROM cymbal_stores limit 3"
Password for user postgres: 
 store_id |       name        | zip_code 
----------+-------------------+----------
     1990 | Mayaguez Store    |      680
     2267 | Ware Supercenter  |     1082
     4359 | Ponce Supercenter |      780
(3 rows)
student@cloudshell:~$ 

Создание эмбеддингов

Подключитесь к демонстрационной базе данных с помощью psql и создайте эмбеддинги для товаров, описанных в таблице cymbal_products, на основе описаний товаров.

Подключитесь к демонстрационной базе данных:

psql "host=$INSTANCE_IP user=postgres sslmode=require dbname=demo"

Используйте столбец embedding типа vector для хранения сгенерированных текстовых эмбеддингов для описаний товаров.

Включите хронометраж запросов:

\timing

Сгенерируйте эмбеддинги для каждого описания товара и сохраните их в таблице cymbal_embedding:

INSERT INTO cymbal_embedding (uniq_id, embedding)
SELECT uniq_id, google_ml.embedding('embeddinggemma', product_description)::vector
FROM cymbal_products;

Ожидаемый результат:

demo=# INSERT INTO cymbal_embedding(uniq_id,embedding)  SELECT uniq_id, google_ml.embedding('embeddinggemma',product_description)::vector FROM cymbal_products;
INSERT 0 941
Time: 497878.136 ms (08:17.878)
demo=#

Как выполнять семантические поисковые запросы

В сеансе psql найдите пять товаров, которые лучше всего соответствуют вопросу "What kind of fruit trees grow well here?", используя косинусное расстояние (<=>).

SELECT
    cp.product_name,
    left(cp.product_description, 80) AS description,
    cp.sale_price,
    cs.zip_code,
    (ce.embedding <=> google_ml.embedding('embeddinggemma', 'What kind of fruit trees grow well here?')::vector) AS distance
FROM
    cymbal_products cp
JOIN cymbal_embedding ce ON ce.uniq_id = cp.uniq_id
JOIN cymbal_inventory ci ON ci.uniq_id = cp.uniq_id
JOIN cymbal_stores cs ON cs.store_id = ci.store_id
WHERE
    ci.inventory > 0
    AND cs.store_id = 1583
ORDER BY
    distance ASC
LIMIT 5;

Ожидаемый результат:

demo=# SELECT
        cp.product_name,
        left(cp.product_description,80) as description,
        cp.sale_price,
        cs.zip_code,
        (ce.embedding <=> google_ml.embedding('embeddinggemma','What kind of fruit trees grow well here?')::vector) as distance
FROM
        cymbal_products cp
JOIN cymbal_embedding ce on ce.uniq_id=cp.uniq_id
JOIN cymbal_inventory ci on ci.uniq_id=cp.uniq_id
JOIN cymbal_stores cs on cs.store_id=ci.store_id
WHERE
    ci.inventory > 0
    AND cs.store_id = 1583
ORDER BY
    distance ASC
LIMIT 5;
     product_name      |                                   description                                    | sale_price | zip_code |      distance
-----------------------+----------------------------------------------------------------------------------+------------+----------+--------------------
 Cherry Tree           | This is a beautiful cherry tree that will produce delicious cherries. It is an d |      75.00 |    93230 | 0.5210549378080666
 California Lilac      | This is a beautiful lilac tree that can grow to be over 10 feet tall. It is an d |       5.00 |    93230 | 0.5639421771781971
 Toyon                 | This is a beautiful toyon tree that can grow to be over 20 feet tall. It is an e |      10.00 |    93230 | 0.5670010914504852
 Rose Bush             | This is a beautiful rose bush that will produce fragrant roses. It is a perennia |      50.00 |    93230 | 0.5731542622882957
 California Peppertree | This is a beautiful peppertree that can grow to be over 30 feet tall. It is an e |      25.00 |    93230 | 0.5750934653011995
(5 rows)

Time: 83.610 ms
demo=#

Запрос выполнялся 83 мс и вернул список деревьев из таблицы cymbal_products, соответствующих запросу и имеющихся в наличии в магазине с номером 1583.

Создание индекса ANN

При небольшом наборе данных легко использовать точный поиск, сканирующий все эмбеддинги, но по мере роста данных время загрузки и ответа также увеличивается. Чтобы повысить производительность, вы можете создать индексы для данных эмбеддингов. Вот пример того, как это сделать с помощью индекса Google ScaNN для векторных данных.

Если подключение к демобазе данных прервалось, восстановите его:

psql "host=$INSTANCE_IP user=postgres sslmode=require dbname=demo"

Включите расширение alloydb_scann:

CREATE EXTENSION IF NOT EXISTS alloydb_scann;

Создайте индекс ScaNN в столбце embedding:

CREATE INDEX cymbal_products_embeddings_scann ON cymbal_embedding
  USING scann (embedding cosine)
  WITH (num_leaves=10, max_num_levels = 1);

Повторно выполните семантический поисковый запрос, чтобы сравнить производительность:

SELECT
    cp.product_name,
    left(cp.product_description, 80) AS description,
    cp.sale_price,
    cs.zip_code,
    (ce.embedding <=> google_ml.embedding('embeddinggemma', 'What kind of fruit trees grow well here?')::vector) AS distance
FROM
    cymbal_products cp
JOIN cymbal_embedding ce ON ce.uniq_id = cp.uniq_id
JOIN cymbal_inventory ci ON ci.uniq_id = cp.uniq_id
JOIN cymbal_stores cs ON cs.store_id = ci.store_id
WHERE
    ci.inventory > 0
    AND cs.store_id = 1583
ORDER BY
    distance ASC
LIMIT 5;

Ожидаемый результат:

demo=# SELECT
    cp.product_name,
    left(cp.product_description,80) as description,
    cp.sale_price,
    cs.zip_code,
    (ce.embedding <=> google_ml.embedding('embeddinggemma', 'What kind of fruit trees grow well here?')::vector) AS distance
FROM
    cymbal_products cp
JOIN cymbal_embedding ce ON ce.uniq_id = cp.uniq_id
JOIN cymbal_inventory ci ON ci.uniq_id = cp.uniq_id
JOIN cymbal_stores cs ON cs.store_id = ci.store_id
WHERE
    ci.inventory > 0
    AND cs.store_id = 1583
ORDER BY
    distance ASC
LIMIT 5;
     product_name      |                                   description                                    | sale_price | zip_code |      distance
-----------------------+----------------------------------------------------------------------------------+------------+----------+--------------------
 Cherry Tree           | This is a beautiful cherry tree that will produce delicious cherries. It is an d |      75.00 |    93230 | 0.5210549378080666
 California Lilac      | This is a beautiful lilac tree that can grow to be over 10 feet tall. It is an d |       5.00 |    93230 | 0.5639421771781971
 Toyon                 | This is a beautiful toyon tree that can grow to be over 20 feet tall. It is an e |      10.00 |    93230 | 0.5670010914504852
 Rose Bush             | This is a beautiful rose bush that will produce fragrant roses. It is a perennia |      50.00 |    93230 | 0.5731542622882957
 California Peppertree | This is a beautiful peppertree that can grow to be over 30 feet tall. It is an e |      25.00 |    93230 | 0.5750934653011995
(5 rows)

Time: 64.783 ms

Время выполнения запроса немного сократилось, и выигрыш будет более заметен при работе с более крупными наборами данных. Возвращенные данные должны быть такими же или очень похожими на те, которые мы получили без индекса.

Попробуйте другие запросы и прочитайте больше об оптимизации векторного индекса в документации.

Выйдите из сеанса psql:

\q

Вернитесь в Google Cloud Shell, отключившись от сеанса SSH instance-1. Для этого нажмите Ctrl + D или введите exit.

8. Развертывание Gemma с помощью vLLM

Добавьте пул узлов для Gemma

Сначала проверьте, какие типы узлов доступны в вашем регионе:

gcloud compute accelerator-types list --filter="zone:${LOCATION}"

Вы увидите список доступных типов ускорителей, включая nvidia-l4.

Создайте манифест развертывания для модели Google Gemini 4 12B с помощью vLLM:

cat << 'EOF' > gemma-12b-gpu-vllm-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: gemma-12b-gpu-vllm-deployment
spec:
  replicas: 1
  selector:
    matchLabels:
      app: gemma-12b-gpu-vllm
  template:
    metadata:
      labels:
        app: gemma-12b-gpu-vllm
        ai.gke.io/model: gemma-4-12b-it
        ai.gke.io/inference-server: vllm
        examples.ai.gke.io/source: user-guide
    spec:
      containers:
      - name: inference-server
        image: us-docker.pkg.dev/vertex-ai/vertex-vision-model-garden-dockers/pytorch-vllm-serve:latest
        resources:
          requests:
            cpu: "4"
            memory: "16Gi"
            ephemeral-storage: "30Gi"
            nvidia.com/gpu: "1"
          limits:
            cpu: "8"
            memory: "24Gi"
            ephemeral-storage: "30Gi"
            nvidia.com/gpu: "1"
        command: ["python3", "-m", "vllm.entrypoints.api_server"]
        args:
          - --model=$(MODEL_ID)
          - --host=0.0.0.0
          - --port=8000
          - --tensor-parallel-size=1
          - --enable-log-requests
          - --enable-chunked-prefill
          - --enable-prefix-caching
          - --enable-auto-tool-choice
          - --generation-config=auto
          - --tool-call-parser=gemma4
          - --dtype=bfloat16
          - --max-num-seqs=16
          - --max-model-len=32768
          - --gpu-memory-utilization=0.95
          - --reasoning-parser=gemma4
          - --trust-remote-code
          - --quantization=fp8
        env:
        - name: LD_LIBRARY_PATH
          value: ${LD_LIBRARY_PATH}:/usr/local/nvidia/lib64
        - name: MODEL_ID
          value: google/gemma-4-12b-it
        - name: HF_TOKEN
          valueFrom:
            secretKeyRef:
              name: hf-secret
              key: hf_api_token
        volumeMounts:
        - mountPath: /dev/shm
          name: dshm
      volumes:
      - name: dshm
        emptyDir:
            medium: Memory
      nodeSelector:
        cloud.google.com/gke-accelerator: nvidia-l4
        cloud.google.com/gke-gpu-driver-version: latest
---
apiVersion: v1
kind: Service
metadata:
  name: gemma-12b-gpu-vllm-service
spec:
  selector:
    app: gemma-12b-gpu-vllm
  type: ClusterIP
  ports:
    - protocol: TCP
      port: 8000
      targetPort: 8000
EOF

Примените сохраненное развертывание gemma-12b-gpu-vllm-deployment.yaml:

kubectl apply -f gemma-12b-gpu-vllm-deployment.yaml

Ожидаемый результат:

$ kubectl apply -f gemma-12b-gpu-vllm-deployment.yaml
deployment.apps/gemma-12b-gpu-vllm-deployment created
service/gemma-12b-gpu-vllm-service created

Дождитесь завершения развертывания и загрузки модели. Это может занять несколько минут.

printf "Waiting for model to load..."; until kubectl logs -l app=gemma-12b-gpu-vllm --tail=50 2>/dev/null | grep -q "Application startup complete"; do printf "."; sleep 3; done; printf '\n\033[1;32m========================================\n[SUCCESS] Model is loaded and ready!\nYou can now proceed to the next step.\n========================================\033[0m\n'

Ожидаемый результат:

Waiting for model to load...
========================================
[SUCCESS] Model is loaded and ready!
You can now proceed to the next step.
========================================

Протестируйте модель. Включите переадресацию портов, чтобы получить доступ к модели:

kubectl port-forward svc/gemma-12b-gpu-vllm-service 8090:8000

В другом окне терминала используйте curl, чтобы отправить запрос модели:

curl http://localhost:8090/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{
    "messages": [
      {"role": "system", "content": "You are a helpful assistant running on GKE."},
      {"role": "user", "content": "What is AlloyDB Omni."}
    ],
    "temperature": 0.7
  }' | jq -r '.choices[0].message.content'

Ожидаемый результат:

  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  3957  100  3761  100   196     85      4  0:00:49  0:00:43  0:00:06   830
**AlloyDB Omni** is a fully managed, PostgreSQL-compatible database engine from Google Cloud that can be run **on-premises, in other clouds, or in your own data centers.**

To understand it simply: It allows you to run the high-performance, enterprise-grade capabilities of Google's **AlloyDB** (a cloud-native database) on your own infrastructure.

Here is a breakdown of what makes it significant:

### 1. The "Best of Both Worlds" Architecture
Normally, you have to choose between:
*   **Managed Cloud Databases:** Easy to scale and manage, but you are locked into the cloud provider's infrastructure.
*   **Self-Managed Databases:** You have full control over the hardware/location, but you are responsible for scaling, patching, and high availability.

**AlloyDB Omni** bridges this gap. It provides the advanced features of a cloud-native database (like intelligent indexing, high availability, and massive scalability) while allowing you to run it anywhere.

Остановите переадресацию портов в первом терминале (если она все ещё выполняется), нажав Ctrl+C.

9. Как зарегистрировать модель Gemma 4 в AlloyDB Omni

Зарегистрируйте модель Gemma 12B в AlloyDB Omni с помощью процедуры google_ml.create_model. Укажите http://gemma-12b-gpu-vllm-service:8000/v1/chat/completions в качестве model_request_url, чтобы направлять запросы в сервис кластера Kubernetes:

Получите IP-адрес конечной точки AlloyDB Omni:

echo "INSTANCE_IP=$(kubectl get dbclusters.alloydbomni.dbadmin.goog my-omni -n default -o jsonpath='{.status.primary.endpoint}')"

Подключитесь к экземпляру виртуальной машины по SSH:

gcloud compute ssh instance-1 --zone=$ZONE

После подключения к виртуальной машине экспортируйте переменную INSTANCE_IP из предыдущего шага (значение 10.128.0.33 приведено в качестве примера, замените его своим IP-адресом):

export INSTANCE_IP=10.128.0.33

Экспортируйте пароль AlloyDB:

export PGPASSWORD=VeryStrongPassword

Подключитесь к базе данных demo:

psql "host=$INSTANCE_IP user=postgres sslmode=require dbname=demo"

Зарегистрируйте модель в сеансе psql:

CALL
  google_ml.create_model(
    model_id => 'gemma-12b-gpu',
    model_request_url => 'http://gemma-12b-gpu-vllm-service:8000/v1/chat/completions',
    model_provider => 'custom',
    model_type => 'llm');

Протестируйте модель с помощью примера SQL-запроса:

SELECT google_ml.predict_row(
  model_id => 'gemma-12b-gpu',
  request_body => json_build_object(
    'messages', json_build_array(
      json_build_object('role', 'user', 'content', 'What is AlloyDB Omni?'))))->'choices'->0->'message'->'content';

Чтобы закрыть окно с результатами и вернуться к запросу psql, нажмите q.

Как объединить векторный поиск с RAG на основе LLM в AlloyDB Omni

Используйте векторный поиск с запросом LLM, чтобы продемонстрировать RAG (генерацию с дополненной выборкой) с LLM.

Выполните SQL-запрос в plsql:

WITH trees AS (
SELECT
        cp.product_name,
        cp.product_description AS description,
        cp.sale_price,
        cs.zip_code,
        cp.uniq_id AS product_id
FROM
    cymbal_products cp
JOIN cymbal_embedding ce ON ce.uniq_id = cp.uniq_id
JOIN cymbal_inventory ci ON ci.uniq_id = cp.uniq_id
JOIN cymbal_stores cs ON cs.store_id = ci.store_id
WHERE
        ci.inventory>0
        AND cs.store_id = 1583
ORDER BY
        (ce.embedding <=> embedding('embeddinggemma',
        'What kind of fruit trees grow well here?')::vector) ASC
LIMIT 1),
prompt AS (
SELECT
        'You are a friendly advisor helping to find a product based on the customer''s needs.
Based on the client request we have loaded a list of products closely related to search.
The list in JSON format with list of values like {"product_name":"name","product_description":"some description","sale_price":10}
Here is the list of products:' || json_agg(trees) || 'The customer asked "What kind of fruit trees grow well here?"
You should give information about the product, price and some supplemental information' AS prompt_text
FROM
        trees),
response AS (
SELECT
        google_ml.predict_row(
          model_id =>'gemma-12b-gpu',
          request_body => json_build_object(
            'messages', json_build_array(
              json_build_object('role', 'user', 'content',prompt_text)
            )))->'choices'->0->'message'->'content' AS resp
FROM
        prompt)
SELECT
REPLACE(resp::text, '\n', CHR(10))
FROM
        response;

Ожидаемый результат:

----------------------------------------------------------------------------------------------------------------------------------------------
 "Hello there! I'd be happy to help you find the perfect tree for your garden.                                                               +
                                                                                                                                             +
 Based on your location, we have a wonderful option that would grow beautifully in your area:                                                +
                                                                                                                                             +
 **Cherry Tree**                                                                                                                             +
 *   **Price:** $75.00                                                                                                                       +
 *   **Description:** This is a stunning deciduous tree that not only provides a beautiful landscape but also produces delicious cherries.   +
 *   **Supplemental Information:**                                                                                                           +
     *   **Growth:** It grows to about 15 feet tall.                                                                                         +
     *   **Appearance:** You can look forward to dark green leaves in the summer that transform into a vibrant red in the fall.              +
     *   **Benefits:** It's a great choice if you're looking for both fruit and extra shade or privacy in your yard.                         +
     *   **Care Tips:** It performs best in a cool, moist climate with sandy soil. Since you are in a suitable zone, it should thrive nicely!+
                                                                                                                                             +
 Would you like more details on how to plant this, or would you like to proceed with an order?"
(1 row)

Запрос дополняет запрос к LLM результатами векторного поиска.

Попробуйте другие запросы и поэкспериментируйте с шаблонами RAG. Преимущество представленной архитектуры заключается в ее полной самодостаточности. Данные не передаются за пределы кластера, и он может работать в полностью изолированных средах.

Выход из сеанса psql:

\q

Отключитесь от сеанса SSH на виртуальной машине:

exit

Не забывайте, что в AlloyDB Omni есть и другие функции и экспериментальные возможности.

10. Очистка среды

Чтобы избежать постоянных списаний средств с вашего аккаунта Google Cloud, удалите ресурсы, созданные в этой практической работе.

Удалите кластер GKE

В Cloud Shell удалите кластер GKE:

export PROJECT_ID=$(gcloud config get-value project)
export CLUSTER_NAME=alloydb-ai-gke
gcloud container clusters delete ${CLUSTER_NAME} \
  --project=${PROJECT_ID} \
  --region=${LOCATION}

Ожидаемый результат:

student@cloudshell:~$ gcloud container clusters delete ${CLUSTER_NAME} \
>   --project=${PROJECT_ID} \
>   --region=${LOCATION}
The following clusters will be deleted.
 - [alloydb-ai-gke] in [us-east4]

Do you want to continue (Y/n)?  Y

Deleting cluster alloydb-ai-gke...done.
Deleted

Удалите клиентскую ВМ

В Cloud Shell удалите экземпляр Compute Engine:

export PROJECT_ID=$(gcloud config get-value project)
gcloud compute instances delete instance-1 \
  --project=${PROJECT_ID} \
  --zone=${ZONE}

Ожидаемый результат:

student@cloudshell:~$ export PROJECT_ID=$(gcloud config get project)
export ZONE=us-east4-a
gcloud compute instances delete instance-1 \
  --project=${PROJECT_ID} \
  --zone=${ZONE}
Your active configuration is: [cloudshell-5399]
The following instances will be deleted. Any attached disks configured to be auto-deleted will be deleted unless they are attached to any other instances or the `--keep-disks` flag is given and specifies them for keeping. Deleting a disk 
is irreversible and any data on the disk will be lost.
 - [instance-1] in [us-east4-a]

Do you want to continue (Y/n)?  Y

Deleted

Если вы создали новый проект для этой практической работы, вы можете удалить его в Google Cloud Resource Manager.

11. Поздравляю!

Поздравляем! Вы выполнили практическую работу.

Что вы узнали

  • Как развернуть AlloyDB Omni в кластере GKE.
  • Как подключиться к AlloyDB Omni
  • Как загрузить данные в AlloyDB Omni
  • Как развернуть ИИ-модели (эмбеддинг и LLM) в GKE.
  • Как зарегистрировать ИИ-модели в AlloyDB Omni
  • Как генерировать эмбеддинги для семантического поиска
  • Как выполнять запросы семантического поиска в AlloyDB Omni
  • Как создавать и использовать векторные индексы в AlloyDB Omni

Подробнее о работе с ИИ в AlloyDB Omni рассказывается в документации.

Опрос

Вывод:

Как вы будете использовать это руководство?

Только прочитал Прочитал и выполнил упражнения