使用 Azure AI 搜索技能集的上下文和源属性引用扩充节点的路径
在技能集执行期间,引擎会生成一个内存中扩充树,用于捕获每个扩充,例如已识别的实体或已翻译的文本。 本文介绍如何在扩充树中引用扩充节点,以便可以将输出传递给下游技能,或指定搜索索引字段的输出字段映射。
本文会使用示例来说明各种方案。 有关完整语法,请参阅技能上下文和输入注释语言。
背景概念
在复习语法之前,让我们回顾一些重要的概念,以便更好地理解本文后面提供的示例。
术语 | 说明 |
---|---|
“扩充文档” | 扩充文档是一种内存中结构,在创建时收集技能输出,并保存与文档相关的所有扩充。 可以把扩充文档看作是树。 通常,树从根文档级别开始,每个新扩充都是从以前的子级创建的。 |
“节点” | 在扩充文档中,节点(有时称为“注释”)由技能(如 OCR 技能中的“text”和“layoutText”)创建和填充。 扩充文档会使用从源复制的扩充和原始源字段值或元数据填充。 |
“上下文” | 扩充的范围,可能是整个文档、文档的一部分,或如果要使用图像,则可能是从文档中提取的图像。 默认情况下,扩充上下文位于 "/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”是对标识为 persons 的实体的全名提取。
因为默认上下文是 "/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 个 lastname 节点,而只有一个 document 节点。 在这种情况下,系统将自动创建包含文档中的所有元素的 "/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"
}
]
}
注释路径故障排除提示
如果在指定技能输入时遇到问题,以下提示可以帮助顺利操作:
对数据运行“导入数据”向导,查看向导生成的技能组定义和字段映射。
在某个技能组上启动调试会话,查看扩充文档的结构。 可以编辑技能定义的路径和其他部分,然后运行技能来验证更改。