Поделиться через


Как сформировать результаты в поиске ИИ Azure

В этой статье объясняется, как работать с ответом на запрос в службе "Поиск ИИ Azure". Структура ответа определяется параметрами в самом запросе, как описано в разделе "Документы поиска" (REST) или класс SearchResults (Azure для .NET).

Параметры запроса определяют:

  • Выбор поля
  • Количество совпадений, найденных в индексе для запроса
  • Разбиение на страницы
  • Число результатов ответа (до 50, по умолчанию)
  • Порядок сортировки
  • Выделение терминов в результатах, сопоставление по всему или частичному термину в тексте

Композиция результатов

Результаты являются табличными, состоящими из полей всех "извлекаемых" полей или ограничены только этими полями, указанными $select в параметрах. Строки — это соответствующие документы.

Вы можете выбрать, какие поля находятся в результатах поиска. Хотя в документе поиска может быть большое количество полей, обычно требуется лишь несколько, чтобы представить каждый документ в результатах. В запросе добавьте $select=<field list> , чтобы указать, какие поля должны отображаться в ответе.

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

POST /indexes/hotels-sample-index/docs/search?api-version=2023-11-01 
    {  
      "search": "sandy beaches",
      "select": "HotelId, HotelName, Description, Rating, Address/City"
      "count": true
    }

Советы по непредвиденным результатам

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

  • Измените searchMode=any (по умолчанию) на searchMode=all, чтобы потребовать соответствие всем указанным условиям, а не любому из них. Это особенно важно, если запрос содержит логические операторы.

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

Подсчет совпадений

Параметр count возвращает количество документов в индексе, которые считаются совпадением для запроса. Чтобы вернуть количество, добавьте $count=true в запрос запроса. Нет максимального значения, введенного службой поиска. В зависимости от запроса и содержимого документов число может быть максимально высоким, чем каждый документ в индексе.

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

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

Совет

Чтобы проверить операции индексирования, можно проверить, содержит ли индекс ожидаемое количество документов, добавив $count=true в пустой search=* поисковый запрос. Результатом является полное количество документов в индексе.

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

Разбиение результатов по страницам

По умолчанию поисковая система возвращает до первых 50 совпадений. Первые 50 определяются оценкой поиска, предполагая, что запрос является полным текстовым поиском или семантикой. В противном случае верхний 50 является произвольным порядком для точных запросов соответствия (где универсальное значение "@searchScore=1.0" указывает произвольный рейтинг).

Верхний предел составляет 1000 документов, возвращаемых на страницу результатов поиска, поэтому вы можете настроить начало до 1000 документов в первом результате. Если вы используете гибридный запрос, вы можете указать maxTextRecallSize для возврата до 10 000 документов.

Чтобы управлять разбиением всех документов, возвращаемых в результирующем наборе, добавьте $top и $skip параметры в запрос GET запроса ИЛИ в запрос topskip POST. Логика этих шагов объясняется в списке ниже.

  • Вернуть первый набор из 15 соответствующих документов, а также общее число совпадений: GET /indexes/<INDEX-NAME>/docs?search=<QUERY STRING>&$top=15&$skip=0&$count=true

  • Вернуть второй набор, пропустив первые 15, чтобы получить следующие 15: $top=15&$skip=15. Повторите для третьего набора 15: $top=15&$skip=30

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

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

{ "id": "1", "rating": 5 }
{ "id": "2", "rating": 3 }
{ "id": "3", "rating": 2 }
{ "id": "4", "rating": 1 }

Теперь предположим, что вы хотите, чтобы результаты возвращались по два за раз, упорядоченные по рейтингу. Вы сделаете этот запрос для получения первой страницы: $top=2&$skip=0&$orderby=rating desc, что выдаст следующие результаты.

{ "id": "1", "rating": 5 }
{ "id": "2", "rating": 3 }

Предположим, что во время работ по обслуживанию в индекс между запросами добавляется пятый документ: { "id": "5", "rating": 4 }. Вскоре после этого вы выполните запрос для получения второй страницы: $top=2&$skip=2&$orderby=rating desc и получите следующие результаты.

{ "id": "2", "rating": 3 }
{ "id": "3", "rating": 2 }

Обратите внимание, что документ 2 извлекается дважды. Это связано с тем, что новый документ 5 имеет большее значение рейтинга, поэтому он при сортировке попадает в индекс раньше документа 2 и появляется на первой странице. Хотя такое поведение может быть неожиданным, обычно оно характерно для поисковой системы.

Разбиение по страницам с большим количеством результатов

Использование $top и $skip разрешение поискового запроса на страницу до 100 000 результатов, но что делать, если результаты больше 100 000? Чтобы выполнить страницу в ответе, используйте порядок сортировки и фильтр диапазона в $skipкачестве обходного решения.

В этом обходном пути сортировка и фильтрация применяются к полю идентификатора документа или другому полю, уникальному для каждого документа. Уникальное поле должно иметь filterable и sortable указывать в индексе поиска.

  1. Выполните запрос, чтобы вернуть полную страницу отсортированных результатов.

    POST /indexes/good-books/docs/search?api-version=2023-11-01
        {  
          "search": "divine secrets",
          "top": 50,
          "orderby": "id asc"
        }
    
  2. Выберите последний результат, возвращенный поисковым запросом. Ниже показан пример результата только значения "id".

    {
        "id": "50"
    }
    
  3. Используйте это значение "id" в запросе диапазона, чтобы получить следующую страницу результатов. Это поле "id" должно иметь уникальные значения, в противном случае разбивка на страницы может содержать повторяющиеся результаты.

    POST /indexes/good-books/docs/search?api-version=2023-11-01
        {  
          "search": "divine secrets",
          "top": 50,
          "orderby": "id asc",
          "filter": "id ge 50"
        }
    
  4. Разбиение на страницы заканчивается, когда запрос возвращает нулевых результатов.

Примечание.

Атрибуты "фильтруемых" и "сортируемых" могут быть включены только при первом добавлении поля в индекс, они не могут быть включены в существующем поле.

Упорядочение результатов

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

  • оценка поиска
  • оценка семантического повтора
  • порядок сортировки в поле "сортируемый"

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

Порядок по оценке поиска

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

Диапазон "@search.score" либо несвязан, либо от 0 до (но не включая) 1,00 на старых службах.

Для любого алгоритма значение "@search.score", равное 1.00, указывает на некорпорированную или неуправляемую результирующий набор, где оценка 1.0 является единообразной для всех результатов. Неподписанные результаты возникают, когда форма запроса является нечетким поиском, подстановочными знаками или регулярными запросами или пустым поиском (search=*). Если необходимо наложить структуру ранжирования на некорпорированные результаты, рассмотрите $orderby выражение для достижения этой цели.

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

Если вы используете семантический рейтинг, функция "@search.rerankerScore" определяет порядок сортировки результатов.

Диапазон "@search.rerankerScore" составляет от 1 до 4,00, где более высокая оценка указывает на более сильное семантический совпадение.

Заказ с помощью $orderby

Если согласованное упорядочение является требованием приложения, можно определить $orderby выражение в поле. Для упорядочивания результатов можно использовать только поля, индексированные как "сортируемые".

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

Числовые поля (Edm.Double, Edm.Int32, Edm.Int64) сортируются в числовом порядке (например, 1, 2, 10, 11, 20).

Строковые поля (подфилды Edm.String, Edm.ComplexType) сортируются в порядке сортировки ASCII или порядке сортировки Юникода в зависимости от языка. Вы не можете сортировать коллекции любого типа.

  • Числовое содержимое в строковых полях отсортировано по алфавиту (1, 10, 11, 2, 20).

  • Верхний регистр строки сортируются впереди нижнего регистра (APPLE, Apple, БАНАН, Банан, яблоко, банан). Вы можете назначить нормализатор текста для предварительной обработки текста перед сортировкой, чтобы изменить это поведение. Использование нижнего регистра токенизатора в поле не влияет на поведение сортировки, так как поиск Azure AI сортируется по неанализируемой копии поля.

  • Строки, которые приводят с diacritics, появляются последние (Äpfel, Öffnen, Üben)

Повышение релевантности с помощью профиля оценки

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

Выделение совпадений

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

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

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

Требования к выделению попаданий

  • Поля должны быть Edm.String или Collection(Edm.String)
  • Поля должны быть атрибутами при поиске

Указание выделения в запросе

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

По умолчанию разметка формата имеет значение <em>, но вы можете переопределить тег с помощью highlightPreTag и highlightPostTag параметрами. Клиентский код обрабатывает ответ (например, применение полужирного шрифта или желтого фона).

POST /indexes/good-books/docs/search?api-version=2023-11-01
    {  
      "search": "divine secrets",  
      "highlight": "title, original_title",
      "highlightPreTag": "<b>",
      "highlightPostTag": "</b>"
    }

По умолчанию поиск ИИ Azure возвращает до пяти выделений на поле. Это число можно изменить, добавив тире, за которым следует целое число. Например, "highlight": "description-10" возвращает до 10 выделенных терминов для сопоставления содержимого в поле описания.

Выделенные результаты

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

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

Снимок экрана: выделение запроса фразы.

Выделение поиска ключевых слов

В выделенном поле форматирование применяется ко всем терминам. Например, на совпадении с "Божественной тайнами я-я сестры", форматирование применяется к каждому термину отдельно, даже если они последовательны.

"@odata.count": 39,
"value": [
    {
        "@search.score": 19.593246,
        "@search.highlights": {
            "original_title": [
                "<em>Divine</em> <em>Secrets</em> of the Ya-Ya Sisterhood"
            ],
            "title": [
                "<em>Divine</em> <em>Secrets</em> of the Ya-Ya Sisterhood"
            ]
        },
        "original_title": "Divine Secrets of the Ya-Ya Sisterhood",
        "title": "Divine Secrets of the Ya-Ya Sisterhood"
    },
    {
        "@search.score": 12.779835,
        "@search.highlights": {
            "original_title": [
                "<em>Divine</em> Madness"
            ],
            "title": [
                "<em>Divine</em> Madness (Cherub, #5)"
            ]
        },
        "original_title": "Divine Madness",
        "title": "Divine Madness (Cherub, #5)"
    },
    {
        "@search.score": 12.62534,
        "@search.highlights": {
            "original_title": [
                "Grave <em>Secrets</em>"
            ],
            "title": [
                "Grave <em>Secrets</em> (Temperance Brennan, #5)"
            ]
        },
        "original_title": "Grave Secrets",
        "title": "Grave Secrets (Temperance Brennan, #5)"
    }
]

Выделение поиска фраз

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

POST /indexes/good-books/docs/search?api-version=2023-11-01 
    {  
      "search": "\"divine secrets\"",
      "select": "title,original_title",
      "highlight": "title",
      "highlightPreTag": "<b>",
      "highlightPostTag": "</b>",
      "count": true
    }

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

{
    "@odata.count": 1,
    "value": [
        {
            "@search.score": 19.593246,
            "@search.highlights": {
                "title": [
                    "<b>Divine</b> <b>Secrets</b> of the Ya-Ya Sisterhood"
                ]
            },
            "original_title": "Divine Secrets of the Ya-Ya Sisterhood",
            "title": "Divine Secrets of the Ya-Ya Sisterhood"
        }
    ]
}

Выделение фраз в старых службах

служба , созданные до 15 июля 2020 г., реализуют другой интерфейс выделения для запросов фраз.

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

"@search.highlights": {
    "sentence": [
        "The <em>super</em> <em>bowl</em> is <em>super</em> awesome with a <em>bowl</em> of chips"
   ]

Для служб поиска, созданных после июля 2020 г., будут возвращены только фразы, соответствующие полному запросу фраз, в разделе "@search.highlights":

"@search.highlights": {
    "sentence": [
        "The <em>super</em> <em>bowl</em> is super awesome with a bowl of chips"
   ]

Следующие шаги

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