你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn

在 Azure AI 搜索中为 Markdown Blob 和文件编制索引

注意

此功能目前处于公开预览状态。 此预览版没有附带服务级别协议,建议不要用于生产工作负载。 某些功能可能不受支持或者受限。 有关详细信息,请参阅 Microsoft Azure 预览版补充使用条款

在 Azure AI 搜索中,适用于 Azure Blob 存储、Azure 文件存储和 OneLake 的索引器均支持 Markdown 文件的 markdown 分析模式。 Markdown 文件可以通过两种方式编制索引:

  • 一对多分析模式,每个 Markdown 文件创建多个搜索文档
  • 一对一分析模式,每个 Markdown 文件创建一个搜索文档

先决条件

  • 支持的数据源包括:Azure Blob 存储、Azure 文件存储以及 Microsoft Fabric 中的 OneLake。

    对于 OneLake,请确保满足 OneLake 索引器的所有要求。

    用于 Blob 索引器文件索引器的 Azure 存储是一种标准性能(常规用途 v2)实例,支持热访问层、冷访问层和寒访问层。

Markdown 分析模式参数

在创建或更新索引器时,可以在索引器定义中指定分析模式参数。

POST https://[service name].search.windows.net/indexers?api-version=2024-11-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 每个 Blob 有多个 (默认)将 Markdown 拆分成多个搜索文档,每个文档表示 Markdown 文件中的一个内容(非标题)节。 除非你想要进行一对一分析,否则可以省略子模式。
markdown oneToOne 每个 Blob 各有一个 将 Markdown 分析为一个搜索文档,其中的各节映射到 Markdown 文件中的特定标题。

对于 oneToMany 子模式,应查阅为一个 Blob 编制索引以生成多个搜索文档,了解对于从同一 Blob 生成的多个搜索文档,Blob 索引器如何消除文档键的歧义。

后面的各个部分更详细地介绍了每个子模式。 如果你不熟悉索引器客户端和概念,请参阅创建搜索索引器。 还应熟悉基本 blob 索引器配置的详细信息,这在此不予重复。

可选的 Markdown 分析参数

参数区分大小写。

参数名称 允许的值 说明
markdownHeaderDepth h1h2h3h4h5h6(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 时,包含字符串字段 h1h2h3。 这些字段通过镜像索引中的此结构或通过格式为 /sections/h1sections/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=2024-11-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 文档的第一个内容节生成的搜索文档将包含以下 contentsectionsh1h2 的值:

{
  {
    "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 文档的各个部分,并将这些部分“提升”到搜索文档的顶级字段。

以下示例对此方案进行了说明。 有关一般字段映射的详细信息,请参阅“字段映射”。

假设某个搜索索引包含以下字段:Edm.String 类型的 raw_contentEdm.String 类型的 h1_header,以及 Edm.String 类型的 h2_header。 要将 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:一个字符串,指示 Markdown 语法中的标题级别(h1h2h3 等)。 此字段有助于理解内容的层次结构和组织方式。

    • header_name:一个字符串,其中包含在 Markdown 文档中显示的标题的文本。 此字段提供相应节的标签或标题。

    • content:一个字符串,其中包含紧跟标题之后的文本内容,直到下一个标题为止。 此字段捕获与标题关联的详细信息或描述。 如果标题下没有内容,则这是一个空字符串。

    • ordinal_position:一个整数值,指示该节在文档层次结构中的位置。 此字段用于按原始顺序对文档中的各节进行排序,从序号位置 1 开始,每个内容块的序号依次递增。

    • sections:一个数组,其中包含表示嵌套在当前节下的小节的对象。 此数组遵循与顶级 sections 数组相同的结构,允许表示多级嵌套内容。 每个子节对象也包括 header_levelheader_namecontentordinal_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=2024-11-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(“##”),因此需要将 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 内容中存在的标题,而不一定包含连续的 h6h1 的嵌套节。 例如,当文档从 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."
}

注意

这些示例展示了完全使用或不使用字段映射的分析模式应用,但在适合你的需求的情况下,也可以在同一场景中同时使用两者。

后续步骤