⚠️ Эта страница автоматически переведена, и перевод может быть несовершенным.
blog-post

Manticore Search 29.9.0: автоэмбеддинги с разбиением на фрагменты и mmap-доступ к columnar-атрибутам

View as markdown

Вышел Manticore Search 29.9.0 . Главное изменение касается автоэмбеддингов: длинные документы теперь можно разбивать на доступные для поиска фрагменты, а для одного документа — хранить несколько векторов вместо того, чтобы сводить все его содержимое к одному. Кроме того, mmap теперь используется по умолчанию для доступа к columnar-атрибутам. В релиз также вошли ограничение размера входных данных для локального построения эмбеддингов, UTF-8-идентификаторы, улучшения резервного копирования и исправления в гибридном поиске, KNN, пакетной загрузке, группировке результатов и изменении схемы.

В этой статье собраны все изменения после 29.0.2 — с 29.0.3 по 29.9.0.

❤️ Спасибо @tudorvasinca за работу над PR #4857 , PR #4859 и PR #4873 .


Примечания по обновлению

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

  • Нормализация немецкой буквы ß (Eszett) включается явно. При переключении существующей таблицы на lemmatize_de_v2 или lemmatize_de_v2_all меняется набор термов в индексе, поэтому plain-таблицу нужно перестроить, а документы для новой RT-таблицы — загрузить заново.
  • Для BACKUP при включенной аутентификации появилось отдельное право backup. Перед откатом до версии 29.3.12 или более ранней удалите все права backup.
  • Для columnar-атрибутов теперь по умолчанию используется mmap вместо буферизованного чтения (file). Чтобы сохранить прежний режим доступа, явно задайте access_columnar_attrs='file'.

Для длинных документов можно хранить несколько эмбеддингов

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

Manticore Search теперь поддерживает пять стратегий разбиения на фрагменты :

  • truncate сохраняет прежнее поведение и остается вариантом по умолчанию.
  • mean создает эмбеддинг для каждого фрагмента и усредняет их в один вектор.
  • fixed разбивает текст на окна из фиксированного числа токенов.
  • recursive старается разбивать текст по границам абзацев, строк, предложений и пробелов — именно в таком порядке.
  • sentence группирует целые предложения во фрагменты до заданного лимита.

Стратегии, создающие несколько векторов, используют float_vector_array . Каждый фрагмент участвует в KNN-поиске независимо, но Manticore возвращает документ только один раз, а knn_dist() — расстояние до ближайшего фрагмента:

CREATE TABLE articles (
  title text,
  content text,
  chunks float_vector_array knn_type='hnsw' hnsw_similarity='cosine'
    model_name='Xenova/all-MiniLM-L6-v2' from='title,content'
    chunk_strategy='sentence' max_tokens='256' overlap_tokens='32'
);

INSERT INTO articles (id, title, content)
VALUES (1, 'Rotating certificates', 'A long guide with many sections ...');

SELECT id, knn_dist()
FROM articles
WHERE knn(chunks, 5, 'how do I rotate a certificate');

MAX_TOKENS, OVERLAP_TOKENS и MAX_CHUNKS задают размер фрагмента, перекрытие между соседними фрагментами и максимальное число векторов. float_vector_array с моделью нужно объявлять при создании таблицы: добавить такой столбец позже через ALTER TABLE ... ADD COLUMN и перестроить эмбеддинги пока нельзя.

Ограничьте нагрузку при локальном построении эмбеддингов

Обработка большого объема входных данных моделью с длинным контекстом может неожиданно потребовать много ресурсов, особенно на CPU. Новая опция столбца MAX_INPUT_TOKENS ограничивает число токенов во входных данных, передаваемых локальной модели эмбеддингов:

ALTER TABLE articles
MODIFY COLUMN chunks MAX_INPUT_TOKENS='512';

Изменение применяется только к новым эмбеддингам; существующие векторы остаются без изменений. Опцию можно задать при CREATE TABLE или изменить позже без повторного построения эмбеддингов для всей таблицы. Значение 0 или отсутствие опции означает, что используется собственный лимит модели.

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


UTF-8-идентификаторы и более точный поиск на немецком

Имена таблиц, полей и атрибутов теперь используют единый безопасный синтаксис UTF-8-идентификаторов . RT-, percolate-, distributed-, template- и plain-таблицы могут использовать локализованные имена — например, китайские или кириллические идентификаторы — в DDL, выражениях, селекторах полей и при выводе схемы источника.

Немецкая AOT-морфология также получила необязательную нормализацию буквы ß (Eszett). С charset_table=non_cont,german и morphology=lemmatize_de_v2 или lemmatize_de_v2_all формы вроде Straße, Strasse и STRAẞE считаются эквивалентными при обычном поиске по целым словам. Если включен index_exact_words=1, точный поиск по-прежнему может различать формы ß и ss.


Улучшенное нагрузочное тестирование и резервное копирование

manticore-load теперь умеет запускать бенчмарки через HTTP JSON API с --http. Для записи используется /bulk, для поиска — /search, а --table задает целевую таблицу. В отчетах теперь отображается RSS локального процесса searchd во время теста, а в итоговой статистике — пиковое значение RSS, использование дискового пространства и статистика CPU. Для нагрузок из нескольких команд добавлен агрегированный мониторинг.

Manticore Backup теперь работает с установками Manticore Search, где включена аутентификация: можно использовать имя пользователя и пароль или bearer-токен. SQL-команда BACKUP получила отдельное право backup и проверяет право на чтение выбранных таблиц.

Резервное копирование в S3 и восстановление из него теперь могут использовать стандартный механизм поиска учетных данных AWS SDK, если статические ключи не заданы. Поддерживаются IRSA, shared credentials, роли задач ECS и профили экземпляров EC2. Для временных учетных данных можно передавать AWS_SESSION_TOKEN.

Columnar-атрибуты теперь используют mmap по умолчанию

Manticore Search теперь по умолчанию использует mmap для access_columnar_attrs . Операционная система отображает файлы columnar-атрибутов *.spc в память и кэширует их по мере обращения, поэтому при запуске не нужно заранее считывать файл целиком. Прежний режим буферизованного чтения остается доступен через access_columnar_attrs='file'.

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


Исправления в векторном поиске и группировке

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

  • В распределенных и шардированных KNN-запросах с локальным шардом оценка объединенных 1-битно-квантованных результатов больше не пересчитывается дважды. Раньше это могло привести к падению координатора или выбору неверного ближайшего соседа. (Issue #4791 )
  • KNN-запросы с дополнительными фильтрами больше не выполняют лишний префильтр по knn_dist, если HNSW уже исключил документы без векторов. (PR #4861 )
  • LENGTH() для float_vector_array теперь возвращает число векторов, а не внутреннее число слов, используемых для хранения. (PR #4879 )
  • Гибридный поиск с GROUP BY сохраняет все группы, включая MVA-группы, и учитывает как итоговую сортировку, так и сортировку внутри каждой группы. (Issue #4639 )
  • Гибридные фильтры по weight(), а также по выражениям и алиасам на основе weight() теперь применяются после объединения результатов — к итоговому текстовому весу — вместо того, чтобы игнорироваться. Фильтры, зависящие от веса, внутри деревьев OR по-прежнему не поддерживаются и возвращают явную ошибку. (Issue #4889 )
  • При группировке RT-таблиц по нескольким чанкам исправлены дублирование групп, неверные значения COUNT(*) и зависание при сортировке по COUNT(DISTINCT ...). (Issue #4856 )
  • Фильтры по ID документов с отрицательным знаковым представлением теперь используют беззнаковый порядок поискового индекса. (Issue #4774 )

Исправлены и несколько падений: второй оператор гибридного поиска в многооператорном запросе (PR #4864 ), распределенная JSON-агрегация с сортировкой по строковому атрибуту (Issue #4822 ) и удаление таблицы на этапе precommit автоэмбеддингов (Issue #4860 ) больше не приводят к падению.

Пакетная загрузка ведет себя предсказуемо

Elasticsearch-совместимые запросы /_bulk теперь после обработки пакета возвращают HTTP 200, а ошибки отдельных элементов по-прежнему видны через errors: true и их собственные статусы. Повторяющиеся операции create возвращают для соответствующих элементов ошибку 409 version_conflict_engine_exception, в том числе если дубликаты находятся внутри одного пакета. Благодаря этому клиенты вроде Fluent Bit не отправляют повторно записи, которые уже были успешно записаны.

Gzip /bulk с фиксированной длиной теперь корректно декодируются, даже если поступают за несколько чтений из сокета. Если нативный обработчик bulk не находит целевую таблицу, корректный NDJSON-запрос снова может быть передан механизму авто-схемы Manticore, при этом сохраняется ожидаемая оболочка bulk-ответа.


Дополнительные исправления надежности

Остальная часть релиза исправляет широкий набор проблем с эксплуатацией и совместимостью:

  • searchd --stopwait больше не зависает во время ребалансировки шардированной таблицы после повторного подключения узла. (Issue #3905 )
  • Старые совместимые binlog-файлы корректно воспроизводятся при обновлении, а завершенные RT-чанки публикуются перед штатным завершением работы. (Issue #4808 ) Диагностика фатальных ошибок при воспроизведении теперь также указывает соответствующий флаг восстановления. (Issue #4811 )
  • indexer создает недостающие родительские каталоги для путей plain-таблиц, если ближайший существующий родительский каталог доступен для записи. (Issue #4793 )
  • UUID-идентификаторы документов больше не приводят к тому, что сохраненные текстовые поля возвращаются пустыми. (Issue #4833 )
  • ALTER TABLE ... RENAME сохраняет скрытые API-ключи моделей эмбеддингов, использующих внешний API, и не раскрывает их в SHOW CREATE TABLE. (Issue #4842 )
  • Проверки совместимости Sequel Ace 5.3.1+ снова работают. (Issue #4828 )
  • JSON /search теперь сохраняет расстояние для NEAR и операторов близости в запросах с отрицанием. (Issue #4784 )
  • Внутренние вспомогательные столбцы для сортировки строк больше не попадают в результаты LEFT JOIN. (Issue #4788 )
  • Некорректное число элементов SEARCH в binary API теперь приводит к отклонению запроса, а не к завершению searchd. (PR #4790 )

Полный список изменений см. в чейнджлоге версии 29.9.0 .


Как установить Manticore Search 29.9.0

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

Нужна помощь или хотите в наш кружок?

  • Присоединяйтесь к нам в Slack
  • Загляните на форум
  • Сообщайте о проблемах и предлагайте новые функции на GitHub
  • Пишите нам на [email protected]

Установить Manticore Search

Установите Manticore Search одной командой в Linux или macOS:

curl https://manticoresearch.com | sh

Для расширенных вариантов установки см. полное руководство по установке и документацию .

Установить Manticore Search