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

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 秒的时间段 (PT30S) 内未返回响应,到终结点的连接就会超时。 索引管道是同步的,如果未在超时时限内收到响应,索引就会生成超时错误。 可以通过设置 timeout 参数 (PT230S),将超时间隔增大至最大值 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, 2023 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" : 2023 }                    
        }
      },
      {
        "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"
          }
        ]
      }
  ]
}

后续步骤

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