将自定义技能添加到 Azure 认知搜索扩充管道

AI 扩充管道可以包含你个人创建和发布的内置技能自定义技能。 自定义代码在搜索服务的外部执行(例如,作为 Azure 函数执行),但像任何其他技能一样,它接受输入并将输出发送到技能组。

自定义技能听起来很复杂,但它的实现可能非常简单直接。 如果你通过现有的包提供模式匹配或分类模型,可将从 Blob 提取的内容传递给这些模型进行处理。 由于 AI 扩充基于 Azure,因此模型也应该在 Azure 上。 一些常用的托管方法包括使用 Azure Functions容器

如果要构建自定义技能,本文介绍了用于将该技能集成到管道中的接口。 主要的要求是,要能够以在技能组内作为整体使用的方式接受输入并发出输出。 因此,本文的重点是扩充管道需要的输入格式和输出格式。

自定义技能的优点

通过生成自定义技能,可插入对内容唯一的转换。 自定义技能独立执行,可应用所需的任何扩充步骤。 例如,可以生成自定义分类模型,以区分商业与金融领域的合同和文档,或者,添加语音识别技能,以便深入探究音频文件获取相关内容。 有关分步示例,请参阅示例:为 AI 扩充创建自定义技能

设置终结点和超时时间间隔

自定义技能的接口是通过自定义 Web API 技能指定的。

"@odata.type": "#Microsoft.Skills.Custom.WebApiSkill",
"description": "This skill has a 230 second timeout",
"uri": "https://[your custom skill uri goes here]",
"authResourceId": "[for managed identity connections, your app's client ID goes here]",
"timeout": "PT230S",

URI 是函数或应用的 HTTPS 终结点。 在设置 URI 时,请确保该 URI 是安全的 (HTTPS)。 如果你的代码托管在 Azure 函数应用中,则 URI 应将 API 密钥包括在标头中或将其用作 URI 参数以对请求进行授权。

如果你的函数或应用使用 Azure 托管标识和 Azure 角色进行身份验证和授权,则自定义技能可以在请求中包含身份验证令牌。 以下几点说明了此方法的要求:

在默认情况下,如果在 30 秒的时间段内未返回响应,到终结点的连接就会超时。 索引管道是同步的,如果未在超时时限内收到响应,索引就会生成超时错误。 通过设置超时参数,可以将该时间间隔增加到最大值 230 秒:

设置 Web API 输入的格式

Web API 必须接受要处理的一组记录。 每条记录都必须包含属性包,它是为 Web API 提供的输入。

假设要创建一个基本的扩充器来识别合同文本中提到的第一个日期。 在此示例中,技能接受一个输入“contractText”作为合同文本。 技能也具有单个输出,即合同的日期。 若要使该扩充器更有趣,请将此“contractDate”以多部分复杂类型的形式返回。

你的 Web API 应该可以接收一批输入记录。 “values”数组中的每个成员都表示某个特定记录的输入。 每条记录都需要具有以下元素:

  • 一个“recordId”成员,它是某个特定记录的独一无二的标识符。 在扩充器返回结果时,它必须提供此“recordId”,以便允许调用方将记录结果匹配到它们的输入。

  • 一个“data”成员,它基本上是用于每条记录的一包输入域。

生成的 Web API 请求可能如下所示:

{
    "values": [
      {
        "recordId": "a1",
        "data":
           {
             "contractText": 
                "This is a contract that was issues on November 3, 2017 and that involves... "
           }
      },
      {
        "recordId": "b5",
        "data":
           {
             "contractText": 
                "In the City of Seattle, WA on February 5, 2018 there was a decision made..."
           }
      },
      {
        "recordId": "c3",
        "data":
           {
             "contractText": null
           }
      }
    ]
}

实际上,你的代码可能会被调用数百或数千条记录,而不仅仅是这里显示的三条。

设置 Web API 输出的格式

输出的格式是一组包含“recordId”的记录,以及一个属性包。 这个具体示例仅有一个输出,但你可以输出多个属性。 最佳做法是,如果无法处理某个记录,请考虑返回错误消息和警告消息。

{
  "values": 
  [
      {
        "recordId": "b5",
        "data" : 
        {
            "contractDate":  { "day" : 5, "month": 2, "year" : 2018 }
        }
      },
      {
        "recordId": "a1",
        "data" : {
            "contractDate": { "day" : 3, "month": 11, "year" : 2017 }                    
        }
      },
      {
        "recordId": "c3",
        "data" : 
        {
        },
        "errors": [ { "message": "contractText field required "}   ],  
        "warnings": [ {"message": "Date not found" }  ]
      }
    ]
}

将自定义技能添加到技能组

创建 Web API 扩充器时,可将 HTTP 标头和参数描述为请求的一部分。 以下代码片段显示了如何在技能组定义中包含请求参数和可选的 HTTP 标头。 如果需要将配置设置传递到代码,设置 HTTP 标头就会很有用。

{
    "skills": [
      {
        "@odata.type": "#Microsoft.Skills.Custom.WebApiSkill",
        "name": "myCustomSkill",
        "description": "This skill calls an Azure function, which in turn calls TA sentiment",
        "uri": "https://indexer-e2e-webskill.chinacloudsites.cn/api/DateExtractor?language=en",
        "context": "/document",
        "httpHeaders": {
            "DateExtractor-Api-Key": "foo"
        },
        "inputs": [
          {
            "name": "contractText",
            "source": "/document/content"
          }
        ],
        "outputs": [
          {
            "name": "contractDate",
            "targetName": "date"
          }
        ]
      }
  ]
}

后续步骤

本文介绍了将自定义技能集成到技能组时所需的接口要求。 通过下面的链接可继续详细了解自定义技能和技能组构成。