Хранение векторов, индексирование и поиск в MariaDB

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

Однако, если вы используете MariaDB, вам не нужно вводить дополнительную базу данных с собственным диалектом SQL — или, что еще хуже, с собственным проприетарным API. С версии MariaDB 11.7 (и MariaDB Enterprise Server 11.4) вы можете просто хранить ваши эмбеддинги (или векторы) в любой колонке любой таблицы — нет необходимости делать ваши приложения полиглотами баз данных.

“После анонса превью векторного поиска в MariaDB Server, возможность векторного поиска теперь была добавлена в релиз MariaDB Community Server 11.7,” пишет Ральф Гебхардт, менеджер продукта для MariaDB Server в MariaDB. Это включает новый тип данных (VECTOR), векторный индекс и набор функций для манипуляции векторами.

Зачем нужны векторы в приложениях генеративного ИИ?

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

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

Например, возьмем следующий ввод от пользователя в чат-боте с рекомендациями:

Plain Text

 

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

Для этого отправьте оригинальный ввод пользователя в эмбеддер и получите вектор, который вы позже можете использовать, чтобы получить ближайшие, скажем, 10 продуктов к вводу пользователя. После того, как вы получите эту информацию (и мы увидим, как это сделать с MariaDB позже), вы можете отправить улучшенное приглашение вашей модели ИИ:

Plain Text

 

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

Создание таблиц для хранения векторов

Для хранения векторов в MariaDB используйте новый тип данных VECTOR. Например:

MariaDB SQL

 

CREATE TABLE products (
    id INT PRIMARY KEY,
    name VARCHAR(100),
    description TEXT,
    embedding VECTOR(2048)
);

В этом примере столбец embedding может содержать вектор из 2048 измерений. Необходимо совпадение количества измерений, генерируемых вашим внедрителем.

Создание векторных индексов

Для повышения производительности чтения важно добавить индекс к вашему векторному столбцу. Это ускоряет поиск похожих элементов. Индекс можно определить при создании таблицы следующим образом:

MariaDB SQL

 

CREATE TABLE products (
    id INT PRIMARY KEY,
    name VARCHAR(100),
    description TEXT,
    embedding VECTOR(2048) NOT NULL,
    VECTOR INDEX (embedding)
);

Для большего контроля можно указать функцию расстояния, которую будет использовать сервер базы данных для построения индекса, а также M значение алгоритма иерархических навигируемых малых миров (HNSW), используемого MariaDB. Например:

MariaDB SQL

 

CREATE TABLE products (
    id INT PRIMARY KEY,
    name VARCHAR(100),
    description TEXT,
    embedding VECTOR(2048) NOT NULL,
    VECTOR INDEX (embedding) M=8 DISTANCE=cosine
);

Проверьте документацию для получения более подробной информации об этих конфигурациях.

Вставка векторов

Когда вы передаете данные (текст, изображение, аудио) через внедрителя, вы получаете вектор. Обычно это серия чисел в массиве в формате JSON. Чтобы вставить этот вектор в таблицу MariaDB, можно использовать функцию VEC_FromText. Например:

MariaDB SQL

 

INSERT INTO products (name, embedding)
VALUES
  ("Alarm clock", VEC_FromText("[0.001, 0, ...]")),
  ("Cow figure", VEC_FromText("[1.0, 0.05, ...]")),
  ("Bicycle", VEC_FromText("[0.2, 0.156, ...]"));

Помните, что вставляемые векторы должны иметь правильное количество измерений, как определено в операторе CREATE TABLE.

Поиск похожих элементов (Сравнение векторов)

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

  • VEC_DISTANCE_EUCLIDEAN: вычисляет прямое расстояние между двумя векторами. Он лучше всего подходит для векторов, полученных из исходных, ненормализованных данных или сценариев, где пространственное разделение прямо коррелирует с сходством, таких как сравнение позиционных или числовых характеристик. Однако он менее эффективен для высокоразмерных или нормализованных встраиваний, поскольку чувствителен к различиям в магнитуде вектора.
  • VEC_DISTANCE_COSINE: измеряет угловое расстояние между векторами. Хорошо подходит для сравнения нормализованных встраиваний, особенно в семантических приложениях, таких как извлечение текста или документов. Он отлично справляется с улавливанием сходства в значении или контексте.

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

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

MariaDB SQL

 

SELECT id, name, description
FROM products
ORDER BY VEC_DISTANCE_COSINE(
  VEC_FromText($user_input_vector),
  embedding
)
LIMIT 10;

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

Практический пример

Я подготовил практический пример, используя Java и без фреймворков искусственного интеллекта, чтобы вы по-настоящему поняли процесс создания генеративных приложений с использованием возможностей векторного поиска MariaDB. Вы можете найти код на GitHub.

Source:
https://dzone.com/articles/vector-storage-indexing-and-search-with-mariadb