Как создать рекомендательную систему для сайта с помощью YDB и векторного поиска
Пошаговое руководство по созданию рекомендательной системы для веб-сайтов, интернет-магазинов и приложений с использованием YDB, эмбеддингов и поиска похожих данных по смыслу.
Если у вас есть информация, которую вы активно используете на своем веб-сайте, в онлайн-магазине или в мобильных приложениях, вы можете дополнить ее системой рекомендаций.
Рекомендательная система — это механизм, который предлагает наиболее подходящую по смыслу информацию, основываясь на исходных данных. Эта система идеально подходит для самых разнообразных целей:
- Магазины: Рекомендательная система поможет показать похожие товары, что позволит увеличить продажи.
- Сайты с услугами: Она поможет предложить клиентам релевантные предложения, что повысит качество обслуживания.
- Поисковые сайты: Благодаря ей пользователи смогут найти точную информацию по своему запросу, что ускорит процесс принятия решений.
- Блоги и информационные сайты: Рекомендации помогут связать тесно связанный по смыслу контент, что сделает контент более привлекательным и полезным.
- Поиск товаров и информации: Система позволит быстро находить товары и информацию по базе данных, что значительно упростит процесс навигации.
Основное отличие от обычного поиска заключается в том, что рекомендательная система ищет данные не по прямому совпадению, а на основе векторного представления и близких совпадений. Чтобы создать эффективную рекомендательную систему, вам потребуется:
- Данные: Соберите всю необходимую информацию, которая будет использоваться в вашей системе.
- Векторная база данных: Эта база данных позволяет эффективно представлять и находить близкие совпадения, что значительно улучшает работу рекомендательной системы.
Введение
В этой статье мы познакомимся с Yandex Database (YDB), которая станет нашим инструментом для:
- Хранения информации
- Сохранения векторов
- Поиска схожих данных
В качестве примера мы будем использовать следующую структуру данных:
- Идентификатор записи
- Название
- Данные
- Вектор
- Дата создания
Это типичная структура таблицы, заполнив которую мы сможем наполнить нашу базу информацией. При таком подходе поиск похожих по смыслу данных будет возвращать дополнительные сведения, такие как название, описание и возможность упорядочить результаты по дате их создания.
Миграция данных
Создание таблицы
Прежде всего, создайте таблицу, например, articles, с помощью следующего YQL запроса:
CREATE TABLE articles (
`id` Uuid,
`title` Utf8,
`summary` Utf8,
`body` Utf8,
`isPublished` Bool,
`createdAt` Timestamp,
`embedding` String,
PRIMARY KEY (`id`)
);
Этот запрос создаст таблицу с необходимыми полями: идентификатор записи, название, описание, текст, а также поля для хранения вектора и даты создания.
Обратите внимание на ключевое слово PRIMARY KEY (id) — это первичный ключ, который будет использоваться для идентификации каждой записи в таблице. Более подробно об этом вы можете узнать из документации YDB.
Загрузка данных
Теперь приступим к заполнению таблицы. Для этого можно использовать функцию INSERT, которая позволяет добавить новую запись в таблицу:
INSERT INTO articles (
id,
title,
summary,
body,
createdAt,
)
VALUES (
RandomUuid(CurrentUtcTimestamp()),
'My title'
'My summary text',
'My body information',
true,
CurrentUtcTimestamp(),
)
RETURNING *`;
Данная функция позволяет добавить новые данные в таблицу, что, в свою очередь, наполняет нашу базу информацией.
Здесь значение для вектора пока что null, поскольку мы создадим вектор для данных позже и добавим его в таблицу отдельно.
Создание векторного представления для данных
Для рекомендательной системы поиск по векторам является одним из ключевых элементов. Чтобы реализовать такой поиск, необходимо преобразовать обычные данные в вектор, по которому будет осуществляться поиск.
Это можно сделать с помощью функции embedding, которая преобразует данные в вектор.
Вы можете сделать это самостоятельно, но я рекомендую воспользоваться уже готовыми решениями. Например, в Yandex Cloud есть готовые модели, которые преобразуют ваши данные в векторное представление.
Более подробную информацию можно найти на этой странице: Модели векторного представления текста.
Для векторизации я буду использовать следующий код на языке Python:
from __future__ import annotations
from yandex_ai_studio_sdk import AIStudio
# Укажи свои значения
YANDEX_FOLDER_ID = "*****"
YANDEX_API_KEY = "*****"
doc_text ="""Здесь основной текст статьи или любых другие данные по которым выполняется поиск."""
def main():
import numpy as np
from scipy.spatial.distance import cdist
sdk = AIStudio(
folder_id=YANDEX_FOLDER_ID,
auth=YANDEX_API_KEY,
)
# Эмбеддинги документов
doc_model = sdk.models.text_embeddings("emb://<идентификатор_каталога>/text-embeddings-v2-doc/latest")
doc_embedding = doc_model.run(doc_text, dimensions=256)
vector = doc_embedding.embedding
print("Размерность:", len(vector))
# Приводим к float32 (ВАЖНО для YDB)
vector = np.asarray(doc_embedding.embedding, dtype=np.float32)
# Делаем строку, которую можно вставить в YQL
vector_sql = "[" + ", ".join(str(float(x)) + "f" for x in vector) + "]"
print(vector_sql)
if __name__ == "__main__":
main()
Обратите внимание на следующие ключевые моменты:
text-embeddings-v2-doc— это версия модели и ее тип, который может бытьdocилиquery.dimensions=256— указывает размерность вектора. Вы можете выбрать значения256,512или768, причем чем больше размер, тем выше глубина и точность.vector = np.asarray(doc_embedding.embedding, dtype=np.float32)— преобразование вектора в число с плавающей запятой, что необходимо для хранения в YDB.vector_sql = "[" + ",".join(str(float(x)) + "f" for x in vector) + "]"— создание строки, которую можно вставить в запрос в YQL.
Пункты 3 и 4 являются лишь необходимыми преобразованиями для сохранения вектора в YDB. В результате вы получите вектор, подобный следующему:
[-0.039563942700624466f, 0.04024477303028107f, -0.00539764016866684f, -0.05466749519109726f, 0.06055353209376335f, ...]
Сохранение вектора в YDB
Для того чтобы добавить вектор к нашим данным, необходимо обновить соответствующую запись в таблице. Это можно выполнить с помощью следующего YQL выражения:
UPDATE articles
SET embedding =
Untag(
Knn::ToBinaryStringFloat([-0.039563942700624466f, 0.04024477303028107f, -0.00539764016866684f, -0.05466749519109726f, 0.06055353209376335f, ...]),
"FloatVector"
)
WHERE id = CAST("5772ab53-78b2-4f05-94b5-2985d98c2c79" AS Uuid);
Обратите внимание, что я обновляю данные для конкретного id, указав соответствующее значение.
Более подробную информацию о векторных индексах вы можете найти в документации: Поиск в таблице без использования векторного индекса.
Поиск похожих данных
Для поиска похожих данных мы будем использовать поиск без глобального индекса. Это может существенно повлиять на скорость поиска данных, особенно если у вас большое количество записей. В качестве примера я использовал следующий запрос:
$K = 3;
$TargetEmbedding = Knn::ToBinaryStringFloat([-0.16292296f, -0.01153724f, -0.00408009f, -0.02625849f, -0.07566188f, ...]);
SELECT id, title, Knn::CosineDistance(embedding, $TargetEmbedding) As CosineDistance
FROM articles
ORDER BY Knn::CosineDistance(embedding, $TargetEmbedding)
LIMIT $K;
Обратите внимание на следующие ключевые моменты:
$K— определяет количество возвращаемых похожих данных.SELECT id, title— указывает на выбранные поля.Knn::ToBinaryStringFloat()— здесь передается запрос, по которому будет осуществляться поиск.
В функцию Knn::ToBinaryStringFloat() следует передать вектор, по которому будет происходить поиск. Это может быть информация или просто поисковый запрос.
После выполнения запроса мы получаем следующий результат:
1. 61a11aab | My title | 0.6590741872787476
2. cb7e144f | My title | 0.6948220729827881
3. 3e24011b | My title | 0.7233924865722656
Таким образом, мы видим, что первые три записи являются наиболее подходящими по критерию схожести с нашим запросом.
YDB возвращает не только данные, но и дополнительное поле CosineDistance.
Это поле измеряет степень совпадения между объектами, и чем выше его значение, тем менее схожими являются данные.
Заключение
Это был простой пример того, как вы уже можете использовать рекомендательные системы в своих веб-приложениях, сайтах, онлайн-магазинах и мобильных приложениях.