DigitalApplications

Как создать рекомендательную систему для сайта с помощью YDB и векторного поиска

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

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

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

  1. Магазины: Рекомендательная система поможет показать похожие товары, что позволит увеличить продажи.
  2. Сайты с услугами: Она поможет предложить клиентам релевантные предложения, что повысит качество обслуживания.
  3. Поисковые сайты: Благодаря ей пользователи смогут найти точную информацию по своему запросу, что ускорит процесс принятия решений.
  4. Блоги и информационные сайты: Рекомендации помогут связать тесно связанный по смыслу контент, что сделает контент более привлекательным и полезным.
  5. Поиск товаров и информации: Система позволит быстро находить товары и информацию по базе данных, что значительно упростит процесс навигации.

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

  1. Данные: Соберите всю необходимую информацию, которая будет использоваться в вашей системе.
  2. Векторная база данных: Эта база данных позволяет эффективно представлять и находить близкие совпадения, что значительно улучшает работу рекомендательной системы.

Введение

В этой статье мы познакомимся с Yandex Database (YDB), которая станет нашим инструментом для:

  1. Хранения информации
  2. Сохранения векторов
  3. Поиска схожих данных

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

  1. Идентификатор записи
  2. Название
  3. Данные
  4. Вектор
  5. Дата создания

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

Миграция данных

Создание таблицы

Прежде всего, создайте таблицу, например, 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()

Обратите внимание на следующие ключевые моменты:

  1. text-embeddings-v2-doc — это версия модели и ее тип, который может быть doc или query.
  2. dimensions=256 — указывает размерность вектора. Вы можете выбрать значения 256, 512 или 768, причем чем больше размер, тем выше глубина и точность.
  3. vector = np.asarray(doc_embedding.embedding, dtype=np.float32) — преобразование вектора в число с плавающей запятой, что необходимо для хранения в YDB.
  4. 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;

Обратите внимание на следующие ключевые моменты:

  1. $K — определяет количество возвращаемых похожих данных.
  2. SELECT id, title — указывает на выбранные поля.
  3. Knn::ToBinaryStringFloat() — здесь передается запрос, по которому будет осуществляться поиск.

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

1. 61a11aab | My title | 0.6590741872787476
2. cb7e144f | My title | 0.6948220729827881
3. 3e24011b | My title | 0.7233924865722656

Таким образом, мы видим, что первые три записи являются наиболее подходящими по критерию схожести с нашим запросом. YDB возвращает не только данные, но и дополнительное поле CosineDistance.

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

Заключение

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

Author: Dmitry Girsky-Updated: 24 июня 2026 г.