Как

Поиск вложенных данных с помощью Python, DocArray и субиндексов

Мультимодальные запросы стали проще

Примечание: данную статью лучше просматривать в формате блокнота. Мы рекомендуем перейти туда, чтобы вы могли запустить код в своем браузере!

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

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

К счастью, для этого есть решение!

Задача: поиск товара

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

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

Для решения этой проблемы нам нужен всего один инструмент: DocArray.

В частности, мы будем активно использовать три функции DocArray:

  1. Мультимодальные документы, для моделирования наших данных
  2. Подиндексы, чтобы сделать наши точки данных и части этих точек данных доступными для поиска.
  3. Хранилища документов, чтобы хранить наши данные на диске (и эффективно извлекать их оттуда)

Поэтому мы будем использовать CLIP-as-Service для создания вложений для наших данных, но вместо этого вы можете использовать свои любимые модели встраивания изображений и текста.

Индексация данных

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

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

Итак, мы будем иметь дело с чем-то вроде этого:

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

Однако субиндексы DocArray позволяют нам сделать именно это.

Объяснение субиндексов

В DocArray данные хранятся в виде Documents, организованных в виде DocumentArray. По умолчанию DocumentArray является структурой данных в памяти, но он также изначально поддерживает хранилища документов, которые представляют собой (векторные) серверные части базы данных, которые можно использовать для сохранения данных на диске.

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

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

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

Посмотреть код в действии

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