将扩充的输出映射到 Azure AI 搜索的搜索索引中的字段

索引器阶段图,其中突出显示了输出字段映射。

本文介绍如何设置输出字段映射,定义了在技能组处理期间生成的内存中数据与搜索索引中目标字段之间的数据路径。 在索引器执行期间,技能生成的信息仅存在于内存中。 若要将此信息持久保存在搜索索引中,需要告知索引器要将数据发送到何处。

输出字段映射在索引器中定义,包含以下元素:

"outputFieldMappings": [
  {
    "sourceFieldName": "document/path-to-a-node-in-an-enriched-document",
    "targetFieldName": "some-search-field-in-an-index",
    "mappingFunction": null
  }
],

与映射逐字源字段和索引字段之间的路径的 fieldMappings 定义不同,outputFieldMappings 定义将内存中的扩充内容映射到搜索索引中的字段。

先决条件

  • 索引器、索引、数据源和技能组。

  • 索引字段必须是简单字段或顶级字段。 无法输出到复杂类型。 但是,如果你有复杂类型,可以使用输出字段定义来平展复杂类型的各个部分,并将其发送到搜索索引中的集合。

何时使用输出字段映射

如果索引器中附加了技能组,而该技能组会创建你要包含在索引中的新信息,则需要使用输出字段映射。 示例包括:

  • 来自嵌入技能的矢量
  • 从图像中提取文本de 光学字符识别 (OCR) 文本
  • 来自实体识别技能的位置、组织或人员

输出字段映射还可用于:

  • 创建生成内容的多个副本(一对多输出字段映射)。

  • 平展源文档的复杂类型。 例如,假设源文档具有复杂类型(如多部分地址),而你只需要城市。 你可以使用输出字段映射来平展嵌套数据结构,然后使用输出字段映射将输出发送到搜索索引中的字符串集合。

输出字段映射仅适用于搜索索引。 如果要填充知识存储,请将投影用于数据路径配置。

定义输出字段映射

输出字段映射将添加到索引器定义中的 outputFieldMappings 数组,通常放在 fieldMappings 数组之后。 输出字段映射由三部分组成。

可以使用 REST API 或 Azure SDK 来定义输出字段映射。

提示

导入数据向导创建的索引器包括向导生成的输出字段映射。 如需示例,请对数据源运行向导,以查看索引器中的输出字段映射。

  1. 在 Azure SDK 中使用创建索引器创建或更新索引器或等效方法。 下面是索引器定义的示例。

    {
       "name": "myindexer",
       "description": null,
       "dataSourceName": "mydatasource",
       "targetIndexName": "myindex",
       "schedule": { },
       "parameters": { },
       "fieldMappings": [],
       "outputFieldMappings": [],
       "disabled": false,
       "encryptionKey": { }
     }
    
  2. 填写 outputFieldMappings 数组以指定映射。 字段映射由 3 部分组成。

    "outputFieldMappings": [
      {
        "sourceFieldName": "/document/path-to-a-node-in-an-enriched-document",
        "targetFieldName": "some-search-field-in-an-index",
        "mappingFunction": null
      }
    ]
    
    属性 说明
    sourceFieldName 必需。 指定扩充内容的路径。 例如,/document/content。 有关路径语法和示例,请参阅 Azure AI 搜索技能集中的参考扩充
    targetFieldName 可选。 指定用于接收扩充内容的搜索字段。 目标字段必须是顶级简单字段或集合。 它不能是复杂类型中的子字段的路径。 如果你要检索复杂结构中的特定节点,可以在内存中平展各个节点,然后将输出发送到索引中的字符串集合。
    mappingFunction 可选。 添加索引器支持的映射函数提供的额外处理。 对于扩充节点,编码和解码是最常用的函数。
  3. targetFieldName 始终是搜索索引中字段的名称。

  4. sourceFieldName 是扩充文档中节点的路径。 它是技能的输出。 路径始终以 /document 开头,如果你从 Blob 编制索引,则路径的第二个元素是 /content。 第三个元素是技能生成的值。 有关详细信息和示例,请参阅 Azure AI 搜索技能组中的参考扩充

    此示例将从 Blob 的内容属性中提取的实体和情绪标签添加到搜索索引中的字段。

    {
        "name": "myIndexer",
        "dataSourceName": "myDataSource",
        "targetIndexName": "myIndex",
        "skillsetName": "myFirstSkillSet",
        "fieldMappings": [],
        "outputFieldMappings": [
            {
                "sourceFieldName": "/document/content/organizations/*/description",
                "targetFieldName": "descriptions",
                "mappingFunction": {
                    "name": "base64Decode"
                }
            },
            {
                "sourceFieldName": "/document/content/organizations",
                "targetFieldName": "orgNames"
            },
            {
                "sourceFieldName": "/document/content/sentiment",
                "targetFieldName": "sentiment"
            }
        ]
    }
    
  5. 在将字段内容存储到索引之前,分配转换它所需的任何映射函数。 对于扩充节点,编码和解码是最常用的函数。

一对多输出字段映射

可以使用输出字段映射将单个源字段路由到搜索索引中的多个字段。 若要进行比较测试,或要获取具有不同属性的字段,可以执行此操作。

假设某个技能组为矢量字段生成嵌入,并且某个索引具有多个因算法和压缩设置而异的矢量字段。 在索引器中,将嵌入技能的输出映射到搜索索引中多个矢量字段中的每一个。

"outputFieldMappings": [
    { "sourceFieldName" : "/document/content/text_vector", "targetFieldName" : "vector_hnsw" }, 
    { "sourceFieldName" : "/document/content/text_vector", "targetFieldName" : "vector_eknn" },
    { "sourceFieldName" : "/document/content/text_vector", "targetFieldName" : "vector_narrow" }, 
    { "sourceFieldName" : "/document/content/text_vector", "targetFieldName" : "vector_no_stored" },
    { "sourceFieldName" : "/document/content/text_vector", "targetFieldName" : "vector_scalar" }       
  ]

源字段路径是技能输出。 在此示例中,输出为 text_vector。 目标名称是可选属性。 如果未为输出映射指定目标名称,则路径将是 embedding,更确切地说,是 /document/content/embedding

{
  "name": "test-vector-size-ss",  
  "description": "Generate embeddings using AOAI",
  "skills": [
    {
      "@odata.type": "#Microsoft.Skills.Text.AzureOpenAIEmbeddingSkill",
      "name": "#1",
      "description": null,
      "context": "/document/content",
      "resourceUri": "https://my-demo-chinaeast.openai.azure.com",
      "apiKey": null,
      "deploymentId": "text-embedding-ada-002",
      "dimensions": 1536,
      "modelName": "text-embedding-ada-002",
      "inputs": [
        {
          "name": "text",
          "source": "/document/content"
        }
      ],
      "outputs": [
        {
          "name": "embedding",
          "targetName": "text_vector"
        }
      ],
      "authIdentity": null
    }
  ]
}

将复杂结构平展为字符串集合

如果源数据由嵌套或分层的 JSON 组成,则你无法使用字段映射来设置数据路径。 在这种情况下,搜索索引必须在每个级别镜像源数据结构以进行完整导入。

本部分引导你完成一个导入过程,该过程在源端和目标端生成复杂文档的一对一反映。 接下来,该过程使用同一源文档来演示如何检索各个节点并将其平展为字符串集合。

下面是 Azure Cosmos DB 中包含嵌套 JSON 的文档示例:

{
   "palette":"primary colors",
   "colors":[
      {
         "name":"blue",
         "medium":[
            "acrylic",
            "oil",
            "pastel"
         ]
      },
      {
         "name":"red",
         "medium":[
            "acrylic",
            "pastel",
            "watercolor"
         ]
      },
      {
         "name":"yellow",
         "medium":[
            "acrylic",
            "watercolor"
         ]
      }
   ]
}

如果你想要为此源文档完整地编制索引,请创建一个索引定义,其中的字段名称、级别和类型反映为复杂类型。 由于搜索索引中的复杂类型不支持字段映射,因此索引定义必须镜像源文档。

{
  "name": "my-test-index",
  "defaultScoringProfile": "",
  "fields": [
    { "name": "id", "type": "Edm.String", "searchable": false, "retrievable": true, "key": true},
    { "name": "palette", "type": "Edm.String", "searchable": true, "retrievable": true },
    { "name": "colors", "type": "Collection(Edm.ComplexType)",
      "fields": [
        {
          "name": "name",
          "type": "Edm.String",
          "searchable": true,
          "retrievable": true
        },
        {
          "name": "medium",
          "type": "Collection(Edm.String)",
          "searchable": true,
          "retrievable": true,
        }
      ]
    }
  ]
}

下面是执行导入的示例索引器定义。 请注意,没有字段映射,也没有技能组。

{
  "name": "my-test-indexer",
  "dataSourceName": "my-test-ds",
  "skillsetName": null,
  "targetIndexName": "my-test-index",

  "fieldMappings": [],
  "outputFieldMappings": []
}

结果是以下示例搜索文档,类似于 Azure Cosmos DB 中的原始文档。

{
  "value": [
    {
      "@search.score": 1,
      "id": "11bb11bb-cc22-dd33-ee44-55ff55ff55ff",
      "palette": "primary colors",
      "colors": [
        {
          "name": "blue",
          "medium": [
            "acrylic",
            "oil",
            "pastel"
          ]
        },
        {
          "name": "red",
          "medium": [
            "acrylic",
            "pastel",
            "watercolor"
          ]
        },
        {
          "name": "yellow",
          "medium": [
            "acrylic",
            "watercolor"
          ]
        }
      ]
    }
  ]
}

搜索索引中的另一种呈现方式是将源嵌套结构中的各个节点平展为搜索索引中的字符串集合。

若要完成此任务,需要一个将内存中节点映射到索引中的字符串集合的 outputFieldMappings。 尽管输出字段映射主要应用于技能输出,但你也可以在文档破解(索引器打开源文档并将其读入内存)之后使用它们来寻址节点。

下面的示例索引定义使用字符串集合来接收平展的输出:

{
  "name": "my-new-flattened-index",
  "defaultScoringProfile": "",
  "fields": [
    { "name": "id", "type": "Edm.String", "searchable": false, "retrievable": true, "key": true },
    { "name": "palette", "type": "Edm.String", "searchable": true, "retrievable": true },
    { "name": "color_names", "type": "Collection(Edm.String)", "searchable": true, "retrievable": true },
    { "name": "color_mediums", "type": "Collection(Edm.String)", "searchable": true, "retrievable": true}
  ]
}

下面是示例索引器定义,它使用 outputFieldMappings 将嵌套的 JSON 与字符串集合字段相关联。 请注意,即使没有技能组,源字段也会对扩充节点使用路径语法。 在文档破解期间会在系统中创建扩充文档,这意味着你可以访问每个文档树中的节点,前提是在文档破解时这些节点存在。

{
  "name": "my-test-indexer",
  "dataSourceName": "my-test-ds",
  "skillsetName": null,
  "targetIndexName": "my-new-flattened-index",
  "parameters": {  },
  "fieldMappings": [   ],
  "outputFieldMappings": [
    {
       "sourceFieldName": "/document/colors/*/name",
       "targetFieldName": "color_names"
    },
    {
       "sourceFieldName": "/document/colors/*/medium",
       "targetFieldName": "color_mediums"
    }
  ]
}

定义的结果如下。 在本例中,简化结构会丢失上下文。 给定颜色与可以使用此颜色的媒体之间不再有任何关联。 但是,根据你的方案,类似于以下示例的结果可能正符合你的需要。

{
  "value": [
    {
      "@search.score": 1,
      "id": "11bb11bb-cc22-dd33-ee44-55ff55ff55ff",
      "palette": "primary colors",
      "color_names": [
        "blue",
        "red",
        "yellow"
      ],
      "color_mediums": [
        "[\"acrylic\",\"oil\",\"pastel\"]",
        "[\"acrylic\",\"pastel\",\"watercolor\"]",
        "[\"acrylic\",\"watercolor\"]"
      ]
    }
  ]
}