Начало работы с векторными внедрениями в Cloud SQL для PostgreSQL

1. Введение

В этой лаборатории вы узнаете, как использовать Cloud SQL для интеграции ИИ PostgreSQL путем объединения векторного поиска с внедрениями ИИ Vertex.

30b7c4dcdd8bb68f.png

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

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

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

  • Как развернуть экземпляр Cloud SQL для PostgreSQL
  • Как создать базу данных и включить интеграцию Cloud SQL AI
  • Как загрузить данные в базу данных
  • Как использовать модель внедрения Vertex AI в Cloud SQL
  • Как обогатить результат с помощью генеративной модели Vertex AI
  • Как повысить производительность с помощью векторного индекса

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

  • Учетная запись Google Cloud и проект Google Cloud
  • Веб-браузер, например Chrome, с поддержкой консоли Google Cloud и Cloud Shell.

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

Самостоятельная настройка среды

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

fbef9caa1602edd0.png

a99b7ace416376c4.png

5e3ff691252acf41.png

  • Имя проекта — это отображаемое имя для участников этого проекта. Это строка символов, не используемая API Google. Вы всегда можете обновить его.
  • Идентификатор проекта уникален для всех проектов Google Cloud и является неизменяемым (невозможно изменить после его установки). Cloud Console автоматически генерирует уникальную строку; обычно тебя не волнует, что это такое. В большинстве лабораторий кода вам потребуется указать идентификатор проекта (обычно идентифицируемый как PROJECT_ID ). Если вам не нравится сгенерированный идентификатор, вы можете создать другой случайный идентификатор. Альтернативно, вы можете попробовать свой собственный и посмотреть, доступен ли он. Его нельзя изменить после этого шага и он сохраняется на протяжении всего проекта.
  • К вашему сведению, есть третье значение — номер проекта , которое используют некоторые API. Подробнее обо всех трех этих значениях читайте в документации .
  1. Затем вам необходимо включить выставление счетов в Cloud Console, чтобы использовать облачные ресурсы/API. Прохождение этой кодовой лаборатории не будет стоить много, если вообще что-то стоить. Чтобы отключить ресурсы и избежать выставления счетов за пределами этого руководства, вы можете удалить созданные вами ресурсы или удалить проект. Новые пользователи Google Cloud имеют право на участие в программе бесплатной пробной версии стоимостью 300 долларов США .

Запустить Cloud Shell

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

В Google Cloud Console щелкните значок Cloud Shell на верхней правой панели инструментов:

55efc1aaa7a4d3ad.png

Подготовка и подключение к среде займет всего несколько минут. Когда все будет готово, вы должны увидеть что-то вроде этого:

7ffe5cbb04455448.png

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

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

Включить API

Выход:

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

gcloud config set project [YOUR-PROJECT-ID]

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

PROJECT_ID=$(gcloud config get-value project)

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

gcloud services enable sqladmin.googleapis.com \
                       compute.googleapis.com \
                       cloudresourcemanager.googleapis.com \
                       servicenetworking.googleapis.com \
                       aiplatform.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 sqladmin.googleapis.com \
                       compute.googleapis.com \
                       cloudresourcemanager.googleapis.com \
                       servicenetworking.googleapis.com \
                       aiplatform.googleapis.com
Operation "operations/acat.p2-4470404856-1f44ebd8-894e-4356-bea7-b84165a57442" finished successfully.

4. Создайте экземпляр Cloud SQL.

Создайте экземпляр Cloud SQL с интеграцией базы данных с Vertex AI.

Создать пароль базы данных

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

export CLOUDSQL_PASSWORD=`openssl rand -hex 12`

Обратите внимание на сгенерированное значение пароля:

echo $CLOUDSQL_PASSWORD

Создать Cloud SQL для экземпляра PostgreSQL

В сеансе Cloud Shell выполните:

gcloud sql instances create my-cloudsql-instance \
--database-version=POSTGRES_16 \
--tier=db-custom-1-3840 \
--region=us-central1 \
--edition=ENTERPRISE \
--enable-google-ml-integration \
--database-flags cloudsql.enable_google_ml_integration=on

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

gcloud sql users set-password postgres \
    --instance=my-cloudsql-instance \
    --password=$CLOUDSQL_PASSWORD

Запустите команду и введите свой пароль в командную строку, когда она будет готова к подключению.

gcloud sql connect my-cloudsql-instance --user=postgres

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

Предоставьте необходимые привилегии внутренней учетной записи облачной службы sql, чтобы иметь возможность использовать интеграцию Vertex AI.

Найдите адрес электронной почты внутренней учетной записи службы Cloud SQL и экспортируйте его как переменную.

SERVICE_ACCOUNT_EMAIL=$(gcloud sql instances describe my-cloudsql-instance --format="value(serviceAccountEmailAddress)")
echo $SERVICE_ACCOUNT_EMAIL

Предоставьте доступ к Vertex AI сервисному аккаунту Cloud SQL:

gcloud projects add-iam-policy-binding $PROJECT_ID \
  --member="serviceAccount:$SERVICE_ACCOUNT_EMAIL" \
  --role="roles/aiplatform.user"

Подробнее о создании и настройке экземпляра читайте в документации Cloud SQL здесь .

5. Подготовьте базу данных

Теперь нам нужно создать базу данных и включить поддержку векторов.

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

Создайте базу данных с именем faststart_db . Для этого у нас есть различные варианты, такие как клиенты базы данных командной строки, такие как psql для PostgreSQL, SDK или Cloud SQL Studio. Мы будем использовать SDK (gcloud) для создания баз данных и подключения к экземпляру.

В Cloud Shell выполните команду для создания базы данных.

gcloud sql databases create quickstart_db --instance=my-cloudsql-instance

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

Чтобы иметь возможность работать с Vertex AI и векторами, нам необходимо включить два расширения в нашей созданной базе данных.

В Cloud Shell выполните команду для подключения к созданной базе данных (вам потребуется ввести пароль)

gcloud sql connect my-cloudsql-instance --database quickstart_db --user=postgres

Затем, после успешного подключения, в сеансе sql вам необходимо выполнить две команды:

CREATE EXTENSION IF NOT EXISTS google_ml_integration CASCADE;
CREATE EXTENSION IF NOT EXISTS vector CASCADE;

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

exit;

6. Загрузить данные

Теперь нам нужно создать объекты в базе данных и загрузить данные. Мы собираемся использовать вымышленные данные Cymbal Store. Данные доступны в общедоступном хранилище Google Storage в формате CSV.

Сначала нам нужно создать все необходимые объекты в нашей базе данных. Для этого мы собираемся использовать уже знакомые команды gcloud sql Connect и gcloud Storage для загрузки и импорта объектов схемы в нашу базу данных.

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

gcloud storage cat gs://cloud-training/gcc/gcc-tech-004/cymbal_demo_schema.sql |gcloud sql connect my-cloudsql-instance --database quickstart_db --user=postgres

Что именно мы сделали в предыдущей команде? Мы подключились к нашей базе данных и выполнили загруженный код SQL, который создал таблицы, индексы и последовательности.

Следующим шагом является загрузка данных, и для этого нам нужно загрузить файлы CSV из облачного хранилища Google.

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

Затем нам нужно подключиться к базе данных.

gcloud sql connect my-cloudsql-instance --database quickstart_db --user=postgres

И импортируйте данные из наших файлов CSV.

\copy cymbal_products from 'cymbal_products.csv' csv header
\copy cymbal_inventory from 'cymbal_inventory.csv' csv header
\copy cymbal_stores from 'cymbal_stores.csv' csv header

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

exit;

Если у вас есть собственные данные и файлы CSV совместимы с инструментом импорта Cloud SQL, доступным в консоли Cloud, вы можете использовать его вместо командной строки.

7. Создание вложений

Следующим шагом будет создание вложений для описаний наших продуктов с использованием модели textembedding-004 от Google Vertex AI и сохранение их в виде векторных данных.

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

gcloud sql connect my-cloudsql-instance --database quickstart_db --user=postgres

И создайте встраивание виртуального столбца в нашу таблицу cymbal_products, используя функцию встраивания.

ALTER TABLE cymbal_products ADD COLUMN embedding vector(768) GENERATED ALWAYS AS (embedding('text-embedding-004',product_description)) STORED;

Это может занять некоторое время, но для 900-1000 строк это не должно занять более 5 минут, а обычно это намного быстрее.

8. Запустите поиск по сходству

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

SQL-запрос можно выполнить из того же интерфейса командной строки, используя соединение gcloud sql или, в качестве альтернативы, из Cloud SQL Studio. Любой многострочный и сложный запрос лучше обрабатывать в Cloud SQL Studio.

Запустите Cloud SQL Studio.

В консоли щелкните экземпляр Cloud SQL, который мы создали ранее.

b8d4844da1114a0b.png

Когда он открыт на правой панели, мы видим Cloud SQL Studio. Нажмите на него.

ce3f27dc21367f2e.png

Откроется диалоговое окно, в котором вы укажите имя базы данных и свои учетные данные:

  • База данных: faststart_db
  • Пользователь: postgres
  • Пароль: указанный вами пароль для основного пользователя базы данных.

И нажмите кнопку «АУТЕНТИФИКАЦИЯ».

2591c8bbc93e4e97.png

Откроется следующее окно, в котором вы щелкнете вкладку «Редактор» справа, чтобы открыть редактор SQL.

74307cb101a3ba9d.png

Теперь мы готовы выполнить наши запросы.

Запустить запрос

Запустите запрос, чтобы получить список доступных продуктов, наиболее соответствующих запросу клиента. Запрос, который мы собираемся передать Vertex AI для получения значения вектора, звучит так: «Какие фруктовые деревья здесь хорошо растут?»

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

SELECT
        cp.product_name,
        left(cp.product_description,80) as description,
        cp.sale_price,
        cs.zip_code,
        (cp.embedding <=> embedding('text-embedding-004','What kind of fruit trees grow well here?')::vector) as distance
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
        distance ASC
LIMIT 10;

Скопируйте и вставьте запрос в редактор Cloud SQL Studio и нажмите кнопку «Выполнить» или вставьте его в сеанс командной строки, подключающийся к базе данных faststart_db.

cd07549522fd04c9.png

А вот список продуктов, выбранных по запросу.

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.43922018972266397
 Meyer Lemon Tree        | Meyer Lemon trees are California's favorite lemon tree! Grow your own lemons by  |         34 |    93230 |  0.4685112926118228
 Toyon                   | This is a beautiful toyon tree that can grow to be over 20 feet tall. It is an e |      10.00 |    93230 |  0.4835677149651668
 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.4947204525907498
 California Peppertree   | This is a beautiful peppertree that can grow to be over 30 feet tall. It is an e |      25.00 |    93230 |  0.5054166905547247
 California Black Walnut | This is a beautiful walnut tree that can grow to be over 80 feet tall. It is a d |     100.00 |    93230 |  0.5084219510932597
 California Sycamore     | This is a beautiful sycamore tree that can grow to be over 100 feet tall. It is  |     300.00 |    93230 |  0.5140519790508755
 Coast Live Oak          | This is a beautiful oak tree that can grow to be over 100 feet tall. It is an ev |     500.00 |    93230 |  0.5143126438081371
 Fremont Cottonwood      | This is a beautiful cottonwood tree that can grow to be over 100 feet tall. It i |     200.00 |    93230 |  0.5174774727252058
 Madrone                 | This is a beautiful madrona tree that can grow to be over 80 feet tall. It is an |      50.00 |    93230 |  0.5227400803389093
(10 rows)

9. Улучшите ответ LLM, используя полученные данные

Мы можем улучшить ответ Gen AI LLM клиентскому приложению, используя результат выполненного запроса, и подготовить значимый вывод, используя предоставленные результаты запроса как часть приглашения к модели генеративного базового языка Vertex AI.

Для этого нам нужно сгенерировать JSON с нашими результатами векторного поиска, а затем использовать этот сгенерированный JSON в качестве дополнения к подсказке для модели LLM в Vertex AI, чтобы создать значимый результат. На первом этапе мы генерируем JSON, затем тестируем его в Vertex AI Studio, а на последнем этапе включаем его в оператор SQL, который можно использовать в приложении.

Создать вывод в формате JSON

Измените запрос, чтобы он генерировал выходные данные в формате JSON и возвращал только одну строку для передачи в Vertex AI.

Облачный SQL для PostgreSQL

Вот пример запроса:

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.embedding <=> embedding('text-embedding-004','What kind of fruit trees grow well here?')::vector) ASC
LIMIT 1)
SELECT json_agg(trees) FROM trees;

А вот ожидаемый JSON на выходе:

[{"product_name":"Cherry Tree","description":"This is a beautiful cherry tree that will produce delicious cherries. It is an d","sale_price":75.00,"zip_code":93230,"product_id":"d536e9e823296a2eba198e52dd23e712"}]

Запустите командную строку в Vertex AI Studio.

Мы можем использовать сгенерированный JSON, чтобы предоставить его как часть запроса на генеративную текстовую модель ИИ в Vertex AI Studio.

Откройте чат Vertex AI Studio в облачной консоли.

449b5959fa0e93bd.png

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

Вот подсказка, которую мы собираемся использовать:

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","description":"some description","sale_price":10,"zip_code": 10234, "produt_id": "02056727942aeb714dc9a2313654e1b0"}
Here is the list of products:
[place your JSON here]
The customer asked "What tree is growing the best here?"
You should give information about the product, price and some supplemental information.
Do not ask any additional questions and assume location based on the zip code provided in the list of products.

А вот как это выглядит, когда мы заменяем заполнитель JSON ответом на запрос:

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","description":"some description","sale_price":10,"zip_code": 10234, "produt_id": "02056727942aeb714dc9a2313654e1b0"}
Here is the list of products:
[{"product_name":"Cherry Tree","description":"This is a beautiful cherry tree that will produce delicious cherries. It is an d","sale_price":75.00,"zip_code":93230,"product_id":"d536e9e823296a2eba198e52dd23e712"}]
The customer asked "What tree is growing the best here?"
You should give information about the product, price and some supplemental information.
Do not ask any additional questions and assume location based on the zip code provided in the list of products.

И вот результат, когда мы запускаем приглашение с нашими значениями JSON и используем модель Gemini-2.0-flash:

2c5145ebc04daae1.png

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

«Хорошо, судя по имеющемуся списку продуктов, лучшее дерево, которое у нас есть и которое может хорошо расти в вашем районе, — это вишня.

Его цена составляет 75,00 долларов.

Хотя у меня нет конкретных подробностей об условиях выращивания в вашем точном почтовом индексе (93230), известно, что вишневые деревья хорошо растут в районах с умеренным климатом и хорошо дренированной почвой. Обычно для плодоношения им требуется определенный период зимних холодов, так что об этом следует помнить. Тем не менее, они могут стать прекрасным дополнением к саду, обеспечивая красоту и вкусную вишню при подходящих условиях».

Запустите командную строку в PSQL

Мы также можем использовать интеграцию Cloud SQL AI с Vertex AI, чтобы получить аналогичный ответ от генеративной модели, использующей SQL непосредственно в базе данных. Но чтобы использовать модель Gemini-2.0-flash-exp, нам необходимо сначала зарегистрировать ее.

Запуск в Cloud SQL для PostgreSQL

Обновите расширение до версии 1.4.2 или выше (если текущая версия ниже). Подключитесь к базе данных Quickstart_db из gcloud sql Connect , как было показано ранее (или используйте Cloud SQL Studio) и выполните:

SELECT extversion from pg_extension where extname='google_ml_integration';

Если возвращаемое значение меньше 1.4.2, выполните:

ALTER EXTENSION google_ml_integration UPDATE TO '1.4.2';

Затем нам нужно установить флаг базы данных google_ml_integration.enable_model_support в положение «on». Для этого вы можете использовать интерфейс веб-консоли или выполнить следующую команду gcloud.

gcloud sql instances patch my-cloudsql-instance \
--database-flags google_ml_integration.enable_model_support=on,cloudsql.enable_google_ml_integration=on

Выполнение команды в фоновом режиме занимает около 1–3 минут. Затем вы можете проверить новый флаг в сеансе psql или с помощью Cloud SQL Studio, подключаясь к базе данных faststart_db.

show google_ml_integration.enable_model_support;

Ожидаемый результат сеанса psql — «включен»:

quickstart_db => show google_ml_integration.enable_model_support;
 google_ml_integration.enable_model_support 
--------------------------------------------
 on
(1 row)

Затем нам нужно зарегистрировать две модели. Первая — это уже используемая модель text-embedding-004 . Его необходимо зарегистрировать, поскольку мы включили возможности регистрации модели.

Чтобы зарегистрировать модель, запустите в psql или Cloud SQL Studio следующий код:

CALL
  google_ml.create_model(
    model_id => 'text-embedding-004',
    model_provider => 'google',
    model_qualified_name => 'text-embedding-004',
    model_type => 'text_embedding',
    model_auth_type => 'cloudsql_service_agent_iam',
    model_in_transform_fn => 'google_ml.vertexai_text_embedding_input_transform',
    model_out_transform_fn => 'google_ml.vertexai_text_embedding_output_transform');

И следующая модель, которую нам нужно зарегистрировать, — это Gemini-2.0-flash-001, которая будет использоваться для создания удобного для пользователя вывода.

CALL
  google_ml.create_model(
    model_id => 'gemini-2.0-flash-001',
    model_request_url => 'https://us-central1-aiplatform.googleapis.com/v1/projects/$PROJECT_ID/locations/us-central1/publishers/google/models/gemini-2.0-flash-001:streamGenerateContent',
    model_provider => 'google',
    model_auth_type => 'cloudsql_service_agent_iam');

Вы всегда можете проверить список зарегистрированных моделей, выбрав информацию из google_ml.model_info_view.

select model_id,model_type from google_ml.model_info_view;

Вот пример вывода

quickstart_db=> select model_id,model_type from google_ml.model_info_view;
               model_id               |   model_type   
--------------------------------------+----------------
 textembedding-gecko                  | text_embedding
 textembedding-gecko@001              | text_embedding
 gemini-1.5-pro:streamGenerateContent | generic
 gemini-1.5-pro:generateContent       | generic
 gemini-1.0-pro:generateContent       | generic
 text-embedding-004                   | text_embedding
 gemini-2.0-flash-001                 | generic

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

В сеансе psql или Cloud SQL Studio к базе данных выполните запрос.

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_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.embedding <=> google_ml.embedding('text-embedding-004',
        '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
        json_array_elements(google_ml.predict_row( model_id =>'gemini-2.0-flash-001',
        request_body => json_build_object('contents',
        json_build_object('role',
        'user',
        'parts',
        json_build_object('text',
        prompt_text)))))->'candidates'->0->'content'->'parts'->0->'text' AS resp
FROM
        prompt)
SELECT
        string_agg(resp::text,
        ' ')
FROM
        response;

И вот ожидаемый результат. Результат может отличаться в зависимости от версии и параметров модели:

"That" "'s a great question! Based on your location (assuming you're" " in zip code 93230), I have a suggestion for a" " fruit tree that should thrive.\n\nWe have the **Cherry Tree** available.\n\n**Product Name:** Cherry Tree\n\n**Description:** This is a beautiful cherry" " tree that will produce delicious cherries. It's a deciduous tree (meaning it loses its leaves in the fall) growing to about 15 feet tall." " The leaves are dark green in summer, turning a beautiful red in the fall. Cherry trees are known for their beauty, shade, and privacy.\n\n**Sale Price:** $75.00\n\n**Important Considerations for Growing" " Cherry Trees:**\n\n* **Climate:** Cherry trees prefer a cool, moist climate, and 93230 falls within a suitable range (USDA zones 4-9). However, it's always a good idea to" " check the specific microclimate of your property (sun exposure, drainage etc.).\n* **Soil:** They do best in sandy soil. If your soil is different, you may need to amend it to improve drainage.\n* **Pollination:** Many cherry varieties require a second, compatible cherry tree for proper pollination" ". Check the specific pollination needs of this variety before purchase if you want a significant cherry yield.\n\nThis cherry tree is a beautiful addition to any yard and will provide you with delicious cherries if you can meet its needs. Would you like to know more about its pollination requirements, or perhaps see if we have any other" " fruit trees suitable for your area?\n" ""

10. Создайте индекс ближайших соседей

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

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

Для нашего теста мы собираемся попробовать тип индекса HNSW. HNSW расшифровывается как Hierarchical Navigable Small World и представляет собой индекс многослойного графа.

Чтобы построить индекс для нашего столбца внедрения, нам нужно определить столбец внедрения, функцию расстояния и, при необходимости, такие параметры, как m или ef_constructions. Подробно о параметрах можно прочитать в документации .

CREATE INDEX cymbal_products_embeddings_hnsw ON cymbal_products
  USING hnsw (embedding vector_cosine_ops)
  WITH (m = 16, ef_construction = 64);

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

quickstart_db=> CREATE INDEX cymbal_products_embeddings_hnsw ON cymbal_products
  USING hnsw (embedding vector_cosine_ops)
  WITH (m = 16, ef_construction = 64);
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.embedding <=> embedding('text-embedding-004','What kind of fruit trees grow well here?')::vector) ASC
LIMIT 1)
SELECT json_agg(trees) FROM trees;

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

 Aggregate  (cost=779.12..779.13 rows=1 width=32) (actual time=1.066..1.069 rows=1 loops=1)
   ->  Subquery Scan on trees  (cost=769.05..779.12 rows=1 width=142) (actual time=1.038..1.041 rows=1 loops=1)
         ->  Limit  (cost=769.05..779.11 rows=1 width=158) (actual time=1.022..1.024 rows=1 loops=1)
               ->  Nested Loop  (cost=769.05..9339.69 rows=852 width=158) (actual time=1.020..1.021 rows=1 loops=1)
                     ->  Nested Loop  (cost=768.77..9316.48 rows=852 width=945) (actual time=0.858..0.859 rows=1 loops=1)
                           ->  Index Scan using cymbal_products_embeddings_hnsw on cymbal_products cp  (cost=768.34..2572.47 rows=941 width=941) (actual time=0.532..0.539 rows=3 loops=1)
                                 Order By: (embedding <=> '[0.008864171,0.03693164,-0.024245683,...
<redacted>
...,0.017593635,-0.040275685,-0.03914233,-0.018452475,0.00826032,-0.07372604
]'::vector)
                           ->  Index Scan using product_inventory_pkey on cymbal_inventory ci  (cost=0.42..7.17 rows=1 width=37) (actual time=0.104..0.104 rows=0 loops=3)
                                 Index Cond: ((store_id = 1583) AND (uniq_id = (cp.uniq_id)::text))
                                 Filter: (inventory > 0)
                                 Rows Removed by Filter: 1
                     ->  Materialize  (cost=0.28..8.31 rows=1 width=8) (actual time=0.133..0.134 rows=1 loops=1)
                           ->  Index Scan using product_stores_pkey on cymbal_stores cs  (cost=0.28..8.30 rows=1 width=8) (actual time=0.129..0.129 rows=1 loops=1)
                                 Index Cond: (store_id = 1583)
 Planning Time: 112.398 ms
 Execution Time: 1.221 ms

Из вывода мы ясно видим, что в запросе использовалось «Индексное сканирование с использованием cymbal_products_embeddings_hnsw».

И если мы запустим запрос без объяснения:

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.embedding <=> embedding('text-embedding-004','What kind of fruit trees grow well here?')::vector) ASC
LIMIT 1)
SELECT json_agg(trees) FROM trees;

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

[{"product_name":"Cherry Tree","description":"This is a beautiful cherry tree that will produce delicious cherries. It is an d","sale_price":75.00,"zip_code":93230,"product_id":"d536e9e823296a2eba198e52dd23e712"}]

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

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

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

Удалить экземпляр Cloud SQL

Уничтожьте экземпляр Cloud SQL, когда закончите лабораторную работу.

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

export INSTANCE_NAME=my-cloudsql-instance
export PROJECT_ID=$(gcloud config get-value project)

Удалите экземпляр:

gcloud sql instances delete $INSTANCE_NAME --project=$PROJECT_ID

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

student@cloudshell:~$ gcloud sql instances delete $INSTANCE_NAME --project=$PROJECT_ID
All of the instance data will be lost when the instance is deleted.

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

Deleting Cloud SQL instance...done.                                                                                                                
Deleted [https://sandbox.googleapis.com/v1beta4/projects/test-project-001-402417/instances/my-cloudsql-instance].

12. Поздравления

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

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

  • Как развернуть экземпляр Cloud SQL для PostgreSQL
  • Как создать базу данных и включить интеграцию Cloud SQL AI
  • Как загрузить данные в базу данных
  • Как использовать модель внедрения Vertex AI в Cloud SQL
  • Как обогатить результат с помощью генеративной модели Vertex AI
  • Как повысить производительность с помощью векторного индекса

Попробуйте аналогичную кодовую работу для AlloyDB с индексом ScaNN вместо HNSW.

13. Опрос

Выход:

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

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