使用 Azure AI 搜索技能集的上下文和源属性引用扩充节点的路径

注释

Azure AI 搜索可通过Azure门户REST APIAzure SDK获取。

在技能集执行期间,引擎会在内存中生成一个增强树,用于捕获每个增强,例如已识别的实体或已翻译的文本。 本文介绍如何在扩充树中引用扩充节点,以便可以将输出传递给下游技能,或指定搜索索引字段的输出字段映射。

本文会使用示例来说明各种方案。 有关完整语法,请参阅 技能上下文和输入注释语言

背景概念

在复习语法之前,让我们回顾一些重要的概念,以便更好地理解本文后面提供的示例。

术语 说明
“扩充文档” 增益文档是一种内存中的结构,在创建期间收集技能输出,并存储与文档相关的所有增益信息。 可以把增强文档看作一棵树。 通常,树从根文档级别开始,每个新扩展都从前一个节点创建为子节点。
“节点” 在富文档中,节点(有时称为“批注”)是特定输出,例如 OCR 功能的“text”或“layoutText”,或源字段值,例如产品 ID 字段的内容,或从源复制的元数据,如从 Azure 存储中的 blob 中复制的 metadata_storage_path。
“上下文” 扩充的范围,即整个文档、文档的一部分(页面或句子),或者如果使用图像,则从文档中提取的图像。 默认情况下,扩充上下文位于 "/document" 级别,作用域为数据源中的单个文档。 当一个技能运行时,该技能的输出将成为定义上下文的属性

不同场景的路径

路径在技能组的“上下文”和“源”属性以及索引器的输出字段映射中指定。

技能组定义的屏幕截图,其中突出显示了上下文和源元素。

屏幕截图中的示例展示了 Azure Cosmos DB 集合中某个项的路径。

  • context 路径为 /document/HotelId,因为集合是通过 /HotelId 字段将数据划分到各个文档中的。

  • source 路径之所以是 /document/Description,是因为该技能为翻译技能,并且您想要翻译的是每个文档中的 Description 字段。

所有路径都以 /document 开头。 在索引器执行的“文档解析”阶段,当索引器打开文档或从数据源中读取一行数据时,便会创建一个扩充文档。 最初,扩充文档中唯一的节点是根节点 (/document),它是所有其他扩充始发的节点。

以下列表包括几个常见示例:

  • /document 是根节点,指示 Azure 存储中的整个 Blob 或 SQL 表中的一行。
  • /document/{key} 是用于 Azure Cosmos DB 集合中描述文档或项的语法形式,其中 {key} 是实际的键,例如在前面的例子中的 /document/HotelId
  • /document/content 指定 JSON Blob 的“内容”属性。
  • /document/{field} 是对特定字段执行的操作的语法,例如转换 /document/Description 字段,如上一示例中所示。
  • 如果要将大型文档分解为较小的区块进行处理,/document/pages/*/document/sentences/* 将成为上下文。 如果“上下文”为 /document/pages/*,则技能会在文档中的每一页上执行一次。 由于可能有多个页面或句子,因此可以追加 /* 以捕获所有这些页面或句子。
  • 如果文档包含图像,则会在文档破解期间创建 /document/normalized_images/*。 图像的所有路径都以 normalized_images 开头。 由于一个文档中经常嵌入多个图像,因此追加 /*

本文剩余部分中的示例基于“上下文”字段,该字段由 Azure blob 索引器文档破解阶段中自动生成。 从 Blob 容器引用文档时,使用 "/document/content" 等格式,其中 content 字段是文档的一部分。

示例 1:简单注释引用

在 Azure Blob 存储中,假设有各种文件,其中包含对想要使用实体识别提取的人员名称的引用。 在以下功能定义中,"/document/content" 是整个文档的文本表示,"people" 是从识别为人的实体中提取的全名。

因为默认上下文是 "/document",所以现在可以将人员列表引用为 "/document/people"。 在此特定示例中 "/document/people" 是一个注释,它现在可以映射到索引中的一个字段,或者用在同一技能集的另一个技能中。

  {
    "@odata.type": "#Microsoft.Skills.Text.V3.EntityRecognitionSkill",
    "categories": [ "Person"],
    "defaultLanguageCode": "en",
    "inputs": [
      {
        "name": "text",
        "source": "/document/content"
      }
    ],
    "outputs": [
      {
        "name": "persons",
        "targetName": "people"
      }
    ]
  }

示例 2:引用文档中的数组

此示例基于前一个示例构建,演示如何在同一个文档中多次调用一个扩充步骤。 假设前面的示例生成了一个字符串数组,其中有 10 个人名来自单个文档。 合理的下一步可能是二次扩充,将姓氏从全名中提取出来。 因为有 10 个姓名,所以你希望在这个文档中调用此步骤 10 次,每个人一次。

若要调用正确的迭代次数,请将上下文设置为 "/document/people/*",其中星号 ("*") 表示扩充文档中作为 "/document/people" 的后代的所有节点。 尽管此技能只在技能数组中定义了一次,但它会对文档中的每个成员调用,直到所有成员都被处理。

  {
    "@odata.type": "#Microsoft.Skills.Custom.WebApiSkill",
    "description": "Fictitious skill that gets the last name from a full name",
    "uri": "http://names.chinacloudsites.cn/api/GetLastName",
    "context" : "/document/people/*",
    "defaultLanguageCode": "en",
    "inputs": [
      {
        "name": "fullname",
        "source": "/document/people/*"
      }
    ],
    "outputs": [
      {
        "name": "lastname",
        "targetName": "last"
      }
    ]
  }

当注释是字符串的数组或集合时,你可能希望针对特定成员而不是整个数组。 上一个示例在上下文表示的每个节点下生成一个名为 "last" 的批注。 如果想要引用此系列的注释,可以使用语法 "/document/people/*/last"。 如果想要引用特定注释,可以使用显式索引:"/document/people/1/last 引用文档中标识的第一个人的姓氏。 请注意,在此语法中数组索引从 0 开始。

示例 3:引用数组中的成员

有时,需要对特定类型的所有注释进行分组,以将它们传递给特定技能。 考虑一种假设的自定义技能,它标识在示例 2 中提取的所有姓氏中最常见的姓氏。 若要仅提供姓氏至自定义技能,请将上下文指定为 "/document",将输入指定为 "/document/people/*/lastname"

请注意,"/document/people/*/lastname" 的基数大于文档的基数。 可能有 10 个姓氏节点,而此文档只有一个文档节点。 在这种情况下,系统将自动创建包含文档中的所有元素的 "/document/people/*/lastname" 数组。

  {
    "@odata.type": "#Microsoft.Skills.Custom.WebApiSkill",
    "description": "Fictitious skill that gets the most common string from an array of strings",
    "uri": "http://names.chinacloudsites.cn/api/MostCommonString",
    "context" : "/document",
    "inputs": [
      {
        "name": "strings",
        "source": "/document/people/*/lastname"
      }
    ],
    "outputs": [
      {
        "name": "mostcommon",
        "targetName": "common-lastname"
      }
    ]
  }

注释路径故障排除提示

如果在指定技能输入时遇到问题,以下提示可以帮助顺利操作:

另请参阅