Начало работы с гибридным поиском в AlloyDB

1. Введение

В этом практическом занятии вы узнаете, как выполнять гибридный поиск в AlloyDB, используя расширение RUM (Ranking Update Method) и индекс Scalable Nearest Neighbor (ScaNN). Это занятие является частью серии практических занятий, посвященных функциям искусственного интеллекта AlloyDB. Подробнее можно узнать на странице AlloyDB AI в документации.

Предварительные требования

  • Базовое понимание Google Cloud и консоли.
  • Базовые навыки работы с командной строкой и оболочкой Google Sheets.

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

  • Как развернуть кластер AlloyDB и основной экземпляр
  • Как подключиться к AlloyDB с виртуальной машины Google Compute Engine
  • Как создать базу данных и включить AlloyDB AI
  • Как загрузить данные в базу данных
  • Как использовать AlloyDB Studio
  • Создавайте векторные представления с помощью Vertex AI.
  • Как создать векторный индекс ScaNN для повышения эффективности векторного поиска
  • Как создать внешний контейнер данных (Foreign Data Wrapper, FDW) для Elasticsearch
  • Выполните гибридный поиск, объединив семантический поиск в AlloyDB с полнотекстовым поиском в Elastic.

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

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

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

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

Войдите в консоль Google Cloud . Если у вас еще нет учетной записи Gmail или Google Workspace, вам необходимо ее создать .

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

Создайте проект в Google Cloud.

  1. В консоли Google Cloud на странице выбора проекта выберите или создайте проект Google Cloud .
  2. Убедитесь, что для вашего облачного проекта включена функция выставления счетов. Узнайте, как проверить, включена ли функция выставления счетов для проекта .

Включить выставление счетов

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

Создайте личный платежный аккаунт.

Если вы настроили оплату с использованием кредитов Google Cloud, этот шаг можно пропустить.

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

Несколько замечаний:

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

Запустить Cloud Shell

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

Cloud Shell — это среда командной строки, работающая в Google Cloud и поставляемая с предустановленными необходимыми инструментами.

  1. В верхней части консоли Google Cloud нажмите кнопку «Активировать Cloud Shell» .
  2. После подключения к Cloud Shell подтвердите свою аутентификацию:
    gcloud auth list
    
  3. Убедитесь, что ваш проект настроен:
    gcloud config get project
    
  4. Если параметры вашего проекта заданы не так, как ожидалось, настройте их следующим образом:
    export PROJECT_ID=<YOUR_PROJECT_ID>
    gcloud config set project $PROJECT_ID
    

Эта виртуальная машина содержит все необходимые инструменты разработки. Она предоставляет постоянный домашний каталог объемом 5 ГБ и работает в облаке Google, что значительно повышает производительность сети и аутентификацию. Вся работа в этом практическом задании может выполняться в браузере. Вам не нужно ничего устанавливать.

3. Прежде чем начать

Включить API

Выход:

Для использования AlloyDB , Compute Engine , сетевых сервисов и Vertex AI необходимо включить соответствующие API в вашем проекте Google Cloud.

Включение API

В терминале Cloud Shell убедитесь, что идентификатор вашего проекта указан правильно:

gcloud config set project [YOUR-PROJECT-ID]

Установите переменную среды PROJECT_ID:

PROJECT_ID=$(gcloud config get-value project)

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

gcloud services enable alloydb.googleapis.com \
                       compute.googleapis.com \
                       cloudresourcemanager.googleapis.com \
                       servicenetworking.googleapis.com \
                       aiplatform.googleapis.com \
                       secretmanager.googleapis.com

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

student@cloudshell:~ (test-project-001-402417)$ gcloud config set project test-project-001-402417
Updated property [core/project].
student@cloudshell:~ (test-project-001-402417)$ PROJECT_ID=$(gcloud config get-value project)
Your active configuration is: [cloudshell-14650]
student@cloudshell:~ (test-project-001-402417)$ 
student@cloudshell:~ (test-project-001-402417)$ gcloud services enable alloydb.googleapis.com \
                       compute.googleapis.com \
                       cloudresourcemanager.googleapis.com \
                       servicenetworking.googleapis.com \
                       aiplatform.googleapis.com \
                       secretmanager.googleapis.com
Operation "operations/acat.p2-4470404856-1f44ebd8-894e-4356-bea7-b84165a57442" finished successfully.

Представляем API.

  • API AlloyDB ( alloydb.googleapis.com ) позволяет создавать, управлять и масштабировать кластеры AlloyDB для PostgreSQL. Он предоставляет полностью управляемый, совместимый с PostgreSQL сервис баз данных, разработанный для ресурсоемких корпоративных транзакционных и аналитических задач.
  • API Compute Engine ( compute.googleapis.com ) позволяет создавать и управлять виртуальными машинами (ВМ), постоянными дисками и сетевыми настройками. Он предоставляет базовую инфраструктуру как услугу (IaaS), необходимую для запуска ваших рабочих нагрузок и размещения базовой инфраструктуры для множества управляемых сервисов.
  • API Cloud Resource Manager ( cloudresourcemanager.googleapis.com ) позволяет программно управлять метаданными и конфигурацией вашего проекта Google Cloud. Он позволяет организовывать ресурсы, управлять политиками управления идентификацией и доступом (IAM) и проверять разрешения в иерархии проекта.
  • API для настройки сетевого взаимодействия сервисов ( servicenetworking.googleapis.com ) позволяет автоматизировать настройку частного подключения между вашей виртуальной частной сетью (VPC) и управляемыми сервисами Google. Он необходим для установления частного IP-доступа для таких сервисов, как AlloyDB, чтобы они могли безопасно взаимодействовать с другими вашими ресурсами.
  • API Vertex AI ( aiplatform.googleapis.com ) позволяет вашим приложениям создавать, развертывать и масштабировать модели машинного обучения. Он предоставляет единый интерфейс для всех сервисов искусственного интеллекта Google Cloud, включая доступ к моделям генеративного ИИ (например, Gemini) и обучению пользовательских моделей.
  • Secret Manager API ( secretmanager.googleapis.com ) — это сервис для управления секретами и учетными данными, позволяющий хранить и управлять конфиденциальными данными, такими как ключи API, имена пользователей, пароли, сертификаты и многое другое.

При желании вы можете настроить свой регион по умолчанию для использования моделей встраивания Vertex AI. Подробнее о доступных регионах для Vertex AI можно прочитать здесь. В примере мы используем регион us-central1.

gcloud config set compute/region us-central1

4. Развертывание AlloyDB

Перед созданием кластера AlloyDB нам необходим доступный диапазон частных IP-адресов в нашей VPC, который будет использоваться будущим экземпляром AlloyDB. Если его нет, нам нужно его создать, назначить для использования внутренними сервисами Google, после чего мы сможем создать кластер и экземпляр.

Создать частный диапазон IP-адресов

Нам необходимо настроить параметры доступа к частным сервисам (Private Service Access, VPC) в нашей VPC для AlloyDB. Предполагается, что в проекте используется «стандартная» сеть VPC, и она будет применяться для всех действий.

Создайте диапазон частных IP-адресов:

gcloud compute addresses create psa-range \
    --global \
    --purpose=VPC_PEERING \
    --prefix-length=24 \
    --description="VPC private service access" \
    --network=default

Создайте частное соединение, используя выделенный диапазон IP-адресов:

gcloud services vpc-peerings connect \
    --service=servicenetworking.googleapis.com \
    --ranges=psa-range \
    --network=default \
    --export-custom-routes

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

student@cloudshell:~ (test-project-402417)$ gcloud compute addresses create psa-range \
    --global \
    --purpose=VPC_PEERING \
    --prefix-length=24 \
    --description="VPC private service access" \
    --network=default
Created [https://www.googleapis.com/compute/v1/projects/test-project-402417/global/addresses/psa-range].

student@cloudshell:~ (test-project-402417)$ gcloud services vpc-peerings connect \
    --service=servicenetworking.googleapis.com \
    --ranges=psa-range \
    --network=default
Operation "operations/pssn.p24-4470404856-595e209f-19b7-4669-8a71-cbd45de8ba66" finished successfully.

student@cloudshell:~ (test-project-402417)$

Создание кластера AlloyDB

В этом разделе мы создаём кластер AlloyDB в регионе us-central1.

Задайте пароль для пользователя postgres. Вы можете задать собственный пароль или использовать функцию генерации случайных чисел.

export PGPASSWORD=`openssl rand -hex 12`

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

student@cloudshell:~ (test-project-402417)$ export PGPASSWORD=`openssl rand -hex 12`

Запишите пароль от PostgreSQL для дальнейшего использования.

echo $PGPASSWORD

Этот пароль понадобится вам в будущем для подключения к экземпляру под учетной записью postgres. Я рекомендую скопировать его в надежное место (например, в менеджер паролей).

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

student@cloudshell:~ (test-project-402417)$ echo $PGPASSWORD
<generated password>

Создание кластера AlloyDB

Определите регион и имя кластера AlloyDB. Мы будем использовать регион us-central1 и имя кластера alloydb-hybrid-search:

export REGION=us-central1
export ADBCLUSTER=alloydb-hybrid-search

Выполните команду для создания кластера:

gcloud alloydb clusters create $ADBCLUSTER \
    --password=$PGPASSWORD \
    --network=default \
    --region=$REGION

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

export REGION=us-central1
export ADBCLUSTER=alloydb-hybrid-search
gcloud alloydb clusters create $ADBCLUSTER \
    --password=$PGPASSWORD \
    --network=default \
    --region=$REGION
Operation ID: operation-1697655441138-6080235852277-9e7f04f5-2012fce4
Creating cluster...done.                                                                                                                                                                                                                                                           

Создайте основной экземпляр AlloyDB для нашего кластера в той же сессии Cloud Shell. Если вы отключены, вам потребуется заново определить переменные среды для региона и имени кластера.

gcloud alloydb instances create $ADBCLUSTER-pr \
    --instance-type=PRIMARY \
    --cpu-count=2 \
    --region=$REGION \
    --cluster=$ADBCLUSTER

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

student@cloudshell:~ (alloydb-hybrid-search)$ gcloud alloydb instances create $ADBCLUSTER-pr \
    --instance-type=PRIMARY \
    --cpu-count=2 \
    --region=$REGION \
    --availability-type ZONAL \
    --cluster=$ADBCLUSTER
Operation ID: operation-1697659203545-6080315c6e8ee-391805db-25852721
Creating instance...done.                                                                                                                                                                                                                                                     

5. Подключитесь к AlloyDB

AlloyDB развертывается с использованием только частного соединения, поэтому для работы с базой данных нам потребуется виртуальная машина с установленным клиентом PostgreSQL. Мы также будем использовать эту виртуальную машину для запуска экземпляра Elasticsearch.

Развертывание виртуальной машины GCE

Создайте виртуальную машину GCE в том же регионе и VPC, что и кластер AlloyDB, убедитесь, что загрузочный диск достаточно велик для работы Elastic. Здесь мы указываем загрузочный диск объемом 20 ГБ в флаге --create-disk .

В оболочке Cloud Shell выполните:

export ZONE=us-central1-a
gcloud compute instances create instance-1 \
    --zone=$ZONE \
    --create-disk=auto-delete=yes,boot=yes,size=20,image=projects/debian-cloud/global/images/$(gcloud compute images list --filter="family=debian-12 AND family!=debian-12-arm64" --format="value(name)") \
    --scopes=https://www.googleapis.com/auth/cloud-platform

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

student@cloudshell:~ (alloydb-hybrid-search)$ export ZONE=us-central1-a
student@cloudshell:~ (talloydb-hybrid-search)$ export ZONE=us-central1-a
gcloud compute instances create instance-1 \
    --zone=$ZONE \
    --create-disk=auto-delete=yes,boot=yes,image=projects/debian-cloud/global/images/$(gcloud compute images list --filter="family=debian-12 AND family!=debian-12-arm64" --format="value(name)") \
    --scopes=https://www.googleapis.com/auth/cloud-platform

Created [https://www.googleapis.com/compute/v1/projects/test-project-402417/zones/us-central1-a/instances/instance-1].
NAME: instance-1
ZONE: us-central1-a
MACHINE_TYPE: n1-standard-1
PREEMPTIBLE:
INTERNAL_IP: 10.128.0.2
EXTERNAL_IP: 34.71.192.233
STATUS: RUNNING

Установите клиент PostgreSQL.

Установите клиентское программное обеспечение PostgreSQL на развернутую виртуальную машину.

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

gcloud compute ssh instance-1 --zone=us-central1-a

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

student@cloudshell:~ (alloydb-hybrid-search)$ gcloud compute ssh instance-1 --zone=us-central1-a
Updating project ssh metadata...working..Updated [https://www.googleapis.com/compute/v1/projects/alloydb-hybrid-search].                                                                                                                                                         
Updating project ssh metadata...done.                                                                                                                                                                                                                                              
Waiting for SSH key to propagate.
Warning: Permanently added 'compute.5110295539541121102' (ECDSA) to the list of known hosts.
Linux instance-1.us-central1-a.c.gleb-test-short-001-418811.internal 6.1.0-18-cloud-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.1.76-1 (2024-02-01) x86_64

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
student@instance-1:~$

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

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

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

student@instance-1:~$ sudo apt-get update
sudo apt-get install --yes postgresql-client
Get:1 https://packages.cloud.google.com/apt google-compute-engine-bullseye-stable InRelease [5146 B]
Get:2 https://packages.cloud.google.com/apt cloud-sdk-bullseye InRelease [6406 B]   
Hit:3 https://deb.debian.org/debian bullseye InRelease  
Get:4 https://deb.debian.org/debian-security bullseye-security InRelease [48.4 kB]
Get:5 https://packages.cloud.google.com/apt google-compute-engine-bullseye-stable/main amd64 Packages [1930 B]
Get:6 https://deb.debian.org/debian bullseye-updates InRelease [44.1 kB]
Get:7 https://deb.debian.org/debian bullseye-backports InRelease [49.0 kB]
...redacted...
update-alternatives: using /usr/share/postgresql/13/man/man1/psql.1.gz to provide /usr/share/man/man1/psql.1.gz (psql.1.gz) in auto mode
Setting up postgresql-client (13+225) ...
Processing triggers for man-db (2.9.4-2) ...
Processing triggers for libc-bin (2.31-13+deb11u7) ...

Подключитесь к экземпляру

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

В той же вкладке Cloud Shell, где открыта SSH-сессия к вашей виртуальной машине instance-1.

Используйте указанное значение пароля AlloyDB (PGPASSWORD) и идентификатор кластера AlloyDB для подключения к AlloyDB с виртуальной машины GCE:

export PGPASSWORD=<Noted password>
export PROJECT_ID=$(gcloud config get-value project)
export REGION=us-central1
export ADBCLUSTER=alloydb-hybrid-search
export INSTANCE_IP=$(gcloud alloydb instances describe $ADBCLUSTER-pr --cluster=$ADBCLUSTER --region=$REGION --format="value(ipAddress)")
psql "host=$INSTANCE_IP user=postgres sslmode=require"

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

student@instance-1:~$ export PGPASSWORD=<noted password>
student@instance-1:~$ ADBCLUSTER=alloydb-aip-01
student@instance-1:~$ REGION=us-central1
student@instance-1:~$ INSTANCE_IP=$(gcloud alloydb instances describe $ADBCLUSTER-pr --cluster=$ADBCLUSTER --region=$REGION --format="value(ipAddress)")
gleb@instance-1:~$ psql "host=$INSTANCE_IP user=postgres sslmode=require"
psql (15.6 (Debian 15.6-0+deb12u1), server 15.5)
SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384, compression: off)
Type "help" for help.

postgres=>

Закройте сессию psql:

exit

6. Подготовка базы данных

Нам необходимо создать базу данных, включить интеграцию с Vertex AI, создать объекты базы данных и импортировать данные.

Предоставьте необходимые разрешения AlloyDB

Добавьте разрешения Vertex AI для агента службы AlloyDB.

Откройте еще одну вкладку Cloud Shell, используя знак "+" вверху.

abc505ac4d41f24e.png

В новой вкладке облачной оболочки выполните:

PROJECT_ID=$(gcloud config get-value project)
gcloud projects add-iam-policy-binding $PROJECT_ID \
  --member="serviceAccount:service-$(gcloud projects describe $PROJECT_ID --format="value(projectNumber)")@gcp-sa-alloydb.iam.gserviceaccount.com" \
  --role="roles/aiplatform.user"

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

student@cloudshell:~ (test-project-001-402417)$ PROJECT_ID=$(gcloud config get-value project)
Your active configuration is: [cloudshell-11039]
student@cloudshell:~ (test-project-001-402417)$ gcloud projects add-iam-policy-binding $PROJECT_ID \
  --member="serviceAccount:service-$(gcloud projects describe $PROJECT_ID --format="value(projectNumber)")@gcp-sa-alloydb.iam.gserviceaccount.com" \
  --role="roles/aiplatform.user"
Updated IAM policy for project [test-project-001-402417].
bindings:
- members:
  - serviceAccount:service-4470404856@gcp-sa-alloydb.iam.gserviceaccount.com
  role: roles/aiplatform.user
- members:
...
etag: BwYIEbe_Z3U=
version: 1

Закройте вкладку, нажав кнопку «X» или выполнив команду:

exit

Создать базу данных

Создайте базу данных с именем quickstart.

В сессии виртуальной машины GCE выполните:

Создать базу данных:

psql "host=$INSTANCE_IP user=postgres" -c "CREATE DATABASE quickstart_db"

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

student@instance-1:~$ psql "host=$INSTANCE_IP user=postgres" -c "CREATE DATABASE quickstart_db"
CREATE DATABASE
student@instance-1:~$  

Включите интеграцию Vertex AI

Включите интеграцию Vertex AI и расширения pgvector в базе данных.

В виртуальной машине GCE выполните:

psql "host=$INSTANCE_IP user=postgres dbname=quickstart_db" -c "CREATE EXTENSION IF NOT EXISTS google_ml_integration CASCADE"
psql "host=$INSTANCE_IP user=postgres dbname=quickstart_db" -c "CREATE EXTENSION IF NOT EXISTS vector"

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

student@instance-1:~$ psql "host=$INSTANCE_IP user=postgres dbname=quickstart_db" -c "CREATE EXTENSION IF NOT EXISTS google_ml_integration CASCADE"
psql "host=$INSTANCE_IP user=postgres dbname=quickstart_db" -c "CREATE EXTENSION IF NOT EXISTS vector"
CREATE EXTENSION
CREATE EXTENSION
student@instance-1:~$

Импорт данных

Загрузите подготовленные данные и импортируйте их в новую базу данных.

В виртуальной машине GCE выполните:

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

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

student@instance-1:~$ gcloud storage cat gs://cloud-training/gcc/gcc-tech-004/cymbal_demo_schema.sql |psql "host=$INSTANCE_IP user=postgres dbname=quickstart_db"
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@instance-1:~$ gcloud storage cat gs://cloud-training/gcc/gcc-tech-004/cymbal_products.csv |psql "host=$INSTANCE_IP user=postgres dbname=quickstart_db" -c "\copy cymbal_products from stdin csv header"
COPY 941
student@instance-1:~$ gcloud storage cat gs://cloud-training/gcc/gcc-tech-004/cymbal_inventory.csv |psql "host=$INSTANCE_IP user=postgres dbname=quickstart_db" -c "\copy cymbal_inventory from stdin csv header"
COPY 263861
student@instance-1:~$ gcloud storage cat gs://cloud-training/gcc/gcc-tech-004/cymbal_stores.csv |psql "host=$INSTANCE_IP user=postgres dbname=quickstart_db" -c "\copy cymbal_stores from stdin csv header"
COPY 4654
student@instance-1:~$

Далее, давайте установим необходимые флаги базы данных. Вы можете использовать веб-консоль и управлять флагами в основном экземпляре или использовать команду gcloud следующим образом:

export PROJECT_ID=$(gcloud config get-value project)
export REGION=us-central1
export ADBCLUSTER=alloydb-hybrid-search
gcloud beta alloydb instances update $ADBCLUSTER-pr \
   --database-flags google_ml_integration.enable_faster_embedding_generation=on,scann.enable_preview_features=on,google_ml_integration.enable_preview_ai_functions=on,google_ml_integration.enable_ai_query_engine=on \
   --region=$REGION \
   --cluster=$ADBCLUSTER \
   --project=$PROJECT_ID \
   --update-mode=FORCE_APPLY

Ожидаемый вывод в консоль

export PROJECT_ID=$(gcloud config get-value project)
export REGION=us-central1
export ADBCLUSTER=alloydb-hybrid-search
gcloud beta alloydb instances update $ADBCLUSTER-pr \
   --database-flags google_ml_integration.enable_faster_embedding_generation=on,scann.enable_preview_features=on,google_ml_integration.enable_preview_ai_functions=on,google_ml_integration.enable_ai_query_engine=on \
   --region=$REGION \
   --cluster=$ADBCLUSTER \
   --project=$PROJECT_ID \
   --update-mode=FORCE_APPLY
Your active configuration is: [cloudshell-724]
Operation ID: operation-1775159889986-64e7f9ea9858a-b031e866-4c7c36df

Для включения флагов базы данных требуется перезапуск экземпляра, который займет несколько минут. После завершения статус экземпляра AlloyDB изменится на «Готов».

7. Создание векторных представлений

После импорта данных у нас есть следующие таблицы: cymbal_products , в которой хранится информация о товарах, cymbal_inventory , которая отслеживает наличие товаров в каждом магазине, и cymbal_stores , представляющая собой список магазинов. Для выполнения семантического поиска по нашим товарам нам необходимо сгенерировать векторные представления описаний товаров с помощью функции initialize_embeddings . Мы будем использовать интеграцию с Vertex AI для вычисления векторных данных на основе описаний товаров и добавления их в таблицу. Подробнее об используемой технологии можно прочитать в документации .

Для использования интеграции подключитесь к базе данных с помощью AlloyDB Studio или psql с вашей виртуальной машины, используя IP-адрес экземпляра AlloyDB и пароль postgres:

psql "host=$INSTANCE_IP user=postgres dbname=quickstart_db"

Проверьте версию расширения google_ml_integration.

SELECT extversion FROM pg_extension WHERE extname = 'google_ml_integration';

Версия должна быть 1.5.2 или выше. Вот пример вывода:

quickstart_db=> SELECT extversion FROM pg_extension WHERE extname = 'google_ml_integration';
 extversion
------------
 1.5.2
(1 row)

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

Установите расширение для работы с векторами и создайте новый столбец для хранения векторных представлений в cymbal_products

CREATE EXTENSION IF NOT EXISTS vector;
ALTER TABLE cymbal_products ADD COLUMN product_embedding vector(768);

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

quickstart_db=> ALTER TABLE cymbal_products ADD COLUMN product_embedding vector(768);
ALTER TABLE
quickstart_db=>

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

Наконец, мы также хотим, чтобы эмбеддинги обновлялись по мере изменения значений столбцов, поэтому мы добавляем аргумент incremental_refresh_mode в вызов функции. Это создает дополнительную нагрузку на нашу базу данных, но это компромисс, на который мы идем, чтобы автоматически синхронизировать эмбеддинги с контентом. Если вы хотите обновлять эмбеддинги вручную, инструкции можно найти в документации .

Теперь, чтобы собрать все воедино и сгенерировать эмбеддинги, мы используем функцию initialize_embeddings , передаем batch_size равный 50 в качестве параметра batch_signal и устанавливаем incremental_refresh_mode в transactional

CALL ai.initialize_embeddings(
    model_id => 'text-embedding-005',
    table_name => 'cymbal_products',
    content_column => 'product_description',
    embedding_column => 'product_embedding',
    batch_size => 50,
    incremental_refresh_mode => 'transactional'
);

А теперь, если мы вставим в таблицу новую строку со значением NULL для столбца product_embedding

INSERT INTO "cymbal_products" ("uniq_id", "crawl_timestamp", "product_url", "product_name", "product_description", "list_price", "sale_price", "brand", "item_number", "gtin", "package_size", "category", "postal_code", "available", "product_embedding") VALUES ('fd604542e04b470f9e6348e640cff794', NOW(), 'https://example.com/new_product', 'New Cymbal Product', 'This is a new cymbal product description.', 199.99, 149.99, 'Example Brand', 'EB123', '1234567890', 'Single', 'Cymbals', '12345', TRUE, NULL);

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

SELECT uniq_id, (product_embedding::real[])[1:5] as product_embedding  FROM cymbal_products WHERE uniq_id='fd604542e04b470f9e6348e640cff794';

Результат должен выглядеть следующим образом:

quickstart_db=> SELECT uniq_id,(product_embedding::real[])[1:5] as product_embedding  FROM cymbal_products WHERE uniq_id='fd604542e04b470f9e6348e640cff794';
             uniq_id              |                      product_embedding                       
----------------------------------+---------------------------------------------------------------
 fd604542e04b470f9e6348e640cff794 | {0.015003494,-0.005349732,-0.059790313,-0.0087091,-0.0271452}
(1 row)

Time: 3.295 ms

8. Создайте векторный индекс.

Для повышения эффективности векторного поиска мы добавим индекс ScaNN .

Создать индекс ScaNN

Для построения индекса SCANN нам необходимо включить еще одно расширение. Расширение alloydb_scann предоставляет интерфейс для работы с векторным индексом типа ANN, использующим алгоритм ScaNN от Google.

CREATE EXTENSION IF NOT EXISTS alloydb_scann;

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

quickstart_db=> CREATE EXTENSION IF NOT EXISTS alloydb_scann;
CREATE EXTENSION
Time: 27.468 ms
quickstart_db=>

Индекс можно создать в ручном (MANUAL) или автоматическом (AUTO) режиме. Ручной режим включен по умолчанию, и вы можете создать индекс и поддерживать его так же, как и любой другой индекс. Но если вы включите автоматический режим, вы сможете создать индекс, который не потребует от вас никакого обслуживания. Подробно обо всех параметрах можно прочитать в документации . В нашем случае у нас недостаточно строк для создания индекса в автоматическом режиме, поэтому мы создадим его в ручном режиме и добавим параметры настройки. О настройке параметров индекса можно прочитать в документации .

CREATE INDEX cymbal_products_embeddings_scann ON cymbal_products
  USING scann (product_embedding cosine)
  WITH (mode='MANUAL', num_leaves=31, max_num_levels = 2);

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

quickstart_db=> CREATE INDEX cymbal_products_embeddings_scann ON cymbal_products
  USING scann (product_embedding cosine)
  WITH (num_leaves=31, max_num_levels = 2);
CREATE INDEX
quickstart_db=>

Проверьте использование индекса

Теперь мы можем выполнить запрос векторного поиска в режиме EXPLAIN и проверить, используется ли индекс.

EXPLAIN (analyze)
WITH trees as (
SELECT
        cp.product_name,
        left(cp.product_description,80) as description,
        cp.sale_price,
        cs.zip_code,
        cp.uniq_id as product_id
FROM
        cymbal_products cp
JOIN cymbal_inventory ci on
        ci.uniq_id=cp.uniq_id
JOIN cymbal_stores cs on
        cs.store_id=ci.store_id
        AND ci.inventory>0
        AND cs.store_id = 1583
ORDER BY
        (cp.product_embedding <=> embedding('text-embedding-005','What kind of fruit trees grow well here?')::vector) ASC
LIMIT 1)
SELECT json_agg(trees) FROM trees;

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

...
Aggregate (cost=16.59..16.60 rows=1 width=32) (actual time=2.875..2.877 rows=1 loops=1)
-> Subquery Scan on trees (cost=8.42..16.59 rows=1 width=142) (actual time=2.860..2.862 rows=1 loops=1)
-> Limit (cost=8.42..16.58 rows=1 width=158) (actual time=2.855..2.856 rows=1 loops=1)
-> Nested Loop (cost=8.42..6489.19 rows=794 width=158) (actual time=2.854..2.855 rows=1 loops=1)
-> Nested Loop (cost=8.13..6466.99 rows=794 width=938) (actual time=2.742..2.743 rows=1 loops=1)
-> Index Scan using cymbal_products_embeddings_scann on cymbal_products cp (cost=7.71..111.99 rows=876 width=934) (actual time=2.724..2.724 rows=1 loops=1)
Order By: (embedding <=> '[0.008864171,0.03693164,-0.024245683,-0.00355923,0.0055611245,0.015985578,...<redacted>...5685,-0.03914233,-0.018452475,0.00826032,-0.07372604]'::vector)
...

Из выходных данных ясно видно, что запрос использовал "Index Scan using cymbal_products_embeddings_scann on cymbal_products".

9. Создание эластичного экземпляра

Elasticsearch является товарным знаком Elastic NV и не связан с Google LLC. Мы будем использовать Elasticsearch для полнотекстового поиска (FTS) в рамках гибридного поиска. Если у вас есть экземпляр Elasticsearch, вы можете пропустить следующие шаги и создать персональный/пользовательский API-ключ только для чтения, который AlloyDB сможет использовать для доступа к вашему кластеру Elasticsearch. В противном случае вы можете запустить экземпляр Elasticsearch в виртуальной машине, созданной ранее.

Подключитесь к виртуальной машине по SSH и установите Docker.

sudo apt-get update
sudo apt-get install -y ca-certificates curl gnupg
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/debian/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg

echo \
  "deb [arch="$(dpkg --print-architecture)" signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/debian \
  "$(. /etc/os-release && echo "$VERSION_CODENAME")" stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update
sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

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

sudo usermod -aG docker $USER
newgrp docker

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

curl -fsSL https://elastic.co/start-local | sh

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

🎉 Congrats, Elasticsearch and Kibana are installed and running in Docker!

🌐 Open your browser at http://localhost:5601

   Username: elastic
   Password: [password_value]

🔌 Elasticsearch API endpoint: http://localhost:9200
🔑 API key: [API Key]

Learn more at https://github.com/elastic/start-local

Скопируйте полученный результат и вставьте его в следующий файл.

nano elastic-last-run.txt

Нажмите Ctrl + O, Enter, Ctrl + X для сохранения и выхода.

По умолчанию контейнер Docker будет прослушивать http://localhost:9200 и может испытывать проблемы с приемом внешних запросов от AlloyDB. Необходимо настроить файл docker-compose.yml для прослушивания адреса 9200:9200

После запуска скрипта должна быть создана новая директория elastic-start-local . Перейдите в эту директорию и отредактируйте файл dockerfile.

cd elastic-start-local/
nano docker-compose.yml

В верхней части вы найдете

  elasticsearch:
    image: docker.elastic.co/elasticsearch/elasticsearch:${ES_LOCAL_VERSION}
    container_name: ${ES_LOCAL_CONTAINER_NAME}
    volumes:
      - dev-elasticsearch:/usr/share/elasticsearch/data
    ports:
      - localhost:9200

Измените поле ports следующим образом:

    ports:
      - 9200:9200

Сохраните изменения и выйдите, используя Ctrl + O, Enter, Ctrl + X. Теперь перезапустите стек.

docker compose up -d

Теперь заполним экземпляр Elastic описаниями и названиями продуктов. Скопируем CSV-файл с продуктами из облачного хранилища на виртуальную машину.

gcloud storage cp gs://cloud-training/gcc/gcc-tech-004/cymbal_products.csv .

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

gcloud storage cp gs://cloud-training/gcc/gcc-tech-004/cymbal_products.csv .
Copying gs://cloud-training/gcc/gcc-tech-004/cymbal_products.csv to file://./cymbal_products.csv
  Completed files 1/1 | 1.4MiB/1.4MiB                                                                       

Average throughput: 147.9MiB/s

Теперь создайте скрипт на Python для извлечения данных из CSV-файла и их форматирования в формат NDJSON для массовой загрузки.

nano convert.py

Вставьте в файл следующее.

import csv
import json

# Configuration
input_file = 'cymbal_products.csv'
output_file = 'products.json'
index_name = 'elasticindexdemo'

def convert():
    try:
        with open(input_file, mode='r', encoding='utf-8') as f_in, \
             open(output_file, mode='w', encoding='utf-8') as f_out:
            
            reader = csv.DictReader(f_in)
            
            count = 0
            for row in reader:
                metadata = {
                    "index": {
                        "_index": index_name,
                        "_id": row['uniq_id'].strip()
                    }
                }
                
                # 2. Data/Source line
                document = {
                    "uniq_id": row['uniq_id'].strip(),
                    "product_name": row['product_name'].strip(),
                    "product_description": row['product_description'].strip()
                }
                
                # Write to file
                f_out.write(json.dumps(metadata) + '\n')
                f_out.write(json.dumps(document) + '\n')
                count += 1
                
            print(f"Success: Processed {count} products.")
            print(f"Output saved to: {output_file}")

    except Exception as e:
        print(f"An error occurred: {e}")

if __name__ == "__main__":
    convert()

Сохраните файл и запустите его.

python3 convert.py

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

~$ python3 convert.py
Success: Processed 941 products.
Output saved to: products.json

Для массовой загрузки данных нам необходимо получить ключ API из файла предыдущего запуска и использовать его для авторизации в экземпляре. Затем передается ранее созданный JSON-файл. В производственных сценариях лучше всего определить индекс и типы данных в Elasticsearch. Поскольку набор данных в этом практическом задании невелик, мы позволяем Elasticsearch обрабатывать данные. Сначала получите ключ API из файла и сохраните его в переменной.

AUTH_HDR=$(grep "API key" elastic-last-run.txt | sed -e "s/^.*API key:[[:space:]]*/ApiKey /g")

Используя сохраненную переменную, выполните следующую команду curl, которая загрузит данные из JSON-файла.

curl -s -X POST "localhost:9200/elasticindexdemo/_bulk?pretty" \
  -H "Content-Type: application/x-ndjson" \
  -H "Authorization: $AUTH_HDR" \
  --data-binary "@products.json"

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

~$ curl -s -X POST "localhost:9200/elasticindexdemo/_bulk?pretty" \
  -H "Content-Type: application/x-ndjson" \
  -H "Authorization: $AUTH_HDR" \
  --data-binary "@products.json"
{
  "errors" : false,
  "took" : 1003,
  "items" : [
    {
      "index" : {
        "_index" : "elasticindexdemo",
        "_id" : "a73d5f754f225ecb9fdc64232a57bc37",
        "_version" : 1,
        "result" : "created",
        "_shards" : {
          "total" : 2,
          "successful" : 1,
          "failed" : 0
        },
        "_seq_no" : 0,
        "_primary_term" : 1,
        "status" : 201
      }
    },
...]
}
Done

Наконец, нам нужно получить ключ API экземпляра Elasticsearch, чтобы сохранить его для использования AlloyDB. Выполните следующую команду и скопируйте значение ключа API.

cat elastic-last-run.txt

Используя ключ API, нам нужно создать секрет в менеджере секретов. В CloudShell выполните следующую команду, используя свой ключ API.

echo -n "[YOUR_API_KEY_VALUE]" | \
gcloud secrets create elasticsearch \
    --replication-policy="automatic" \
    --data-file=-

10. Создание внешней оболочки данных в AlloyDB

Продолжительность 20:00

Для запроса данных, хранящихся в Elasticsearch, из AlloyDB необходимо создать внешний контейнер данных (Foreign Data Wrapper, FDW) для Elastic и внешнюю таблицу. Предварительно сохранив ключ API Elastic в менеджере секретов, для доступа AlloyDB к секрету предоставьте учетной записи службы необходимые разрешения.

В Cloudshell предоставьте учетной записи службы доступ к секрету elasticsearch

gcloud secrets add-iam-policy-binding elasticsearch \
    --member="serviceAccount:service-$(gcloud projects describe $(gcloud config get-value project) --format='value(projectNumber)')@gcp-sa-alloydb.iam.gserviceaccount.com" \
    --role="roles/secretmanager.secretAccessor"

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

gcloud secrets add-iam-policy-binding elasticsearch \
    --member="serviceAccount:service-$(gcloud projects describe $(gcloud config get-value project) --format='value(projectNumber)')@gcp-sa-alloydb.iam.gserviceaccount.com" \
    --role="roles/secretmanager.secretAccessor"
Updated IAM policy for secret [elasticsearch].
bindings:
- members:
  - serviceAccount:service-257907437930@gcp-sa-alloydb.iam.gserviceaccount.com
  role: roles/secretmanager.secretAccessor
etag: BwZOghJiP5U=
version: 1

Перейдите в кластер AlloyDB и откройте AlloyDB Studio (вы также можете использовать psql для подключения с виртуальной машины). Войдите в quickstart_db под пользователем postgres .

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

CREATE EXTENSION external_search_fdw;

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

Statement executed successfully

Для доступа к Elasticsearch создайте внешний сервер данных. Внутренний IP-адрес виртуальной машины можно найти в Compute Engine > Экземпляры виртуальных машин. Для указания пути к секрету перейдите в Secret Manager и выберите свой секрет; путь должен быть вверху. Убедитесь, что вы указали /versions/latest чтобы получить самую последнюю версию секрета.

CREATE SERVER elastic_demo_server
FOREIGN DATA WRAPPER external_search_fdw
OPTIONS(
    server 'http://[VM INTERNAL IP ADDRESS]:9200',
    search_provider 'elastic',
    auth_method 'ApiKey',
    secret_path '[SECRET PATH]/versions/latest'
);

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

CREATE FOREIGN TABLE elasticindexdemo (
    metadata external_search_fdw_schema.OpaqueMetadata,
    uniq_id TEXT,
    product_name TEXT,
    product_description TEXT
)
SERVER elastic_demo_server
OPTIONS(
    remote_table_name 'elasticindexdemo'
);

Создайте сопоставление пользователей для сервера.

CREATE USER MAPPING FOR CURRENT_USER SERVER elastic_demo_server;

Теперь вы можете протестировать внешнюю таблицу.

SELECT uniq_id, product_name
FROM elasticindexdemo
ORDER BY metadata <@> 'product_description:lamp' DESC
limit 10;

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

"uniq_id","product_name"
"59c05332f09426c23d8d005528e3c12e","CVL Mini Vintage Metal Lamp Shade: Black Metal with Punched Pattern"
"c24dd78c0d570105256e1bf1cb2fea9d","Better Homes & Gardens Tapered Drum Shade, White Box Pleat"
"7ba20db2bcfab28f88fc714d73af1eb8","4 Pack E27 Wireless Remote Control Light Lamp Bulb Holder Cap Socket Switch 30m"
"0fad1469ea9dfa80b35cfe5266b8bfe7","Star Projector Lamp, 360 Degree Star Night Light Romantic Room Rotating Cosmos Star Projuctor With USB Cable, Light Lamp Starry Moon Sky Night Projector Kid Bedroom Lamp"
"70b37e483ef3678078236d36954525ce","Lucille 10.5\""h Duck Egg Blue Empire Stitched Lamp Shade 7x10x8"
"b7a4b9151598f4cae7707cbedabe3c1b","10x12x8\"" SLIP UNO FITTER Hardback Shallow Drum Lamp Shade Textured Slate"
"5962cf47b88186eed76d14f6376882df","E27 To E14 Lampshade Lamp Light Shades Socket Reducing Ring Adapter Washer"
"7c54fdebfe0b1dd3f649741b8928a95b","iMounTEK LED Projector Lamp Kids Night Light Star Moon Projection Night Lamp 360\u00b0 Rotation Timer for Children Bedroom"
"4531201095c2653530747e215fcc1435","Home Concept Inc 11 Classics Brass Empire Lamp Shade"
"350527adb4299a015bcce74dee97805e","6 Colors LED Star Projector Lamp 360 Degree Romantic Rotating Night Cosmos Star Sky Moon Projector Kids Sleep Night Light For Children Gift Bedroom Decor"

11. Использование гибридного поиска

Продолжительность 15:00

Теперь, когда все настроено, мы можем использовать функцию ai.hybrid_search() для объединения векторного поиска и полнотекстового поиска. Подробнее о гибридном поиске можно прочитать в документации . При использовании гибридного поиска по умолчанию результаты запроса упорядочиваются с помощью алгоритма Reciprocal Rank Fusion для ранжирования результатов из нескольких запросов. Сначала давайте попробуем векторный поиск и гибридный поиск по отдельности, чтобы проанализировать их различия.

Следующий запрос выполняет векторный поиск для нахождения товаров, похожих на вишню. Массив предоставляет список поисковых запросов; в данном случае мы используем только векторный поиск, но позже мы предоставим как векторный, так и полнотекстовый поиск.

SELECT id, score, cymbal_products.product_name, cymbal_products.product_description
FROM ai.hybrid_search(
  ARRAY[
      '{
        "data_type": "vector",
        "table_name": "cymbal_products",
        "key_column": "uniq_id",
        "vec_column": "product_embedding",
        "distance_operator": "public.<=>",
        "limit": 3,
        "query_vector": "ai.embedding(''text-embedding-005'', ''cherry'')::vector"
      }'::JSONB
  ]
) JOIN cymbal_products ON id = cymbal_products.uniq_id;

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

"id","score","product_name","product_description"
"d536e9e823296a2eba198e52dd23e712","0.01639344262295082","Cherry Tree","This is a beautiful cherry tree that will produce delicious cherries. It is an deciduous tree that grows to be about 15 feet tall. The leaves are dark green in the summer and turn a beautiful red in the fall. Cherry trees are known for their beauty and their ability to provide shade and privacy. Cherry trees prefer a cool, moist climate and sandy soil. They are best suited for USDA zones 4-9."
"b70c44b1a38c0a2329fa583c9109a80f","0.016129032258064516","Peach Tree","This is a beautiful peach tree that will produce delicious peaches. It is an evergreen tree that grows to be about 20 feet tall. The leaves are dark green in the summer and turn a beautiful yellow in the fall. Peach trees are known for their beauty and their ability to provide shade and privacy. Peach trees prefer a cool, moist climate and sandy soil. They are best suited for USDA zones 2-9."
"23e41a71d63d8bbc9bdfa1d118cfddc5","0.015873015873015872","Apple Tree","This is a beautiful apple tree that will produce delicious apples. It is a deciduous tree that grows to be about 30 feet tall. The leaves are dark green in the summer and turn a beautiful red, orange, and yellow in the fall. Apple trees are known for their strength and durability. They are also a popular choice for shade trees. Apple trees prefer a cool, moist climate and loamy soil. They are best suited for USDA zones 4-8."

Для выполнения полнотекстового поиска выполните следующий запрос.

SELECT id, score, cymbal_products.product_name, cymbal_products.product_description
FROM ai.hybrid_search(
  ARRAY[
      '{
        "limit": 3,
        "data_type": "external_search_fdw",
        "table_name": "elasticindexdemo",
        "key_column": "uniq_id",
        "query_text_input": "product_description:(cherry)"
      }'::JSONB
  ]
) JOIN cymbal_products ON id = cymbal_products.uniq_id;

Обратите внимание, что в результатах поиска, поскольку полнотекстовый поиск использует точное совпадение, отображаются все товары, в описании которых содержится слово «вишня».

"id","score","product_name","product_description"
"d536e9e823296a2eba198e52dd23e712","0.01639344262295082","Cherry Tree","This is a beautiful cherry tree that will produce delicious cherries. It is an deciduous tree that grows to be about 15 feet tall. The leaves are dark green in the summer and turn a beautiful red in the fall. Cherry trees are known for their beauty and their ability to provide shade and privacy. Cherry trees prefer a cool, moist climate and sandy soil. They are best suited for USDA zones 4-9."
"390cf08feac229e7b752709fd1f943b3","0.016129032258064516","Woven Round Placemat, Set of Twelve, Grass","...These placemats are great for special occasions and holidays, but are also perfect to accessorize your everyday place settings.|Measurements. 15-inch round diameter is the perfect size for most table sizes and shapes.|Pop Colors. Choose from 7 pop woven color placemats including: Black, Cherry, Grass, Taupe, Navy, Sun and Graphite."
"2c9aa7ac98c30abf78dd9c62a68a34e6","0.015873015873015872","48 Scented Wax Melts Wax Cubes: Jelly Belly Jelly Beans Candy Bulk Soy Wax Melts For Candle Warmer, Wax Warmers, Wax Melt Warmers In 8 Pack Set","...From These Flavors: Lemon Drop, Mixed Berry Smoothie, Sizzling Cinnamon, Crushed Pineapple, Juicy Pear, Cotton Candy, Toasted Marshmallow, French Vanilla, Watermelon, Red Apple, Very Cherry, Buttered Popcorn..."

Теперь вы можете комбинировать семантический поиск и полнотекстовый поиск для получения более значимых результатов. Допустим, мы хотим найти дерево, которое может вырасти выше дома, и хотим, чтобы оно было из Калифорнии. Мы разделяем запрос, чтобы использовать семантическое намерение, а не буквальное совпадение. Векторный поиск обрабатывает описательную часть: «дерево, которое может вырасти выше дома», потому что он понимает концепцию высоты и масштаба без необходимости точных ключевых слов. В то же время полнотекстовый поиск использует «Калифорнию» в качестве строгого фильтра, чтобы гарантировать получение точного географического совпадения, а не просто чего-то концептуально похожего.

SELECT id, score, cymbal_products.product_name, cymbal_products.product_description
FROM ai.hybrid_search(
  ARRAY[
    '{
        "data_type": "vector",
        "table_name": "cymbal_products",
        "key_column": "uniq_id",
        "vec_column": "product_embedding",
        "distance_operator": "public.<=>",
        "limit": 3,
        "query_vector": "ai.embedding(''text-embedding-005'', ''tree that can grow taller than a house'')::vector"
      }'::JSONB,
      '{
        "limit": 3,
        "data_type": "external_search_fdw",
        "table_name": "elasticindexdemo",
        "key_column": "uniq_id",
        "query_text_input": "product_description:(California)"
      }'::JSONB
  ]
) JOIN cymbal_products ON id = cymbal_products.uniq_id;

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

"id","score","product_name","product_description"
"a589fd36a8a20fd9472d2403d6ed692a","0.00819672631147241","California Redwood","This is a beautiful redwood tree that can grow to be over 300 feet tall. It is an evergreen tree that grows in the coastal forests of California. Redwoods are known for their beauty and their strength. They are best suited for USDA zones 7-10."
"ef9432802da24041594c2cf368dfb4d2","0.008064521129029258","Madrone","This is a beautiful madrona tree that can grow to be over 80 feet tall. It is an evergreen tree that grows in the coastal forests of California. Madronas are known for their beauty and their bark. They are best suited for USDA zones 7-10."
"1360d8642bc218e4ea28e9c32b2e1721","0.007936512936504936","California Sycamore","This is a beautiful sycamore tree that can grow to be over 100 feet tall. It is an deciduous tree that grows in the valleys and foothills of California. California sycamores are known for their beauty and their shade. They are best suited for USDA zones 7-10."

12. Очистка окружающей среды

После завершения лабораторной работы удалите экземпляры AlloyDB и кластер.

Удалите кластер AlloyDB и все его экземпляры.

Если вы использовали пробную версию AlloyDB, не удаляйте пробный кластер, если планируете тестировать другие тестовые среды и ресурсы с его помощью. Вы не сможете создать другой пробный кластер в том же проекте.

Кластер уничтожается с помощью опции force, которая также удаляет все экземпляры, принадлежащие кластеру.

В облачной оболочке укажите переменные проекта и среды на случай, если соединение было разорвано и все предыдущие настройки были потеряны:

gcloud config set project <your project id>
export REGION=us-central1
export ADBCLUSTER=alloydb-hybrid-search
export PROJECT_ID=$(gcloud config get-value project)

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

gcloud alloydb clusters delete $ADBCLUSTER --region=$REGION --force

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

student@cloudshell:~ (test-project-001-402417)$ gcloud alloydb clusters delete $ADBCLUSTER --region=$REGION --force
All of the cluster data will be lost when the cluster is deleted.

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

Operation ID: operation-1697820178429-6082890a0b570-4a72f7e4-4c5df36f
Deleting cluster...done.   

Удалить резервные копии AlloyDB

Удалите все резервные копии AlloyDB для кластера:

for i in $(gcloud alloydb backups list --filter="CLUSTER_NAME: projects/$PROJECT_ID/locations/$REGION/clusters/$ADBCLUSTER" --format="value(name)" --sort-by=~createTime) ; do gcloud alloydb backups delete $(basename $i) --region $REGION --quiet; done

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

student@cloudshell:~ (test-project-001-402417)$ for i in $(gcloud alloydb backups list --filter="CLUSTER_NAME: projects/$PROJECT_ID/locations/$REGION/clusters/$ADBCLUSTER" --format="value(name)" --sort-by=~createTime) ; do gcloud alloydb backups delete $(basename $i) --region $REGION --quiet; done
Operation ID: operation-1697826266108-60829fb7b5258-7f99dc0b-99f3c35f
Deleting backup...done.                                                                                                                                                                                                                                                            

Теперь мы можем уничтожить нашу виртуальную машину.

Удалить виртуальную машину GCE

В оболочке Cloud Shell выполните:

export GCEVM=instance-1
export ZONE=us-central1-a
gcloud compute instances delete $GCEVM \
    --zone=$ZONE \
    --quiet

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

student@cloudshell:~ (test-project-001-402417)$ export GCEVM=instance-1
export ZONE=us-central1-a
gcloud compute instances delete $GCEVM \
    --zone=$ZONE \
    --quiet
Deleted

13. Поздравляем!

Поздравляем с завершением практического занятия!

Что мы рассмотрели

  • Как развернуть кластер AlloyDB и основной экземпляр
  • Как подключиться к AlloyDB с виртуальной машины Google Compute Engine
  • Как создать базу данных и включить AlloyDB AI
  • Как загрузить данные в базу данных
  • Как использовать AlloyDB Studio
  • Создавайте векторные представления с помощью Vertex AI.
  • Как создать векторный индекс ScaNN для повышения эффективности векторного поиска
  • Как создать внешний контейнер данных (Foreign Data Wrapper, FDW) для Elasticsearch
  • Выполните гибридный поиск, объединив семантический поиск в AlloyDB с полнотекстовым поиском в Elastic.

Следующие шаги

Вы можете ознакомиться с другими примерами кода AlloyDB на официальном сайте .