Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Примечание
Поиск с использованием ИИ Azure доступна через портал Azure, REST API и Azure SDKs. Он также лежит в основе Foundry IQ — управляемого слоя знаний, который преобразует корпоративный контент в многократно используемые базы знаний с учетом разрешений доступа для агентов на портале Microsoft Foundry.
Important
Эти возможности и функции обеспечивают подключение к другим службам Microsoft и сторонним службам. Использование этих служб регулируется соответствующими условиями и может привести к обработке или хранению данных за пределами периметра соответствия требованиям Azure, а также к передаче данных в периметр соответствия требованиям Azure.
Вы несете ответственность за управление тем, будут ли данные передаваться за пределы соответствия вашей организации и географических границ и любых связанных последствий, а также предоставлять соответствующие разрешения, границы и утверждения.
Вы несете ответственность за тщательное изучение и тестирование приложений, которые вы создаете в контексте конкретных вариантов использования и принятия всех соответствующих решений и настроек. Это включает в себя реализацию собственных ответственных мер по устранению рисков искусственного интеллекта, таких как метаподсказки, фильтры содержимого или другие системы безопасности, а также обеспечение соответствия приложений соответствующим стандартам качества, надежности, безопасности и доверия. Дополнительные сведения см. в примечании о прозрачности Поиск с использованием ИИ Azure.
В Поиск с использованием ИИ Azure индексаторы для Хранилище BLOB-объектов Azure, Файлы Azure и Microsoft OneLake поддерживают режим синтаксического анализа markdown для файлов Markdown. Файлы Markdown можно индексировать двумя способами:
- Режим парсинга «один ко многим», который создает несколько поисковых документов для каждого файла Markdown.
- Режим синтаксического анализа один к одному, который создает один документ поиска на файл Markdown.
Совет
После просмотра этой статьи перейдите к Tutorial: поиск данных Markdown из Хранилище BLOB-объектов Azure.
Необходимые условия
Поддерживаемый источник данных: Хранилище BLOB-объектов Azure, хранилище файлов Azure, Microsoft OneLake.
Для OneLake убедитесь, что выполнены все требования индексатора OneLake.
служба хранилища Azure для индексаторов blob и индексаторов файлов — это стандартный экземпляр производительности (общего назначения версии 2), поддерживающий уровни горячего и холодного доступа.
Параметры режима синтаксического анализа Markdown
Параметры режима синтаксического анализа указываются в определении индексатора при создании или обновлении индексатора.
POST https://[service name].search.windows.net/indexers?api-version=2026-04-01
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 предоставляет следующие параметры подрежимов:
| Режим парсинга | подрежим | Поиск документа | Описание |
|---|---|---|---|
markdown |
oneToMany |
Несколько для каждого объекта | (по умолчанию) Разбивает Markdown на несколько документов поиска, каждый из которых представляет собой раздел с содержимым (не заголовок) файла Markdown. Вы можете опустить подрежим, если не хотите выполнять синтаксический анализ по одному. |
markdown |
oneToOne |
По одному на блоб | Анализирует Markdown в один документ поиска с разделами, сопоставленными с определенными заголовками в файле Markdown. |
Для oneToMany подмоде необходимо изучить индексирование одного блоба для создания множества документов поиска, чтобы понять, как индексатор блобов обрабатывает дизамбигуацию ключа документа для нескольких создаваемых из одного блоба документов поиска.
В последующих разделах подробно описан каждый подрежим. Если вы не знакомы с клиентами и понятиями индексатора, см. статью "Создание индексатора поиска". Кроме того, вы должны ознакомиться с подробными сведениями о базовой конфигурации индексатора BLOB-объектов, которая здесь не повторяется.
Необязательные параметры синтаксического анализа Markdown
Параметры чувствительны к регистру.
| Имя параметра | Допустимые значения | Описание |
|---|---|---|
markdownHeaderDepth |
h1, h2, h3, h4, h5, 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=2026-04-01
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, иh2h3т. д.) в синтаксисе Markdown. Это поле помогает понять иерархию и структурировать содержимое.header_name: строка, содержащая текст заголовка, как она отображается в документе Markdown. Это поле предоставляет метку или заголовок для раздела.content: строка, содержащая текстовое содержимое, которое сразу же следует за заголовком, вплоть до следующего заголовка. Это поле записывает подробные сведения или описание, связанные с заголовком. Если под заголовком нет содержимого, значение является пустой строкой.ordinal_position: целочисленное значение, указывающее положение раздела в иерархии документов. Это поле используется для упорядочивания разделов в исходной последовательности, как они отображаются в документе, начиная с порядковой позиции 1 и последовательного увеличения для каждого блока содержимого.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": "id",
"type": "Edm.String",
"key": true
},
{
"name": "document_content",
"type": "Edm.String"
},
{
"name": "sections",
"type": "Collection(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.Int32"
},
{
"name": "sections",
"type": "Collection(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.Int32"
}]
}]
}]
}
Определение индексатора для однозначного синтаксического анализа
POST https://[service name].search.windows.net/indexers?api-version=2026-04-01
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 ("##"), нам необходимо, чтобы поля были вложены в глубину до sections 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 имеют заголовок документа в первом h1, заголовок подраздела в первом h2, и сводку в содержании окончательного абзаца под окончательным 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."
}
Примечание
В этих примерах указывается, как использовать эти режимы синтаксического анализа полностью с сопоставлениями полей или без них, но можно применить оба в одном сценарии, если это соответствует вашим потребностям.
Управление устаревшими документами в процессе повторного индексирования файлов Markdown.
При использовании режима синтаксического анализа "один ко многим" повторно индексирование измененного файла Markdown может привести к устаревшим или повторяющимся документам, если разделы удаляются. Это поведение относится к режиму "один ко многим" и не применяется к синтаксическому анализу один к одному.
Общие сведения о поведении
Режим синтаксического анализа "один ко многим"
В oneToMany режиме каждый раздел Markdown (на основе заголовков) индексируется как отдельный документ поиска. При повторном индексировании файла:
- Без автоматического удаления: индексатор перезаписывает существующие документы новыми, но не удаляет документы, которые больше не соответствуют содержимому обновленного файла.
- Потенциал для повторяющихся данных: эта проблема возникает только тогда, когда между запуском индексации удаляется больше разделов, чем вставляется. В таких случаях оставшиеся документы из предыдущей версии остаются в индексе, что приводит к устаревшим записям, которые больше не отражают текущее состояние исходного файла.
Режим синтаксического анализа один к одному
В oneToOne режиме весь файл Markdown индексируется как один документ поиска. При повторном индексировании файла:
- Поведение перезаписи: существующий документ полностью заменен новой версией.
- Нет устаревших разделов: когда файл переиндексирован, существующий документ заменяется обновленной версией, и удаленное содержимое больше не включается. Единственное исключение — если изменится путь к файлу или URI блоба, что может привести к созданию нового документа наряду со старым.
Варианты обходного решения
Чтобы убедиться, что индекс отражает текущее состояние файлов Markdown, рассмотрите один из следующих подходов:
Вариант 1. Мягкое удаление с метаданными
Этот метод использует мягкое удаление для удаления документов, связанных с определенным объектом. Дополнительные сведения см. в разделе обнаружение изменений и удаления с помощью индексаторов для служба хранилища Azure в Поиск с использованием ИИ Azure.
Шаги:
- Пометьте BLOB как удаленный, задав поле метаданных.
- Пусть индексатор запускается. Он удаляет все документы в индексе, связанном с этим BLOB-объектом.
- Удалите маркер обратимого удаления и переиндексируйте файл.
Вариант 2. Использование API удаления
Перед повторной индексированием измененного файла Markdown явным образом удалите существующие документы, связанные с этим файлом, с помощью API удаления. Вы можете выполнить следующие действия:
- Вручную определите отдельные устаревшие документы, определив дубликаты в индексе, которые необходимо удалить. Это возможно для небольших, хорошо понятных изменений, но может занять много времени.
- (Рекомендуется) Удалите все документы, созданные из одного родительского файла перед повторным индексированием, что гарантирует избегание несоответствий.
Шаги:
Определите идентификатор документов, связанных с файлом. Используйте запрос, например, как в следующем примере, чтобы получить идентификаторы ключей документа (например,
idилиchunk_id) для всех документов, которые привязаны к конкретному файлу. Заменитеmetadata_storage_pathс соответствующим полем в индексе, которое сопоставляется с путем к файлу или URI объекта BLOB. Это поле должно быть ключевым.GET https://[service name].search.windows.net/indexes/[index name]/docs?api-version=2026-04-01 Content-Type: application/json api-key: [admin key] { "filter": "metadata_storage_path eq 'https://<storage-account>.blob.core.windows.net/<container-name>/<file-name>.md'", "select": "id" }Отправьте запрос на удаление документов с указанными ключами.
POST https://[service name].search.windows.net/indexes/[index name]/docs/index?api-version=2026-04-01 Content-Type: application/json api-key: [admin key] { "value": [ { "@search.action": "delete", "id": "aHR0c...jI1" }, { "@search.action": "delete", "id": "aHR0...MQ2" } ] }Переиндексировать обновленный файл.