AlloyDB Omni i EmbeddingGemma z Gemma 4 w Kubernetes

1. Wprowadzenie

Z tego ćwiczenia dowiesz się, jak wdrożyć AlloyDB Omni w Google Kubernetes Engine (GKE) i używać go z otwartymi modelami, takimi jak EmbeddingGemma i Gemma 4, do generowania wektorów dystrybucyjnych i prognoz. Uruchamianie bazy danych i modeli w tym samym klastrze zmniejsza opóźnienia sieci i pozwala uniknąć zależności od usług innych firm. Pomaga też spełnić wymagania dotyczące zgodności i miejsca przechowywania danych, ponieważ dane nigdy nie opuszczają Twojego środowiska.

Schemat architektury AlloyDB Omni i EmbeddingGemma w GKE

Wymagania wstępne

  • podstawowa wiedza o Google Cloud i konsoli Google Cloud,
  • podstawową wiedzę o Kubernetes i GKE,
  • znajomość interfejsu wiersza poleceń i Google Cloud Shell,

Czego się nauczysz

  • Jak wdrożyć AlloyDB Omni w klastrze GKE
  • Jak połączyć się z AlloyDB Omni
  • Jak wczytać dane do AlloyDB Omni
  • jak wdrażać modele AI (wektory dystrybucyjne i LLM) w GKE,
  • Jak zarejestrować modele AI w AlloyDB Omni
  • Jak wygenerować wektory dystrybucyjne na potrzeby wyszukiwania semantycznego
  • Jak wykonywać zapytania wyszukiwania semantycznego w AlloyDB Omni
  • Jak tworzyć i wykorzystywać indeksy wektorowe w AlloyDB Omni

Czego potrzebujesz

  • konto Google Cloud i projekt w chmurze Google Cloud,
  • przeglądarkę internetową, np. Chrome;

2. Konfiguracja i wymagania

Konfigurowanie projektu

  1. Zaloguj się w konsoli Google Cloud. Jeśli nie masz jeszcze konta Gmail lub Google Workspace, utwórz je. Użyj konta osobistego zamiast służbowego lub szkolnego.
  1. Utwórz nowy projekt lub wybierz już istniejący. W nagłówku konsoli Google Cloud kliknij Wybierz projekt, a następnie Nowy projekt.

Okno Wybierz projekt w konsoli Google Cloud

W oknie Wybierz projekt kliknij Nowy projekt, aby otworzyć okno tworzenia projektu.

Okno tworzenia nowego projektu

W oknie wpisz nazwę projektu i wybierz organizację lub lokalizację.

Pola do wprowadzania danych dotyczących szczegółów projektu

  • Nazwa projektu to wyświetlana nazwa dla uczestników tego projektu. Nazwa projektu nie jest używana przez interfejsy API Google i możesz ją zmienić w dowolnym momencie.
  • Identyfikator projektu jest unikalny we wszystkich projektach Google Cloud i nie można go zmienić po ustawieniu. Konsola Google Cloud automatycznie wygeneruje unikalny identyfikator, ale możesz też podać własny. W tym ćwiczeniu identyfikator projektu jest oznaczony obiektem zastępczym .
  • Numer projektu to trzeci identyfikator używany przez niektóre interfejsy API. Więcej informacji znajdziesz w dokumentacji Menedżera zasobów.

Włącz płatności

Jeśli konfigurujesz płatności za pomocą środków w Google Cloud, możesz pominąć ten krok.

Aby skonfigurować osobiste konto rozliczeniowe, włącz płatności w konsoli Google Cloud.

Uruchamianie Cloud Shell

W tym ćwiczeniu używasz Google Cloud Shell, czyli środowiska wiersza poleceń działającego w chmurze.

W konsoli Google Cloud kliknij ikonę Aktywuj Cloud Shell na pasku narzędzi w prawym górnym rogu:

Przycisk aktywacji Cloud Shell

Możesz też nacisnąć G, a potem S lub otworzyć Google Cloud Shell bezpośrednio.

Po nawiązaniu połączenia Cloud Shell wyświetla znak zachęty terminala:

Zrzut ekranu terminala Google Cloud Shell

Cloud Shell obejmuje pamięć trwałą i narzędzia dla programistów. Wszystkie kroki opisane w tym ćwiczeniu możesz wykonać w przeglądarce.

3. Włącz interfejsy API

Aby używać Google Kubernetes Engine (GKE) do wdrażania AlloyDB Omni i modeli, włącz interfejsy Compute Engine i GKE API w projekcie Google Cloud.

W Cloud Shell sprawdź, czy identyfikator projektu jest skonfigurowany:

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

Jeśli identyfikator projektu nie jest zdefiniowany, skonfiguruj go:

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

Włącz wymagane interfejsy API:

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

Oczekiwane dane wyjściowe:

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.

Informacje o każdym włączonym interfejsie API znajdziesz w dokumentacji.

4. Wdrażanie AlloyDB Omni w GKE

Aby wdrożyć AlloyDB Omni w GKE, przygotuj klaster Kubernetes zgodnie z wymaganiami operatora AlloyDB Omni.

Tworzenie klastra GKE

Wdróż klaster GKE w trybie Autopilota, aby uruchomić AlloyDB Omni, operatora i kontenery monitorowania. Dzięki trybowi Autopilot upraszczamy wdrażanie – wszystkie zasoby operatora AlloyDB Omni, klastra i innych komponentów zostaną przypisane automatycznie.

Wybierz region, w którym wdrażasz zasoby. Wybierz region geograficznie bliski Twojej lokalizacji:

export LOCATION=<your region>

Ustaw zmienne środowiskowe dla wdrożenia:

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

Utwórz klaster GKE z Autopilotem:

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

Oczekiwane dane wyjściowe konsoli:

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

Przygotowywanie klastra

Zainstaluj wymagane komponenty, takie jak cert-manager, czyli kontroler certyfikatów dla Kubernetes. Szczegółowe informacje znajdziesz w dokumentacji instalacji cert-manager.

Cloud Shell zawiera narzędzie wiersza poleceń Kubernetes kubectl i helm. Uzyskaj dane logowania do klastra za pomocą gcloud:

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

Zainstaluj cert-manager za pomocą narzędzia 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

Oczekiwane dane wyjściowe konsoli (zredagowane):

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!

Instalowanie operatora AlloyDB Omni

Zainstaluj operatora AlloyDB Omni za pomocą narzędzia Helm.

Pobierz i zainstaluj wykres operatora 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

Oczekiwane dane wyjściowe konsoli (zredagowane):

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

Wdróż klaster bazy danych.

Poniższy plik manifestu konfiguruje klaster bazy danych z włączoną funkcją googleMLExtension i wewnętrznym systemem równoważenia obciążenia:

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

Wartość obiektu tajnego hasła to reprezentacja Base64 ciągu VeryStrongPassword. W środowiskach produkcyjnych do zarządzania hasłami używaj usługi Google Secret Manager. Więcej informacji znajdziesz w dokumentacji Secret Managera.

Plik manifestu zostanie zapisany jako my-omni.yaml. W Cloud Shell kliknij Otwórz edytor w prawym górnym rogu okna terminala i przeczytaj plik.

Otwieranie edytora w Cloud Shell

Po przeczytaniu pliku manifestu my-omni.yaml kliknij Otwórz terminal, aby powrócić do znaku zachęty.

Otwieranie terminala w Cloud Shell

Zastosuj plik manifestu my-omni.yaml:

kubectl apply -f my-omni.yaml

Oczekiwane dane wyjściowe konsoli:

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

Sprawdź stan klastra my-omni:

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

Podczas wdrażania klaster bazy danych przechodzi przez kolejne fazy konfiguracji, aż osiągnie stan DBClusterReady.

Oczekiwane dane wyjściowe konsoli:

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

Opcjonalnie możesz monitorować wdrażanie klastra za pomocą polecenia kubectl log:

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

Łączenie z AlloyDB Omni

Gdy klaster będzie gotowy, połącz się z zasobnikiem bazy danych za pomocą klienta PostgreSQL (psql). Hasło to VeryStrongPassword, zgodnie z definicją w 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

Przykładowe dane wyjściowe konsoli:

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

Zakończ sesję psql, wpisując \q i naciskając Enter:

postgres=# \q

5. Wdrażanie modelu EmbeddingGemma w GKE

Aby przetestować integrację AlloyDB Omni AI z modelami lokalnymi, wdróż model wektora dystrybucyjnego w klastrze GKE. W tym samouczku używany jest model EmbeddingGemma od Google.

Uzyskiwanie tokena Hugging Face

W tym samouczku wdrażamy model EmbeddingGemma z Hugging Face. Aby uzyskać dostęp do wag modelu, wygeneruj token dostępu Hugging Face:

  1. Zaloguj się na konto Hugging Face lub utwórz je.
  2. Kliknij Your Profile (Twój profil) > Access Tokens (Tokeny dostępu).
  3. Kliknij Utwórz nowy token.
  4. Wpisz nazwę tokena i wybierz rolę Odczyt.
  5. Kliknij Utwórz token i skopiuj wygenerowaną wartość tokena.
  6. Jeśli nie zostało to jeszcze zrobione, zaakceptuj warunki korzystania z modelu na stronie modelu EmbeddingGemma.

Utwórz w Cloud Shell obiekt tajny Kubernetes zawierający token Hugging Face (zastąp obiekt zastępczy tokena swoim tokenem):

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 -

Przygotowanie pliku manifestu wdrożenia

Aby wdrożyć model, użyj pakietu kontenera Text Embeddings Inference (TEI) firmy Hugging Face. Więcej informacji znajdziesz w dokumentacji Hugging Face GKE TEI.

Sklonuj repozytorium wdrożenia z GitHuba:

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

Sprawdź i zmodyfikuj plik manifestu konfiguracji procesora:

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

Zaktualizowany manifest do wdrożenia na procesorze:

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"

Zapisz zmiany, naciskając ctrl+s, i wróć do terminala.

Wdróż model

Zastosuj plik manifestu, aby wdrożyć serwer TEI:

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

Monitoruj wdrożenie, aż będzie gotowe:

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'

Sprawdź usługę Kubernetes tei-service:

kubectl get service tei-service

Oczekiwane dane wyjściowe:

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

Usługa CLUSTER-IP obsługuje żądania wewnętrznie pod adresem http://34.118.233.48:8080/embed.

Przetestuj punkt końcowy modelu lokalnie za pomocą kubectl port-forward:

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

Otwórz drugą kartę Cloud Shell, klikając + u góry terminala:

Dodaj kartę Cloud Shell

Na nowej karcie przetestuj generowanie wektorów dystrybucyjnych za pomocą curl:

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

Oczekiwane dane wyjściowe (tablica wektorów):

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

Zatrzymaj przekierowanie portów na pierwszej karcie, naciskając ctrl+c.

6. Zarejestruj model wektorów dystrybucyjnych w AlloyDB Omni

Aby użyć wdrożonego modelu z AlloyDB Omni, utwórz bazę danych, zdefiniuj funkcje przekształcania i zarejestruj punkt końcowy modelu.

Tworzenie klienckiej maszyny wirtualnej i bazy danych

Utwórz instancję maszyny wirtualnej Compute Engine w tej samej sieci VPC, która będzie działać jako serwer skokowy klienta:

Schemat architektury sieci przedstawiający maszynę wirtualną klienta i AlloyDB Omni

W Cloud Shell utwórz kliencką maszynę wirtualną:

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

Pobierz adres IP punktu końcowego AlloyDB Omni:

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

Oczekiwane dane wyjściowe:

INSTANCE_IP=10.128.0.33

Wartość INSTANCE_IP to wewnętrzny adres IP systemu równoważenia obciążenia klastra AlloyDB Omni. W tym przykładzie jest to 10.131.0.33.

Połącz się z instancją maszyny wirtualnej przez SSH:

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

W sesji SSH na maszynie instance-1 zainstaluj klienta PostgreSQL:

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

Wyeksportuj adres IP systemu równoważenia obciążenia AlloyDB Omni (zastąp go adresem IP PRIMARYENDPOINT):

export INSTANCE_IP=10.131.0.33

Połącz się z AlloyDB Omni za pomocą psql (hasło to VeryStrongPassword):

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

W sesji psql utwórz bazę danych demo:

CREATE DATABASE demo;

Przełącz na bazę danych demo:

\c demo

Tworzenie funkcji przekształcenia

Niestandardowe punkty końcowe wektorów dystrybucyjnych wymagają funkcji przekształcania danych wejściowych i wyjściowych, aby dostosować formaty danych między AlloyDB Omni a interfejsem API modelu.

Utwórz funkcję przekształcenia danych wejściowych:

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;
$$;

Oczekiwane dane wyjściowe:

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

Utwórz funkcję przekształcania danych wyjściowych, aby przeanalizować odpowiedź tablicy wektorowej:

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;
$$;

Oczekiwane dane wyjściowe:

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

Zarejestruj model

Zarejestruj model w AlloyDB Omni za pomocą procedury google_ml.create_model. Określ http://tei-service:8080/embed jako model_request_url, aby kierować żądania do usługi klastra 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');

Oczekiwane dane wyjściowe:

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

Przetestuj zarejestrowany model za pomocą przykładowego zapytania SQL:

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

Funkcja zwraca reprezentację tablicy liczb rzeczywistych wygenerowaną przez lokalny model EmbeddingGemma działający w GKE.

Naciśnij q, aby wrócić do prompta sesji psql.

Zakończ sesję psql:

\q

7. Przetestuj model na przykładowych danych

Wczytaj przykładowe dane

W tym samouczku używamy zbioru danych Cymbal Retail, aby zademonstrować wyszukiwanie podobieństwa wektorów. Do zaimportowania danych do AlloyDB Omni użyjesz Google Cloud SDK i klienta PostgreSQL.

W sesji SSH na maszynie wirtualnej instance-1 połącz się z demonstracyjną bazą danych i włącz rozszerzenie vector:

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

W sesji psql:

CREATE EXTENSION IF NOT EXISTS vector;

Zakończ sesję psql:

\q

Pobierz i zastosuj schemat, aby utworzyć tabele w bazie danych demo:

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

Oczekiwane dane wyjściowe:

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:~$

Sprawdź utworzone tabele:

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

Oczekiwane dane wyjściowe:

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)

Wczytaj dane do tabeli 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"

Oczekiwane dane wyjściowe:

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:~$ 

Oto kilka przykładowych wierszy z tabeli 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"

Oczekiwane dane wyjściowe:

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:~$ 

Wczytaj dane do tabeli 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"

Oczekiwane dane wyjściowe:

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:~$ 

Oto kilka przykładowych wierszy z tabeli cymbal_inventory.

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

Dane wyjściowe:

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:~$ 

Wczytaj dane do tabeli 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"

Oczekiwane dane wyjściowe konsoli:

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:~$

Oto kilka przykładowych wierszy z tabeli cymbal_stores.

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

Dane wyjściowe:

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:~$ 

Tworzenie wektorów dystrybucyjnych

Połącz się z demonstracyjną bazą danych za pomocą psql i utwórz wektory dystrybucyjne dla produktów opisanych w tabeli cymbal_products na podstawie ich opisów.

Połącz się z demonstracyjną bazą danych:

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

Użyj kolumny embedding typu vector do przechowywania wygenerowanych wektorów dystrybucyjnych tekstu dla opisów produktów.

Włącz pomiar czasu zapytania:

\timing

Wygeneruj wektory dystrybucyjne dla każdego opisu produktu i zapisz je w tabeli cymbal_embedding:

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

Oczekiwane dane wyjściowe:

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

Wykonywanie semantycznych zapytań wyszukiwania

W sesji psql znajdź 5 najlepszych produktów pasujących do pytania "What kind of fruit trees grow well here?", używając odległości cosinusowej (<=>):

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;

Oczekiwane dane wyjściowe:

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

Zapytanie zostało wykonane w 83 ms i zwróciło listę drzew z tabeli cymbal_products, które pasują do żądania i są dostępne w sklepie o numerze 1583.

Tworzenie indeksu ANN

W przypadku małego zbioru danych łatwo jest użyć wyszukiwania dokładnego, które skanuje wszystkie wektory dystrybucyjne, ale gdy danych przybywa, czas wczytywania i odpowiedzi również się wydłuża. Aby zwiększyć wydajność, możesz utworzyć indeksy na danych wektorów dystrybucyjnych. Oto przykład, jak to zrobić za pomocą indeksu Google ScaNN w przypadku danych wektorowych.

Jeśli połączenie z demonstracyjną bazą danych zostało przerwane, połącz się z nią ponownie:

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

Włącz rozszerzenie alloydb_scann:

CREATE EXTENSION IF NOT EXISTS alloydb_scann;

Utwórz indeks ScaNN w kolumnie embedding:

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

Uruchom ponownie zapytanie wyszukiwania semantycznego, aby porównać wydajność:

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;

Oczekiwane dane wyjściowe:

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

Czas wykonywania zapytania nieco się skrócił, a wzrost wydajności będzie bardziej widoczny w przypadku większych zbiorów danych. Zwrócone dane powinny być takie same lub bardzo podobne do tych, które otrzymaliśmy bez indeksu.

Wypróbuj inne zapytania i dowiedz się więcej o optymalizacji indeksu wektorowego z dokumentacji.

Zakończ sesję psql:

\q

Wróć do Google Cloud Shell, rozłączając się z sesją SSH instance-1 przez naciśnięcie CTRL+D lub wpisanie exit.

8. Wdrażanie Gemma z vLLM

Dodawanie puli węzłów dla Gemmy

Najpierw sprawdź, jakie typy węzłów są dostępne w Twoim regionie:

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

Powinna pojawić się lista dostępnych typów akceleratorów, w tym akcelerator nvidia-l4.

Utwórz plik manifestu wdrożenia dla modelu Google Gemini 4 12B za pomocą 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

Zastosuj zapisane wdrożenie gemma-12b-gpu-vllm-deployment.yaml:

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

Oczekiwane dane wyjściowe:

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

Poczekaj na zakończenie wdrażania i wczytanie modelu. Może to potrwać kilka minut.

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'

Oczekiwane dane wyjściowe:

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

przetestować model. Aby uzyskać dostęp do modelu, włącz przekierowanie portów:

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

In another terminal window, use curl to send a prompt to the model:

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'

Oczekiwane dane wyjściowe:

  % 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.

Zatrzymaj przekierowanie portów w pierwszym terminalu (jeśli nadal działa), naciskając Ctrl+C.

9. Zarejestruj model Gemma 4 w AlloyDB Omni

Zarejestruj model Gemma 12B w AlloyDB Omni za pomocą procedury google_ml.create_model. Określ http://gemma-12b-gpu-vllm-service:8000/v1/chat/completions jako model_request_url, aby kierować żądania do usługi klastra Kubernetes:

Pobierz adres IP punktu końcowego AlloyDB Omni:

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

Połącz się z instancją maszyny wirtualnej przez SSH:

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

Po połączeniu się z maszyną wirtualną wyeksportuj zmienną INSTANCE_IP z poprzedniego kroku (wartość 10.128.0.33 jest podana jako przykład – zastąp ją swoim adresem IP):

export INSTANCE_IP=10.128.0.33

Wyeksportuj hasło AlloyDB:

export PGPASSWORD=VeryStrongPassword

Nawiąż połączenie z bazą danych demo:

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

W sesji psql zarejestruj model:

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');

Przetestuj model za pomocą przykładowego zapytania 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';

Naciśnij q, aby zamknąć okno wyników i wrócić do prompta psql

Łączenie wyszukiwania wektorowego z LLM RAG w AlloyDB Omni

Użyj wyszukiwania wektorowego z żądaniem LLM, aby zademonstrować RAG (generowanie wspomagane wyszukiwaniem) z LLM.

Uruchom zapytanie SQL w 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;

Oczekiwane dane wyjściowe:

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

Zapytanie uzupełnia prompt do LLM o wyniki wyszukiwania wektorowego.

Wypróbuj inne zapytania i poeksperymentuj ze wzorcami RAG. Zaletą przedstawionej architektury jest jej pełna samowystarczalność. Dane nie są wysyłane poza klaster i mogą działać w całkowicie odizolowanych środowiskach.

Zakończ sesję psql:

\q

Zakończ sesję SSH z maszyną wirtualną:

exit

Pamiętaj, że AlloyDB Omni ma więcej funkcji i modułów.

10. Czyszczenie środowiska

Aby uniknąć obciążenia konta Google Cloud bieżącymi opłatami, usuń zasoby utworzone w tym ćwiczeniu.

Usuwanie klastra GKE

W Cloud Shell usuń klaster 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}

Oczekiwane dane wyjściowe:

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

Usuwanie klienckiej maszyny wirtualnej

W Cloud Shell usuń instancję Compute Engine:

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

Oczekiwane dane wyjściowe:

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

Jeśli do wykonania zadań z tego ćwiczenia posłużył Ci nowy, specjalnie utworzony projekt, możesz go usunąć w Cloud Resource Manager.

11. Gratulacje

Gratulujemy ukończenia tego ćwiczenia!

Omówione kwestie

  • Jak wdrożyć AlloyDB Omni w klastrze GKE
  • Jak połączyć się z AlloyDB Omni
  • Jak wczytać dane do AlloyDB Omni
  • jak wdrażać modele AI (wektory dystrybucyjne i LLM) w GKE,
  • Jak zarejestrować modele AI w AlloyDB Omni
  • Jak wygenerować wektory dystrybucyjne na potrzeby wyszukiwania semantycznego
  • Jak wykonywać zapytania wyszukiwania semantycznego w AlloyDB Omni
  • Jak tworzyć i wykorzystywać indeksy wektorowe w AlloyDB Omni

Więcej informacji o pracy ze sztuczną inteligencją w AlloyDB Omni znajdziesz w dokumentacji.

Ankieta

Dane wyjściowe:

Jak będziesz korzystać z tego samouczka?

Tylko przeczytać Przeczytać i wykonać ćwiczenia