如何在 Azure 认知搜索中的 AI 扩充管道中创建技能组

索引器阶段

技能组定义提取和扩充数据以使其可搜索的操作。 从源文档提取文本和图像内容后,以及在将源文档中的任何字段(可选)映射到索引或知识存储中的目标字段后,技能组都会执行。

技能组包含一个或多个表示特定扩充操作的认知技能,如翻译文本、提取关键短语或从图像文件执行光学字符识别。 若要创建技能组,可以使用 Microsoft 提供的内置技能,或包含你提供的模型或处理逻辑的自定义技能(请参阅示例:在 AI 扩充管道中创建自定义技能来了解详细信息)。

本文介绍如何对想要使用的技能创建扩充管道。 技能组将附加到 Azure 认知搜索索引器。 本文介绍的管道设计的一个部分是构造技能集本身。

备注

管道设计的另一个部分是指定下一步骤所述的索引器。 索引器定义包括对技能的引用,以及用于将目标索引中的输入连接到输出的字段映射。

请记住以下要点:

  • 只能为每个索引器创建一个技能集。
  • 技能组合必须具有至少一种技能。
  • 可以创建相同类型的多个技能(例如,图像分析技能的变体)。

一开始就想到最终结果

建议的初始步骤是确定要从原始数据提取哪些数据,以及如何在搜索解决方案中使用该数据。 创建整个扩充管道的演示有助于确定所需的步骤。

假设我们要处理一系列金融分析师评论。 对于每个文件,我们需要提取公司名称和一般性的评论情绪。 此外,可能还需要编写自定义的扩充器,以便使用自定义实体搜索来查找有关公司的其他信息,例如,该公司经营哪种业务。 实质上,我们需要提取针对每个文档编制索引的如下所述的信息:

记录文本 公司 情绪 公司说明
sample-record ["Microsoft", "LinkedIn"] 0.99 ["Microsoft Corporation is an American multinational technology company ..." , "LinkedIn is a business- and employment-oriented social networking..."]

下图演示了一个虚构的扩充管道:

假设的扩充管道

对管道包含的内容进行适当的构思后,可以表达用于提供这些步骤的技能集。 在功能上,在将索引器定义上传到 Azure 认知搜索时,即会表达该技能组。 若要详细了解如何上传索引器,请参阅索引器文档

在图中,文档破解步骤会自动发生。 实质上,Azure 认知搜索知道如何打开已知的文件,并创建一个内容字段,其中包含从每个文档中提取的文本。 白框是内置的扩充器,“自定义实体搜索”虚线框表示要创建的自定义扩充器。 如图所示,该技能集包含三个技能。

REST 中的技能集定义

技能定义为技能数组。 每个技能定义其输入的源,以及生成的输出的名称。 使用创建技能 REST API 可以定义对应于上图的技能集:

PUT https://[servicename].search.azure.cn/skillsets/[skillset name]?api-version=2020-06-30
api-key: [admin key]
Content-Type: application/json
{
  "description": 
  "Extract sentiment from financial records, extract company names, and then find additional information about each company mentioned.",
  "skills":
  [
    {
      "@odata.type": "#Microsoft.Skills.Text.EntityRecognitionSkill",
      "context": "/document",
      "categories": [ "Organization" ],
      "defaultLanguageCode": "en",
      "inputs": [
        {
          "name": "text",
          "source": "/document/content"
        }
      ],
      "outputs": [
        {
          "name": "organizations",
          "targetName": "orgs"
        }
      ]
    },
    {
      "@odata.type": "#Microsoft.Skills.Text.SentimentSkill",
      "inputs": [
        {
          "name": "text",
          "source": "/document/content"
        }
      ],
      "outputs": [
        {
          "name": "score",
          "targetName": "mySentiment"
        }
      ]
    },
    {
      "@odata.type": "#Microsoft.Skills.Custom.WebApiSkill",
     "description": "Calls an Azure function, which in turn calls Custom Entity Search",
      "uri": "https://indexer-e2e-webskill.chinacloudsites.cn/api/InvokeTextAnalyticsV3?code=foo",
      "httpHeaders": {
          "Ocp-Apim-Subscription-Key": "foobar"
      },
      "context": "/document/orgs/*",
      "inputs": [
        {
          "name": "query",
          "source": "/document/orgs/*"
        }
      ],
      "outputs": [
        {
          "name": "description",
          "targetName": "companyDescription"
        }
      ]
    }
  ]
}

创建技能集

创建技能集时,可以提供说明,使技能集具有自述性。 说明是可选的,但可用于跟踪技能集的用途。 由于技能集是不允许注释的 JSON 文档,因此必须为其使用 description 元素。

{
  "description": 
  "This is our first skill set, it extracts sentiment from financial records, extract company names, and then finds additional information about each company mentioned.",
  ...
}

技能集的下一个片段是技能数组。 可将每个技能视为扩充的基元。 每个技能在此扩充管道中执行小型任务。 每个技能接受一个输入(或一组输入),并返回一些输出。 以下几个部分重点介绍如何指定内置技能和自定义技能,并通过输入和输出引用将技能链接在一起。 输入可以来自源数据或来自另一个技能。 输出可映射到搜索索引中的字段,或用作下游技能的输入。

添加内置技能

让我们看看第一个技能,它是内置的实体识别技能

    {
      "@odata.type": "#Microsoft.Skills.Text.EntityRecognitionSkill",
      "context": "/document",
      "categories": [ "Organization" ],
      "defaultLanguageCode": "en",
      "inputs": [
        {
          "name": "text",
          "source": "/document/content"
        }
      ],
      "outputs": [
        {
          "name": "organizations",
          "targetName": "orgs"
        }
      ]
    }
  • 每个内置技能具有 odata.typeinputoutput 属性。 技能特定的属性提供适用于该技能的附加信息。 对于实体识别,categories 是一组固定的实体类型中,可由预先训练的模型识别的一个实体。

  • 每个技能应包含 "context"。 上下文表示发生操作的级别。 在上面的技能中,上下文是整个文档,这意味着,针对每个文档调用实体识别技能一次。 输出也会在该级别生成。 该技能返回一个名为 organizations 的属性,该属性被捕获为 orgs。 更具体地说,现将 "orgs" 添加为 "/document" 的成员。 在下游技能中,可使用 "/document/orgs" 的形式引用此新建的扩充。 如果未显式设置 "context" 字段,则默认上下文是文档。

  • 一种技能的输出可能与另一种技能的输出发生冲突。 如果有多个返回 result 属性的技能,可使用技能输出的 targetName 属性将一个技能的命名 JSON 输出捕获到不同的属性中。

  • 技能包含一个名为“text”的输入,其源输入设置为 "/document/content"。 该技能(实体识别)对每个文档的内容字段进行操作,内容字段是 Azure Blob 索引器创建的标准字段。

  • 该技能有一个名为 "organizations" 的输出,该输出在属性 orgs 中进行捕获。 输出只会在处理期间存在。 若要将此输出链接到下游技能的输入,请以 "/document/orgs" 的形式引用输出。

  • 对于特定的文档,"/document/orgs" 的值是从文本提取的组织数组。 例如:

    ["Microsoft", "LinkedIn"]
    

在某些情况下,需要单独引用数组的每个元素。 例如,假设我们要将 "/document/orgs" 的每个元素单独传递给另一个技能(例如自定义实体搜索扩充器)。 可以通过在路径中添加星号,来引用该数组的每个元素:"/document/orgs/*"

第二个情绪提取技能遵循与第一个扩充器相同的模式。 它采用 "/document/content" 作为输入,并返回每个内容实例的情绪评分。 由于未显式设置 "context" 字段,输出 (mySentiment) 现在是 "/document" 的子级。

    {
      "@odata.type": "#Microsoft.Skills.Text.SentimentSkill",
      "inputs": [
        {
          "name": "text",
          "source": "/document/content"
        }
      ],
      "outputs": [
        {
          "name": "score",
          "targetName": "mySentiment"
        }
      ]
    },

添加自定义技能

回顾自定义实体搜索扩充器的结构:

    {
      "@odata.type": "#Microsoft.Skills.Custom.WebApiSkill",
     "description": "This skill calls an Azure function, which in turn calls Custom Entity Search",
      "uri": "https://indexer-e2e-webskill.chinacloudsites.cn/api/InvokeTextAnalyticsV3?code=foo",
      "httpHeaders": {
          "Ocp-Apim-Subscription-Key": "foobar"
      },
      "context": "/document/orgs/*",
      "inputs": [
        {
          "name": "query",
          "source": "/document/orgs/*"
        }
      ],
      "outputs": [
        {
          "name": "description",
          "targetName": "companyDescription"
        }
      ]
    }

此定义是在扩充过程中调用某个 Web API 的自定义技能。 对于实体识别技能所识别到的每个组织,此技能调用 Web API 来查找该组织的说明。 扩充引擎会在内部协调处理何时调用 Web API,以及如何流式传输收到的信息。 但是,必须在 JSON 中提供调用此自定义 API 所需的初始化(例如所需的 uri、httpHeaders 和 inputs)。 有关为扩充管道创建自定义 Web API 的指导,请参阅如何定义自定义接口

请注意,“上下文”字段设置为包含星号的 "/document/orgs/*",这意味着,将对 "/document/orgs" 下的每个组织调用扩充步骤。

将为识别到的每个组织生成输出(在本例中为公司说明)。 引用下游步骤中的说明时(例如,在关键短语提取中),应该使用路径 "/document/orgs/*/description" 执行此操作。

添加结构

技能集基于非结构化数据生成结构化信息。 请考虑以下示例:

“在第四季度,Azure 去年收购的社交网络公司 LinkedIn 为其带来了 11 亿美元的营收。此次收购使 Azure 能够将 LinkedIn 功能与其 CRM 和 Office 功能整合。股东们为目前的进展感到激动。”

可能的结果是下图所示的生成结构:

示例输出结构

到目前为止,此结构仅限内部使用、仅限内存中使用,并仅限在 Azure 认知搜索索引中使用。 添加知识存储可以保存整形的扩充,以便在搜索外部使用。

添加知识存储

知识存储是 Azure 认知搜索中的一项功能,用于保存扩充的文档。 创建的由 Azure 存储帐户支持的知识存储是扩充的数据要载入到的存储库。

知识存储定义将添加到技能集。 有关整个过程的演练,请参阅在 REST 中创建知识存储

"knowledgeStore": {
  "storageConnectionString": "<an Azure storage connection string>",
  "projections" : [
    {
      "tables": [ ]
    },
    {
      "objects": [
        {
          "storageContainer": "containername",
          "source": "/document/EnrichedShape/",
          "key": "/document/Id"
        }
      ]
    }
  ]
}

可以选择将扩充的文档另存为保留分层关系的表,或另存为 Blob 存储中的 JSON 文档。 技能集中任何技能的输出可寻源为投影的输入。 若要将数据投影为特定的形状,更新的整形程序技能现在可为要使用的复杂类型建模。

后续步骤

熟悉扩充管道和技能集后,请继续阅读如何在技能集中引用注释如何将输出映射到索引中的字段