Перейти к содержанию

Основные положения#

LVSM состоит из двух основных компонентов:

  • основной сервис, который обрабатывает задачи по созданию коллекций и автоматически синхронизирует их с LUNA PLATFORM, чтобы данные всегда оставались актуальными.
  • Плагин поиска, который выполняет поиск по коллекциям и интегрирован в LUNA PLATFORM через систему плагинов Python Matcher Proxy.

Для работы модуля требуются следующие сервисы LUNA PLATFORM:

  • LUNA Configurator — для управления конфигурацией системы.

  • LUNA Events — как источник данных о событиях для создания и синхронизации векторных коллекций.

  • LUNA Faces — для доступа к биометрическим шаблонам лиц, которые используются при поиске.

  • LUNA Python Matcher Proxy — для интеграции плагина поиска.

Коллекции#

Коллекции — это основа для организации векторного поиска. Коллекция представляет собой набор сущностей (события, лица и др.), объединённых общими фильтрами. Каждая запись в коллекции содержит:

  • идентификатор сущности (например, event_id);
  • биометрические шаблоны — векторы признаков, извлеченные нейронной сетью из медиаданных, содержащих человеческое лицо, тело или сцену;
  • дополнительные данные (payload) в формате JSON, содержащие дополнительные поддерживаемые таргеты LUNA PLATFORM, которые пользователь хочет получить в результатах поиска.

В настоящее время модуль поддерживает работу только с сущностями типа 'событие'.

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

Параметры хранения нескольких биометрических шабонов задаются при создании коллекции через POST-запрос /collections в конфигурации биометрических шабонов:

...
"descriptors": [
    {
        "descriptor_type": "face",
        "descriptor_version": 65
    },
    {
        "descriptor_type": "body",
        "descriptor_version": 105
    }
],
...

Метаданные коллекций#

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

  • collection_name - имя коллекции;
  • parameters - параметры коллекции, определяемые пользователем в POST-запросе /collections;
  • max_link_key - максимальный идентификатор добавленных сущностей (техническая информация о синхронизации с исходной базой данных, предоставлена ​​только для справки);
  • max_unlink_key - максимальный идентификатор удаленных сущностей (техническая информация о синхронизации с исходной базой данных, предоставлена ​​только для справки);
  • sync_time - время последней синхронизации коллекции.

Пример структуры метаданных:

{
    "collection_name": "my-shiny-collection",
    "parameters": {
        "object_type": "events",
        "descriptors": [{"descriptor_type": "face", "descriptor_version": 65}],
        "payload": ["event_id", "handler_id"],
        "conditions": {"account_id": "00000000-0000-4000-a000-000000311001"}
    },
    "max_link_key": 123456789,
    "max_unlink_key": 123,
    "sync_time": "2025-09-15T00:00:00Z"
}

Процесс синхронизации коллекций#

После первоначального заполнения коллекция начинает синхронизироваться с настроенным периодом (по умолчанию 1 секунда).

Цикл синхронизации для каждой коллекции представляет собой следующую последовательность шагов:

1․ Получение сущностей из исходной базы данных в соответствии с параметрами коллекции за период с последней синхронизации и их добавление в коллекцию.

2․ Обнаружение идентификаторов сущностей, удаленных из исходной базы данных за период с последней синхронизации, и удаление элементов с такими идентификаторами из коллекции.

3․ Обновление метаданных коллекции с учетом идентификаторов и времени последней синхронизации

Особенности процесса синхронизации коллекций

Если задача синхронизации не выполняется (например, из-за занятости воркеров), она ставится в очередь и повторяется позже. Ограничение по воркерам: По умолчанию — 100 воркеров, поэтому одновременно синхронизируется ограниченное количество коллекций. Процесс синхронизации между сбоями сбрасывается и начинается с предыдущего состояния синхронизации.

Информацию о процессе синхронизации коллекции можно найти в логах сервиса. Статус синхронизации коллекции (временная метка последней синхронизации) также можно получить через GET-запрос /collections.

Для корректной синхронизации удалённых событий необходимо включить параметр "EVENT_DELETION_LOG" в сервисе LUNA Events.

База данных Qdrant#

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

Ключевые возможности векторной базы данных Qdrant:

  • Встроенное шардирование — механизм горизонтального масштабирования, обеспечивающий равномерное распределение нагрузки и отказоустойчивость за счет автоматического распределения данных между шардами.
  • Построение индексов на GPU — расширяет область применения векторного поиска на задачи с большими объемами данных и требованиями к производительности.
  • Расширенные фильтры при поиске (включая временные промежутки и GPS-координаты) с возможностью постфильтрации — применения дополнительных фильтров к результатам поиска.

Хранилище векторов#

Все данные в Qdrant организованы в коллекции, которые делятся на сегменты. Каждый сегмент хранит векторы, дополнительные данные (payload) и индексы. См. документацию Qdrant.

Типы хранилищ для векторов:

  • In-memory — все векторы хранятся в оперативной памяти, что обеспечивает максимальную скорость поиска, поскольку доступ к диску требуется только для обеспечения сохранности данных.

  • Memmap — создает виртуальное адресное пространство, связанное с файлом на диске. При достаточном объёме ОЗУ работает почти так же быстро, как и In-memory.

Типы хранилищ для дополнительных данных (payload):

  • In-memory — все дополнительные данные хранятся в оперативной памяти, что обеспечивает высокую скорость операций, но может требовать значительный объем ресурсов.

  • OnDisk — данные хранятся на диске, что предпочтительнее для больших объемов payload. Однако, если нужно фильтровать данные по payload, рекомендуется создавать индексы для ускорения доступа.

Индексы#

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

Для ускорения поиска Qdrant поддерживает два типа индексов:

1․ Векторные индексы

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

Для подробной информации см. документацию Qdrant.

2․ Payload-индексы

Ускоряют фильтрацию по дополнительным данным (payload). Эти индексы строятся для конкретного поля и типа данных (uuid, datetime, int, text и др.).

Для подробной информации см. документацию Qdrant.

Пример создания индексов для различных типов данных с помощью PUT-запроса /collections/{collection_name}/index:

{
   "field_name": "handler_id",
   "field_schema": "uuid"
}
{
   "field_name": "create_time",
   "field_schema": "datetime"
}
{
   "field_name": "age",
   "field_schema": "int"
}
{
   "field_name": "upper_body.sleeve.length",
   "field_schema": "text"
}

Управление коллекциями#

Qdrant предоставляет возможности для управления коллекциями, включая динамическое обновление параметров конфигурации.

Параметры коллекции могут быть изменены после ее создания с помощью API запроса PATCH /collections/{collection_name}:

{
   "vectors_config": {
      "face_65": {
        "on_disk": false
     },
     "body_105": {
        "on_disk": false
     }
   },
   "hnsw_config": {
      "on_disk": false
   },
   "params": {
      "on_disk_payload": false
   }
}

Для управления коллекциями, отслеживания статуса индексации и конфигурации доступен пользовательский интерфейс.

Распределенное развертывание#

Qdrant поддерживает горизонтальное масштабирование через механизм шардирования.

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

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

Подробнее см. распределенное развертывание.

Настройки биометрических шабонов#

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

  • object_type — тип объекта, к которому относится биометрический шабон (например, лица, события);
  • descriptor_type — тип биометрического шабона (например, лицо, тело);
  • descriptor_version — версия биометрического шабона;
  • descriptor_length — размер биометрического шабона в байтах;
  • platt_scaling — параметры (a, b) для нормализации оценок совпадений с использованием шкалы Платта;

Пример конфигурации биометрических шабонов:

    [
        {
            "object_type": "events",
            "descriptor_type": "face",
            "descriptor_version": 52,
            "descriptor_length": 256,
            "platt_scaling": {
                "a": 0.5,
                "b": 1.0
            }
        },
        {
            "object_type": "events",
            "descriptor_type": "body",
            "descriptor_version": 116,
            "descriptor_length": 512,
            "platt_scaling": {
                "a": 0.7,
                "b": 0.13
            }
        },
    ]

Сценарии использования#

1․ Создание коллекции — при создании коллекции система автоматически извлекает параметры descriptor_length и platt_scaling на основе указанных object_type, descriptor_type и descriptor_version. Пользователь может переопределить параметры platt_scaling, если это необходимо.

2․ Матчинг с помощью плагина — во время выполнения операций сравнения в LUNA PLATFORM плагин автоматически извлекает параметры platt_scaling, связанные с коллекцией. Эти параметры используются для калибровки исходных оценок схожести, возвращаемых из базы данных. Это обеспечивает их нормализацию и единообразное форматирование.

Плагин поиска#

Плагин поиска интегрируется в сервис Python Matcher Proxy и позволяет выполнять векторный поиск по коллекциям, созданным в LUNA Vector Search Module.

1․ В сервис LUNA Configurator нужно добавить настройки для подключения к векторной базе данных. Пример конфигурации:

LUNA_VECTOR_SEARCH_PLUGIN = {
    "DB": [{"type": "qdrant", "url": "http://127.0.0.1:6333", "token": "luna"}],
    "SEARCH_PARAMETERS": {"exact": true, "ef_search": 3200},
    "COLLECTION_OBSOLETE_PERIOD": null,
    "REQUEST_TIMEOUT": 60
}

Важно: Убедитесь, база данных запущена с параметрами, переданными в настройке LUNA_VECTOR_SEARCH_PLUGIN.DB.

После добавления настроек подключения к Qdrant необходимо перезапустить сервис LUNA PLATFORM, если он уже был запущен.

2․ Добавьте имя плагина в список активных плагинов:

LUNA_MATCHER_PROXY_ACTIVE_PLUGINS = ["vector_search_plugin"]

Примечание. В документации по установке приведены конкретные шаги для включения плагина.

Обзор работы плагина#

После интеграции плагин анализирует каждый поисковый запрос и определяет, соответствует ли поисковый запрос какой-либо созданной коллекции. Для этого плагин проверяет метаданные коллекций и выполняет следующие проверки:

1․ Актуальность коллекции
Коллекция считается актуальной, если с момента последней синхронизации прошло меньше времени, чем указано в параметре COLLECTION_OBSOLETE_PERIOD. Если COLLECTION_OBSOLETE_PERIOD установлен в null, проверка актуальности не выполняется.

2․ Тип объекта
Тип объекта в запросе должен совпадать с типом объектов в коллекции.

3․ Тип и версия биометрического шабона
Дескрипторы в запросе должны соответствовать типам и версиям биометрических шабонов, хранящихся в коллекции.

4․ Фильтры запроса
Фильтры в запросе должны быть подмножеством условий, по которым построена коллекция.

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

Пример работы плагина#

Для коллекции с параметрами:

{
    "object_type": "events",
    "descriptors": [{"descriptor_type": "face", "descriptor_version": 65}],
    "payload": ["event_id", "handler_id"],
    "conditions": {"account_id": "00000000-0000-4000-a000-000000311001"}
}

Подходящие запросы:

{
    "origin": "events",
    "account_id": "00000000-0000-4000-a000-000000311001"
}
{
    "origin": "events",
    "account_id": "00000000-0000-4000-a000-000000311001",
    "event_id__gte": "5f8d954f-e76f-4381-be1a-7f4052013c63",
    "handler_ids": ["a9a98a13-94bf-4147-9b47-2041e0ee00b6"]
}

Неподходящие запросы:

{
    "origin": "events",
    "handler_ids": ["a9a98a13-94bf-4147-9b47-2041e0ee00b6"]
}

Причина: фильтры не являются подмножеством условий коллекции.

{
    "origin": "events",
    "account_id": "00000000-0000-4000-a000-000000311001",
    "handler_ids": ["a9a98a13-94bf-4147-9b47-2041e0ee00b6"],
    "age__gte": 42
}

Причина: поле age отсутствует в payload коллекции.

Результат поиска#

После выполнения поиска, применения пороговых значений и ограничений плагин возвращает результаты, дополненные данными из payload, в Python Matcher Proxy.

Ограничения#

Плагин поиска не поддерживает:

  • фильтрацию по географическому положению (geo_position);
  • операторы like/nlike для текстовых полей (например, user_data, поля в meta).

Если значения этих фильтров отличаются от указанных в коллекции, выполнение поиска невозможно.