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


Индексирование BLOB-объектов Markdown и файлов в поиске искусственного интеллекта Azure

Примечание.

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

В службе поиска ИИ Azure индексаторы для Хранилище BLOB-объектов Azure, Файлы Azure и OneLake поддерживают markdown режим синтаксического анализа для файлов Markdown. Файлы Markdown можно индексировать двумя способами:

  • Режим разбора «один ко многим», создание нескольких документов поиска для каждого файла Markdown
  • Режим синтаксического анализа один к одному, создание одного документа поиска на файл Markdown

Совет

Перейдите к руководству: Поиск данных Markdown из хранилища BLOB Azure после просмотра этой статьи.

Предпосылки

  • Поддерживаемый источник данных: хранилище BLOB-объектов Azure, хранилище файлов Azure, OneLake в Microsoft Fabric.

    Для OneLake убедитесь, что выполнены все требования индексатора OneLake.

    Служба хранилища Azure для индексаторов BLOB-объектов и индексаторов файлов — это стандартный экземпляр с высокой производительностью (версия 2 общего назначения), поддерживающий уровни горячего и холодного доступа.

Параметры режима синтаксического анализа Markdown

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

POST https://[service name].search.windows.net/indexers?api-version=2025-05-01-preview
Content-Type: application/json
api-key: [admin key]

{
  "name": "my-markdown-indexer",
  "dataSourceName": "my-blob-datasource",
  "targetIndexName": "my-target-index",
  "parameters": {
    "configuration": {
      "parsingMode": "markdown",
      "markdownParsingSubmode": "oneToMany",
      "markdownHeaderDepth": "h6"
    }
  },
}

Индексатор BLOB-объектов предоставляет submode параметр для определения структуры выходных данных документов поиска. Режим синтаксического анализа Markdown предоставляет следующие параметры подрежимов:

parsingMode подрежим Поиск документа Описание
markdown oneToMany Несколько на блок данных (по умолчанию) Разбивает Markdown на несколько документов поиска, каждый из которых представляет собой секцию содержимого (не заголовочную) файла Markdown. Вы можете опустить подмод, если только не хотите выполнять синтаксический анализ по одному.
markdown oneToOne Один на один блоб Анализирует Markdown в один документ поиска с разделами, сопоставленными с определенными заголовками в файле Markdown.

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

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

Необязательные параметры синтаксического анализа Markdown

Параметры зависят от регистра.

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

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

Поддерживаемые элементы Markdown

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

Пример содержимого Markdown

Для примеров на этой странице используется следующее содержимое Markdown:

# Section 1
Content for section 1.

## Subsection 1.1
Content for subsection 1.1.

# Section 2
Content for section 2.

Используйте режим синтаксического анализа "один ко многим"

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

  • content: строка, содержащая необработанный Markdown, найденный в определённой части на основе метаданных заголовка на этом этапе документа.

  • sections: объект, содержащий подфилды для метаданных заголовка до требуемого уровня заголовка. Например, если markdownHeaderDepth задано значение h3, содержит строковые поля h1и h2h3. Эти поля индексируются путем зеркального отображения этой структуры в индексе или сопоставления полей в формате /sections/h1, sections/h2 и т. д. Сведения о конфигурациях индекса и индексатора показаны в следующих примерах. Содержимые подполе:

    • h1 — Строка, содержащая значение заголовка h1. Пустая строка, если она не задана в данный момент в документе.
    • (Необязательно) h2— Строка, содержащая значение заголовка h2. Пустая строка, если она не задана в данный момент в документе.
    • (Необязательно) h3— Строка, содержащая значение заголовка h3. Пустая строка, если она не задана в данный момент в документе.
    • (Необязательно) h4— Строка, содержащая значение заголовка h4. Пустая строка, если она не задана в данный момент в документе.
    • (Необязательно) h5— Строка, содержащая значение заголовка h5. Пустая строка, если она не задана в данный момент в документе.
    • (Необязательно) h6— Строка, содержащая значение заголовка h6. Пустая строка, если она не задана в данный момент в документе.
  • ordinal_position: целочисленное значение, указывающее положение раздела в иерархии документов. Это поле используется для упорядочивания разделов в первоначальной последовательности, как они отображаются в документе, начиная с позиции 1 и увеличиваясь последовательно для каждого заголовка.

Схема индекса для парсинга "один ко многим"

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

{
  "name": "my-markdown-index",
  "fields": [
  {
    "name": "id",
    "type": "Edm.String",
    "key": true
  },
  {
    "name": "content",
    "type": "Edm.String",
  },
  {
    "name": "ordinal_position",
    "type": "Edm.Int32"
  },
  {
    "name": "sections",
    "type": "Edm.ComplexType",
    "fields": [
    {
      "name": "h1",
      "type": "Edm.String"
    },
    {
      "name": "h2",
      "type": "Edm.String"
    }]
  }]
}

Определение индексатора для синтаксического анализа "один ко многим"

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

POST https://[service name].search.windows.net/indexers?api-version=2025-05-01-preview
Content-Type: application/json
api-key: [admin key]

{
  "name": "my-markdown-indexer",
  "dataSourceName": "my-blob-datasource",
  "targetIndexName": "my-target-index",
  "parameters": {
    "configuration": { "parsingMode": "markdown" }
  },
}

Примечание.

В submode нет необходимости явно задавать здесь, так как oneToMany используется как значение по умолчанию.

Выходные данные индексатора для анализа по схеме "один ко многим"

Этот файл Markdown приведет к трем документам поиска после индексирования из-за трех разделов содержимого. Документ поиска, полученный из первого раздела содержимого предоставленного документа Markdown, будет содержать следующие значения для content, sectionsh1иh2:

{
  {
    "content": "Content for section 1.\r\n",
    "sections": {
      "h1": "Section 1",
      "h2": ""
    },
    "ordinal_position": 1
  },
  {
    "content": "Content for subsection 1.1.\r\n",
    "sections": {
      "h1": "Section 1",
      "h2": "Subsection 1.1"
    },
    "ordinal_position": 2
  },
  {
    "content": "Content for section 2.\r\n",
    "sections": {
      "h1": "Section 2",
      "h2": ""
    },
    "ordinal_position": 3
  }
}   

Сопоставлять поля "один ко многим" в индексе поиска

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

Следующий пример иллюстрирует этот сценарий. Дополнительные сведения о сопоставлениях полей см. в разделе сопоставления полей.

Допустим, что у вас есть индекс поиска со следующими полями: raw_content типа Edm.String, h1_header типа Edm.String и h2_header типа Edm.String. Чтобы сопоставить Markdown с нужной фигурой, используйте следующие сопоставления полей:

"fieldMappings" : [
    { "sourceFieldName" : "/content", "targetFieldName" : "raw_content" },
    { "sourceFieldName" : "/sections/h1", "targetFieldName" : "h1_header" },
    { "sourceFieldName" : "/sections/h2", "targetFieldName" : "h2_header" },
  ]

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

{
  {
    "raw_content": "Content for section 1.\r\n",
    "h1_header": "Section 1",
    "h2_header": "",
  },
  {
    "raw_content": "Content for section 1.1.\r\n",
    "h1_header": "Section 1",
    "h2_header": "Subsection 1.1",
  },
  {
    "raw_content": "Content for section 2.\r\n",
    "h1_header": "Section 2",
    "h2_header": "",
  }
}

Используйте режим синтаксического анализа один к одному

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

В определении индексатора задайте parsingMode"markdown" и используйте необязательный markdownHeaderDepth параметр, чтобы определить максимальную глубину заголовка для фрагментирования. Если значение не указано, по умолчанию h6 захватывает все возможные глубины заголовков.

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

  • document_content: содержит полный текст Markdown в виде одной строки. Это поле служит необработанным представлением входного документа.

  • sections: массив объектов, содержащих иерархическое представление разделов в документе Markdown. Каждый раздел представлен как объект в этом массиве и записывает структуру документа в вложенный способ, соответствующий заголовкам и их соответствующему содержимому. Доступ к полям осуществляется через сопоставления полей, ссылаясь на путь, например /sections/content. Объекты в этом массиве имеют следующие свойства:

    • header_level: строка, указывающая уровень заголовка (h1, h2, h3и т. д.) в синтаксисе Markdown. Это поле помогает понять иерархию и структурировать содержимое.

    • header_name: строка, содержащая текст заголовка, как она отображается в документе Markdown. Это поле предоставляет метку или заголовок для раздела.

    • content: строка, содержащая текстовое содержимое, которое сразу же следует за заголовком, вплоть до следующего заголовка. Это поле записывает подробные сведения или описание, связанные с заголовком. Если под заголовком нет содержимого, это пустая строка.

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

    • sections: массив, содержащий объекты, представляющие подразделы, вложенные в текущий раздел. Этот массив следует той же структуре, что и массив верхнего уровня sections , что позволяет представить несколько уровней вложенного содержимого. Каждый объект подраздела также включает свойства header_level, header_name, content и ordinal_position, обеспечивая рекурсивную структуру, представляющую иерархию содержимого Markdown.

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

# Section 1
Content for section 1.

## Subsection 1.1
Content for subsection 1.1.

# Section 2
Content for section 2.

Схема индекса для однозначного синтаксического анализа

Если вы не используете сопоставления полей, форма индекса должна отражать форму содержимого Markdown. Учитывая структуру примера Markdown с двумя разделами и одним подразделом, индекс должен выглядеть следующим образом:

{
  "name": "my-markdown-index",
  "fields": [
  {
    "name": "document_content",
    "type": "Edm.String",
  {
    "name": "sections",
    "type": "Edm.ComplexType",
    "fields": [
    {
      "name": "header_level",
      "type": "Edm.String",
    },
    {
      "name": "header_name",
      "type": "Edm.String",
    },
    {
      "name": "content",
      "type": "Edm.String"
    },
    {
      "name": "ordinal_position",
      "type": "Edm.Int"
    },
    {
      "name": "sections",
      "type": "Edm.ComplexType",
      "fields": [
      {
        "name": "header_level",
        "type": "Edm.String",
      },
      {
        "name": "header_name",
        "type": "Edm.String",
      },
      {
        "name": "content",
        "type": "Edm.String"
      },
      {
        "name": "ordinal_position",
        "type": "Edm.Int"
      }]
    }]
  }
}

Определение индексатора для синтаксического анализа

POST https://[service name].search.windows.net/indexers?api-version=2025-05-01-preview
Content-Type: application/json
api-key: [admin key]

{
  "name": "my-markdown-indexer",
  "dataSourceName": "my-blob-datasource",
  "targetIndexName": "my-target-index",
  "parameters": {
    "configuration": {
      "parsingMode": "markdown",
      "markdownParsingSubmode": "oneToOne",
    }
  }
}

Выходные данные индексатора для анализа один-к-одному

Поскольку мы хотим индексировать Markdown только до глубины h2 ("##"), нам нужны поля, вложенные на глубину 2, чтобы это соответствовало. Эта конфигурация приведет к следующим данным в индексе:

  "document_content": "# Section 1\r\nContent for section 1.\r\n## Subsection 1.1\r\nContent for subsection 1.1.\r\n# Section 2\r\nContent for section 2.\r\n",
  "sections": [
    {
      "header_level": "h1",
      "header_name": "Section 1",
      "content": "Content for section 1.",
      "ordinal_position": 1,
      "sections": [
        {
          "header_level": "h2",
          "header_name": "Subsection 1.1",
          "content": "Content for subsection 1.1.",
          "ordinal_position": 2,
        }]
    }],
    {
      "header_level": "h1",
      "header_name": "Section 2",
      "content": "Content for section 2.",
      "ordinal_position": 3,
      "sections": []
    }]
  }

Как видно, порядковое положение увеличивается в зависимости от расположения содержимого в документе.

Также следует отметить, что если уровни заголовков пропускаются в содержимом, структура результирующего документа отражает заголовки, которые присутствуют в содержимом Markdown, а не обязательно содержат вложенные разделы для h1 последовательного выполнения h6 . Например, когда документ начинается с h2, то первый элемент в массиве разделов верхнего уровня — h2.

Сопоставление полей "один к одному" в индексе поиска

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

{
  "name": "my-markdown-index",
  "fields": [
    {
      "name": "document_content",
      "type": "Edm.String",
    },
    {
      "name": "document_title",
      "type": "Edm.String",
    },
    {
      "name": "opening_subsection_title"
      "type": "Edm.String",
    }
    {
      "name": "summary_content",
      "type": "Edm.String",
    }
  ]
}

Извлечение определенных полей из синтаксического Markdown обрабатывается аналогично тому, как пути к документу находятся в outputFieldMappings, за исключением того, что путь начинается вместо /sections/documentнего. Например, /sections/0/content будет сопоставляться с содержимым под элементом в позиции 0 в массиве разделов.

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

"fieldMappings" : [
  { "sourceFieldName" : "/content", "targetFieldName" : "raw_content" },
  { "sourceFieldName" : "/sections/0/header_name", "targetFieldName" : "document_title" },
  { "sourceFieldName" : "/sections/0/sections/header_name", "targetFieldName" : "opening_subsection_title" },
  { "sourceFieldName" : "/sections/1/content", "targetFieldName" : "summary_content" },
]

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

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

{
  "content": "Content for section 1.\r\n",
  "document_title": "Section 1",
  "opening_subsection_title": "Subsection 1.1",
  "summary_content": "Content for section 2."
}

Примечание.

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

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