Создайте и разверните динамический гибридный поиск в розничной торговле с помощью AlloyDB, Gemini и Cloud Run

1. Обзор

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

Теперь у нас уже есть базовое понимание трех вещей:

  1. Что означает контекстный поиск для вашего агента и как его добиться с помощью Vector Search.
  2. Мы также глубоко погрузились в реализацию векторного поиска в пределах ваших данных, то есть внутри самой вашей базы данных (все облачные базы данных Google поддерживают это, если вы еще не знали!).
  3. Мы пошли на шаг дальше остального мира, рассказав вам, как реализовать столь легкую возможность векторного поиска RAG с высокой производительностью и качеством с помощью возможности векторного поиска AlloyDB на основе индекса ScaNN.

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

Вызов

Выход за рамки фильтров, ключевых слов и контекстного соответствия: простой поиск по ключевым словам может вернуть тысячи результатов, многие из которых нерелевантны. Идеальное решение должно понимать цель запроса, сочетать её с точными критериями фильтрации (например, бренд, материал или цена) и выдавать наиболее релевантные товары за миллисекунды. Для этого требуется мощная, гибкая и масштабируемая поисковая инфраструктура. Конечно, мы прошли долгий путь от поиска по ключевым словам до контекстного соответствия и поиска по сходству. Но представьте, что клиент ищет «удобную, стильную, водонепроницаемую куртку для весенних походов», одновременно применяя фильтры. Ваше приложение не только возвращает качественные ответы, но и отличается высокой производительностью, а последовательность всех этих запросов динамически выбирается вашей базой данных.

Цель

Чтобы решить эту проблему путем интеграции

  • Контекстный поиск (векторный поиск): понимание семантического значения запросов и описаний продуктов
  • Фасетная фильтрация: предоставление пользователям возможности уточнять результаты с помощью определенных атрибутов
  • Гибридный подход: гармоничное сочетание контекстного поиска и структурированной фильтрации
  • Расширенная оптимизация: использование специализированной индексации, адаптивной фильтрации и переранжирования для скорости и релевантности
  • Генеративный контроль качества на основе искусственного интеллекта: включение проверки LLM для получения результатов высочайшего качества.

Давайте подробно рассмотрим процесс разработки архитектуры и внедрения.

Что вы построите

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

В рамках этого вам предстоит:

  1. Создайте экземпляр AlloyDB и таблицу для набора данных электронной коммерции.
  2. Настройка встраивания и поиска векторов
  3. Создать индекс метаданных и индекс ScaNN
  4. Реализуйте расширенный поиск векторов в AlloyDB с использованием метода встроенной фильтрации ScaNN.
  5. Настройте фасетные фильтры и гибридный поиск в одном запросе
  6. Уточните релевантность запроса с помощью повторного ранжирования и отзыва (необязательно)
  7. Оцените ответ на запрос с помощью Gemini (необязательно)
  8. Набор инструментов MCP для баз данных и прикладного уровня
  9. Разработка приложений (Java) с фасетным поиском

Требования

  • Браузер, например Chrome или Firefox
  • Проект Google Cloud с включенным биллингом.

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

Создать проект

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

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

  1. Вы будете использовать Cloud Shell — среду командной строки, работающую в Google Cloud. Нажмите «Активировать Cloud Shell» в верхней части консоли Google Cloud.

Изображение кнопки «Активировать Cloud Shell»

  1. После подключения к Cloud Shell вы проверяете, что вы уже прошли аутентификацию и что проекту присвоен ваш идентификатор проекта, с помощью следующей команды:
gcloud auth list
  1. Выполните следующую команду в Cloud Shell, чтобы подтвердить, что команда gcloud знает о вашем проекте.
gcloud config list project
  1. Если ваш проект не настроен, используйте следующую команду для его настройки:
gcloud config set project <YOUR_PROJECT_ID>
  1. Включите необходимые API: Перейдите по ссылке и включите API.

В качестве альтернативы вы можете использовать команду gcloud. Подробности о командах и использовании gcloud см. в документации .

3. Настройка базы данных

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

Давайте создадим кластер, экземпляр и таблицу AlloyDB, куда будет загружен набор данных электронной коммерции.

Создать кластер и экземпляр

  1. Перейдите на страницу AlloyDB в Cloud Console. Большинство страниц в Cloud Console легко найти, используя строку поиска в консоли.
  2. Выберите СОЗДАТЬ КЛАСТЕР на этой странице:

f76ff480c8c889aa.png

  1. Вы увидите экран, подобный показанному ниже. Создайте кластер и экземпляр со следующими значениями (убедитесь, что значения совпадают, если вы клонируете код приложения из репозитория):
  • идентификатор кластера : " vector-cluster "
  • пароль : " alloydb "
  • PostgreSQL 15 / последняя рекомендуемая версия
  • Region : " us-central1 "
  • Сетевое подключение : " default "

538dba58908162fb.png

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

Выберите НАСТРОЙКА ПОДКЛЮЧЕНИЯ .

7939bbb6802a91bf.png

  1. Далее выберите « Использовать автоматически назначенный диапазон IP-адресов » и нажмите «Продолжить». После ознакомления с информацией нажмите «СОЗДАТЬ ПОДКЛЮЧЕНИЕ». 768ff5210e79676f.png
  2. После настройки сети вы можете продолжить создание кластера. Нажмите «СОЗДАТЬ КЛАСТЕР» , чтобы завершить настройку кластера, как показано ниже:

e06623e55195e16e.png

ВАЖНОЕ ПРИМЕЧАНИЕ:

  1. Обязательно измените идентификатор экземпляра (который вы можете найти во время настройки кластера/экземпляра) на ** vector-instance **. Если изменить его невозможно, не забудьте **использовать идентификатор экземпляра** во всех последующих ссылках.
  2. Обратите внимание, что создание кластера займёт около 10 минут. После успешного завершения вы увидите экран с обзором только что созданного кластера.

4. Прием данных

Теперь пора добавить таблицу с данными о магазине. Перейдите в AlloyDB, выберите основной кластер, а затем AlloyDB Studio:

847e35f1bf8a8bd8.png

Возможно, вам придётся дождаться завершения создания вашего экземпляра. После этого войдите в AlloyDB, используя учётные данные, которые вы создали при создании кластера. Для аутентификации в PostgreSQL используйте следующие данные:

  • Имя пользователя: " postgres "
  • База данных: " postgres "
  • Пароль: " alloydb "

После успешной аутентификации в AlloyDB Studio команды SQL вводятся в редакторе. Вы можете добавить несколько окон редактора, нажав на значок «плюс» справа от последнего окна.

91a86d9469d499c4.png

Вы будете вводить команды для AlloyDB в окнах редактора, используя при необходимости параметры «Выполнить», «Форматировать» и «Очистить».

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

Для создания этого приложения мы будем использовать расширения pgvector и google_ml_integration . Расширение pgvector позволяет хранить и искать векторные представления. Расширение google_ml_integration предоставляет функции для доступа к конечным точкам прогнозирования Vertex AI для получения прогнозов в SQL. Включите эти расширения, выполнив следующие DDL-файлы:

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

Если вы хотите проверить расширения, включенные в вашей базе данных, выполните следующую команду SQL:

select extname, extversion from pg_extension;

Создать таблицу

Вы можете создать таблицу, используя приведенный ниже оператор DDL в AlloyDB Studio:

CREATE TABLE apparels ( 
  id BIGINT, 
  category VARCHAR(100), 
  sub_category VARCHAR(50), 
  uri VARCHAR(200), 
  gsutil_uri VARCHAR(200),
  image VARCHAR(100), 
  content VARCHAR(2000), 
  pdt_desc VARCHAR(5000), 
  color VARCHAR(2000),
  gender VARCHAR(200),
  embedding vector(768),
  img_embeddings vector(1408),
  additional_specification VARCHAR(100000));

Встраиваемый столбец позволит хранить векторные значения текста.

Предоставить разрешение

Выполните указанный ниже оператор, чтобы предоставить разрешение на выполнение функции «встраивания»:

GRANT EXECUTE ON FUNCTION embedding TO postgres;

Предоставьте роль пользователя Vertex AI учетной записи службы AlloyDB.

В консоли Google Cloud IAM предоставьте учётной записи сервиса AlloyDB (которая выглядит так: service-<<PROJECT_NUMBER>>@gcp-sa-alloydb.iam.gserviceaccount.com) доступ к роли «Пользователь Vertex AI». PROJECT_NUMBER будет содержать номер вашего проекта.

В качестве альтернативы вы можете выполнить следующую команду из терминала Cloud Shell:

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"

Загрузить данные в базу данных

  1. Скопируйте операторы запроса на insert из insert scripts sql в указанную выше таблицу в редактор. Вы можете скопировать 10–50 операторов для быстрой демонстрации этого варианта использования. Список выбранных вставок представлен на вкладке «Выбранные вставки 25–30 строк».

Ссылку на данные можно найти в этом файле репозитория github .

  1. Нажмите кнопку «Выполнить» . Результаты запроса появятся в таблице «Результаты» .

ВАЖНОЕ ПРИМЕЧАНИЕ:

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

5. Создайте вложения для данных.

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

Мы преобразовали описания продуктов и запросы пользователей в многомерные числовые представления, называемые «эмбеддингами», используя предварительно обученные языковые модели. Эти эмбеддинги отражают семантическое значение, позволяя нам находить продукты, «сходные по значению», а не просто содержащие совпадающие слова. Изначально мы экспериментировали с прямым поиском векторного сходства на этих эмбеддингах, чтобы определить базовый уровень, продемонстрировав эффективность семантического понимания ещё до оптимизации производительности.

Столбец «embedding» позволяет хранить векторные значения текста описания товара. Столбец «img_embeddings» позволяет хранить вложения изображений (мультимодальные). Таким образом, вы также можете использовать текст для поиска по расстоянию между изображениями. Но в этой лабораторной работе мы будем использовать только вложения текста.

SELECT embedding('text-embedding-005', 'AlloyDB is a managed, cloud-hosted SQL database service.');

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

25a1d7ef0e49e91e.png

Обновите векторное поле abstract_embeddings

Запустите приведенный ниже DML-код, чтобы обновить описание содержимого в таблице с соответствующими внедрениями:

UPDATE apparels SET embedding = embedding('text-embedding-005',pdt_desc)::vector 
WHERE pdt_desc IS NOT NULL;

При использовании пробной учётной записи Google Cloud с оплатой кредита могут возникнуть проблемы с генерацией большего количества вложений (например, максимум 20–25). Поэтому ограничьте количество строк в скрипте вставки.

Если вы хотите сгенерировать вставки изображений (для выполнения мультимодального контекстного поиска), запустите также следующее обновление:

update apparels set img_embeddings = ai.image_embedding(
  model_id => 'multimodalembedding@001',
  image => gsutil_uri,
  mimetype => 'image/jpg')       
where gsutil_uri is not null

6. Выполните расширенный RAG с помощью новых функций AlloyDB

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

SELECT id, content, uri, category, sub_category,color,gender 
FROM apparels 
ORDER BY embedding <=> embedding('text-embedding-005','T-shirt with round neck')::vector limit 10 ;

В этом запросе мы сравниваем встраивание текста в поисковый запрос пользователя «Футболка с круглым вырезом» с встраиванием текста всех описаний товаров в таблице «Одежда» (сохраненной в столбце с именем «встраивание»), используя функцию косинусного расстояния сходства (представленную символом «<=>»). Мы преобразуем результат метода встраивания в векторный тип, чтобы сделать его совместимым с векторами, хранящимися в базе данных. LIMIT 10 означает, что мы выбираем 10 наиболее близких совпадений поискового текста.

AlloyDB выводит Vector Search RAG на новый уровень:

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

Индекс ScaNN (масштабируемый алгоритм ближайших соседей)

Для сверхбыстрого поиска по методу приближенного ближайшего соседа (ИНС) мы включили индекс scaNN в AlloyDB. ScaNN, современный алгоритм приближенного поиска по методу ближайшего соседа, разработанный Google Research, предназначен для эффективного масштабируемого поиска по сходству векторов. Он значительно ускоряет выполнение запросов за счёт эффективного сокращения пространства поиска и использования методов квантования, обеспечивая до 4 раз более быстрые векторные запросы по сравнению с другими методами индексации и меньший объём занимаемой памяти. Подробнее об этом можно узнать здесь и здесь .

Давайте включим расширение и создадим индексы:

CREATE EXTENSION IF NOT EXISTS alloydb_scann;

Создание индексов как для полей встраивания текста, так и для полей встраивания изображений (если вы хотите использовать встраивание изображений в своем поиске):

CREATE INDEX apparels_index ON apparels 
USING scann (embedding cosine)
WITH (num_leaves=32);

CREATE INDEX apparels_img_index ON apparels 
USING scann (img_embeddings cosine)
WITH (num_leaves=32);

Индексы метаданных

В то время как scaNN обрабатывает векторную индексацию, традиционные индексы B-дерева или GIN были тщательно настроены на основе структурированных атрибутов (таких как категория, подкатегория, стиль, цвет и т. д.). Эти индексы критически важны для эффективности фасетной фильтрации. Выполните следующие операторы, чтобы настроить индексы метаданных:

CREATE INDEX idx_category ON apparels (category);

CREATE INDEX idx_sub_category ON apparels (sub_category);

CREATE INDEX idx_color ON apparels (color);

CREATE INDEX idx_gender ON apparels (gender);

ВАЖНОЕ ПРИМЕЧАНИЕ:

Поскольку вы могли вставить только 25–50 записей, индексы (ScaNN или любой другой индекс) не будут эффективными.

Встроенная фильтрация

Распространенной проблемой векторного поиска является его сочетание со структурированными фильтрами (например, «красные туфли»). Встроенная фильтрация AlloyDB оптимизирует этот процесс. Вместо пост-фильтрации результатов широкого векторного поиска, встроенная фильтрация применяет условия фильтрации непосредственно в процессе поиска, что значительно повышает производительность и точность отфильтрованных векторных поисков.

Чтобы узнать больше о необходимости встроенной фильтрации, обратитесь к этой документации . Также о поиске векторов с фильтрацией для оптимизации производительности можно узнать здесь . Теперь, если вы хотите включить встроенную фильтрацию в своём приложении, выполните следующую команду в редакторе:

SET scann.enable_inline_filtering = on;

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

Адаптивная фильтрация

Для дальнейшей оптимизации производительности адаптивная фильтрация AlloyDB динамически выбирает наиболее эффективную стратегию фильтрации (встроенную или предварительную) во время выполнения запроса. Она анализирует шаблоны запросов и распределение данных, обеспечивая оптимальную производительность без ручного вмешательства, что особенно полезно для поиска векторных данных с фильтрацией, где функция автоматически переключается между использованием векторных данных и индекса метаданных. Чтобы включить адаптивную фильтрацию, используйте флаг scann.enable_preview_features.

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

SET scann.enable_preview_features = on;

ВАЖНОЕ ПРИМЕЧАНИЕ: Если вы столкнетесь с ошибкой, вы, возможно, не сможете выполнить приведенный выше оператор без перезапуска экземпляра — лучше включите флаг enable_preview_features в разделе флагов базы данных вашего экземпляра.

Фасетные фильтры, использующие все индексы

Фасетный поиск позволяет пользователям уточнять результаты, применяя несколько фильтров на основе определённых атрибутов или «фасетов» (например, бренд, цена, размер, рейтинг клиента). Наше приложение органично интегрирует эти фасеты с векторным поиском. Теперь один запрос может сочетать естественный язык (контекстный поиск) с несколькими фасетными выборками, динамически используя как векторные, так и традиционные индексы. Это обеспечивает по-настоящему динамичный гибридный поиск, позволяя пользователям точно детализировать результаты.

Поскольку в нашем приложении мы уже создали все индексы метаданных, мы полностью готовы к использованию фасетного фильтра в Интернете, обращаясь к нему напрямую с помощью SQL-запросов:

SELECT id, content, uri, category, sub_category,color,gender 
FROM apparels
WHERE category = ANY($1) and sub_Category = ANY($2) and color = ANY($3) and gender = ANY($4)
ORDER BY embedding <=> embedding('text-embedding-005',$5)::vector limit 10 ;

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

  1. Фасетная фильтрация в предложении WHERE и
  2. Векторный поиск в предложении ORDER BY с использованием метода косинусного подобия.

$1, $2, $3 и $4 представляют значения фасетного фильтра в массиве, а $5 — текст поискового запроса пользователя. Замените $1–$4 значениями фасетного фильтра по вашему выбору, как показано ниже:

категория = ЛЮБАЯ(['Одежда', 'Обувь'])

Замените $5 на поисковый текст по вашему выбору, например, «Футболки-поло».

ВАЖНОЕ ПРИМЕЧАНИЕ: Если у вас нет индексов из-за ограниченного набора вставленных записей, вы не заметите влияния на производительность. Но в полном производственном наборе данных вы заметите, что время выполнения того же векторного поиска значительно сокращается благодаря использованию индекса ScaNN со встроенной фильтрацией в векторном поиске, что сделало это возможным!

Далее давайте оценим полноту для векторного поиска с использованием ScaNN.

Переоценка

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

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

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

WITH initial_ranking AS (
SELECT id,content, pdt_desc, uri, category, sub_category,color,gender,
ROW_NUMBER() OVER () AS ref_number 
FROM apparels 
    order by embedding <=>embedding('text-embedding-005', 'Pink top')::vector),
reranked_results AS (
            SELECT index, score from 
            ai.rank(
              model_id => 'semantic-ranker-default-003',
              search_string => 'Pink top',
              documents => (SELECT ARRAY_AGG(pdt_desc ORDER BY ref_number) FROM initial_ranking)
            )
)
SELECT id,content, pdt_desc, uri, category, sub_category,color,gender, score
FROM initial_ranking, reranked_results 
WHERE initial_ranking.ref_number = reranked_results.index
ORDER BY reranked_results.score DESC
limit 25;

В этом запросе мы выполняем ПЕРЕРАНЖИРОВАНИЕ набора результатов контекстного поиска, указанного в предложении ORDER BY, используя метод косинусного сходства. Пользователь ищет текст «Розовый топ».

ВАЖНОЕ ПРИМЕЧАНИЕ: У некоторых из вас может не быть доступа к функции Reranking, поэтому я исключил ее из кода приложения, но если вы хотите включить ее, вы можете следовать примеру, который мы рассмотрели выше.

Оценщик отзывов

Полнота в поиске по сходству — это процент релевантных экземпляров, полученных в результате поиска, то есть количество истинно положительных результатов. Это наиболее распространённая метрика, используемая для оценки качества поиска. Одним из источников потери полноты является разница между приблизительным поиском ближайшего соседа (aNN) и точным поиском ближайшего соседа (kNN). Векторные индексы, такие как ScaNN от AlloyDB, реализуют алгоритмы aNN , позволяя ускорить векторный поиск в больших наборах данных за счёт небольшого снижения полноты. Теперь AlloyDB предоставляет возможность измерять этот компромисс непосредственно в базе данных для отдельных запросов и обеспечивать его стабильность с течением времени. Вы можете обновлять параметры запроса и индекса в соответствии с этой информацией для достижения лучших результатов и повышения производительности.

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

В контексте векторного поиска полнота означает процент векторов, возвращаемых индексом, которые являются истинными ближайшими соседями. Например, если запрос по 20 ближайшим соседям возвращает 19 истинных ближайших соседей, то полнота составляет 19/20x100 = 95%. Полнота — это метрика, используемая для оценки качества поиска, которая определяется как процент возвращенных результатов, объективно наиболее близких к векторам запроса.

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

ВАЖНОЕ ПРИМЕЧАНИЕ:

Если на следующих этапах вы столкнётесь с ошибкой «Отказано в доступе» для индекса HNSW, пропустите пока весь раздел об оценке отзыва. На данном этапе это может быть связано с ограничениями доступа, поскольку они были опубликованы только на момент документирования этой практической работы.

  1. Установите флаг «Включить сканирование индекса» для индекса ScaNN и индекса HNSW:
SET scann.enable_indexscan = on
SET hnsw.enable_index_scan = on
  1. Выполните следующий запрос в AlloyDB Studio:
SELECT
  *
FROM
  evaluate_query_recall($$
SELECT id,content, pdt_desc, uri, category, sub_category,color,gender
FROM 
apparels 
    order by embedding <=> embedding('text-embedding-005', 'skirts for women')::vector 
  LIMIT 25 $$,
    '{"scann.num_leaves_to_search":1, "scann.pre_reordering_num_neighbors":10}',
    ARRAY['scann']);

Функция estimate_query_recall принимает запрос в качестве параметра и возвращает его значение. В качестве входного запроса я использую тот же запрос, который использовался для проверки производительности. Я добавил SCaNN в качестве метода индексирования. Подробнее о параметрах см. в документации .

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

4918ec4780156527.png

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

Протестируйте его с измененными параметрами запроса и индекса.

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

  1. Изменение параметров индекса:

Для этого теста я собираюсь использовать функцию расстояния сходства «L2 Distance» вместо функции расстояния сходства «Cosine» .

Очень важное замечание: «Откуда мы знаем, что в этом запросе используется косинусное сходство?» — спросите вы. Вы можете определить функцию расстояния, используя «<=>» для обозначения косинусного расстояния.

Ссылка на документацию по функциям расстояния поиска векторов.

В предыдущем запросе использовалась функция расстояния косинусного сходства, а теперь мы попробуем использовать расстояние L2. Однако для этого необходимо также убедиться, что базовый индекс ScaNN также использует функцию расстояния L2. Теперь создадим индекс с другим запросом функции расстояния: расстояние L2: <->

drop index apparels_index;

CREATE INDEX apparels_index ON apparels 
USING scann (embedding L2)
WITH (num_leaves=32);

Оператор удаления индекса нужен только для того, чтобы убедиться в отсутствии ненужных индексов в таблице.

Теперь я могу выполнить следующий запрос для оценки RECALL после изменения функции расстояния моей функциональности поиска вектора.

[ПОСЛЕ] Запрос, использующий функцию расстояния L2 :

SELECT
  *
FROM
  evaluate_query_recall($$
SELECT id,content, pdt_desc, uri, category, sub_category,color,gender
FROM 
apparels 
    order by embedding <-> embedding('text-embedding-005', 'skirts for women')::vector 
  LIMIT 25 $$,
    '{"scann.num_leaves_to_search":1, "scann.pre_reordering_num_neighbors":10}',
    ARRAY['scann']);

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

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

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

Для достижения максимально высокого качества контролируемого поиска мы включили дополнительный уровень проверки LLM. Большие языковые модели могут использоваться для оценки релевантности и согласованности результатов поиска, особенно для сложных или неоднозначных запросов. Это может включать:

Семантическая проверка:

Перекрестные ссылки LLM на цели запроса.

Логическая фильтрация:

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

Гарантия качества:

Автоматическое определение и пометка менее релевантных результатов для проверки человеком или уточнения модели.

Вот как мы добились этого в функциях искусственного интеллекта AlloyDB:

WITH 
          apparels_temp as (
                  SELECT id,content, pdt_desc, uri, category, sub_category,color,gender 
                  FROM apparels 
                 -- where category = ANY($1) and sub_category = ANY($2) and color = ANY($3) and gender = ANY($4)
                      order by embedding <=> embedding('text-embedding-005', $5)::vector
                  limit 25
          ),
          prompt AS (
          SELECT 'You are a friendly advisor helping to filter whether a product match' || pdt_desc || 'is reasonably (not necessarily 100% but contextually in agreement) related to the customer''s request: ' || $5 || '. Respond only in YES or NO. Do not add any other text.'
          AS prompt_text, *
          from apparels_temp
          )
          ,
          response AS (
          SELECT id,content,pdt_desc,uri,
                  json_array_elements(ml_predict_row('projects/abis-345004/locations/us-central1/publishers/google/models/gemini-1.5-pro:streamGenerateContent',
                  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 id, content,uri,replace(replace(resp::text,'\n',''),'"','') as result
          FROM
                  response where replace(replace(resp::text,'\n',''),'"','') in ('YES', 'NO')
                  limit 10;  

Базовый запрос — тот же, что мы видели в разделах фасетного поиска, гибридного поиска и переранжирования. В этот запрос мы включили слой оценки GEMINI для переранжированного набора результатов, представленного конструкцией ml_predict_row. Я закомментировал фасетные фильтры, но вы можете свободно добавлять элементы по своему выбору в массив для плейсхолдеров $1–$4. Замените $5 любым текстом, который вы хотите найти, например, «Розовый топ без цветочного узора».

7. Набор инструментов MCP для баз данных и прикладного уровня

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

Набор инструментов MCP (Model Context Protocol) для баз данных упрощает интеграцию инструментов генеративного ИИ и агентных инструментов с AlloyDB. Он действует как сервер с открытым исходным кодом, оптимизирующий пул соединений, аутентификацию и безопасный доступ к функциям базы данных агентам ИИ или другим приложениям.

В нашем приложении мы использовали MCP Toolbox for Databases в качестве уровня абстракции для всех наших интеллектуальных гибридных поисковых запросов.

Чтобы настроить и развернуть Toolbox для нашего варианта использования, выполните следующие действия:

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

  1. Перейдите в терминал Cloud Shell и убедитесь, что ваш проект выбран и отображается в строке запроса. Выполните следующую команду в терминале Cloud Shell, чтобы перейти в каталог вашего проекта:
mkdir toolbox-tools

cd toolbox-tools
  1. Выполните следующую команду, чтобы загрузить и установить toolbox в новую папку:
# see releases page for other versions
export VERSION=0.7.0
curl -O https://storage.googleapis.com/genai-toolbox/v$VERSION/linux/amd64/toolbox
chmod +x toolbox
  1. Перейдите в редактор Cloud Shell (для режима редактирования кода) и в корневой папке проекта добавьте файл с именем «tools.yaml».
sources:
    alloydb:
        kind: "alloydb-postgres"
        project: "<<YOUR_PROJECT_ID>>"
        region: "us-central1"
        cluster: "vector-cluster"
        instance: "vector-instance"
        database: "postgres"
        user: "postgres"
        password: "alloydb"


tools:
        <<tools go here... Refer to the github repo file>>

Обязательно замените скрипт Tools.yaml кодом из этого файла репозитория .

Давайте разберемся с tools.yaml:

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

Инструменты определяют действия, которые может выполнять агент, например, чтение и запись в источник. Инструмент представляет собой действие, которое может выполнить ваш агент, например, выполнение SQL-оператора. Вы можете определить инструменты как карту в разделе инструментов файла tools.yaml. Как правило, для работы с инструментом требуется источник.

Более подробную информацию о настройке tools.yaml см. в этой документации .

  1. Выполните следующую команду (из папки mcp-toolbox), чтобы запустить сервер:
./toolbox --tools-file "tools.yaml"

Теперь, если вы откроете сервер в режиме веб-предварительного просмотра в облаке, вы сможете увидеть сервер Toolbox, работающий с вашим новым инструментом под названием get-order-data.

Сервер MCP Toolbox по умолчанию работает на порту 5000. Давайте воспользуемся Cloud Shell для проверки.

Нажмите «Веб-просмотр» в Cloud Shell, как показано ниже:

52f1a9646b55eeb2.png

Нажмите «Изменить порт» и установите порт 5000, как показано ниже, затем нажмите «Изменить и просмотреть».

71c8c4659a947acd.png

Это должно дать следующий результат:

261efdaf0019a65.png

  1. Давайте развернем наш Toolbox в Cloud Run:

Для начала мы можем начать с сервера MCP Toolbox и разместить его в Cloud Run. Это создаст публичную конечную точку, которую можно будет интегрировать с любым другим приложением и/или приложениями-агентами. Инструкции по размещению этого сервера в Cloud Run приведены здесь . Теперь рассмотрим основные этапы.

  1. Запустите новый терминал Cloud Shell или используйте существующий. Перейдите в папку проекта, где находятся исполняемый файл toolbox и файл tools.yaml (в данном случае toolbox-tools), если вы ещё не находитесь в ней:
cd toolbox-tools
  1. Установите переменную PROJECT_ID так, чтобы она указывала на идентификатор вашего проекта Google Cloud.
export PROJECT_ID="<<YOUR_GOOGLE_CLOUD_PROJECT_ID>>"
  1. Включить эти сервисы Google Cloud
gcloud services enable run.googleapis.com \
                       cloudbuild.googleapis.com \
                       artifactregistry.googleapis.com \
                       iam.googleapis.com \
                       secretmanager.googleapis.com
  1. Давайте создадим отдельную учетную запись службы, которая будет действовать как удостоверение для службы Toolbox, которую мы будем развертывать в Google Cloud Run.
gcloud iam service-accounts create toolbox-identity
  1. Мы также гарантируем, что эта учетная запись службы будет иметь правильные роли, то есть возможность доступа к Secret Manager и взаимодействия с AlloyDB.
gcloud projects add-iam-policy-binding $PROJECT_ID \
   --member serviceAccount:toolbox-identity@$PROJECT_ID.iam.gserviceaccount.com \
   --role roles/secretmanager.secretAccessor

gcloud projects add-iam-policy-binding $PROJECT_ID \
   --member serviceAccount:toolbox-identity@$PROJECT_ID.iam.gserviceaccount.com \
   --role roles/alloydb.client

gcloud projects add-iam-policy-binding $PROJECT_ID \
   --member serviceAccount:toolbox-identity@$PROJECT_ID.iam.gserviceaccount.com \
   --role roles/serviceusage.serviceUsageConsumer
  1. Мы загрузим файл tools.yaml в секрете:
gcloud secrets create tools --data-file=tools.yaml

Если у вас уже есть секрет и вы хотите обновить его версию, выполните следующее:

gcloud secrets versions add tools --data-file=tools.yaml
  1. Задайте переменную среды для образа контейнера, который вы хотите использовать для Cloud Run:
export IMAGE=us-central1-docker.pkg.dev/database-toolbox/toolbox/toolbox:latest
  1. Последний шаг в знакомой команде развертывания в Cloud Run:
gcloud run deploy toolbox \
--image $IMAGE \
--service-account toolbox-identity \
--region us-central1 \
--set-secrets "/app/tools.yaml=tools:latest" \
--args="--tools-file=/app/tools.yaml","--address=0.0.0.0","--port=8080" \
--allow-unauthenticated \
--labels dev-tutorial=codelab-alloydb-search-toolbox

Это должно запустить процесс развертывания Toolbox Server с настроенным файлом tools.yaml в Cloud Run. При успешном развертывании вы увидите сообщение, похожее на следующее:

Deploying container to Cloud Run service [toolbox] in project [YOUR_PROJECT_ID] region [us-central1]
OK Deploying new service... Done.                                                                                                                                                                                     
  OK Creating Revision...                                                                                                                                                                                             
  OK Routing traffic...                                                                                                                                                                                               
  OK Setting IAM Policy...                                                                                                                                                                                            
Done.                                                                                                                                                                                                                 
Service [toolbox] revision [toolbox-00001-zsk] has been deployed and is serving 100 percent of traffic.
Service URL: https://toolbox-<SOME_ID>.us-central1.run.app

Все готово к использованию недавно развернутого инструмента в вашем агентском приложении!!!

Доступ к инструментам на сервере Toolbox

После развёртывания Toolbox мы создадим оболочку Python Cloud Run Functions для взаимодействия с развёрнутым сервером Toolbox. Поскольку в настоящее время Toolbox не имеет Java SDK , мы создали оболочку Python для взаимодействия с сервером. Вот исходный код этой функции Cloud Run.

Вам необходимо создать и развернуть эту функцию Cloud Run, чтобы получить доступ к инструментам набора инструментов, которые мы только что создали и развернули на предыдущих этапах:

  1. В консоли Google Cloud перейдите на страницу Cloud Run.
  2. Нажмите «Написать функцию».
  3. В поле «Название услуги» введите название, описывающее вашу функцию. Названия услуг должны начинаться только с буквы и содержать не более 49 символов, включая буквы, цифры и дефисы. Названия услуг не могут заканчиваться дефисами и должны быть уникальными для каждого региона и проекта. Название услуги нельзя изменить позже, оно доступно для публичного просмотра. (Введите «retail-product-search-quality»).
  4. В списке «Регион» используйте значение по умолчанию или выберите регион, в котором вы хотите развернуть свою функцию. (Выберите us-central1)
  5. В списке «Среда выполнения» используйте значение по умолчанию или выберите версию среды выполнения. (Выберите Python 3.11)
  6. В разделе «Аутентификация» выберите «Разрешить публичный доступ».
  7. Нажмите кнопку «Создать».
  8. Функция создается и загружается с помощью шаблона main.py и requirements.txt.
  9. Замените это файлами main.py и requirements.txt из репозитория этого проекта.
  10. Разверните функцию, и вы получите конечную точку для своей функции Cloud Run.

Ваша конечная точка должна выглядеть так (или похоже):

Конечная точка функции Cloud Run для доступа к набору инструментов: «https://retail-product-search-quality-<<YOUR_PROJECT_NUMBER>>.us-central1.run.app»

Для удобства завершения работы в установленные сроки (для практических занятий под руководством инструктора) номер проекта для конечной точки будет сообщен во время практического занятия.

ВАЖНОЕ ПРИМЕЧАНИЕ:

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

8. Разработка приложений (Java) с фасетным поиском

Наконец, все эти мощные бэкэнд-компоненты реализуются на уровне приложения. Приложение, разработанное на Java, предоставляет пользовательский интерфейс для взаимодействия с поисковой системой. Оно координирует запросы к AlloyDB, обрабатывает отображение фасетных фильтров, управляет пользовательским выбором и представляет повторно ранжированные, проверенные результаты поиска в удобном и интуитивно понятном виде.

  1. Вы можете начать с перехода в Cloud Shell Terminal и клонирования репозитория:
git clone https://github.com/AbiramiSukumaran/faceted_searching_retail
  1. Перейдите в редактор Cloud Shell, где вы увидите недавно созданную папку faceted_searching_retail.
  2. Удалите следующее, так как эти шаги уже выполнены в предыдущих разделах:
  3. Удалить папку Cloud_Run_Function
  4. Удалить файл db_script.sql
  5. Удалить файл tools.yaml
  6. Перейдите в папку проекта retail-faceted-search, и вы увидите структуру проекта:

1d736dfa45583f52.png

  1. В файле ProductRepository.java вам необходимо изменить переменную TOOLBOX_ENDPOINT на конечную точку из вашей развернутой функции Cloud Run или взять конечную точку из выступления докладчика.

Найдите следующую строку кода и замените ее своей конечной точкой:

public static final String TOOLBOX_ENDPOINT = "https://retail-product-search-quality-<<YOUR_PROJECT_NUMBER>>.us-central1.run.app";
  1. Убедитесь, что Dockerfile и pom.xml соответствуют конфигурации вашего проекта (изменения не требуются, если только вы явно не изменили какую-либо версию или конфигурацию).
  2. В терминале Cloud Shell убедитесь, что вы находитесь в основной папке и в папке проекта (faceted_searching_retail / retail-faceted-search). Используйте следующие команды, чтобы убедиться в этом, если вы ещё не находитесь в нужной папке в терминале:
cd faceted_searching_retail

cd retail-faceted-search
  1. Упакуйте, соберите и протестируйте свое приложение локально:
mvn package

mvn spring-boot:run

Вы сможете просмотреть свое приложение, нажав «Предварительный просмотр на порту 8080» в терминале Cloud Shell, как показано ниже:

52f1a9646b55eeb2.png

9. Развертывание в облаке. Запуск: ***ВАЖНЫЙ ШАГ

В терминале Cloud Shell убедитесь, что вы находитесь в основной папке и в папке проекта (faceted_searching_retail / retail-faceted-search). Используйте следующие команды, чтобы убедиться в этом, если вы ещё не находитесь в нужной папке в терминале:

cd faceted_searching_retail

cd retail-faceted-search

Убедившись, что вы находитесь в папке проекта, выполните следующую команду:

gcloud run deploy retail-search --source . \
--region us-central1 \
--allow-unauthenticated \
--labels dev-tutorial=codelab-alloydb-hybrid-search

После развертывания вы должны получить развернутую конечную точку Cloud Run, которая выглядит следующим образом:

https://retail-search-**********-uc.a.run.app/

10. Демонстрация

Давайте посмотрим, как все это работает на практике:

80b59305a9a7b068.png

На изображении выше показана целевая страница приложения динамического гибридного поиска.

264bc437cd5c3ae9.png

На изображении выше представлены результаты поиска по запросу «Коричневый цвет без кружева». Выбраны следующие многогранные фильтры: Обувь, Сандалии.

aff5849c73fe743c.png

На изображении выше показаны результаты поиска по запросу «Футболка без воротника». Многогранные фильтры: Одежда.

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

Попробуйте и вдохновитесь на самостоятельное строительство!!!

11. Уборка

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

  1. В консоли Google Cloud перейдите на страницу менеджера ресурсов .
  2. В списке проектов выберите проект, который вы хотите удалить, а затем нажмите Удалить .
  3. В диалоговом окне введите идентификатор проекта, а затем нажмите кнопку «Завершить» , чтобы удалить проект.
  4. Альтернативно, вы можете просто удалить кластер AlloyDB (измените местоположение в этой гиперссылке, если вы не выбрали us-central1 для кластера во время настройки), который мы только что создали для этого проекта, нажав кнопку УДАЛИТЬ КЛАСТЕР.

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

Поздравляем! Вы успешно создали и развернули ПРИЛОЖЕНИЕ ГИБРИДНОГО ПОИСКА с ALLOYDB в ОБЛАКЕ!!!

Почему это важно для бизнеса:

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

Превосходная релевантность. Комбинируя контекстный (векторный) поиск с точной фасетной фильтрацией и интеллектуальным изменением рейтинга, клиенты получают очень релевантные результаты, что приводит к повышению удовлетворенности и конверсий.

Масштабируемость: архитектура AlloyDB и индексация scanNN предназначены для обработки огромных каталогов продуктов и больших объемов запросов, что имеет решающее значение для растущего бизнеса электронной коммерции.

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

Перспективность в будущее: интеграция возможностей искусственного интеллекта (встраивание, проверка LLM) позволяет приложению развиваться в будущем в области персонализированных рекомендаций, диалоговой коммерции и интеллектуального обнаружения продуктов.

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

Допустим, пользователь ввел запрос на естественном языке, например «экологичные кроссовки для женщин с высокой поддержкой свода стопы».

9e27fc58aea9a081.png

одновременно пользователь применяет фасетные фильтры для «Категория: <<>>» «Цвет: <<>>» и произносит «Цена: 100–150 долларов США»:

  • Система мгновенно возвращает уточненный список товаров, семантически выровненный с естественным языком и точно соответствующий выбранным фильтрам.
  • За кулисами индекс scanNN ускоряет векторный поиск, встроенная и адаптивная фильтрация обеспечивают производительность при использовании комбинированных критериев, а переранжирование отображает оптимальные результаты наверху.
  • Скорость и точность результатов ясно иллюстрируют эффективность объединения этих технологий для создания действительно интеллектуального поиска в розничной торговле.

Создание приложения для поиска розничной торговли нового поколения требует выхода за рамки традиционных методов, и, используя возможности AlloyDB, Vertex AI, Vector Search с индексацией scanNN, динамической фасетной фильтрацией, изменением рейтинга и проверкой LLM, мы можем обеспечить беспрецедентный уровень обслуживания клиентов, который стимулирует взаимодействие и увеличивает продажи. Это надежное, масштабируемое и интеллектуальное решение демонстрирует, как современные возможности баз данных, дополненные искусственным интеллектом, меняют будущее розничной торговли!!!

Начните сегодня !