1. Обзор
В различных отраслях контекстный поиск является важнейшей функциональностью, которая формирует сердце и центр их приложений. Дополненная генерация поиска уже довольно давно является ключевым драйвером этой важной технологической эволюции с ее механизмами поиска на основе генеративного ИИ. Генеративные модели с их большими контекстными окнами и впечатляющим качеством вывода преобразуют ИИ. RAG обеспечивает систематический способ внедрения контекста в приложения и агенты ИИ, заземляя их в структурированных базах данных или информации из различных носителей. Эти контекстные данные имеют решающее значение для ясности истины и точности вывода, но насколько точны эти результаты? Ваш бизнес в значительной степени зависит от точности этих контекстных соответствий и релевантности? Тогда этот проект вас пощекочет!
Грязный секрет векторного поиска заключается не только в его создании, но и в знании того, действительно ли ваши векторные совпадения хороши. Мы все были в такой ситуации, тупо уставившись на список результатов, задаваясь вопросом: «Эта штука вообще работает?!» Давайте углубимся в то, как на самом деле оценить качество ваших векторных совпадений. «Так что же изменилось в RAG?», спросите вы? Все! В течение многих лет Retrieval Augmented Generation (RAG) казался многообещающей, но труднодостижимой целью. Теперь, наконец, у нас есть инструменты для создания приложений RAG с производительностью и надежностью, необходимыми для критически важных задач.
Теперь у нас уже есть базовое понимание трех вещей:
- Что означает контекстный поиск для вашего агента и как его реализовать с помощью векторного поиска.
- Мы также глубоко погрузились в реализацию векторного поиска в пределах ваших данных, то есть в самой вашей базе данных (все облачные базы данных Google поддерживают это, если вы еще не знали!).
- Мы пошли на шаг дальше остального мира, рассказав вам, как реализовать такую легкую возможность векторного поиска RAG с высокой производительностью и качеством с помощью возможности векторного поиска AlloyDB на основе индекса ScaNN.
Если вы еще не прошли эти базовые, средние и немного продвинутые эксперименты RAG, я бы рекомендовал вам прочитать эти 3 здесь , здесь и здесь в указанном порядке.
Поиск патентов помогает пользователю находить патенты, соответствующие контексту их поискового текста, и мы уже создали версию этого в прошлом . Теперь мы построим его с новыми и расширенными функциями RAG, которые позволят осуществлять качественный контекстный поиск для этого приложения. Давайте погрузимся в это!
На рисунке ниже показан общий поток событий, происходящих в этом приложении.~
Цель
Позволяет пользователю выполнять поиск патентов на основе текстового описания с улучшенной производительностью и лучшим качеством, а также оценивать качество сгенерированных совпадений с помощью новейших функций RAG AlloyDB.
Что вы построите
В рамках этой лабораторной работы вы:
- Создайте экземпляр AlloyDB и загрузите публичный набор данных Patents
- Создать индекс метаданных и индекс ScaNN
- Реализуйте расширенный векторный поиск в AlloyDB с использованием метода встроенной фильтрации ScaNN
- Реализовать функцию оценки отзыва
- Оценить ответ на запрос
Требования
2. Прежде чем начать
Создать проект
- В Google Cloud Console на странице выбора проекта выберите или создайте проект Google Cloud.
- Убедитесь, что для вашего проекта Cloud включена функция выставления счетов. Узнайте, как проверить, включена ли функция выставления счетов для проекта .
- Вы будете использовать Cloud Shell , командную среду, работающую в Google Cloud. Нажмите Activate Cloud Shell в верхней части консоли Google Cloud.
- После подключения к Cloud Shell вы проверяете, что вы уже аутентифицированы и что проекту присвоен ваш идентификатор проекта, с помощью следующей команды:
gcloud auth list
- Выполните следующую команду в Cloud Shell, чтобы подтвердить, что команда gcloud знает о вашем проекте.
gcloud config list project
- Если ваш проект не настроен, используйте следующую команду для его настройки:
gcloud config set project <YOUR_PROJECT_ID>
- Включите требуемые API. Вы можете использовать команду gcloud в терминале Cloud Shell:
gcloud services enable alloydb.googleapis.com compute.googleapis.com cloudresourcemanager.googleapis.com servicenetworking.googleapis.com run.googleapis.com cloudbuild.googleapis.com cloudfunctions.googleapis.com aiplatform.googleapis.com
Альтернативой команде gcloud является поиск каждого продукта через консоль или использование этой ссылки .
Информацию о командах и использовании gcloud см. в документации .
3. Настройка базы данных
В этой лабораторной работе мы будем использовать AlloyDB в качестве базы данных для патентных данных. Она использует кластеры для хранения всех ресурсов, таких как базы данных и журналы. Каждый кластер имеет первичный экземпляр , который обеспечивает точку доступа к данным. Таблицы будут хранить фактические данные.
Давайте создадим кластер, экземпляр и таблицу AlloyDB, куда будет загружен набор данных по патентам.
Создать кластер и экземпляр
- Перейдите на страницу AlloyDB в Cloud Console. Самый простой способ найти большинство страниц в Cloud Console — воспользоваться строкой поиска консоли.
- Выберите СОЗДАТЬ КЛАСТЕР на этой странице:
- Вы увидите экран, подобный показанному ниже. Создайте кластер и экземпляр со следующими значениями (убедитесь, что значения совпадают, если вы клонируете код приложения из репозитория):
- идентификатор кластера : "
vector-cluster
" - пароль : "
alloydb
" - PostgreSQL 15 / последняя рекомендуемая версия
- Регион : "
us-central1
" - Сетевое взаимодействие : "
default
"
- При выборе сети по умолчанию вы увидите экран, подобный показанному ниже.
Выберите НАСТРОЙКА ПОДКЛЮЧЕНИЯ .
- Оттуда выберите « Использовать автоматически выделенный диапазон IP-адресов » и «Продолжить». После просмотра информации выберите «СОЗДАТЬ ПОДКЛЮЧЕНИЕ».
- После настройки сети вы можете продолжить создание кластера. Нажмите CREATE CLUSTER , чтобы завершить настройку кластера, как показано ниже:
Обязательно измените идентификатор экземпляра (который вы можете найти во время настройки кластера/экземпляра) на
vector-instance
. Если вы не можете его изменить, не забудьте использовать идентификатор вашего экземпляра во всех последующих ссылках.
Обратите внимание, что создание кластера займет около 10 минут. После успешного завершения вы должны увидеть экран, на котором будет показан обзор вашего кластера, который вы только что создали.
4. Прием данных
Теперь пришло время добавить таблицу с данными о магазине. Перейдите в AlloyDB, выберите основной кластер, а затем AlloyDB Studio:
Возможно, вам придется подождать, пока ваш экземпляр не будет создан. После этого войдите в AlloyDB, используя учетные данные, которые вы создали при создании кластера. Используйте следующие данные для аутентификации в PostgreSQL:
- Имя пользователя: "
postgres
" - База данных: "
postgres
" - Пароль: "
alloydb
"
После успешной аутентификации в AlloyDB Studio, команды SQL вводятся в редакторе. Вы можете добавить несколько окон редактора, используя плюс справа от последнего окна.
Команды для 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 patents_data ( id VARCHAR(25), type VARCHAR(25), number VARCHAR(20), country VARCHAR(2), date VARCHAR(20), abstract VARCHAR(300000), title VARCHAR(100000), kind VARCHAR(5), num_claims BIGINT, filename VARCHAR(100), withdrawn BIGINT, abstract_embeddings vector(768)) ;
Столбец abstract_embeddings позволит хранить векторные значения текста.
Предоставить разрешение
Выполните приведенный ниже оператор, чтобы предоставить разрешение на выполнение функции «встраивания»:
GRANT EXECUTE ON FUNCTION embedding TO postgres;
Предоставьте учетную запись службы AlloyDB роль пользователя Vertex AI.
Из консоли 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"
Загрузить данные патентов в базу данных
В качестве нашего набора данных будут использоваться общедоступные наборы данных Google Patents на BigQuery. Для выполнения запросов мы будем использовать AlloyDB Studio. Данные берутся в файл insert_scripts.sql
, и мы запустим его для загрузки данных патентов.
- В консоли Google Cloud откройте страницу AlloyDB .
- Выберите только что созданный кластер и щелкните экземпляр.
- В меню навигации AlloyDB нажмите AlloyDB Studio . Войдите, используя свои учетные данные.
- Откройте новую вкладку, нажав на значок «Новая вкладка» справа.
- Скопируйте оператор запроса
insert
из скриптаinsert_scripts.sql
, упомянутого выше, в редактор. Вы можете скопировать 10-50 операторов вставки для быстрой демонстрации этого варианта использования. - Нажмите Выполнить . Результаты вашего запроса появятся в таблице результатов .
Примечание: Вы можете заметить, что в скрипте вставки много данных. Это связано с тем, что мы включили вставки в скрипты вставки. Нажмите «Просмотреть необработанные данные», если у вас возникли проблемы с загрузкой файла в github. Это сделано для того, чтобы избавить вас от необходимости (на следующих этапах) генерировать больше, чем несколько вставок (скажем, 20-25 максимум) в случае, если вы используете пробную учетную запись для выставления счетов за кредит для Google Cloud.
5. Создание вложений для данных патентов
Сначала давайте протестируем функцию внедрения, выполнив следующий пример запроса:
SELECT embedding('text-embedding-005', 'AlloyDB is a managed, cloud-hosted SQL database service.');
Это должно вернуть вектор вложений, который выглядит как массив чисел с плавающей точкой, для образца текста в запросе. Выглядит так:
Обновите векторное поле abstract_embeddings
Запустите приведенный ниже DML-код, чтобы обновить аннотации патентов в таблице с соответствующими вложениями, только если вы не вставили данные abstract_embeddings как часть скрипта вставки:
UPDATE patents_data set abstract_embeddings = embedding( 'text-embedding-005', abstract);
У вас могут возникнуть проблемы с генерацией более нескольких внедрений (скажем, 20-25 максимум), если вы используете пробный кредитный счет для Google Cloud. Поэтому по этой причине я уже включил внедрения в скрипты вставки, и они должны быть загружены в вашей таблице, если вы выполнили шаг «загрузить данные патента в базу данных».
6. Выполните расширенный RAG с новыми функциями AlloyDB
Теперь, когда таблица, данные, вложения готовы, давайте выполним векторный поиск в реальном времени для текста пользовательского поиска. Вы можете проверить это, выполнив запрос ниже:
SELECT id || ' - ' || title as title FROM patents_data ORDER BY abstract_embeddings <=> embedding('text-embedding-005', 'Sentiment Analysis')::vector LIMIT 10;
В этом запросе
- Пользователь искал текст: «Анализ настроений».
- Мы преобразуем его во встраивание в методе embedding(), используя модель: text-embedding-005.
- «<=>» представляет собой использование метода расстояния КОСИНУСНОГО ПОДОБИЯ.
- Мы преобразуем результат метода внедрения в векторный тип, чтобы сделать его совместимым с векторами, хранящимися в базе данных.
- LIMIT 10 означает, что мы выбираем 10 наиболее близких совпадений искомого текста.
AlloyDB выводит Vector Search RAG на новый уровень:
Введено много новых вещей. Две из них ориентированы на разработчиков:
- Встроенная фильтрация
- Оценщик отзывов
Встроенная фильтрация
Раньше, как разработчик, вам приходилось выполнять запрос поиска векторов и иметь дело с фильтрацией и отзывом. Оптимизатор запросов AlloyDB делает выбор относительно того, как выполнять запрос с фильтрами. Встроенная фильтрация — это новый метод оптимизации запросов, который позволяет оптимизатору запросов AlloyDB оценивать как условия фильтрации метаданных, так и векторный поиск, используя как векторные индексы, так и индексы в столбцах метаданных. Это увеличило производительность отзыва, позволяя разработчикам использовать преимущества того, что AlloyDB может предложить из коробки.
Встроенная фильтрация лучше всего подходит для случаев со средней селективностью. Поскольку AlloyDB выполняет поиск по индексу вектора, он вычисляет расстояния только для векторов, которые соответствуют условиям фильтрации метаданных (ваши функциональные фильтры в запросе, обычно обрабатываемые в предложении WHERE). Это значительно повышает производительность для этих запросов, дополняя преимущества пост-фильтра или предварительного фильтра .
- Установите или обновите расширение pgvector
CREATE EXTENSION IF NOT EXISTS vector WITH VERSION '0.8.0.google-3';
Если расширение pgvector уже установлено, обновите расширение вектора до версии 0.8.0.google-3 или более поздней, чтобы получить возможности оценщика отзыва.
ALTER EXTENSION vector UPDATE TO '0.8.0.google-3';
Этот шаг необходимо выполнить только в том случае, если расширение вашего вектора — <0.8.0.google-3>.
Важное примечание: Если количество строк меньше 100, вам не нужно будет создавать индекс ScaNN изначально, поскольку он не будет применяться для меньшего количества строк. В этом случае пропустите следующие шаги.
- Для создания индексов ScaNN установите расширение soliddb_scann.
CREATE EXTENSION IF NOT EXISTS alloydb_scann;
- Сначала запустите векторный поисковый запрос без индекса и без включенного встроенного фильтра:
SELECT id || ' - ' || title as title FROM patents_data
WHERE num_claims >= 15
ORDER BY abstract_embeddings <=> embedding('text-embedding-005', 'Sentiment Analysis')::vector LIMIT 10;
Результат должен быть похож на:
- Запустите Explain Analyze для него: (без индекса и встроенной фильтрации)
Время выполнения 2,4 мс.
- Давайте создадим обычный индекс по полю num_claims, чтобы иметь возможность фильтровать по нему:
CREATE INDEX idx_patents_data_num_claims ON patents_data (num_claims);
- Давайте создадим индекс ScaNN для нашего приложения поиска патентов. Запустите следующее из вашей студии AlloyDB:
CREATE INDEX patent_index ON patents_data
USING scann (abstract_embeddings cosine)
WITH (num_leaves=32);
Важное примечание: (num_leaves=32)
применяется к нашему общему набору данных с 1000+ строками. Если количество строк меньше 100, вам не нужно будет создавать индекс изначально, поскольку он не будет применяться для меньшего количества строк.
- Включите встроенную фильтрацию в индексе ScaNN:
SET scann.enable_inline_filtering = on
- Теперь давайте выполним тот же запрос с фильтром и векторным поиском:
SELECT id || ' - ' || title as title FROM patents_data
WHERE num_claims >= 15
ORDER BY abstract_embeddings <=> embedding('text-embedding-005', 'Sentiment Analysis')::vector LIMIT 10;
Как вы можете видеть, время выполнения значительно сократилось для того же поиска векторов. Индекс ScaNN, встроенный в Inline Filtering, в поиске векторов сделал это возможным!!!
Далее давайте оценим полноту для векторного поиска с использованием ScaNN.
Оценщик отзывов
Полнота в поиске по сходству — это процент релевантных экземпляров, которые были извлечены из поиска, т. е. количество истинно положительных результатов. Это наиболее распространенная метрика, используемая для измерения качества поиска. Одним из источников потери полноты является разница между приблизительным поиском ближайшего соседа, или aNN, и k (точным) поиском ближайшего соседа, или kNN. Векторные индексы, такие как ScaNN от AlloyDB, реализуют алгоритмы aNN, позволяя ускорить векторный поиск в больших наборах данных в обмен на небольшой компромисс в полноте. Теперь AlloyDB предоставляет вам возможность измерять этот компромисс непосредственно в базе данных для отдельных запросов и гарантировать его стабильность с течением времени. Вы можете обновлять параметры запроса и индекса в ответ на эту информацию, чтобы добиться лучших результатов и производительности.
Какова логика отзыва результатов поиска?
В контексте векторного поиска отзыв относится к проценту векторов, которые возвращает индекс, которые являются истинными ближайшими соседями. Например, если запрос ближайшего соседа для 20 ближайших соседей возвращает 19 из истинных ближайших соседей, то отзыв составляет 19/20x100 = 95%. Отзыв — это метрика, используемая для оценки качества поиска, и определяется как процент возвращенных результатов, которые объективно ближе всего к векторам запроса.
Вы можете найти отзыв для векторного запроса по векторному индексу для заданной конфигурации, используя функцию estimate_query_recall . Эта функция позволяет вам настраивать параметры для достижения желаемых результатов отзыва векторного запроса.
Важное примечание:
Если вы столкнулись с ошибкой отказа в доступе на индексе HNSW на следующих этапах, пропустите весь этот раздел оценки отзыва на данный момент. Это может быть связано с ограничениями доступа на данном этапе, поскольку он только что был выпущен на момент документирования этой кодовой лаборатории.
- Установите флаг «Включить сканирование индекса» для индекса ScaNN и индекса HNSW:
SET scann.enable_indexscan = on
SET hnsw.enable_index_scan = on
- Выполните следующий запрос в AlloyDB Studio:
SELECT
*
FROM
evaluate_query_recall($$
SELECT
id || ' - ' || title AS title,
abstract
FROM
patents_data
where num_claims >= 15
ORDER BY
abstract_embeddings <=> embedding('text-embedding-005',
'sentiment analysis')::vector
LIMIT 25 $$,
'{"scann.num_leaves_to_search":1, "scann.pre_reordering_num_neighbors":10}',
ARRAY['scann']);
Функция estimate_query_recall принимает запрос в качестве параметра и возвращает его отзыв. Я использую тот же запрос, который я использовал для проверки производительности в качестве входного запроса функции. Я добавил SCaNN в качестве метода индекса. Для получения дополнительных параметров обратитесь к документации .
Для этого запроса поиска векторов мы использовали следующие данные:
Я вижу, что RECALL составляет 70%. Теперь я могу использовать эту информацию для изменения параметров индекса, методов и параметров запроса и улучшить свою полноту для этого поиска вектора!
7. Протестируйте его с измененными параметрами запроса и индекса.
Теперь давайте проверим запрос, изменив параметры запроса на основе полученного отзыва.
- Я изменил количество строк в результирующем наборе до 7 (ранее было 25) и вижу улучшение RECALL, т.е. 86%.
Это означает, что в режиме реального времени я могу изменять количество совпадений, которые видят мои пользователи, чтобы повысить релевантность совпадений в соответствии с контекстом поиска пользователей.
- Давайте попробуем еще раз, изменив параметры индекса:
Для этого теста я собираюсь использовать функцию расстояния сходства "L2 Distance" вместо функции расстояния "Cosine" . Я также изменю предел запроса на 10, чтобы продемонстрировать, есть ли улучшение качества результатов поиска даже при увеличении количества наборов результатов поиска.
[ДО] Запрос, использующий функцию расстояния косинусного сходства:
SELECT
*
FROM
evaluate_query_recall($$
SELECT
id || ' - ' || title AS title,
abstract
FROM
patents_data
where num_claims >= 15
ORDER BY
abstract_embeddings <=> embedding('text-embedding-005',
'sentiment analysis')::vector
LIMIT 10 $$,
'{"scann.num_leaves_to_search":1, "scann.pre_reordering_num_neighbors":10}',
ARRAY['scann']);
Очень важное примечание: «Откуда мы знаем, что этот запрос использует сходство КОСИНУСА?» — спросите вы. Вы можете определить функцию расстояния, используя «<=>» для представления расстояния Косинус.
Ссылка на документацию по функциям расстояния векторного поиска.
Результат запроса выше:
Как вы видите, RECALL составляет 70% без каких-либо изменений в нашей логике индекса. Помните индекс ScaNN, который мы создали на шаге 6 раздела Inline Filtering, " patent_index
"? Тот же индекс все еще эффективен, пока мы запускали вышеуказанный запрос.
Теперь давайте создадим индекс с другим запросом функции расстояния: расстояние L2: <->
drop index patent_index;
CREATE INDEX patent_index_L2 ON patents_data
USING scann (abstract_embeddings L2)
WITH (num_leaves=32);
Оператор удаления индекса нужен только для того, чтобы убедиться в отсутствии ненужных индексов в таблице.
Теперь я могу выполнить следующий запрос для оценки RECALL после изменения функции расстояния моей функциональности поиска вектора.
[ПОСЛЕ] Запрос, использующий функцию расстояния косинусного сходства:
SELECT
*
FROM
evaluate_query_recall($$
SELECT
id || ' - ' || title AS title,
abstract
FROM
patents_data
where num_claims >= 15
ORDER BY
abstract_embeddings <-> embedding('text-embedding-005',
'sentiment analysis')::vector
LIMIT 10 $$,
'{"scann.num_leaves_to_search":1, "scann.pre_reordering_num_neighbors":10}',
ARRAY['scann']);
Результат запроса выше:
Какое изменение в ценности отзыва, 90%!!!
В индексе можно изменить и другие параметры, например num_leaves и т. д., в зависимости от желаемого значения полноты и набора данных, который использует ваше приложение.
8. Уборка
Чтобы избежать списания средств с вашего аккаунта Google Cloud за ресурсы, использованные в этой публикации, выполните следующие действия:
- В консоли Google Cloud перейдите на страницу менеджера ресурсов .
- В списке проектов выберите проект, который вы хотите удалить, и нажмите Удалить .
- В диалоговом окне введите идентификатор проекта, а затем нажмите «Завершить работу» , чтобы удалить проект.
- В качестве альтернативы вы можете просто удалить кластер AlloyDB (измените местоположение в этой гиперссылке, если вы не выбрали us-central1 для кластера во время настройки), который мы только что создали для этого проекта, нажав кнопку УДАЛИТЬ КЛАСТЕР.
9. Поздравления
Поздравляю! Вы успешно построили свой контекстный запрос поиска патентов с помощью расширенного поиска векторов AlloyDB для высокой производительности и для того, чтобы сделать его действительно осмысленным. Я собрал многофункциональное агентское приложение с контролем качества, которое использует ADK и все, что мы здесь обсуждали, чтобы создать высокопроизводительный и качественный агент поиска и анализа векторов патентов, который вы можете увидеть здесь: https://youtu.be/Y9fvVY0yZTY
Если вы хотите научиться создавать такого агента, обратитесь к этой лабораторной работе .