Поиск и аналитика

Сопоставления

Сопоставления и типы полей

Сопоставления сообщают Подсистеме, как хранить и индексировать документы и их поля. Можно указать тип данных для каждого поля (например, year как date), чтобы повысить эффективность хранения и запросов.

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

Например, с помощью явных сопоставлений можно гарантировать, что year будет обрабатываться как текст, а age — как целое число, вместо того чтобы динамическое сопоставление интерпретировало их как целые числа.

Динамическое сопоставление

При индексировании документа Подсистема автоматически добавляет поля с помощью динамического сопоставления. Также можно вручную добавить поля в сопоставление индекса. Типы динамического сопоставления приведены в таблице 95.

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

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

PUT index
{
"mappings": {
"dynamic_templates": [
{
"fields": {
"mapping": {
"type": "short"
},
"match_mapping_type": "string",
"path_match": "status*"
}
}
]
}
}

Эта конфигурация сопоставления динамически сопоставляет любое поле с именем, начинающимся с status (например, status_code), с типом данных short, если начальное значение, указанное при индексировании, является строкой.

dynamic_templates поддерживает указанные в таблице 96 параметры для условий сопоставления и правил отображения. Значение по умолчанию — null.

Если точно известно какие типы данных полей нужно использовать, можно указать их в теле запроса при создании индекса, как показано в примере запроса явного сопоставления:

PUT sample-index1
{
"mappings": {
"properties": {
"year":    { "type" : "text" },
"age":     { "type" : "integer" },
"director":{ "type" : "text" }
}
}
}

Пример ответа:

{
"acknowledged": true,
"shards_acknowledged": true,
"index": "sample-index1"
}

Чтобы добавить сопоставления в существующий индекс или поток данных, можно отправить запрос на конечную точку _mapping с помощью HTTP-метода PUT или POST, как показано в следующем примере запроса:

POST sample-index1/_mapping
{
"properties": {
"year":    { "type" : "text" },
"age":     { "type" : "integer" },
"director":{ "type" : "text" }
}
}

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

Параметры сопоставления

Параметры сопоставления используются для настройки поведения индексных полей.

В Подсистеме есть определенные ограничения и настройки сопоставления, например, настройки, перечисленные в таблице 97. Настройки можно изменить в соответствии с пользовательскими требованиями.

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

GET <index>/_mapping

В этом запросе может быть именем индекса или списком имен индексов, разделенных запятыми.

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

GET _mapping

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

GET _mapping/field/<fields>
GET /<index>/_mapping/field/<fields>

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

Параметры сопоставления используются для настройки поведения полей индекса (таблица 98).

Поддерживаемые типы полей

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

Массивы

В Подсистеме нет специального типа поля для массивов. Вместо этого можно передать массив значений в любое поле. Все значения в массиве должны иметь одинаковый тип поля.

PUT testindex1/_doc/1
{
"number": 1
}
PUT testindex1/_doc/2
{
"number": [1, 2, 3]
}

Мультиполя

Мультиполя используются для индексирования одного и того же поля по-разному. Строки часто сопоставляются как text для полнотекстовых запросов и keyword – для запросов с точным соответствием.

Многопольные объекты можно создавать с помощью параметра fields. Например, можно сопоставить книгу title с типом text и сохранить подпольное поле title.raw типа keyword.

PUT books
{
"mappings" : {
"properties" : {
"title" : {
"type" : "text",
"fields" : {
"raw" : {
"type" : "keyword"
}
}
}
}
}
}

NULL

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

Чтобы сделать поле доступным для поиска по значениям null, можно указать его параметр null_value в сопоставлениях индекса. Тогда все значения null, передаваемые в это поле, будут заменены на указанные null_value.

Следует обратить внимание, что параметр null_value должен иметь тот же тип, что и поле. Например, если поле является строкой, null_value для этого поля также должна быть строкой.

Поля метаданных

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

Анализ текста

При поиске документов с помощью полнотекстового поиска требуется получить все релевантные результаты. Например, при поиске слова "прогулка", могут интересовать результаты, содержащие любую форму этого слова, например "прогулка", "прогуливался" или "прогуливаясь". Для облегчения полнотекстового поиска Подсистема использует анализ текста.

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

С технической точки зрения процесс анализа текста состоит из нескольких этапов, некоторые из которых являются необязательными:

  1. Прежде чем разбивать произвольный текст на отдельные слова, может быть полезно уточнить текст на уровне символов. Основная цель этого необязательного этапа — помочь токенизатору (следующему этапу процесса анализа) генерировать более качественные токены. Это может включать удаление тегов разметки (например, HTML) или обработку определенных шаблонов символов;
  2. Разделение свободного текста на отдельные слова — токены –выполняется токенизатором. Например, после токенизации предложение "Actions speak louder than words" разделяется на токены Actions, speak, louder, than и words;
  3. Обработка отдельных токенов с помощью ряда фильтров токенов. Цель состоит в том, чтобы преобразовать каждый токен в предсказуемую форму, которая напрямую сохраняется в индексе, например, путем преобразования в нижний регистр или выполнения стемминга (сведения слова к корню). Например, токен Actions становится action, louder становится loud, а words становится word.

Примечание – Хотя термины token и term могут звучать похоже и иногда используются как взаимозаменяемые, полезно понимать разницу между ними. В контексте Apache Lucene каждый из них выполняет отдельную роль. token создается токенизатором во время анализа текста и часто подвергается ряду дополнительных изменений по мере прохождения через цепочку фильтров токенов. С каждым токеном связаны метаданные, которые могут использоваться в процессе анализа текста. term — это значение данных, которое напрямую хранится в инвертированном индексе и связано с гораздо меньшим количеством метаданных. Во время поиска сопоставление выполняется на уровне терминов.

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

  1. Фильтры символов – сначала фильтр символов получает исходный текст в виде потока символов и добавляет, удаляет или изменяет символы в тексте. Например, фильтр символов может удалить из строки символы HTML, чтобы текст "Actions speak louder than words" стал "\nActions speak louder than words\n". На выходе фильтра символов получается поток символов.
  2. Токенизатор – далее токенизатор получает поток символов, обработанных фильтром символов, и разбивает текст на отдельные токены (обычно это слова). Например, токенизатор может разбивать текст по пробелам, чтобы предыдущий текст стал "Actions, speak, louder, than, words". Токенизаторы также сохраняют метаданные о токенах, например их начальную и конечную позиции в тексте. На выходе токенизатора получается поток токенов.
  3. Токен-фильтры – наконец, токен-фильтр получает поток токенов от токенизатора и добавляет, удаляет или изменяет токены. Например, токен-фильтр может преобразовывать токены в нижний регистр, чтобы Actions стало action, удалять стоп-слова, такие как than, или добавлять синонимы, такие как talk для слова speak.

Следует обратить внимание, что анализатор должен содержать ровно один токенизатор и может содержать ноль или более фильтров символов и ноль или более фильтров токенов.

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

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

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

  • Анализатор индекса выполняет анализ во время индексирования: когда индексируется текстовое поле, Подсистема анализирует его перед индексированием.
  • Анализатор поиска выполняет анализ во время запроса: Подсистема анализирует строку запроса при выполнении полнотекстового запроса к текстовому полю.

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

Нормализаторы

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

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

  • Нормализация регистра – преобразует все токены в нижний регистр для обеспечения сопоставления без учета регистра. Например, "Hello" преобразуется в "hello".
  • Стемминг – сокращает слова до их корневой формы. Например, "cars" сокращается до "car", а "running" – до "run".
  • Обработка синонимов – рассматривает синонимы как эквиваленты. Например, "бег трусцой" и "бег" могут быть проиндексированы как общий термин "бег".

Анализаторы

В следующих разделах перечислены все анализаторы, поддерживаемые Подсистемой.

Встроенные анализаторы

В таблице 101 перечислены встроенные анализаторы, предоставляемые Подсистемой. Последний столбец таблицы содержит результат применения анализатора к строке "It’s fun to contribute a brand-new PR or 2 to OpenSearch!".

Языковые анализаторы

Подсистема поддерживает несколько языковых анализаторов: arabic, armenian, basque, bengali, brazilian, bulgarian, catalan, czech, danish, dutch, english, estonian, finnish, french, galician, german, greek, hindi, hungarian, indonesian, irish, italian, latvian, lithuanian, norwegian, persian, portuguese, romanian, russian, sorani, spanish, swedish, thai и turkish.

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

"analyzer": "french"

Дополнительные анализаторы

В таблице 102 перечислены дополнительные анализаторы, поддерживаемые Подсистемой.

Токенизаторы

Токенизатор получает поток символов и разбивает текст на отдельные токены. Токен состоит из термина (обычно слова) и метаданных об этом термине. Например, токенизатор может разбивать текст по пробелам, чтобы текст "Actions speak louder than words." стал "Actions, speak, louder, than, words.".

На выходе токенизатора получается поток токенов. Токенизаторы также сохраняют следующие метаданные о токенах:

  • Порядок или позиция каждого токена – эта информация используется для запросов по близости слов и фраз;
  • Начальная и конечная позиции (смещение) токенов в тексте – эта информация используется для выделения поисковых запросов;
  • Тип токена – некоторые токенизаторы (например, standard) классифицируют токены по типу, например, или . Более простые токенизаторы (например, letter) классифицируют токены только по типу word.

Можно использовать токенизаторы для определения пользовательских анализаторов.

Встроенные токенизаторы

В таблицах ниже перечислены встроенные токенизаторы, предоставляемые Подсистемой.

Токенизаторы слов разбивают полный текст на слова (таблица 103). Последний столбец таблицы содержит результат применения анализатора к строке "It’s fun to contribute a brand-new PR or 2 to OpenSearch!".

Токенизаторы части слов разбивают текст на слова и генерируют фрагменты этих слов для частичного сопоставления слов (таблица 104).

Токенизаторы структурированного текста анализируют структурированный текст, например идентификаторы, адреса электронной почты, пути или почтовые индексы (таблица 105).

Фильтры токенов

Фильтры токенов получают поток токенов от токенизатора и добавляют, удаляют или изменяют токены. Например, фильтр токенов может преобразовывать токены в нижний регистр, чтобы Actions стало action, удалять стоп-слова, такие как than, или добавлять синонимы, такие как talk для слова speak.

В таблице 106 перечислены все фильтры токенов, поддерживаемые Подсистемой.

Таблица 106 — Фильтры токенов

Фильтр токеновБазовый фильтр токенов LuceneОписание
apostropheApostropheFilterВ каждом токене, содержащем апостроф, фильтр токенов apostrophe удаляет сам апостроф и все последующие за ним символы
asciifoldingASCIIFoldingFilterПреобразует буквенные, цифровые и символьные символы
cjk_bigramCJKBigrammFilterФормирует биграммы из китайских, японских и корейских символов (CJK)
cjk_widthCJKWidthFilterНормализует китайские, японские и корейские (CJK) токены в соответствии со следующими правилами:— преобразует полноширинные варианты символов ASCII в эквивалентные им базовые латинские символы.— преобразует полуширинные варианты символов катаканы в эквивалентные им символы кана
classicClassicFilterВыполняет дополнительную постобработку токенов, сгенерированных классическим токенизатором. Удаляет притяжательные местоимения "'s" и "."из аббревиатур
common_gramsCommonGramsFilterГенерирует биграммы для списка часто встречающихся терминов. На выходе получаются как отдельные термины, так и биграммы
conditionalConditionalTokenFilterПрименяет упорядоченный список фильтров токенов к токенам, которые соответствуют условиям, указанным в скрипте
decimal_digitDecimalDigitFilterПреобразует все цифры в десятичном числе Юникода в базовые латинские цифры (0–9)
delimited_payloadDelimitedPayloadTokenFilterРазделяет поток токенов на токены с соответствующими полезными данными на основе заданного разделителя. Токен состоит из всех символов, предшествующих разделителю, а полезная нагрузка состоит из всех символов, следующих за разделителем. Например, если разделитель — "|", то для строки "foo|bar" "foo" является токеном, а "bar" — полезной нагрузкой
delimited_term_freqDelimitedTermFrequencyTokenFilterРазделяет поток токенов на токены с соответствующими частотами терминов на основе заданного разделителя. Токен состоит из всех символов до разделителя, а частота термина — это целое число после разделителя. Например, если разделитель — "|", то для строки "foo|5" "foo" является токеном, а "5" — частотой термина
dictionary_decompounderDictionaryCompoundWordTokenFilterРазлагает сложные слова, встречающиеся во многих германских языках
edge_ngramEdgeNGramTokenFilterРазбивает заданный токен на крайние n-граммы (n-граммы, которые начинаются с начала токена) длиной от min_gram до max_gram. При необходимости сохраняет исходный токен
elisionElisionFilterУдаляет указанные сокращения в начале токенов. Например, меняет l'avion (the plane) на avion (plane)
fingerprintFingerprintFilterСортирует и удаляет дубликаты из списка токенов и объединяет токены в один
flatten_graphFlattenGraphFilterСглаживает граф токенов, созданный фильтром токенов графа, например synonym_graph или word_delimiter_graph, делая его пригодным для индексирования
hunspellHunspellStemFilterИспользует правила Hunspell для создания основ токенов. Поскольку Hunspell позволяет слову иметь несколько основ, этот фильтр может создавать несколько токенов для каждого потребляемого токена. Требуется настройка одного или нескольких языковых словарей Hunspell
hyphenation_decompounderHyphenationCompoundWordTokenFilterИспользует шаблоны переключения слов на основе XML для поиска потенциальных подслов в сложных словах и проверяет подслова по указанному списку слов. Выводимые токены содержат только подслова, найденные в списке слов
keep_typesTypeTokenFilterСохраняет или удаляет токены определенного типа
keep_wordsKeepWordFilterПроверяет токены на соответствие указанному списку слов и сохраняет только те, которые есть в списке
keyword_markerKeywordMarkerFilterПомечает указанные токены как ключевые слова, предотвращая их использование
keyword_repeatKeywordRepeatFilterВыводит каждый входящий токен дважды: один раз как ключевое слово и один раз как неключевое слово
kstemKStemFilterОбеспечивает стемминг на основе KStem для английского языка. Сочетает алгоритмический стемминг со встроенным словарем
kuromoji_completionJapaneseCompletionFilterДобавляет японские латинизированные термины в поток токенов (в дополнение к исходным токенам). Обычно используется для поддержки автозаполнения поисковых запросов на японском языке. Следует обратить внимание, что, что у фильтра есть mode параметр, для которого следует установить значение index при использовании в анализаторе индексов и query при использовании в анализаторе поиска. Требуется плагин analysis-kuromoji
lengthLengthFilterУдаляет токены, которые короче или длиннее диапазона длин, указанного min и max
limitLimitTokenCountFilterОграничивает количество выходных токенов. Например, размер значений полей документа может быть ограничен в зависимости от количества токенов
lowercaseLowerCaseFilterПреобразует токены в нижний регистр. LowerCaseFilter по умолчанию обрабатывает английский язык. Для обработки других языков установить параметр language в greek (используется GreekLowerCaseFilter), irish (используется IrishLowerCaseFilter) или turkish (используется TurkishLowerCaseFilter)
min_hashMinHashFilterИспользует метод MinHash для оценки сходства документов. Последовательно выполняет следующие операции с потоком токенов: Хэш-кодирует каждый токен в потоке; Распределяет хеши по сегментам, сохраняя только наименьшие хеши в каждом сегменте; Выводит наименьший хеш из каждого сегмента в виде потока токенов
multiplexerN/AВыводит несколько токенов в одной и той же позиции. Пропускает каждый токен через каждый из указанных списков фильтров по отдельности и выводит результаты в виде отдельных токенов
ngramNGramTokenFilterРазбивает заданный токен на n-граммы длиной от min_gram до max_gram
Нормализацияarabic_normalization: ArabicNormalizergerman_normalization: GermanNormalizationFilterhindi_normalization: HindiNormalizerindic_normalization: IndicNormalizersorani_normalization: SoraniNormalizerpersian_normalization: PersianNormalizerscandinavian_normalization : ScandinavianNormalizationFilterscandinavian_folding: ScandinavianFoldingFilterserbian_normalization: SerbianNormalizationFilterНормализует символы одного из перечисленных языков
pattern_captureN/AСоздает токен для каждой группы захвата в заданном регулярном выражении. Использует синтаксис регулярных выражений Java
pattern_replaceN/AСоответствует шаблону в заданном регулярном выражении и заменяет совпадающие подстроки. Использует синтаксис регулярных выражений Java
phoneticN/AИспользует фонетический кодировщик для создания метафонического токена для каждого токена в потоке токенов. Требуется установка плагина analysis-phonetic
porter_stemPorterStemFilterИспользует алгоритм стемминга Портера для выполнения алгоритмического стемминга в английском языке
predicate_token_filterN/AУдаляет токены, которые не соответствуют указанному скрипту предиката. Поддерживает только встроенные скрипты Painless
remove_duplicatesRemoveDuplicatesTokenFilterУдаляет дублирующиеся токены, находящиеся в одном и том же положении
reverseReverseStringFilterОбращает вспять строку, соответствующую каждому токену в потоке токенов. Например, токен dog становится god
shingleShingleFilterГенерирует чередование длиной от min_shingle_size до max_shingle_size для токенов в потоке токенов. Чередование похоже на n-граммы, но генерируется с использованием слов, а не букв. Например, чередование из двух слов, добавленное к списку униграмм "contribute, to, opensearch", — это "contribute to, to opensearch"
snowballN/AСоздает основы для слов, используя сгенерированный "снежным комом" стеммер. Этот snowball маркер фильтр поддерживает следующие языки в language сфере: Arabic, Armenian, Basque, Catalan, Danish, Dutch, English, Estonian, Finnish, French, German, German2, Hungarian, Irish, Italian, Kp, Lithuanian, Lovins, Norwegian, Porter, Portuguese, Romanian, Russian, Spanish, Swedish, Turkish
stemmerN/AОбеспечивает алгоритм стемминга в следующих языках, используемых в поле language: arabic, armenian, basque, bengali, brazilian, bulgarian, catalan, czech, danish, dutch, dutch_kp, english, light_english, lovins, minimal_english, porter2, possessive_english, estonian, finnish, light_finnish, french, light_french, minimal_french, galician, minimal_galician, german, german2, light_german, minimal_german, greek, hindi, hungarian, light_hungarian, indonesian, irish, italian, light_italian, latvian, Lithuanian, norwegian, light_norwegian, minimal_norwegian, light_nynorsk, minimal_nynorsk, portuguese, light_portuguese, minimal_portuguese, portuguese_rslp, romanian, russian, light_russian, sorani, spanish, light_spanish, swedish, light_swedish, turkish
stemmer_overrideN/AПереопределяет алгоритмы стемминга, применяя пользовательское сопоставление, чтобы не стеммировать указанные термины
stopStopFilterУдаляет стоп-слова из потока токенов
synonymN/AПредоставляет список синонимов для процесса анализа. Список синонимов предоставляется с помощью файла конфигурации
synonym_graphN/AПредоставляет список синонимов, в том числе многословных, для процесса анализа
trimTrimFilterУдаляет начальные и завершающие символы пробела из каждого токена в потоке
truncateTruncateTokenFilterУсекает токены длиной, превышающей указанный лимит символов
uniqueN/AГарантирует, что каждый токен уникален, удаляя дублирующиеся токены из потока
uppercaseTruncateTokenFilterПреобразует символы в верхний регистр
word_delimiterWordDelimiterGraphFilterРазделяет токены на небуквенные и нецифровые символы и выполняет нормализацию по заданным правилам
word_delimiter_graphWordDelimiterGraphFilterРазделяет токены на небуквенные и числовые символы и выполняет нормализацию в соответствии с заданными правилами. Присваивает токенам с несколькими позициями атрибут positionLength

Фильтры символов

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

В отличие от фильтров токенов, которые работают с токенами (словами или терминами), фильтры символов обрабатывают исходный текст перед токенизацией. Они особенно полезны для очистки или преобразования структурированного текста, содержащего нежелательные символы, например HTML-теги или специальные символы. Фильтры символов помогают удалять или заменять эти элементы, чтобы текст был правильно отформатирован для анализа.

Варианты использования фильтров символов включают:

  • Удаление HTML-тегов – фильтр символов html_strip удаляет HTML-теги из содержимого, чтобы индексировался только обычный текст;
  • Замена шаблона – фильтр символов pattern_replace заменяет или удаляет нежелательные символы или шаблоны в тексте, например, преобразуя дефисы в пробелы;
  • Пользовательские сопоставления – фильтр символов mapping заменяет определенные символы или последовательности другими значениями, например, для преобразования символов валют в их текстовые эквиваленты.

Нормализаторы

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

Нормализатор полезен при поиске по ключевым словам (то есть при запросах на основе терминов), поскольку он позволяет применять фильтры токенов и символов к любому вводу. Например, он позволяет сопоставить входящий запрос "Naïve" с индексируемым термином "naive".

Запросы DSL

Подсистема предоставляет язык поиска под названием Query Domain-Specific Language (DSL), который можно использовать для поиска в пользовательских данных. Query DSL — это гибкий язык с интерфейсом JSON.

При использовании DSL-запросов необходимо указать запрос в query-параметре поиска. Один из самых простых поисковых запросов в Подсистеме использует запрос match_all для поиска всех документов в индексе:

GET testindex/_search
{
"query": {
"match_all": {
}
}
}

Запрос может состоять из множества предложений. Можно комбинировать предложения для создания сложных запросов.

Запросы можно разделить на простые запросы и составные запросы:

  • Простые запросы – ищут заданное значение в определенном поле или полях. Можно использовать простые запросы самостоятельно. Они включают в себя следующие типы запросов:
    • Полнотекстовые запросы – для поиска текстовых документов. При поиске в анализируемом текстовом поле полнотекстовые запросы разбивают строку запроса на термины с помощью того же анализатора, который использовался при индексировании поля. При поиске точного значения полнотекстовые запросы ищут указанное значение без применения анализа текста;
    • Запросы на уровне терминов – для поиска документов по точному термину, например идентификатору или диапазону значений. Запросы на уровне терминов не анализируют поисковые запросы и не сортируют результаты по релевантности;
    • Географические и XY-запросы – для поиска документов, содержащих географические данные, а XY-запросы для поиска документов, содержащих точки и фигуры в двумерной системе координат;
    • Объединенные запросы – для поиска вложенных полей или возврата родительских и дочерних документов, соответствующих определенному запросу. Типы объединенных запросов включают nested, has_child, has_parent и parent_id-запросы;
    • Запросы диапазона – для выполнения точного позиционного поиска – это низкоуровневые конкретные запросы, которые позволяют управлять порядком и близостью заданных условий поиска; в основном они используются для поиска в юридических документах;
    • Специализированные запросы – все остальные типы запросов (distance_feature, more_like_this, percolate, rank_feature, script, script_score и wrapper).
  • Составные запросы – служат для объединения нескольких простых или составных предложений, чтобы объединить их результаты или изменить их поведение. К ним относятся логические запросы, запросы на максимальное значение дизъюнкции, запросы с постоянным значением, запросы с функцией и запросы с ускорением.

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

Ресурсоемкие запросы могут потреблять много памяти и приводить к снижению производительности кластера. Следующие запросы могут потреблять много ресурсов:

  • fuzzy-запросы;
  • prefix-запросы;
  • range-запросы по полям text и keyword;
  • regexp-запросы;
  • wildcard-запросы;
  • query_string-запросы, которые внутренне преобразуются в префиксные запросы.

Чтобы запретить выполнение ресурсоемких запросов, можно отключить параметр кластера search.allow_expensive_queries следующим образом:

PUT _cluster/settings
{
"persistent": {
"search.allow_expensive_queries": false
}
}

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

Контекст запроса и фильтрации

Запросы состоят из предложений-запросов, которые могут выполняться в контексте фильтра или контексте запроса. Предложение-запрос в контексте фильтра задает вопрос "Соответствует ли документ предложению-запросу?" и возвращает соответствующие документы. Предложение-запрос в контексте запроса задает вопрос "Насколько хорошо документ соответствует предложению-запросу?", возвращает соответствующие документы и определяет релевантность каждого документа в виде показателя релевантности.

Оценка релевантности

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

"hits" : [
{
"_index" : "shakespeare",
"_id" : "32437",
"_score" : 18.781435,
"_source" : {
"type" : "line",
"line_id" : 32438,
"play_name" : "Hamlet",
"speech_number" : 3,
"line_number" : "1.1.3",
"speaker" : "BERNARDO",
"text_entry" : "Long live the king!"
}
},
...

Более высокий балл указывает на более релевантный документ. Хотя разные типы запросов рассчитывают баллы релевантности по-разному, все типы запросов учитывают, выполняется ли запрос в контексте фильтра или запроса.

Рекомендуется использовать предложения запроса, которыми требуется повлиять на оценку релевантности, в контексте запроса, а все остальные предложения запроса — в контексте фильтра.

Контекст фильтра Предложение запроса в контексте фильтра задает вопрос "Соответствует ли документ предложению запроса?", на который можно дать однозначный ответ. Например, если есть индекс с данными об учащихся, можно использовать контекст фильтра, чтобы ответить на следующие вопросы об учащемся:

  • Установлен ли статус студента honors на true?
  • Находится ли студент в диапазоне graduation_year 2020–2022 годов?

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

Чтобы выполнить запрос в контексте фильтра, следует передать его в параметр filter. Например, следующий логический запрос ищет студентов, окончивших обучение с отличием в 2020–2022 годах:

GET students/_search
{
"query": {
"bool": {
"filter": [
{ "term":  { "honors": true }},
{ "range": { "graduation_year": { "gte": 2020, "lte": 2022 }}}
]
}
}
}

Чтобы повысить производительность, Подсистема кеширует часто используемые фильтры.

Контекст запроса

Предложение запроса в контексте запроса задает вопрос "Насколько хорошо документ соответствует предложению запроса?", на который нет однозначного ответа. Контекст запроса подходит для полнотекстового поиска, когда требуется не только получить соответствующие документы, но и определить релевантность каждого документа. Например, если есть индекс с полным собранием сочинений Шекспира, можно использовать контекст запроса для следующих поисковых запросов:

  • Найди документы, содержащие слово dream, включая его различные формы (dreaming или dreams) и синонимы (contemplate).
  • Найти документы, соответствующие этим словам "long live king".

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

Чтобы выполнить запрос в контексте запроса, нужно передать его в параметр query: Например, следующий запрос ищет документы, содержащие слова "long live king" в индексе shakespeare:

GET shakespeare/_search
{
"query": {
"match": {
"text_entry": "long live king"
}
}
}

Показатели релевантности — это числа с плавающей запятой одинарной точности с 24-битной точностью мантиссы. Если при вычислении показателя точность мантиссы будет превышена, точность может снизиться.

Сравнение запросов на уровне терминов и полнотекстовых запросов

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

Примечание – Подсистема использует алгоритм ранжирования BM25 для вычисления показателей релевантности

Запросы на уровне терминов

Запросы на уровне терминов ищут в индексе документы, содержащие точное поисковое выражение. Документы, возвращаемые запросом на уровне терминов, не сортируются по степени релевантности.

При работе с текстовыми данными используют запросы на уровне терминов только для полей, сопоставленных как keyword.

Запросы на уровне терминов не подходят для поиска в анализируемых текстовых полях. Чтобы вернуть анализируемые поля, используют полнотекстовый запрос.

В таблице 108 перечислены все типы запросов на уровне терминов.

Полнотекстовые запросы

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

Типы полнотекстовых запросов, показанные в этом разделе, используют стандартный анализатор, который автоматически анализирует текст при отправке запроса.

В таблице 109 перечислены все типы полнотекстовых запросов.

Составные запросы

Составные запросы служат для объединения нескольких простых или составных запросов в один или для изменения их поведения.

В таблице 110 перечислены все типы составных запросов.

Географические и XY-запросы

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

XY-запросы

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

XY-запросы возвращают документы, содержащие:

  • фигуры XY и точки XY, которые имеют одно из четырех пространственных отношений к заданной фигуре: INTERSECTS, DISJOINT, WITHIN или CONTAINS;
  • точки XY, пересекающие заданную фигуру.

Географические запросы

Географические запросы позволяют искать документы, содержащие геопространственные данные. Эти данные можно указать в geo_point-полях, которые поддерживают точки на карте, и geo_shape-полях, которые поддерживают точки, линии, окружности и многоугольники.

Подсистема предоставляет следующие географические типы запросов:

  • Запросы с геопривязкой – возвращают документы со значениями полей геоточек, которые находятся в пределах географических границ;
  • Запросы по географическому расстоянию – возвращают документы с геоданными, которые находятся на заданном расстоянии от указанной геоточкой.
  • Запросы по геополигонам – возвращают документы, содержащие геоточки, которые находятся внутри полигона;
  • Запросы по геофигурам – возвращают документы, содержащие:
    • геоформы и геоточки, которые имеют одно из четырех пространственных отношений к заданной форме: INTERSECTS, DISJOINT, WITHIN или CONTAINS;
    • геоточки, пересекающие заданную фигуру.

Объединенные запросы

В Подсистеме данные распределены по нескольким узлам. Таким образом, выполнение операции JOIN, подобной SQL, в Подсистеме требует больших ресурсов. В качестве альтернативы Подсистема предоставляет следующие запросы, которые выполняют операции объединения и оптимизированы для масштабирования на нескольких узлах:

  • Запросы для поиска по вложенным полям:
    • nested-запросы – выступают в качестве оболочки для других запросов для поиска по вложенным полям. Вложенные объекты полей ищутся так, как если бы они были проиндексированы как отдельные документы;
  • Запросы для поиска документов, связанных полем join-типа, которое устанавливает отношения "родитель-потомок" между документами в одном индексе:
    • has_child-запросы – поиск родительских документов, дочерние документы которых соответствуют запросу;
    • has_parent-запросы – поиск дочерних документов, родительские документы которых соответствуют запросу;
    • parent_id-запросы – поиск дочерних документов, которые присоединены к определенному родительскому документу.

Примечание – Если для search.allow_expensive_queries установлено значение false, то запросы на объединение не выполняются.

Запросы диапазона

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

Запросы диапазона включают следующие типы запросов:

  • Содержащий диапазон – объединяет список запросов диапазонов и возвращает только диапазоны, соответствующие второму запросу диапазона;
  • Маскировка полей диапазона – объединяет разные поля через span_near или span_or;
  • Первый диапазон – совпадения проходят близко к началу поля;
  • Многострочный диапазон – обеспечивает поддержку следующих типов запросов: term, range, prefix, wildcard, regexp или fuzzy;
  • Близко расположенные диапазоны – сопоставляет диапазоны, расположенные близко друг к другу. Объединяет несколько запросов диапазонов, которые должны совпадать в пределах указанного slop-расстояния друг от друга и, при необходимости, в том же порядке. Величина отклонения представляет собой максимальное количество промежуточных несовпадающих позиций и указывает, требуется ли возвращать совпадения в порядке их следования;
  • Исключая диапазон – обеспечивает оболочку для другого запроса и исключает все документы, соответствующие внутреннему запросу;
  • Включая диапазон – предоставляет оболочку для нескольких пространственных запросов и включает все документы, соответствующие любому из указанных запросов;
  • Диапазон терминов – работает так же, как запрос term, но предназначен для использования с другими запросами диапазона;
  • Диапазон в пределах – используется с другими запросами диапазона для возврата одного запроса диапазона, если его диапазон находится в пределах диапазонов, возвращаемых списком других запросов диапазона.

Запрос всех соответствий

Запрос match_all возвращает все документы. Этот запрос может быть полезен при тестировании больших наборов документов, если нужно вернуть весь набор.

GET _search
{
"query": {
"match_all": {}
}
}

У match_all запроса есть аналог match_none, который редко бывает полезен:

GET _search
{
"query": {
"match_none": {}
}
}

Специализированные запросы

Подсистема поддерживает следующие специализированные запросы:

  • distance_feature – вычисляет оценки документов на основе динамически рассчитанного расстояния между источником и полями date, date_nanos или geo_point документа; может пропускать нерелевантные совпадения;
  • more_like_this – находит документы, похожие на указанный текст, документ или набор документов;
  • neural – используется для поиска по векторному полю в нейронном поиске;
  • neural_sparse – используется для поиска по векторному полю в разделенном нейронном поиске;
  • percolate – находит запросы (сохраненные в виде документов), соответствующие предоставленному документу;
  • rank_feature – вычисляет баллы на основе значений числовых характеристик; может пропускать нерелевантные совпадения;
  • script – использует скрипт в качестве фильтра;
  • script_score – вычисляет пользовательский балл для сопоставления документов с помощью скрипта;
  • wrapper – принимает другие запросы в виде строк JSON или YAML.

Минимальное соответствие

Параметр minimum_should_match можно использовать для полнотекстового поиска. Он определяет минимальное количество терминов, которым должен соответствовать документ, чтобы попасть в результаты поиска.

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

GET /shakespeare/_search
{
"query": {
"match": {
"text_entry": {
"query": "prince king star",
"minimum_should_match": "2"
}
}
}
}

В этом примере запрос содержит три необязательных условия, которые объединены с помощью "OR", поэтому документ должен соответствовать либо prince и king, либо prince и star, либо king и star.

Допустимые значения

Можно указать параметр minimum_should_match в виде одного значений из таблицы 110.

Использование параметра в логических запросах

Логический запрос содержит необязательные условия в выражении should и обязательные условия в выражении must. При необходимости он может содержать выражение filter для фильтрации результатов.

Агрегации

Обзор

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

Варианты использования агрегации варьируются от анализа данных в реальном времени для принятия каких-либо мер до использования "Панелей мониторинга" для создания панели визуализации.

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

Агрегации по текстовым полям

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

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

Рекомендуется сохранять исходную версию текстового поля в виде поля keyword для агрегации данных.

В этом случае можно выполнять агрегацию по полю title.raw вместо поля title:

PUT movies
{
"mappings": {
"properties": {
"title": {
"type": "text",
"fielddata": true,
"fields": {
"raw": {
"type": "keyword"
}
}
}
}
}
}

Общая структура агрегации

Структура запроса агрегации выглядит следующим образом:

GET _search
{
"size": 0,
"aggs": {
"NAME": {
"AGG_TYPE": {}
}
}
}

Если интересует только результат агрегации, а не результаты запроса, следует установить значение size на 0.

В свойстве aggs (при желании используют aggregations) можно определить любое количество агрегаций. Каждая агрегация определяется своим именем и одним из типов агрегаций, которые поддерживает Подсистема.

Название агрегации помогает различать разные агрегации в ответе. Свойство AGG_TYPE позволяет указать тип агрегации.

Типы агрегаций Существует три основных типа агрегаций:

  • Агрегация показателей – вычисление показателей таких, как sum, min, max и avg для числовых полей;
  • Агрегация групп – сортировка результатов запроса по группам на основе определенных критериев.
  • Агрегации конвейеров — объединение выходных данных одной агрегации в качестве входных данных для другой.

Вложенные агрегированные данные

Агрегации внутри агрегаций называются вложенными или субагрегациями.

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

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

Общий синтаксис вложенной агрегации выглядит следующим образом:

{
"aggs": {
"name": {
"type": {
"data"
},
"aggs": {
"nested": {
"type": {
"data"
}
}
}
}
}
}

Внутреннее ключевое слово aggs начинает новую вложенную агрегацию. Синтаксис родительской агрегации и вложенной агрегации одинаков. Вложенные агрегации выполняются в контексте предшествующих родительских агрегаций.

Также можно комбинировать агрегации с поисковыми запросами, чтобы сузить область поиска перед агрегацией. Если не добавлять запрос, Подсистема неявно использует запрос match_all.

Ограничения

Поскольку агрегации обрабатываются с использованием типа данных double для всех значений, значения long от 253 и выше являются приблизительными.

Агрегация показателей

Агрегация показателей позволяет выполнять простые вычисления, например, находить минимальное, максимальное и среднее значения поля.

Существует два типа агрегации показателей: агрегация показателей с одним значением и агрегация показателей с несколькими значениями.

Агрегация показателей с одним значением возвращает единственный показатель, например, sum, min, max avg, cardinality или value_count.

Агрегация показателей с несколькими значениями возвращает более одного показателя. К ним относятся stats, extended_stats, matrix_stats percentile, percentile_ranks geo_bound, top_hits и scripted_metric.

Подсистема поддерживает следующие агрегированные показатели:

  • Средний;
  • Мощность;
  • Расширенная статистика;
  • Географические границы;
  • Матричная статистика;
  • Максимальный;
  • Минимальный;
  • Процентильные ранги;
  • Процентиль;
  • Скриптовый показатель;
  • Статистика;
  • Сумма;
  • Популярный;
  • Количество значений.

Агрегация по группам

Агрегация по группам распределяет наборы документов по группам. Тип агрегации по группам определяет группу для конкретного документа.

Можно использовать агрегацию по группам для реализации многомерной навигации (обычно размещаемой на боковой панели целевой страницы результатов поиска), чтобы помочь пользователям фильтровать результаты.

Подсистема поддерживает следующие агрегации по группам:

  • Матрица смежности;
  • Потомки;
  • Гистограмма даты;
  • Диапазон дат;
  • Диверсифицированный примерный;
  • Фильтр;
  • Фильтры;
  • Геодезическое расстояние;
  • Сетка геоширины;
  • Geohash-сетка;
  • Geohex-сетка;
  • Глобальный;
  • Гистограмма;
  • Диапазон IP-адресов;
  • Отсутствующий;
  • Мульти-термины;
  • Вложенный;
  • Диапазон;
  • Обратный вложенный;
  • Примерный;
  • Значимые термины;
  • Важный текст;
  • Термины.

Агрегации конвейеров

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

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

Агрегация конвейера использует свойство buckets_path для доступа к результатам других агрегаций. Свойство buckets_path имеет особый синтаксис:

buckets_path = <AGG_NAME>[<AGG_SEPARATOR>,<AGG_NAME>]*[<METRIC_SEPARATOR>, <METRIC>];

где:

  • AGG_NAME – название агрегации;
  • AGG_SEPARATOR – разделение агрегированных данных; в данном случае – ">";
  • METRIC_SEPARATOR – разделение агрегированных данных от своих показателей; в данном случае – ".".
  • METRIC – название показателя в случае агрегации нескольких значений показателя.

Также можно использовать следующие дополнительные параметры:

  • gap_policy – Реальные данные могут содержать пробелы или нулевые значения. Можно указать политику для обработки таких отсутствующих данных с помощью свойства gap_policy. Можно либо установить для свойства gap_policy значение skip, чтобы пропустить недостающие данные и продолжить со следующего доступного значения, либо с помощью insert_zeros заменить недостающие значения на ноль и продолжить выполнение;
  • format – Тип формата для выходного значения, например, yyyy-MM-dd для значения даты.

Типы агрегаций конвейеров

Агрегации конвейеров бывают двух типов: агрегации-потомки и агрегации-родители.

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

Агрегация по родственным группам должна быть многосегментной (иметь несколько сгруппированных значений для определенного поля), а показатель должен быть числовым значением.

min_bucket, max_bucket, sum_bucket и avg_bucket являются обычными агрегациями-потомками.

Агрегации-родители берут выходные данные внешней агрегации и создают новые сегменты или новые агрегации на том же уровне, что и существующие сегменты.

Для агрегации-родителя min_doc_count должно быть установлено значение 0 (по умолчанию для histogram-агрегаций), а указанный показатель должен быть числовым значением. Если min_doc_count больше 0, некоторые сегменты не учитываются, что может привести к неверным результатам.

derivatives и cumulative_sum являются обычными агрегациями-родителями.

Агрегации avg_bucket, sum_bucket, min_bucket, и max_bucket — это родственные агрегации, которые вычисляют среднее, суммарное, минимальное и максимальное значения показателя в каждом сегменте предыдущей агрегации.

Агрегация stats_bucket — это агрегация-потомок, которая возвращает различные статистические данные (count, min, max, avg и sum) для сегментов предыдущей агрегации.

Агрегация extended_stats – это расширенная версия агрегации stats. Помимо включения базовой статистики, extended_stats также предоставляет такую статистику, как sum_of_squares, variance и std_deviation.

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

Агрегация bucket_selector – это основанная на сценарии агрегация, которая выбирает сегменты, возвращаемые агрегацией histogram (или date_histogram). Агрегацию используют в сценариях, когда не нужны определенные сегменты в выводе на основе заданных условий.

Агрегация bucket_sort – это родительская агрегация, которая сортирует сегменты предыдущей агрегации. Можно указать несколько полей сортировки вместе с соответствующим порядком сортировки. Кроме того, можно сортировать каждую группу по ключу, количеству или подмножествам. Также можно усекать группы, задав параметры from и size.

Агрегация cumulative_sum — это родительская агрегация, которая вычисляет совокупную сумму для каждого сегмента предыдущей агрегации. Совокупная сумма — это последовательность частичных сумм заданной последовательности. Например, совокупные суммы последовательности {a,b,c,…} равны a, a+b, a+b+c и так далее. Совокупную сумму можно использовать для визуализации скорости изменения показателя с течением времени.

Агрегация derivative — это родительская агрегация, которая вычисляет производные 1-го и 2-го порядка для каждого сегмента предыдущей агрегации. В математике производная функции измеряет ее чувствительность к изменениям. Другими словами, производная оценивает скорость изменения некоторой функции по отношению к некоторой переменной. Можно использовать производные для вычисления скорости изменения числовых значений по сравнению с предыдущими периодами времени. Производная 1-го порядка показывает, увеличивается или уменьшается показатель и насколько он увеличивается или уменьшается. Производная 2-го порядка — это двойная производная или производная от производной. Она показывает, как изменяется скорость изменения величины. Это разница между производными первого порядка соседних сегментов.

Агрегация moving_avg – это родительская агрегация, которая вычисляет показатель скользящего среднего. Агрегация moving_avg находит средние значения для разных подмножеств набора данных. Размер подмножества представляет собой количество точек данных, охватываемых подмножеством на каждой итерации (задается свойством window и по умолчанию равно 5). На каждой итерации алгоритм вычисляет среднее значение для всех точек данных, попадающих в подмножество, а затем сдвигается вперед, исключая первый элемент предыдущего подмножества и включая первый элемент следующего подмножества. Можно использовать агрегацию moving_avg для сглаживания краткосрочных колебаний или выделения долгосрочных тенденций или циклов в данных временных рядов.

Агрегация serial_diff – это родительская агрегация конвейера, которая вычисляет ряд разностей значений между временными интервалами сегментов предыдущих агрегаций. Можно использовать агрегацию serial_diff для поиска изменений данных между периодами времени вместо поиска всего значения. С помощью параметра lag (положительное ненулевое целое число) можно указать, какое предыдущее значение вычесть из текущего. Если не указать параметр lag, Подсистема установит его значение равным 1.

Функции поиска

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

Обзор

Подсистема поддерживает следующие методы поиска:

  • Традиционный лексический поиск – по ключевым словам (BM25), который ищет в теле документов слова, встречающиеся в запросе;
  • Поиск с поддержкой ML – основанные на машинном обучении (ML):
    • Векторный поиск – поиск k-NN по поисковому запросу в индексе векторов;
    • Нейронный поиск – упрощает создание векторных представлений во время обработки данных и поиск по ним во время поиска. Нейронный поиск позволяет интегрировать модели машинного обучения в поиск и служит основой для реализации других методов поиска. На основе нейронного поиска созданы следующие методы поиска:
    • семантический поиск – учитывает значение слов в контексте поиска. Использует плотный поиск на основе моделей встраивания текста для поиска текстовых данных;
    • мультимодальный поиск – использует мультимодальные модели встраивания для поиска текстовых и графических данных;
    • нейронный разреженный поиск – использует разреженный поиск на основе разделенных моделей встраивания для поиска текстовых данных;
    • гибридный поиск – сочетает традиционный поиск и векторный поиск для повышения релевантности результатов поиска;
    • диалоговый поиск – реализует генерирующий поиск с расширенным поиском.

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

  • Query domain-specific language (DSL) – основной язык запросов, который поддерживает создание сложных, полностью настраиваемых запросов;
  • Query string query language – упрощенный язык запросов, который можно использовать в параметре запроса поискового запроса или в "Панелях мониторинга";
  • SQL – традиционный язык запросов, который устраняет разрыв между традиционными концепциями реляционных баз данных и гибкостью документоориентированного хранилища данных;
  • Piped Processing Language (PPL) – основной язык, используемый для мониторинга, с синтаксисом конвейера, который объединяет команды в запрос;
  • Dashboards Query Language (DQL) – простой текстовый язык запросов для фильтрации данных в "Панелях мониторинга".

Подсистема предлагает несколько способов повысить производительность поиска:

  • асинхронный поиск выполняет ресурсоемкие запросы асинхронно;
  • одновременный поиск по сегментам выполняет поиск по сегментам одновременно.

Подсистема предоставляет следующие функции релевантности для поиска:

  • Compare Search Results – инструмент сравнения результатов поиска в "Панелях мониторинга", который можно использовать для одновременного сравнения результатов двух запросов;
  • Querqy – предоставляет возможность перезаписи запросов;
  • User Behavior Insights – связывает поведение пользователей с их запросами для повышения качества поиска.

Подсистема поддерживает следующие часто используемые операции с результатами поиска:

  • разбиение на страницы;
  • разбиение на страницы с указанием момента времени;
  • сортировка;
  • выделение поисковых запросов;
  • автозаполнение
  • подразумевание.

С помощью поисковых конвейеров можно обрабатывать поисковые запросы и результаты поиска.

Параметры поиска

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

Поиск по ключевым словам

По умолчанию Подсистема рассчитывает оценки документов с использованием алгоритма Okapi BM25. BM25 – это алгоритм на основе ключевых слов, который выполняет лексический поиск по словам, которые появляются в запросе.

При определении релевантности документа BM25 учитывает частоту термина/обратную частоту встречаемости в документе (TF/IDF):

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

В таблице 112 перечислены поддерживаемые алгоритмы подобия.

В параметре similarity можно указать алгоритм подобия при настройке сопоставлений на уровне полей.

Параметры подобия BM25 на уровне индекса можно настроить следующим образом:

PUT /testindex
{
"settings": {
"index": {
"similarity": {
"custom_similarity": {
"type": "BM25",
"k1": 1.2,
"b": 0.75,
"discount_overlaps": "true"
}
}
}
}
}

Подобие BM25 поддерживает параметры из таблицы 113.

Поиск k-NN

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

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

Этот плагин поддерживает три различных метода получения k-NN из индекса векторов:

  • Приблизительный k-NN – Первый метод использует приближенный подход к ближайшим соседям. Он применяет один из нескольких алгоритмов для возврата приближенных k-NN к вектору запроса. Приблизительный k-NN — лучший выбор для поиска по большим индексам (то есть по сотням тысяч векторов и более), для которых требуется низкая задержка. Не следует использовать приблизительный k-NN, если требуется применить фильтр к индексу перед поиском k-NN, что значительно сократит количество векторов для поиска. В этом случае следует использовать либо метод оценки сценария, либо расширения Painless.
  • Оценка сценария k-NN – Второй метод расширяет функциональность сценариев для выполнения точного поиска методом "грубой силы" по полям "knn_vector" или полям, которые могут представлять двоичные объекты. С помощью этого подхода можно выполнять поиск методом "грубой силы" по подмножеству векторов в индексе (иногда это называют поиском с предварительной фильтрацией). Следует использовать этот подход для поиска по небольшим массивам документов или когда требуется предварительная фильтрация. Использование этого подхода для больших индексов может привести к высокой задержке.
  • Painless-расширения – Третий метод добавляет функции расстояния в качестве Painless-расширений, которые можно использовать в более сложных комбинациях. Как и в случае с оценкой сценария k-NN, этот метод можно использовать для точного поиска k-NN по индексу методом перебора, который также поддерживает предварительную фильтрацию. Этот подход обеспечивает немного более низкую производительность запросов по сравнению с оценкой по сценарию k-NN. Если требуется более тонкая настройка итогового результата, следует использовать этот подход вместо оценки по сценарию k-NN.

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

Обучение ранжированию

Плагин "Learning to Ranking" (обучение ранжированию) для Подсистемы позволяет использовать машинное обучение (ML) и поведенческие данные для точной настройки релевантности документов. Он использует модели из библиотек XGBoost и RankLib. Эти модели повторно анализируют результаты поиска с учетом функций, зависящих от запроса, таких как данные о переходах по ссылкам или совпадения полей, что может еще больше повысить релевантность.

Векторный поиск

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

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

  • Создать вложения с помощью выбранной библиотеки, прежде чем загружать их в Подсистему. После загрузки векторов в индекс можно выполнить поиск по векторному сходству в векторном пространстве.
  • Автоматически генерировать вложения в Подсистеме. Чтобы использовать вложения для семантического поиска, необходимо, чтобы загруженный текст (тело документа) и запрос были встроены с помощью одной и той же модели. Нейронный поиск объединяет эти функции, избавляя от необходимости управлять внутренними деталями.

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

Индекс k-NN

Чтобы создать векторную базу данных и использовать векторный поиск, при ее создании необходимо указать индекс как индекс k-NN, установив index.knn в true:

PUT test-index
{
"settings": {
"index": {
"knn": true,
"knn.algo_param.ef_search": 100
}
},
"mappings": {
"properties": {
"my_vector1": {
"type": "knn_vector",
"dimension": 1024,
"space_type": "l2",
"method": {
"name": "hnsw",
"engine": "nmslib",
"parameters": {
"ef_construction": 128,
"m": 24
}
}
}
}
}
}

Вектор k-NN

Необходимо указать поле, в котором будут храниться векторы, в качестве типа поля knn_vector. Подсистема поддерживает векторы до 16 000 измерений, каждое из которых представлено в виде 32-битного или 16-битного числа с плавающей запятой.

Для экономии места в памяти можно использовать byte- или binary-векторы.

Векторный поиск k-NN

Векторный поиск находит в базе данных векторы, наиболее похожие на вектор запроса.

Приблизительный поиск

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

  • Hierarchical Navigable Small World (HNSW);
  • Inverted File System (IVF).

Кроме того, следует указать библиотеку, реализующую этот метод, в параметре engine:

  • Non-Metric Space Library (NMSLIB);
  • Facebook AI Similarity Search (Faiss);
  • Lucene.

В таблице 114 перечислены комбинации методов поиска и библиотек, поддерживаемых механизмом k-NN для приблизительного векторного поиска.

Рекомендации по библиотекам

В целом, для крупномасштабных сценариев использования лучше выбрать NMSLIB или Faiss. Lucene – хороший вариант для небольших развертываний, он предлагает такие преимущества, как интеллектуальная фильтрация, при которой оптимальная стратегия фильтрации – предварительная, пост-фильтрация или точная k-NN – применяется автоматически в зависимости от ситуации. В таблице 115 приведены различия между этими вариантами.

Генерация векторных вложений

Нейронный поиск включает инфраструктуру, необходимую для выполнения семантического векторного поиска. После интеграции сервиса логического вывода (встраивания) нейронный поиск работает как лексический поиск, принимая текстовый запрос и возвращая соответствующие документы.

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

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

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

  • Семантический поиск – использует плотный поиск на основе моделей встраивания текста для поиска текстовых данных.
  • Гибридный поиск – сочетает лексический и нейронный поиск для повышения релевантности результатов.
  • Мультимодальный поиск – использует нейронный поиск с мультимодальными моделями встраивания для поиска текстовых и графических данных.
  • Нейронный поиск с разреженным извлечением – использует нейронный поиск с разреженным извлечением на основе моделей разреженного встраивания для поиска текстовых данных.
  • Диалоговый поиск – с помощью диалогового поиска можно задавать вопросы на естественном языке, получать текстовые ответы и задавать дополнительные уточняющие вопросы.

Нейронный поиск

Нейронный поиск преобразует текст в векторы и упрощает векторный поиск как во время загрузки, так и во время поиска. Во время загрузки нейронный поиск преобразует текст документа в векторные представления и индексирует как текст, так и его векторные представления в векторном индексе. При использовании нейронного запроса во время поиска нейронный поиск преобразует текст запроса в векторные представления, применяет векторный поиск для сравнения векторных представлений запроса и документа и возвращает наиболее близкие результаты.

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

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

  • использование предварительно обученной модели, предоставленной Подсистемой;
  • загрузка своей собственной модели в Подсистему;
  • подключение к базовой модели, размещенной на внешней платформе.

Использование ML-модели для нейронного поиска

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

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

Семантический поиск

Семантический поиск учитывает контекст и цель запроса. В Подсистеме семантический поиск осуществляется с помощью нейронного поиска с использованием моделей встраивания текста. Семантический поиск создает плотный вектор (список чисел с плавающей точкой) и загружает данные в индекс k-NN.

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

Чтобы использовать семантический поиск, нужно выполнить следующие действия:

  1. Шаг 1: Создать входной конвейер

Чтобы создать векторные вложения, нужно создать конвейер обработки данных, который содержит процессор text_embedding, преобразующий текст в поле документа в векторные вложения. field_map процессора определяет входные поля, из которых будут создаваться векторные вложения, и выходные поля, в которых будут храниться вложения.

Чтобы разделить длинный текст на фрагменты, используют процессор text_chunking перед процессором text_embedding.

  1. Шаг 2: Создать индекс для встраивания

Чтобы использовать процессор встраивания текста, определенный в конвейере, необходимо создать индекс k-NN, добавив конвейер, созданный на предыдущем шаге, в качестве конвейера по умолчанию. Следует убедиться, что поля, определенные в field_map, сопоставлены с правильными типами.

  1. Шаг 3: Вставить документы в индекс
  2. Шаг 4: Выполнить поиск по индексу с помощью нейронного поиска

Чтобы выполнить векторный поиск в индексе, используют предложение neural запроса в API плагина k-NN или запросах Query DSL. Можно уточнить результаты с помощью фильтра поиска k-NN.

Для запроса neural требуется идентификатор модели для создания векторных представлений. Чтобы не передавать идентификатор модели при каждом запросе нейронного запроса, можно установить модель по умолчанию для индекса k-NN или поля.

Мультимодальный поиск

Мультимодальный поиск используют для поиска текстовых и графических данных. В нейронном поиске текстовый поиск упрощается с помощью мультимодальных моделей встраивания.

Перед использованием текстового поиска необходимо настроить мультимодальную модель встраивания.

Чтобы использовать нейронный поиск с встраиванием текста и изображений, требуется выполнить следующие действия:

  1. Шаг 1: Создать входной конвейер

Чтобы создать векторные вложения, нужно создать конвейер обработки данных, который содержит процессор text_image_embedding, преобразующий текст или изображение в поле документа в векторные вложения. field_map процессора определяет поля текста и изображений, из которых будут создаваться векторные вложения, а также выходное векторное поле, в котором будут храниться вложения.

  1. Шаг 2: Создать индекс для встраивания

Чтобы использовать процессор встраивания текста, определенный в конвейере, нужно создать индекс k-NN, добавив конвейер, созданный на предыдущем шаге, в качестве конвейера по умолчанию. Следует убедиться, что поля, определенные в field_map, сопоставлены с правильными типами.

  1. Шаг 3: Вставить документы в индекс
  2. Шаг 4: Выполнить поиск по индексу с помощью нейронного поиска

Чтобы выполнить векторный поиск в индексе, используют предложение neural запроса в API-интерфейсе k-NN или запросах Query DSL. Можно уточнить результаты с помощью фильтра поиска k-NN. Можно выполнять поиск по тексту, изображению или по тексту и изображению одновременно.

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

Нейронный разреженный поиск

Семантический поиск основан на плотном поиске, который, в свою очередь, основан на моделях встраивания текста. Однако плотные методы используют поиск k-NN, который требует большого объема памяти и ресурсов процессора. Альтернативой семантическому поиску является нейронный разреженный поиск, который реализован с помощью инвертированного индекса и, таким образом, является таким же эффективным, как BM25. Нейронный разреженный поиск упрощается за счет моделей встраивания. При выполнении нейронного разреженного поиска создается разреженный вектор (список пар ключ-значение "token: weight", представляющих запись и ее вес) и данные помещаются в индекс признаков ранжирования.

Чтобы еще больше повысить релевантность поиска, можно комбинировать нейронный разреженный поиск с плотным семантическим поиском с помощью гибридного запроса.

Можно настроить нейронный разреженный поиск следующими способами:

  • Создать векторные вложения в Подсистеме – настроить конвейер обработки для создания и хранения разреженных векторных вложений из текста документа во время обработки. Во время запроса ввести обычный текст, который будет автоматически преобразован в векторные вложения для поиска.
  • Загрузить необработанные разреженные векторы и выполнять поиск, используя разреженные векторы напрямую.

Ускорение нейронного разреженного поиска

Возможно значительно ускорить процесс поиска, создав конвейер поиска с помощью neural_sparse_two_phase_processor.

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

PUT /_search/pipeline/two_phase_search_pipeline
{
"request_processors": [
{
: {
"tag": "neural-sparse",
"description": "Creates a two-phase processor for neural sparse search."
}
}
]
}

Затем следует выбрать индекс, который требуется настроить с помощью конвейера поиска, и указать index.search.default_pipeline в качестве имени конвейера, как показано в следующем примере:

PUT /my-nlp-index/_settings
{
"index.search.default_pipeline" : "two_phase_search_pipeline"
}

Гибридный поиск

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

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

  1. Шаг 1: Создать входной конвейер

Чтобы создать векторные вложения, нужно создать конвейер обработки данных, который содержит процессор text_embedding, преобразующий текст в поле документа в векторные вложения. field_map процессора определяет входные поля, из которых будут создаваться векторные вложения, и выходные поля, в которых будут храниться вложения.

  1. Шаг 2: Создать индекс для встраивания

Чтобы использовать процессор встраивания текста, определенный в конвейере, требуется создать индекс k-NN, добавив конвейер, созданный на предыдущем шаге, в качестве конвейера по умолчанию. Следует убедиться, что поля, определенные в field_map, сопоставлены с правильными типами.

  1. Шаг 3: Вставить документы в индекс
  2. Шаг 4: Настроить конвейер поиска
  3. Шаг 5: Выполнить поиск по индексу с помощью гибридного поиска

Чтобы выполнить гибридный поиск в индексе, используют запрос hybrid, который объединяет результаты поиска по ключевым словам и семантического поиска.

Гибридный поиск с последующей фильтрацией

Можно выполнить постобработку результатов гибридного поиска, указав в запросе параметр post_filter

Предложение post_filter применяется после получения результатов поиска. Постфильтрация полезна для применения дополнительных фильтров к результатам поиска без влияния на оценку или порядок результатов.

Постфильтрация не влияет на показатели релевантности документа или результаты агрегации.

Сочетание гибридного поиска и агрегации

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

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

Чтобы использовать агрегации в гибридном запросе, следует сначала создать индекс. Агрегации обычно используются для полей специальных типов, таких как keyword или integer.

Использование сортировки с помощью гибридного запроса

По умолчанию гибридный поиск возвращает результаты, упорядоченные по баллам в порядке убывания. Можно применить сортировку к результатам гибридного запроса, указав критерии sort в поисковом запросе. При применении сортировки к гибридному поиску результаты извлекаются из сегментов на основе указанных критериев сортировки. В результате результаты поиска сортируются соответствующим образом, а баллы документов равны null. Баллы присутствуют в результатах сортировки гибридного поиска только в том случае, если документы сортируются по _score.

Гибридный поиск с search_after

Можно управлять результатами сортировки, применяя условие search_after для получения индикатора в реальном времени и используя результаты предыдущей страницы для получения результатов следующей страницы.

Можно разбить отсортированные результаты на страницы, применив условие search_after в запросах сортировки.

Межкластерный поиск

Можно использовать межкластерный поиск (CCS – cross-cluster search) в Подсистеме для поиска и анализа данных в нескольких кластерах, что позволит получать аналитические сведения из распределенных источников данных. Межкластерный поиск доступен по умолчанию с плагином Security, но нужно настроить каждый кластер, чтобы разрешить удаленные подключения из других кластеров. Для этого необходимо настроить удаленные подключения к кластерам и разрешения на доступ.

Поток аутентификации

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

  1. плагин Security проверяет подлинность пользователя в координирующем кластере;
  2. плагин Security получает сведения о ролях пользователя в серверной части координирующего кластера;
  3. вызов, включая аутентифицированного пользователя, перенаправляется в удаленный кластер;
  4. разрешения пользователя оцениваются в удаленном кластере.

Настройка разрешений

Чтобы запрашивать индексы в удаленных кластерах, пользователи должны иметь разрешения READ или SEARCH. Кроме того, если поисковый запрос содержит параметр ccs_minimize_roundtrips=false, который указывает Подсистеме не минимизировать исходящие и входящие запросы к удаленным кластерам, пользователям необходимо иметь следующее дополнительное разрешение для индекса:

indices:admin/shards/search_shards

Настройки прокси-сервера

Можно настроить межкластерный поиск в кластере, работающем за прокси-сервером. Существует множество способов настройки обратного прокси-сервера и различных прокси-серверов на выбор. Чтобы использовать режим прокси-сервера, следует убедиться, что узлы исходного кластера могут подключиться к настроенному proxy_address.

Разбиение текста на фрагменты

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

  1. создать конвейер;
  2. создать индекс для приема;
  3. вставить документы в индекс;
  4. выполнить поиск по индексу с помощью нейронного поиска.

Диалоговый поиск

Диалоговый поиск позволяет задавать вопросы на естественном языке и уточнять ответы, задавая дополнительные вопросы. Таким образом, диалог становится диалогом между пользователем и большой языковой моделью (large language model –LLM). Для этого вместо ответа на каждый вопрос по отдельности, модель должна запоминать контекст всего диалога.

Диалоговый поиск реализован с помощью следующих компонентов:

  • История диалогов – позволяет LLM запоминать контекст текущего диалога и понимать последующие вопросы;
  • Расширенное извлечение (Retrieval-Augmented Generation – RAG) – позволяет LLM дополнять свою статичную базу знаний собственной или актуальной информацией.

История диалогов

История диалогов состоит из простого CRUD-подобного API, включающего два ресурса: память и сообщения. Все сообщения для текущего диалога хранятся в одной памяти диалога. Сообщение представляет собой пару "вопрос/ответ": вопрос, заданный человеком, и ответ ИИ. Сообщения не существуют сами по себе; они должны быть добавлены в память.

RAG

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

Когда плагин Security включен, вся память существует в режиме безопасности private. Только пользователь, создавший память, может взаимодействовать с этой памятью. Ни один пользователь не может видеть память другого пользователя.

Чтобы начать использовать диалоговый поиск, нужно включить функцию сохранения диалогов и конвейер RAG:

PUT /_cluster/settings
{
"persistent": {
"plugins.ml_commons.memory_feature_enabled": true,
"plugins.ml_commons.rag_pipeline_feature_enabled": true
}
}

Чтобы использовать диалоговый поиск, следует выполнить следующие действия:

  1. создать коннектор с моделью;
  2. зарегистрировать и развернуть модель;
  3. создать поисковый конвейер;
  4. ввести данные RAG в индекс;
  5. создать память о диалоге;
  6. использовать конвейер для RAG.

Конвейер RAG

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

Для настройки модели Cohere Command для включения RAG необходимо использовать функцию постобработки для преобразования выходных данных модели.

Чтобы использовать конвейер RAG, нужно отправить запрос в Подсистему и указать дополнительные параметры в объекте ext.generative_qa_parameters, который поддерживает параметры из таблицы 116.

Если в LLM установлено ограничение на количество токенов, следует указать в запросе поле size для ограничения количества документов, используемых в результатах поиска. В противном случае конвейер RAG отправит все документы из результатов поиска в LLM.

Релевантность поиска

Релевантность поиска оценивает точность результатов поиска, возвращаемых по запросу. Чем выше релевантность, тем лучше поисковая система.

Подсистема предоставляет следующие функции релевантности для поиска:

  • сравнение результатов поиска по двум запросам в "Панелях мониторинга";
  • повторное ранжирование результатов поиска с использованием средства кросс-кодирования;
  • переписывание запросов с использованием Querqy.

Сравнение результатов поиска

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

Например, можно увидеть, как меняются результаты, если применить одно из следующих изменений запроса:

  • применение весов к полям по-разному;
  • различные стратегии стемминга или лемматизации;
  • использование последовательности токенов.

Повторное ранжирование результатов поиска

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

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

  • с помощью модели кросс-кодирования;
  • по полю документа.

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

Порядок обработки следующий:

  • процессор нормализации – этот процессор нормализует оценки документов в соответствии с настроенным методом нормализации;
  • процессор повторной оценки – после нормализации процессор повторной оценки дополнительно корректирует оценки документов. Эта корректировка может существенно повлиять на окончательный порядок результатов поиска.

Этот порядок обработки имеет следующие последствия:

  • изменение баллов – процессор повторной оценки изменяет баллы, которые изначально были скорректированы процессором нормализации, что может привести к другим результатам ранжирования, чем ожидалось изначально;
  • гибридные запросы – в контексте гибридных запросов, в которых объединяются несколько типов запросов и механизмов оценки, такое поведение особенно примечательно. Сначала комбинированные оценки из исходного запроса нормализуются, а затем ранжируются, что приводит к двухэтапной модификации оценки.

Querqy

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

Анализ поведения пользователей

User Behavior Insights (UBI) – Анализ поведения пользователей – это плагин, который фиксирует события и запросы на стороне клиента для повышения релевантности поиска и удобства пользователей. Это причинно-следственная система, которая связывает запрос пользователя со всеми его последующими взаимодействиями с приложением до тех пор, пока он не выполнит другой поиск.

UBI включает в себя следующие элементы:

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

Схемы индексов UBI

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

  • индекс запроса, в котором хранятся результаты поиска;
  • индекс событий, в котором хранятся все последующие действия пользователя после запроса.

Ключевые идентификаторы

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

  • object_id представляет собой идентификатор любого объекта, который пользователь получает в ответ на запрос;
  • query_id – это уникальный идентификатор для исходного языка запроса и значений object_id, возвращаемых запросом пользователя;
  • client_id представляет собой уникальный источник запросов; обычно это веб-браузер, используемый конкретным пользователем;
  • object_id_field указывает имя поля в индексе, которое содержит object_id;
  • action_name – хотя технически и не является идентификатором, указывает точное действие пользователя (например, click, add_to_cart, watch view, purchase или object_id), которое было предпринято (или не предпринято) для объекта с заданным object_id.

Подводя итог, можно сказать, что query_id сигнализирует о начале уникального поиска клиента, отслеживаемого с помощью client_id. Поиск возвращает различные объекты, каждый из которых имеет уникальный object_id. action_name указывает, какое действие выполняет пользователь, и связан с объектами, каждый из которых имеет определенный object_id. Типы объектов различают, просматривая object_id_field.

Как правило, можно получить представление об общей истории поиска пользователя, получив все данные для пользователя client_id и просмотрев отдельные данные query_id. Каждое приложение определяет, что представляет собой сеанс поиска, изучая внутренние данные.

Важные роли UBI

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

Синие стрелки обозначают стандартный поиск, жирные пунктирные линии обозначают дополнения, характерные для UBI, а красные стрелки обозначают передачу query_id в Подсистему и из Подсистемы.

Рисунок 56 — Процесс взаимодействия

Вот несколько ключевых моментов, касающихся ролей:

  • клиент поиска отвечает за поиск и последующее получение объектов из индекса документов (1, 2, 5 и 7 на предыдущей схеме);

Примечание – Шаг 5 выделен жирным шрифтом, потому что он обозначает дополнения, характерные для UBI, такие как query_id, к стандартным взаимодействиям Подсистемы.

  • если он активирован в ext.ubi-строке поискового запроса, плагин User Behavior Insights управляет хранилищем запросов UBI в фоновом режиме, индексируя каждый запрос, обеспечивая уникальность query_id для всех возвращаемых object_id значений, а затем передавая их query_id обратно поисковому клиенту, чтобы события могли быть связаны с запросом (3, 4 и 5 на предыдущей схеме);
  • объекты представляют собой элементы, которые пользователь ищет с помощью запросов. Для активации UBI необходимо сопоставить объекты реального мира (используя их идентификаторы, такие как isbn или sku) с полями object_id в индексируемом поиске;
  • клиент поиска, если он не является клиентом UBI, пересылает индексированные query_id-данные клиенту UBI. Несмотря на то, что на этой схеме роли поиска и индексирования событий UBI разделены, во многих реализациях можно использовать один и тот же экземпляр клиента Подсистемы для обеих ролей (6 на предыдущей схеме);
  • клиент UBI затем индексирует все пользовательские события с указанным query_id-значением до тех пор, пока не будет выполнен новый поиск. В это время новый query_id генерируется плагином User Behavior Insights и передается обратно клиенту UBI;
  • если клиент UBI взаимодействует с объектом результата, например, во время события "Добавить в корзину", то все object_id, add_to_cart action_name и query_id индексируются вместе, сигнализируя о причинно-следственной связи между поиском и объектом (8 и 9 на предыдущей диаграмме).

Хранилища UBI

Для поддержки сбора данных UBI используются два отдельных хранилища:

  • запросы UBI;
  • события UBI.

Индекс запросов UBI

Вся базовая информация о запросах и их результатах (object_ids) хранится в индексе ubi_queries и остается практически невидимой на заднем плане.

Индексная схема ubi_queries включает следующие поля:

  • timestamp (события и запросы) – временная метка UNIX, указывающая, когда был получен запрос;
  • query_id (события и запросы) – уникальный идентификатор запроса, предоставленный клиентом или сгенерированный автоматически. Разные запросы с одинаковым текстом генерируют разные query_id-значения;
  • client_id (события и запросы) – идентификатор пользователя/клиента, предоставляемый клиентским приложением;
  • query_response_objects_ids (запросы) – массив идентификаторов объектов. Идентификатор может иметь то же значение, что и _id, но он должен быть внешним идентификатором документа, элемента или продукта.

Поскольку UBI управляет индексом ubi_queries, нет необходимости писать напрямую в этот индекс (кроме случаев импорта данных).

Индекс событий UBI

Клиентская сторона напрямую индексирует события в индексе ubi_events, связывая событие action_name, объекты (каждый с object_id), запросы (каждый с query_id), а также любую другую важную информацию о событии. Поскольку эта схема является динамической, можно добавлять любые новые поля или структуры (например, информацию о пользователе или геолокации), которых нет в текущей схеме событий UBI на момент индексации.

Ниже приведены предопределенные минимальные поля в индексе ubi_events:

  • application (размер 100) – название приложения, отслеживающего события UBI (например, amazon-shop или ABC-microservice);
  • action_name (размер 100) – название действия, вызвавшего событие. В спецификации UBI определены некоторые распространенные названия действий, но можно использовать любое название;
  • query_id (размер 100) – уникальный идентификатор запроса, который обычно представляет собой UUID, но может быть любой строкой. Значение query_id либо предоставляется клиентом, либо генерируется во время индексирования плагином UBI. Значения query_id в индексах запросов UBI и событий UBI должны быть согласованными;
  • client_id – клиент, который выполняет запрос. Обычно это веб-браузер, используемый уникальным пользователем. Индексы client_id в запросах UBI и событиях UBI должны быть согласованными;
  • timestamp – время события либо в формате UNIX, либо в формате "2018-11-13T20:20:39+00:00";
  • message_type (размер 100) – логическая ячейка для группировки действий (каждое с action_name). Например, QUERY или CONVERSION;
  • message (размер 1024) – необязательное текстовое сообщение для записи в журнале. Например, для message_type "QUERY message" может содержать текст, связанный с поиском пользователя;
  • event_attributes – расширяемая структура, описывающая важный контекст события. Эта структура состоит из двух основных структур – position и object. Структура является расширяемой, поэтому можно добавлять пользовательскую информацию о событии, например о времени события, пользователе или сеансе.
  • event_attributes.position – структура, содержащая информацию о местоположении источника события, например, координаты x, y на экране или положение объекта в списке результатов:
    • event_attributes.position.ordinal – отслеживает позицию в списке, которую может выбрать пользователь (например, выбор третьего элемента можно описать как event{onClick, results4});
    • event_attributes.position.{x,y} – отслеживает значения x и y, определенные клиентом;
    • event_attributes.position.page_depth – отслеживает глубину результатов на странице;
    • event_attributes.position.scroll_depth – отслеживает глубину прокрутки результатов страницы;
    • event_attributes.position.trail – текстовое поле, отслеживающее путь/маршрут, по которому пользователь добрался до этого места.
  • event_attributes.object – содержит идентифицирующую информацию об объекте, возвращаемом запросом. Структура object может ссылаться на объект по внутреннему идентификатору или идентификатору объекта. object_id — это идентификатор, который связывает предыдущие запросы с этим объектом. Это поле состоит из следующих подразделов:
    • event_attributes.object.internal_id – уникальный идентификатор, который Подсистема может использовать для внутреннего индексирования объекта, например, поле _id в индексах;
    • event_attributes.object.object_id – идентификатор, по которому пользователь может найти экземпляр объекта в теле документов. Для инициализации UBI необходимо сопоставить первичный ключ индекса документа с этим object_id;
    • event_attributes.object.object_id_field – указывает тип/класс объекта и имя поля поискового индекса, содержащего object_id;
    • event_attributes.object.description – необязательное описание объекта;
    • event_attributes.object.object_detail – необязательная дополнительная информация об объекте;
    • расширяемые поля – следует учитывать, что любые новые индексируемые поля в object будут динамически расширять эту схему.

Поисковые конвейеры

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

Терминология

Ниже приведен список терминов поискового конвейера:

  • Обработчик поисковых запросов – компонент, который перехватывает поисковый запрос (запрос и передаваемые в запросе метаданные), выполняет операцию с поисковым запросом или над поисковым запросом и возвращает поисковый запрос;
  • Обработчик ответа на поиск – компонент, который перехватывает поисковый запрос и поисковый ответ (запрос, результаты и метаданные, переданные в запросе), выполняет операцию с поисковым ответом или над ним и возвращает поисковый ответ;
  • Обработчик результатов этапа поиска – компонент, который работает между этапами поиска на уровне координирующего узла. Обработчик результатов этапа поиска перехватывает результаты, полученные на одном этапе поиска, и преобразует их перед передачей на следующий этап поиска;
  • Процессор – либо процессор запросов на поиск, либо процессор ответов на поиск;
  • Поисковый конвейер – упорядоченный список обработчиков, интегрированных в Подсистеме. Конвейер перехватывает запрос, обрабатывает его, отправляет в Подсистему, перехватывает результаты, обрабатывает их и возвращает вызывающему приложению, как показано на рисунке 57.

Рисунок 57 — Поисковый конвейер

Примечание – Обработка запросов и ответов для конвейера выполняется на узле-координаторе, поэтому обработка на уровне сегментов не выполняется.

Создание поискового конвейера

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

Использование поискового конвейера

Поисковый конвейер можно использовать следующими способами:

  • указать существующий конвейер для запроса;
  • использовать временный конвейер для запроса;
  • установить конвейер по умолчанию для всех запросов в индексе.

Отладка поискового конвейера

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

Чтобы включить отладку конвейера, нужно указать verbose_pipeline=true в качестве параметра запроса в поисковом запросе. Эта функция доступна для всех трех методов поиска:

  • поисковый конвейер по умолчанию;
  • конкретный поисковый конвейер;
  • временный поисковый конвейер.

Извлечение поисковых конвейеров

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

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

GET /_search/pipeline

Удаление конвейеров поиска

Чтобы удалить определенный конвейер поиска, нужно передать идентификатор конвейера в качестве параметра:

DELETE /_search/pipeline/<pipeline-id>

Чтобы удалить все поисковые конвейеры в кластере, используют символ подстановки "*":

DELETE /_search/pipeline/*

Поисковые процессоры

Поисковые процессоры могут быть следующих типов:

  • процессоры поисковых запросов;
  • процессоры ответов на поисковые запросы;
  • процессоры обработки результатов этапа поиска.

Процессоры поисковых запросов

Процессор поисковых запросов перехватывает поисковый запрос (запрос и передаваемые в нем метаданные), выполняет операцию с поисковым запросом или над ним и отправляет поисковый запрос в индекс.

В таблице 117 перечислены все поддерживаемые процессоры поисковых запросов.

Процессоры ответов на поисковые запросы

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

В таблице 118 перечислены все поддерживаемые процессоры поиска ответов.

Поиск показателей конвейера

Чтобы просмотреть показатели конвейера поиска, используют Nodes Stats API:

GET /_nodes/stats/search_pipeline

Повышение эффективности поиска

Подсистема предлагает несколько способов повысить производительность поиска:

  • выполнение ресурсоемких запросов асинхронно с помощью асинхронного поиска;
  • одновременный поиск сегментов с помощью параллельного поиска по сегментам;
  • повышение производительности агрегаций, используя индекс star-tree.

SQL и PPL

Подсистема позволяет писать запросы на SQL, а не только на DSL.

Автоматизация конфигураций

Обзор

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

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

Автоматизация рабочего процесса обеспечивает следующие преимущества:

  • Шаблоны вариантов использования – начало работы с готовыми шаблонами, которые описывают процесс настройки для общих вариантов использования;
  • Настраиваемые рабочие процессы – настройка шаблонов рабочих процессов в соответствии с конкретным вариантом использования;
  • Настройка автоматизации – простая настройка ИИ-коннекторов, инструментов, агентов и других компонентов с помощью одного вызова API.

Шаблоны реализуют автоматизацию рабочих процессов в Подсистеме в формате JSON или YAML. Можно описать один или несколько шаблонов с последовательностью шагов, необходимых для конкретного сценария использования. Каждый шаблон состоит из следующих элементов:

  • Метаданные – название, описание, категория использования, версия шаблона и диапазон совместимости с версией Подсистемы;
  • Ввод данных пользователем – параметры, которые пользователь должен ввести и которые являются общими для всех этапов автоматизации во всех рабочих процессах, например, название индекса;
  • Рабочие процессы – один или несколько рабочих процессов, содержащих следующие элементы:
    • Ввод данных пользователем – ожидаемые от пользователя параметры, характерные для этапов этого рабочего процесса;
    • Этапы рабочего процесса – этапы рабочего процесса, описанные в виде ориентированного ациклического графа (DAG):
    • Узлы описывают этапы процесса, которые могут выполняться параллельно;
    • Графы последовательности узлов, которые должны быть выполнены после завершения предыдущего шага, могут использовать выходные поля предыдущих шагов. Если узел содержит ключ в previous_node_input-карте, относящийся к предыдущему шагу рабочего процесса, соответствующий граф автоматически добавляется в шаблон во время синтаксического анализа и может быть опущено для простоты.

Этапы рабочего процесса

Этапы рабочего процесса образуют базовые "строительные блоки" для автоматизации процессов. Большинство этапов напрямую соответствуют операциям Подсистемы или API-плагинов, таким как операции CRUD для ML, моделей и агентов. Некоторые этапы упрощают настройку за счет повторного использования тела запроса, ожидаемого этими API, на нескольких этапах. Например, после настройки инструмента можно использовать его с несколькими агентами.

Поля шагов рабочего процесса

Этапы рабочего процесса активно используются для расширения возможностей автоматизации. Конфигурация этапа рабочего процесса (узла графа) включает поля из таблицы 119.

Типы этапов рабочего процесса

В таблице 120 перечислены типы шагов рабочего процесса. Поля user_inputs для этих шагов напрямую связаны с соответствующими API.

Рекомендации по переиндексации

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

При использовании шага reindex необходимо следовать этим рекомендациям, чтобы обеспечить бесперебойный процесс переиндексации и предотвратить нестабильность кластера:

  • Масштабирование кластера – перед началом операции переиндексации следует убедиться, что кластер правильно масштабирован для обработки дополнительной рабочей нагрузки. Следует увеличить количество узлов и при необходимости скорректировать распределение ресурсов (ЦП, памяти и диска), чтобы процесс переиндексации не влиял на другие операции.
  • Управление скоростью запросов – используют параметр requests_per_second для управления скоростью, с которой запросы на переиндексацию отправляются в кластер. Это помогает регулировать нагрузку на кластер и предотвращать исчерпание ресурсов. Следует начать с более низкого значения и постепенно увеличивать его в зависимости от возможностей и производительности его кластера.
  • Разделение на сегменты и распараллеливание – параметр slices позволяет разделить процесс переиндексации на более мелкие параллельные задачи. Это может помочь распределить рабочую нагрузку между несколькими узлами и повысить общую производительность. Однако следует быть внимательными при увеличении количества сегментов, поскольку добавление сегментов может увеличить потребление ресурсов.
  • Мониторинг и настройка – следует внимательно отслеживать показатели производительности кластера (такими как загрузка ЦП, памяти, диска и пулов потоков) во время процесса переиндексации. Если появятся какие-либо признаки нехватки ресурсов или снижения производительности, необходимо соответствующим образом настроить параметры переиндексации или приостановить работу до стабилизации кластера.
  • Расстановка приоритетов и планирование – по возможности рекомендуется планировать операции переиндексации на непиковые часы или периоды низкой загруженности кластера, чтобы минимизировать влияние на другие операции и пользовательский трафик.

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

Дополнительные поля

Можно включить следующие дополнительные поля в поле user_inputs при условии, что поле поддерживается указанным типом шага (таблица 121).

При необходимости можно включить следующие дополнительные поля в поле previous_node_inputs (таблица 122).

Организация рабочего процесса

Можно автоматизировать настройку распространенных сценариев использования, таких как диалоговый чат, с помощью агента Chain-of-Thought (CoT). Агент управляет моделями и инструментами машинного обучения и запускает их. Инструмент выполняет набор конкретных задач. На этой странице представлен полный пример настройки агента CoT.

Для настройки требуется следующая последовательность запросов API с использованием подготовленных ресурсов в последующих запросах (названия шагов соответствуют названиям в шаблоне):

  1. Развертывание модели в кластере:
  • create_connector_1 – создать коннектор с моделью, размещенной на внешнем сервере;
  • register_model_2 – зарегистрировать модель с помощью созданного коннектора;
  • deploy_model_3 – развернуть модель;
  1. Использование развернутой модель для вывода:
  • настроить несколько инструментов, выполняющих определенные задачи:
  • cat_index_tool – настроить инструмент для получения индексной информации;
  • ml_model_tool – настроить инструмент моделирования машинного обучения (ML);
  • настроить один или несколько агентов, которые используют определенную комбинацию инструментов:
  • sub_agent – создать агента, который использует cat_index_tool;
  • настроить инструменты, представляющие эти агенты:
  • agent_tool – настроить sub_agent так, чтобы могли использовать его как инструмент;
  • root_agent – настроить корневой агент, который может делегировать задачу инструменту или другому агенту.

График рабочего процесса

Рабочий процесс, описанный в предыдущем разделе, организован в виде шаблона. Следует обратить внимание, что шаги можно упорядочивать несколькими способами. В примере шаблона шаг ml_model_tool указан непосредственно перед шагом root_agent, но можно указать его в любой момент после шага deploy_model_3 и перед шагом root_agent. На следующей схеме (рисунок 58) показан ориентированный ациклический граф (DAG), который Подсистема создает для всех шагов в порядке, указанном в шаблоне.

Рисунок 58 — DAG

Полный шаблон рабочего процесса YAML

Ниже представлен полный шаблон, включающий все этапы рабочего процесса provision в формате YAML:

This template demonstrates provisioning the resources for a
Chain-of-Thought chat bot
name: tool-register-agent
description: test case
use_case: REGISTER_AGENT
version:
template: 1.0.0
compatibility:
 2.12.0
 3.0.0
workflows:
This workflow defines the actions to be taken when the Provision Workflow API is used
provision:
nodes:
The first three nodes create a connector to a remote model, registers and deploy that model
 id: create_connector_1
type: create_connector
user_inputs:
name: OpenAI Chat Connector
description: The connector to public OpenAI model service for GPT 3.5
version: '1'
protocol: http
parameters:
endpoint: api.openai.com
model: gpt-3.5-turbo
credential:
openAI_key: '12345'
actions:
 action_type: predict
method: POST
url: https://${parameters.endpoint}/v1/chat/completions
 id: register_model_2
type: register_remote_model
previous_node_inputs:
create_connector_1: connector_id
user_inputs:
deploy: true could be added here instead of the deploy step below
name: openAI-gpt-3.5-turbo
description: test model
 id: deploy_model_3
type: deploy_model
previous_node_inputs:
register_model_2: model_id
For example purposes, the model_id obtained as the output of the deploy_model_3 step will be used
for several below steps.  However, any other deployed model_id can be used for those steps.
This is one example tool from the Agent Framework.
 id: cat_index_tool
type: create_tool
user_inputs:
name: CatIndexTool
type: CatIndexTool
parameters:
max_iteration: 5
This simple agent only has one tool, but could be configured with many tools
 id: sub_agent
type: register_agent
previous_node_inputs:
deploy-model-3: model_id
cat_index_tool: tools
user_inputs:
name: Sub Agent
type: conversational
parameters:
hello: world
llm.parameters:
max_iteration: '5'
stop_when_no_tool_found: 'true'
memory:
type: conversation_index
app_type: chatbot
An agent can be used itself as a tool in a nested relationship
 id: agent_tool
type: create_tool
previous_node_inputs:
sub_agent: agent_id
user_inputs:
name: AgentTool
type: AgentTool
parameters:
max_iteration: 5
An ML Model can be used as a tool
 id: ml_model_tool
type: create_tool
previous_node_inputs:
deploy-model-3: model_id
user_inputs:
name: MLModelTool
type: MLModelTool
alias: language_model_tool
parameters:
prompt: Answer the question as best you can.
response_filter: choices[0].message.content
This final agent will be the interface for the CoT chat user
Using a flow agent type tools_order matters
 id: root_agent
type: register_agent
previous_node_inputs:
deploy-model-3: model_id
ml_model_tool: tools
agent_tool: tools
user_inputs:
name: DEMO-Test_Agent
type: flow
parameters:
prompt: Answer the question as best you can.
llm.parameters:
max_iteration: '5'
stop_when_no_tool_found: 'true'
tools_order: ['agent_tool', 'ml_model_tool']
memory:
type: conversation_index
app_type: chatbot
These edges are all automatically created with previous_node_input
edges:
 source: create_connector_1
dest: register_model_2
 source: register_model_2
dest: deploy_model_3
 source: cat_index_tool
dest: sub_agent
 source: deploy_model_3
dest: sub_agent
 source: sub_agent
dest: agent_tool
 source: deploy-model-3
dest: ml_model_tool
 source: deploy-model-3
dest: root_agent
 source: ml_model_tool
dest: root_agent
 source: agent_tool
dest: root_agent

Полный шаблон рабочего процесса JSON

Ниже приведен тот же шаблон в формате JSON:

{
"name": "tool-register-agent",
"description": "test case",
"use_case": "REGISTER_AGENT",
"version": {
"template": "1.0.0",
"compatibility": [
"2.12.0",
"3.0.0"
]
},
"workflows": {
"provision": {
"nodes": [
{
"id": "create_connector_1",
"type": "create_connector",
"user_inputs": {
"name": "OpenAI Chat Connector",
"description": "The connector to public OpenAI model service for GPT 3.5",
"version": "1",
"protocol": "http",
"parameters": {
"endpoint": "api.openai.com",
"model": "gpt-3.5-turbo"
},
"credential": {
"openAI_key": "12345"
},
"actions": [
{
"action_type": "predict",
"method": "POST",
"url": "https://${parameters.endpoint}/v1/chat/completions"
}
]
}
},
{
"id": "register_model_2",
"type": "register_remote_model",
"previous_node_inputs": {
"create_connector_1": "connector_id"
},
"user_inputs": {
"name": "openAI-gpt-3.5-turbo",
"description": "test model"
}
},
{
"id": "deploy_model_3",
"type": "deploy_model",
"previous_node_inputs": {
"register_model_2": "model_id"
}
},
{
"id": "cat_index_tool",
"type": "create_tool",
"user_inputs": {
"name": "CatIndexTool",
"type": "CatIndexTool",
"parameters": {
"max_iteration": 5
}
}
},
{
"id": "sub_agent",
"type": "register_agent",
"previous_node_inputs": {
"deploy-model-3": "llm.model_id",
"cat_index_tool": "tools"
},
"user_inputs": {
"name": "Sub Agent",
"type": "conversational",
"parameters": {
"hello": "world"
},
"llm.parameters": {
"max_iteration": "5",
"stop_when_no_tool_found": "true"
},
"memory": {
"type": "conversation_index"
},
"app_type": "chatbot"
}
},
{
"id": "agent_tool",
"type": "create_tool",
"previous_node_inputs": {
"sub_agent": "agent_id"
},
"user_inputs": {
"name": "AgentTool",
"type": "AgentTool",
"parameters": {
"max_iteration": 5
}
}
},
{
"id": "ml_model_tool",
"type": "create_tool",
"previous_node_inputs": {
"deploy-model-3": "model_id"
},
"user_inputs": {
"name": "MLModelTool",
"type": "MLModelTool",
"alias": "language_model_tool",
"parameters": {
"prompt": "Answer the question as best you can.",
"response_filter": "choices[0].message.content"
}
}
},
{
"id": "root_agent",
"type": "register_agent",
"previous_node_inputs": {
"deploy-model-3": "llm.model_id",
"ml_model_tool": "tools",
"agent_tool": "tools"
},
"user_inputs": {
"name": "DEMO-Test_Agent",
"type": "flow",
"parameters": {
"prompt": "Answer the question as best you can."
},
"llm.parameters": {
"max_iteration": "5",
"stop_when_no_tool_found": "true"
},
"tools_order": [
"agent_tool",
"ml_model_tool"
],
"memory": {
"type": "conversation_index"
},
"app_type": "chatbot"
}
}
],
"edges": [
{
"source": "create_connector_1",
"dest": "register_model_2"
},
{
"source": "register_model_2",
"dest": "deploy_model_3"
},
{
"source": "cat_index_tool",
"dest": "sub_agent"
},
{
"source": "deploy_model_3",
"dest": "sub_agent"
},
{
"source": "sub_agent",
"dest": "agent_tool"
},
{
"source": "deploy-model-3",
"dest": "ml_model_tool"
},
{
"source": "deploy-model-3",
"dest": "root_agent"
},
{
"source": "ml_model_tool",
"dest": "root_agent"
},
{
"source": "agent_tool",
"dest": "root_agent"
}
]
}
}
}

Шаблоны рабочего процесса

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

Можно указать шаблон рабочего процесса при вызове Create Workflow API:

  • чтобы использовать шаблон рабочего процесса, предоставляемый Подсистемой, указать вариант использования шаблона в качестве параметра запроса use_case;
  • чтобы использовать пользовательский шаблон рабочего процесса, указать полный шаблон в теле запроса.

Чтобы подготовить рабочий процесс, следует указать provision=true в качестве параметра запроса.

Параметры

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

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

POST /_plugins/_flow_framework/workflow?use_case=semantic_search_with_cohere_embedding
{
"create_connector.model" : "embed-multilingual-v3.0",
"text_embedding.field_map.output": "book_embedding",
"create_index.name": "sparse-book-index"
}

Просмотр ресурсов рабочего процесса

Созданный рабочий процесс подготавливает все необходимые ресурсы для семантического поиска. Чтобы просмотреть подготовленные ресурсы, вызывают Get Workflow Status API и указывают workflowID для его рабочего процесса:

GET /_plugins/_flow_framework/workflow/8xL8bowB8y25Tqfenm50/_status

Поддерживаемые шаблоны рабочего процесса

В таблице 123 перечислены поддерживаемые шаблоны рабочих процессов. Чтобы использовать шаблон рабочего процесса, нужно указать его в параметре запроса use_case при создании рабочего процесса.

Настройки рабочего процесса

Следующие ключи (таблица 124) представляют собой настраиваемые параметры рабочего процесса.

API-интерфейсы рабочих процессов

Подсистема поддерживает следующие API рабочих процессов:

  • создание или обновление;
  • получение шаблона;
  • подготовка;
  • получение статуса;
  • получение шагов;
  • поиск;
  • поиск состояния;
  • отмена настройки;
  • удаление.