在知识存储中定义投影

投影知识存储定义的组成部分,后者决定了 AI 扩充内容存储在 Azure 存储中的哪个位置。 投影决定了包含内容的数据结构的类型、数量和组成。

本文介绍每种投影类型的语法:

回想一下,投影在技能集的“knowledgeStore”属性下定义。

"knowledgeStore" : {
    "storageConnectionString": "DefaultEndpointsProtocol=https;AccountName=<Acct Name>;AccountKey=<Acct Key>;",
    "projections": [
      {
        "tables": [ ],
        "objects": [ ],
        "files": [ ]
      }
    ]

如果在入门之前需要更多背景知识,请查看此检查列表,了解提示和工作流。

提示

开发投影时,请启用扩充缓存(预览版),以便在编辑投影定义时重用现有扩充。 扩充缓存是一项预览功能,请务必对索引器请求使用预览版 REST API(API 版本为 2020-06-30-preview 或更高版本)。 如果不进行缓存,对投影的简单编辑将导致完全重新处理扩充内容。 通过缓存扩充,可以循环访问投影,而不会产生任何技能组处理费用。

要求

所有投影都有源属性和目标属性。 源始终是技能组执行期间创建的扩充树中的内部内容。 目标是在 Azure 存储中创建和填充的外部对象的名称和类型。

除仅接受二进制图像的文件投影外,源必须是:

  • 有效的 JSON
  • 扩充树中节点的路径(例如,"source": "/document/objectprojection"

虽然节点可以解析为单个字段,但更常见的表示形式是引用复杂形状。 复杂形状是通过整形方法(整形程序技能内联整形定义)创建的,但通常是通过整形程序技能创建。 形状的字段或元素决定了容器和表中的字段。

整形程序技能之所以受欢迎,是因为它输出 JSON,而大多数技能本身不会输出有效的 JSON。 在许多情况下,表投影和对象投影都可以使用由整形程序技能创建的相同数据形状。

根据给定的源输入要求,了解如何修整数据成为了投影定义的实际要求,尤其是在使用表时。

定义表投影

对于需要数据研究的方案(例如,使用 Power BI 的分析或使用数据帧的工作负载),建议定义表投影。 投影数组的表部分是想要投影的表的列表。

要定义表投影,请在投影属性中使用 tables 数组。 表投影具有三个必需属性:

属性 说明
tableName 决定在 Azure 表存储中创建的新表名称。
generatedKeyName 可唯一标识每个行的键的列名。 值由系统生成。 如果省略此属性,将自动创建一个使用表名和“键”作为命名约定的列。
source 扩充树中节点的路径。 节点应该是对复杂形状的引用,该形状决定了将在表中创建的列。

在表投影中,“源”通常是定义表形状的整形程序技能的输出。 表具有行和列,整形是指定行和列的机制。 可以使用“整形程序”技能或内联形状。 整形程序技能可生成有效的 JSON,但源可以是任何技能的输出,只要是有效的 JSON 即可。

注意

表投影受限于 Azure 存储施加的存储限制。 实体大小不能超过 1 MB,且单个属性不能大于 64 KB。 这些约束使得表成了用于存储大量小型实体的适当解决方案。

单表示例

表的架构部分由投影(表名和键)以及提供表形状(列)的源指定。 此示例只显示一个表,以便你可以专注于定义的详细信息。

"projections" : [
  {
    "tables": [
      { "tableName": "Hotels", "generatedKeyName": "HotelId", "source": "/document/tableprojection" }
    ]
  }
]

列派生自“源”。 包含 HotelId、HotelName、Category 和 Description 的以下数据形状将导致在表中创建这些列。

{
    "@odata.type": "#Microsoft.Skills.Util.ShaperSkill",
    "name": "#3",
    "description": null,
    "context": "/document",
    "inputs": [
    {
        "name": "HotelId",
        "source": "/document/HotelId"
    },
    {
        "name": "HotelName",
        "source": "/document/HotelName"
    },
    {
        "name": "Category",
        "source": "/document/Category"
    },
    {
        "name": "Description",
        "source": "/document/Description"
    },
    ],
    "outputs": [
    {
        "name": "output",
        "targetName": "tableprojection"
    }
    ]
}

多表(切片)示例

表投影的常见模式是具有多个相关的表,其中创建了系统生成的 partitionKey 和 rowKey 列,以支持同一个投影组下所有表的跨表关系。

如果要控制如何聚合相关数据,则创建多个表非常有用。 如果扩充内容具有不相关的或独立的组件,例如,从文档提取的关键字可能与同一个文档中识别的实体无关,可以将这些字段拆分到相邻的表。

投影到多个表时,除非子节点是同一个组中另一个表的源,否则整个形状将投影到每个表。 添加投影时,如果源路径是现有投影的子级,将导致子节点从父节点中分割出来,并投影到新的但相关的表。 利用此方法,可以使用整形程序技能定义单个节点,该节点可以作为所有投影的源。

多个表的模式包括:

  • 一个表,作为父表或主表
  • 其他表,以包含扩充内容的切片

例如,假设整形程序技能输出包含酒店信息的“EnrichedShape”,以及关键短语、位置和组织等扩充内容。 主表将包括描述酒店的字段(ID、名称、说明、地址和类别)。 关键短语将生成关键短语列。 实体将生成实体列。

"projections" : [
  {
    "tables": [
    { "tableName": "MainTable", "generatedKeyName": "HotelId", "source": "/document/EnrichedShape" },
    { "tableName": "KeyPhrases", "generatedKeyName": "KeyPhraseId", "source": "/document/EnrichedShape/*/KeyPhrases/*" },
    { "tableName": "Entities", "generatedKeyName": "EntityId", "source": "/document/EnrichedShape/*/Entities/*" }
    ]
  }
]

命名关系

generatedKeyNamereferenceKeyName 属性用于关联表之间的数据,甚至可以关联投影类型之间的数据。 子表中的每一行都有一个指向回父级的属性。 子级中的列或属性的名称是来自父级的 referenceKeyName。 如果未提供 referenceKeyName,服务默认使用来自父级中 generatedKeyName 的名称。

Power BI 依赖于这些生成的键来发现表中的关系。 如果需要以不同的方式命名子表中的列,请在父表中设置 referenceKeyName 属性。 例如,将 generatedKeyName 设置为 tblDocument 表的 ID,并将 referenceKeyName 设置为 DocumentID。 这会导致包含文档 ID 的 tblEntities 和 tblKeyPhrases 表中的列被命名为 DocumentID。

定义对象投影

对象投影是可以从任何节点寻源的扩充树的 JSON 表示形式。 与表投影相比,对象投影的定义更简单,并且在投影整个文档时使用。 对象投影限制为容器中的单个投影,并且无法切片。

要定义对象投影,请在投影属性中使用 objects 数组。 对象投影具有三个必需属性:

属性 说明
storageContainer 决定在 Azure 存储中创建的新容器的名称。
generatedKeyName 可唯一标识每个行的键的列名。 值由系统生成。 如果省略此属性,将自动创建一个使用表名和“键”作为命名约定的列。
扩充树中作为投影根的节点的路径。 此节点通常是对决定 Blob 结构的复杂数据形状的引用。

以下示例将各个酒店文档投影到名为 hotels 的容器(每个 Blob 一个酒店文档)中。

"knowledgeStore": {
  "storageConnectionString": "an Azure storage connection string",
  "projections" : [
    {
      "tables": [ ]
    },
    {
      "objects": [
        {
        "storageContainer": "hotels",
        "source": "/document/objectprojection",
        }
      ]
    },
    {
        "files": [ ]
    }
  ]
}

源是整形程序技能“objectprojection”的输出。 每个 blob 的每个字段输入都有一个 JSON 表示法。

    {
      "@odata.type": "#Microsoft.Skills.Util.ShaperSkill",
      "name": "#3",
      "description": null,
      "context": "/document",
      "inputs": [
        {
          "name": "HotelId",
          "source": "/document/HotelId"
        },
        {
          "name": "HotelName",
          "source": "/document/HotelName"
        },
        {
          "name": "Category",
          "source": "/document/Category"
        },
        {
          "name": "keyPhrases",
          "source": "/document/HotelId/keyphrases/*"
        },
      ],
      "outputs": [
        {
          "name": "output",
          "targetName": "objectprojection"
        }
      ]
    }

定义文件投影

文件投影始终是规范化的二进制图像,其中规范化是指在执行技能组时可能使用的大小调整和旋转。 文件投影与对象投影类似,在 Azure 存储中创建为 blob,并且包含二进制数据(而不是 JSON)。

要定义文件投影,请在投影属性中使用 files 数组。 文件投影具有三个必需属性:

属性 说明
storageContainer 决定在 Azure 存储中创建的新容器的名称。
generatedKeyName 可唯一标识每个行的键的列名。 值由系统生成。 如果省略此属性,将自动创建一个使用表名和“键”作为命名约定的列。
扩充树中作为投影根的节点的路径。 对于图像文件,源始终为 /document/normalized_images/*。 文件投影仅作用于 normalized_images 集合。 索引器和技能组都不会通过原始的非规范化图像。

目标始终是一个 blob 容器,其中包含文档 ID 的 base64 编码值的文件夹前缀。 如果有多个图像,它们将放在同一个文件夹中。 文件投影不能与对象投影共享同一个容器,需要将其投影到不同的容器。

以下示例将从已扩充文档的文档节点提取的所有规范化图像投影到名为 myImages 的容器。

"projections": [
    {
        "tables": [ ],
        "objects": [ ],
        "files": [
            {
                "storageContainer": "myImages",
                "source": "/document/normalized_images/*"
            }
        ]
    }
]

测试投影

可以执行以下步骤来处理投影:

  1. 将知识存储的 storageConnectionString 属性设置为有效的 V2 常规用途存储帐户连接字符串。

  2. 通过在技能组的主体中使用投影定义发出 PUT 请求来更新技能组

  3. 运行索引器,使技能组开始执行。

  4. 监视索引器执行,以检查进度并捕获任何错误。

  5. 使用 Azure 门户验证 Azure 存储中的对象创建。

  6. 如果要投影表,请将它们导入到 Power BI 中进行表操作和可视化。 在大多数情况下,Power BI 会自动发现表之间的关系。

常见问题

提供以下任何步骤可能会导致意外结果。 如果输出看起来不正确,请检查是否存在以下情况。

  • 字符串扩充未整形为有效的 JSON。 扩充字符串后(例如,使用关键短语扩充 merged_content),扩充的属性将表示为扩充树中 merged_content 的子级。 默认的表示形式不是适当格式的 JSON。 在投影时,请确保将扩充转换为包含名称和值的有效 JSON 对象。 使用整形程序技能或定义内联形状有助于解决此问题。

  • 省略源路径末尾的 /*。 如果投影的源是 /document/projectionShape/keyPhrases,则关键字短语数组将投影为单个对象/行。 请改为将源路径设置为 /document/projectionShape/keyPhrases/*,以便为每个关键短语生成单个行或对象。

  • 路径语法错误。 路径选择器区分大小写,如果不对选择器使用确切的大小写,可能会导致出现“缺少输入”警告。

后续步骤

后续步骤将指导你对丰富的技能组的输出进行修整和投影。 如果你的技能组很复杂,以下文章提供了形状和投影的示例。