Azure 认知搜索中的技能组概念Skillset concepts in Azure Cognitive Search

本文适用于需要更深入地了解技能组概念和构成的开发人员,并且假定这些开发人员熟悉 AI 扩充流程。This article is for developers who need a deeper understanding of skillset concepts and composition, and assumes familiarity with the AI enrichment process. 如果你不熟悉此概念,请从 Azure 认知搜索中的 AI 扩充开始。If you are new to this concept, start with AI enrichment in Azure Cognitive Search.

技能组简介Introducing skillsets

技能组是 Azure 认知搜索中附加到某个索引器的可重用资源,它指定在编制索引期间用于分析、转换和扩充文本或图像内容的技能集合。A skillset is a reusable resource in Azure Cognitive Search that is attached to an indexer, and it specifies a collection of skills used for analyzing, transforming, and enriching text or image content during indexing. 技能具有输入和输出,一项技能的输出通常会成为一系列流程中另一项技能的输入。Skills have inputs and outputs, and often the output of one skill becomes the input of another in a chain or sequence of processes.

技能组有三个主要属性:A skillset has three main properties:

  • skills,技能的无序集合,平台将根据每项技能所需的输入来确定这些技能的执行顺序。skills, an unordered collection of skills for which the platform determines the sequence of execution based on the inputs required for each skill.
  • cognitiveServices,这是认知服务资源的键,它为技能组(包括内置技能)执行图像和文本处理。cognitiveServices, the key of a Cognitive Services resource that performs image and text processing for skillsets that include built-in skills.
  • knowledgeStore(可选),要将扩充的文档投影到的 Azure 存储帐户。knowledgeStore, (optional) an Azure Storage account where your enriched documents will be projected. 搜索索引也使用扩充的文档。Enriched documents are also consumed by search indexes.

技能集是以 JSON 格式创作的。Skillsets are authored in JSON. 下面的示例是此 hotel-reviews 技能组的稍简版本,用于阐释本文中的概念。The following example is a slightly simplified version of this hotel-reviews skillset, used to illustrate concepts in this article.

前两个技能如下所示:The first two skills are shown below:

  • 技能 #1 是一个文本拆分技能,它接受“reviews_text”字段的内容作为输入,并将该内容拆分为大小为 5000 个字符的“页面“作为输出。Skill #1 is a Text Split skill that accepts the contents of the "reviews_text" field as input, and splits that content into "pages" of 5000 characters as output.
  • 技能 #2 是一个情绪检测技能,它接受“页面”作为输入,并生成一个名为“Sentiment”的新字段作为输出,该输出包含情绪分析结果。Skill #2 is a Sentiment Detection skill accepts "pages" as input, and produces a new field called "Sentiment" as output that contains the results of sentiment analysis.
{
    "skills": [
        {
            "@odata.type": "#Microsoft.Skills.Text.SplitSkill",
            "name": "#1",
            "description": null,
            "context": "/document/reviews_text",
            "defaultLanguageCode": "en",
            "textSplitMode": "pages",
            "maximumPageLength": 5000,
            "inputs": [
                {
                    "name": "text",
                    "source": "/document/reviews_text"
                }
            ],
            "outputs": [
                {
                    "name": "textItems",
                    "targetName": "pages"
                }
            ]
        },
        {
            "@odata.type": "#Microsoft.Skills.Text.SentimentSkill",
            "name": "#2",
            "description": null,
            "context": "/document/reviews_text/pages/*",
            "defaultLanguageCode": "en",
            "inputs": [
                {
                    "name": "text",
                    "source": "/document/reviews_text/pages/*",
                }
            ],
            "outputs": [
                {
                    "name": "score",
                    "targetName": "Sentiment"
                }
            ]
        },
  "cognitiveServices": null,
  "knowledgeStore": {  }
}

备注

你可以构建带循环和分支的复杂技能组,并使用条件技能来创建表达式。You can build complex skillsets with looping and branching, using the Conditional skill to create the expressions. 语法基于 JSON 指针路径表示法,做了少量的修改来标识扩充树中的节点。The syntax is based on the JSON Pointer path notation, with a few modifications to identify nodes in the enrichment tree. "/" 遍历树中的较低级别,"*" 充当上下文中的 for-each 运算符。A "/" traverses a level lower in the tree and "*" acts as a for-each operator in the context. 本文中的许多示例阐释了此语法。Numerous examples in this article illustrate the syntax.

扩充树Enrichment tree

扩充管道中的步骤的进度图中,内容处理跟在从源中提取文本和图像的“文档破解”阶段之后。In the progression of steps in an enrichment pipeline, content processing follows the document cracking phase where text and images are extracted from the source. 然后,可以将图像内容路由到指定了图像处理的技能,而文本内容将排队等待进行文本处理。Image content can then be routed to skills that specify image processing, while text content is queued for text processing. 对于包含大量文本的源文档,可在索引器上设置“分析模式”,将文本分段为较小的区块进行更好的处理。For source documents that contain large quantities of text, you can set a parsing mode on the indexer to segment text into smaller chunks for more optimal processing.

管道中的知识存储示意图Knowledge store in pipeline diagram

将文档放入扩充管道后,它将表示为内容和关联扩充内容的树。Once a document is in the enrichment pipeline, it is represented as a tree of content and associated enrichments. 此树实例化为文档破解的输出。This tree is instantiated as the output of document cracking. 扩充管道可以使用扩充树格式将元数据附加到平整基元数据类型。扩充树格式不是有效的 JSON 对象,但可以投影为有效的 JSON 格式。The enrichment tree format enables the enrichment pipeline to attach metadata to even primitive data types, it is not a valid JSON object but can be projected into a valid JSON format. 下表显示了进入扩充管道的文档的状态:The following table shows the state of a document entering into the enrichment pipeline:

数据源\分析模式Data Source\Parsing Mode 默认Default JSON、JSON 行 和 CSVJSON, JSON Lines & CSV
Blob 存储Blob Storage /document/content/document/content
/document/normalized_images/*/document/normalized_images/*
/document/{key1}/document/{key1}
/document/{key2}/document/{key2}
SQLSQL /document/{column1}/document/{column1}
/document/{column2}/document/{column2}
空值N/A
Cosmos DBCosmos DB /document/{key1}/document/{key1}
/document/{key2}/document/{key2}
空值N/A

技能在执行时,会将新节点添加到扩充树。As skills execute, they add new nodes to the enrichment tree. 然后,这些新节点可用作下游技能的输入、投影到知识存储,或映射到索引字段。These new nodes may then be used as inputs for downstream skills, projecting to the knowledge store, or mapping to index fields. 扩充是不可变的:创建节点后无法对其进行编辑。Enrichments aren't mutable: once created, nodes cannot be edited. 随着技能集变得越来越复杂,扩充树也会更加复杂,但是,并非扩充树中的所有节点都需要将扩充保存到索引或知识存储中。As your skillsets get more complex, so will your enrichment tree, but not all nodes in the enrichment tree need to make it to the index or the knowledge store.

你可以选择性地将一部分扩充保存到索引或知识存储中。You can selectively persist only a subset of the enrichments to the index or the knowledge store.

上下文Context

每个技能都需要一个上下文。Each skill requires a context. 上下文确定:A context determines:

  • 根据所选节点执行技能的次数。The number of times the skill executes, based on the nodes selected. 对于类型集合的上下文值,在末尾添加 /* 会导致为该集合中的每个实例调用技能一次。For context values of type collection, adding an /* at the end will result in the skill being invoked once for each instance in the collection.

  • 在扩充树中添加技能输出的位置。Where in the enrichment tree the skill outputs are added. 输出始终作为上下文节点的子级添加到树中。Outputs are always added to the tree as children of the context node.

  • 输入的形状。Shape of the inputs. 对于多级别集合,将上下文设置为父集合会影响技能输入的形状。For multi level collections, setting the context to the parent collection will affect the shape of the input for the skill. 例如,如果某个扩充树包含国家/地区列表,其中的每个国家/地区已使用包含邮政编码列表的省/自治区/直辖市列表进行扩充。For example if you have an enrichment tree with a list of countries/regions, each enriched with a list of states containing a list of ZIP codes.

上下文Context 输入Input 输入的形状Shape of Input 技能调用Skill Invocation
/document/countries/* /document/countries/*/states/*/zipcodes/* 国家/地区中所有邮政编码的列表A list of all ZIP codes in the country/region 对每个国家/地区调用一次Once per country/region
/document/countries/*/states/* `/document/countries/ /states/ /zipcodes/*```/document/countries//states//zipcodes/*`` 省/自治区/直辖市中邮政编码的列表A list of ZIP codes in the state 对每个国家/地区和州/省的组合调用一次Once per combination of country/region and state

生成扩充数据Generate enriched data

我们将使用酒店评论技能组作为参考点来查看:Using the hotel reviews skillset as a reference point, we are going to look at:

  • 扩充树如何随着每个技能的执行而演变How the enrichment tree evolves with the execution of each skill
  • 如何结合上下文和输入来确定技能的执行次数How the context and inputs work to determine how many times a skill executes
  • 哪种输入形状基于上下文What the shape of the input is based on the context

扩充流程中的“文档“表示 hotel_reviews.csv 源文件内的单个行(酒店评论)。A "document" within the enrichment process represents a single row (a hotel review) within the hotel_reviews.csv source file.

技能 #1:拆分技能Skill #1: Split skill

当源内容由大块文本组成时,将其分解成较小的部分会很有帮助,可以提高语言、情绪和关键短语检测的准确度。When source content consists of large chunks of text, it's helpful to break it into smaller components for greater accuracy of language, sentiment, and key phrase detection. 有两个可用的粒度:页面和句子。There are two grains available: pages and sentences. 一个页面包含大约 5000 个字符。A page consists of approximately 5000 characters.

文本拆分技能通常是技能组中的第一个技能。A text split skill is typically first in a skillset.

      "@odata.type": "#Microsoft.Skills.Text.SplitSkill",
      "name": "#1",
      "description": null,
      "context": "/document/reviews_text",
      "defaultLanguageCode": "en",
      "textSplitMode": "pages",
      "maximumPageLength": 5000,
      "inputs": [
        {
          "name": "text",
          "source": "/document/reviews_text"
        }
      ],
      "outputs": [
        {
          "name": "textItems",
          "targetName": "pages"
        }

在技能上下文为 "/document/reviews_text" 的情况下,拆分技能将针对 reviews_text 执行一次。With the skill context of "/document/reviews_text", the split skill will execute once for the reviews_text. 技能输出是一个列表,其中的 reviews_text 分块成包含 5000 个字符的段。The skill output is a list where the reviews_text is chunked into 5000 character segments. 拆分技能的输出名为 pages,将添加到扩充树中。The output from the split skill is named pages and it is added to the enrichment tree. 使用 targetName 功能可以在将技能输出添加到扩充树之前对其重命名。The targetName feature allows you to rename a skill output before being added to the enrichment tree.

现在,扩充树的技能上下文下包含一个新节点。The enrichment tree now has a new node placed under the context of the skill. 此节点可用于任何技能、投影或输出字段映射。This node is available to any skill, projection, or output field mapping. 从概念上讲,该树如下所示:Conceptually, the tree looks as follows:

完成文档破解后的扩充树enrichment tree after document cracking

所有扩充的根节点是 "/document"The root node for all enrichments is "/document". 使用 Blob 索引器时,"/document" 节点包含 "/document/content""/document/normalized_images" 的子节点。When working with blob indexers, the "/document" node will have child nodes of "/document/content" and "/document/normalized_images". 使用 CSV 数据时(如本示例所示),列名称将映射到 "/document" 下的节点。When working with CSV data, as we are in this example, the column names will map to nodes beneath "/document".

若要访问由技能添加到节点的任何扩充,需要使用扩充的完整路径。To access any of the enrichments added to a node by a skill, the full path for the enrichment is needed. 例如,若要使用 pages 节点中的文本作为另一技能的输入,需将该节点指定为 "/document/reviews_text/pages/*"For example, if you want to use the text from the pages node as an input to another skill, you will need to specify it as "/document/reviews_text/pages/*".

执行技能 #1 后的扩充树enrichment tree after skill #1

技能 #2:语言检测Skill #2 Language detection

酒店评论文档包含以多种语言表达的客户反馈。Hotel review documents include customer feedback expressed in multiple languages. 语言检测技能确定使用的是哪种语言。The language detection skill determines which language is used. 然后,结果将传递给关键短语提取和情绪检测,在检测情绪和短语时将考虑语言。The result is then passed to key phrase extraction and sentiment detection, taking language into consideration when detecting sentiment and phrases.

尽管语言检测技能是技能集中定义的第三个技能(技能 #3),但它是下一个要执行的技能。While the language detection skill is the third (skill #3) skill defined in the skillset, it is the next skill to execute. 由于它不会受到阻止(无需输入),因此它将与前一个技能同时执行。Since it is not blocked by requiring any inputs, it will execute in parallel with the previous skill. 与前面的拆分技能一样,语言检测技能也只对每个文档调用一次。Like the split skill that preceded it, the language detection skill is also invoked once for each document. 扩充树现在包含新的语言节点。The enrichment tree now has a new node for language.

执行技能 #2 后的扩充树enrichment tree after skill #2

技能 #3:关键短语技能Skill #3: Key phrases skill

将会针对 pages 集合中的每个项,根据给定的 /document/reviews_text/pages/* 上下文调用关键短语技能一次。Given the context of /document/reviews_text/pages/* the key phrases skill will be invoked once for each of the items in the pages collection. 该技能的输出是关联的页元素下的一个节点。The output from the skill will be a node under the associated page element.

现在,你应该可以查看技能集中的其他技能,并直观地了解扩充树如何随着每个技能的执行而不断扩大。You should now be able to look at the rest of the skills in the skillset and visualize how the tree of enrichments will continue to grow with the execution of each skill. 某些技能(例如合并技能和整形程序技能)也会创建新的节点,但只使用现有节点中的数据,而不会创建全新的扩充。Some skills, such as the merge skill and the shaper skill, also create new nodes but only use data from existing nodes and don't create net new enrichments.

执行所有技能后的扩充树enrichment tree after all skills

上述树中的连接器颜色指示扩充由不同的技能创建,节点需要单独寻址,并且在选择父节点时不会成为返回的对象部分。The colors of the connectors in the tree above indicate that the enrichments were created by different skills and the nodes will need to be addressed individually and will not be part of the object returned when selecting the parent node.

保存扩充Save enrichments

在 Azure 认知搜索中,索引器保存它创建的输出。In Azure Cognitive Search, an indexer saves the output it creates. 其中一个输出始终是可搜索的索引One of the outputs is always a searchable index. 必须指定索引。在附加技能组时,索引所引入的数据将包括扩充的内容。Specifying an index is a requirement, and when you attach a skillset, the data ingested by an index includes the substance of the enrichments. 通常,特定技能的输出(例如关键短语或情绪评分)将引入到为此目的而创建的字段的索引中。Usually, the outputs of specific skills, such as key phrases or sentiment scores, are ingested into the index in a field created for that purpose.

此外,索引器还可以将输出发送到知识存储,以便在其他工具或流程中使用。Optionally, an indexer can also send the output to a knowledge store for consumption in other tools or processes. 知识存储是作为技能组的一部分定义的。A knowledge store is defined as part of the skillset. 它的定义决定了你的已扩充文档是被投影为表还是对象(文件或 blob)。It's definition determines whether your enriched documents are projected as tables or objects (files or blobs). 表格投影非常适用于 Power BI 等工具中的交互式分析,而文件和 blob 通常用于数据科学或类似的流程中。Tabular projections are well-suited for interactive analysis in tools like Power BI, whereas files and blobs are typically used in data science or similar processes. 在本部分中,你将了解技能组成分如何对你要投影的表或对象进行整形。In this section, you'll learn how skillset composition can shape the tables or objects you want to project.

投影数Projections

对于以知识存储为目标的内容,你需要考虑内容的构造方式。For content that targets a knowledge store, you will want to consider how the content is structured. 投影是从扩充树中选择节点并在知识存储中创建其物理表示形式的过程。Projection is the process of selecting the nodes from the enrichment tree and creating a physical expression of them in the knowledge store. 投影是可输出为表或对象投影的文档(内容和扩充)的自定义形状。Projections are custom shapes of the document (content and enrichments) that can be output as either table or object projections. 若要详细了解如何使用投影,请参阅使用投影To learn more about working with projections, see working with projections.

字段映射选项Field mapping options

SourceContextSourceContext

sourceContext 元素仅用于技能输入和投影。The sourceContext element is only used in skill inputs and projections. 它用于构造多级别嵌套对象。It is used to construct multi-level, nested objects. 你可能需要创建一个新对象,以将其作为技能或项目的输入传递到知识存储中。You may need to create a new object to either pass it as an input to a skill or project into the knowledge store. 由于扩充节点可能不是扩充树中的有效 JSON 对象,并且引用树中的某个节点仅返回该节点在创建时的状态,因此,使用扩充作为技能输入或预测时,需要创建一个格式正确的 JSON 对象。As enrichment nodes may not be a valid JSON object in the enrichment tree and referencing a node in the tree only returns that state of the node when it was created, using the enrichments as skill inputs or projections requires you to create a well formed JSON object. sourceContext 可用于构造分层的匿名类型对象,如果你仅使用上下文,则需要多个技能。The sourceContext enables you to construct a hierarchical, anonymous type object, which would require multiple skills if you were only using the context.

下面的示例展示了如何使用 sourceContextUsing sourceContext is shown in the following examples. 查看生成了扩充的技能输出,以确定它是否为有效的 JSON 对象而不是基元类型。Look at the skill output that generated an enrichment to determine if it is a valid JSON object and not a primitive type.

切片投影Slicing projections

定义表投影组时,可将扩充树中的单个节点切片为多个相关表。When defining a table projection group, a single node in the enrichment tree can be sliced into multiple related tables. 如果添加的表的源路径是现有表投影的子级,则生成的子节点将不是现有表投影的子级,而会投影到新的相关表。If you add a table with a source path that is a child of an existing table projection, the resulting child node will not be a child of the existing table projection, but instead will be projected into the new, related, table. 借助此切片技术,可以使用整形程序技能定义单个节点,该节点可以用作所有表投影的源。This slicing technique allows you to define a single node in a shaper skill that can be the source for all your table projections.

整形投影Shaping projections

可通过两种方式来定义投影:There are two ways to define a projection:

  • 使用文本整形程序技能来创建一个新节点,该节点可充当你要投影的所有扩充的根节点。Use the Text Shaper skill to create a new node that is the root node for all the enrichments you are projecting. 然后,在投影中,只需引用整形程序技能的输出。Then, in your projections, you would only reference the output of the shaper skill.

  • 使用投影定义本身中的内联整形投影。Use an inline shape a projection within the projection definition itself.

整形程序方法比内联整形更繁琐,但可确保扩充树的所有变换都包含在技能中,并确保输出是可重用的对象。The shaper approach is more verbose than inline shaping but ensures that all the mutations of the enrichment tree are contained within the skills and that the output is an object that can be reused. 相反,内联整形可让你创建所需的形状,但它是一个匿名对象,仅适用于定义它时所针对的投影。In contrast, inline shaping allows you to create the shape you need, but is an anonymous object and is only available to the projection for which it is defined. 这些方法可以结合使用,也可以单独使用。The approaches can be used together or separately. 在门户工作流中创建的技能集包含这两种方法。The skillset created for you in the portal workflow contains both. 该技能集对表投影使用整形程序技能,但同时使用内联整形来投影关键短语表。It uses a shaper skill for the table projections, but also uses inline shaping to project the key phrases table.

为了延伸该示例,可以选择删除内联整形,并使用整形程序技能为关键短语创建新节点。To extend the example, you could choose to remove the inline shaping and use a shaper skill to create a new node for the key phrases. 若要创建投影到三个表(即 hotelReviewsDocumenthotelReviewsPageshotelReviewsKeyPhrases)的形状,请使用后续部分所述的两个选项。To create a shape projected into three tables, namely, hotelReviewsDocument, hotelReviewsPages, and hotelReviewsKeyPhrases, the two options are described in the following sections.

整形程序技能和投影Shaper skill and projection

This

备注

为简洁起见,本示例中已删除了文档表中的某些列。Some of the columns from the document table have been removed from this example for brevity.

{
    "@odata.type": "#Microsoft.Skills.Util.ShaperSkill",
    "name": "#5",
    "description": null,
    "context": "/document",
    "inputs": [        
        {
            "name": "reviews_text",
            "source": "/document/reviews_text",
            "sourceContext": null,
            "inputs": []
        },
        {
            "name": "reviews_title",
            "source": "/document/reviews_title",
            "sourceContext": null,
            "inputs": []
        },
        {
            "name": "AzureSearch_DocumentKey",
            "source": "/document/AzureSearch_DocumentKey",
            "sourceContext": null,
            "inputs": []
        },  
        {
            "name": "pages",
            "source": null,
            "sourceContext": "/document/reviews_text/pages/*",
            "inputs": [
                {
                    "name": "SentimentScore",
                    "source": "/document/reviews_text/pages/*/Sentiment",
                    "sourceContext": null,
                    "inputs": []
                },
                {
                    "name": "LanguageCode",
                    "source": "/document/Language",
                    "sourceContext": null,
                    "inputs": []
                },
                {
                    "name": "Page",
                    "source": "/document/reviews_text/pages/*",
                    "sourceContext": null,
                    "inputs": []
                },
                {
                    "name": "keyphrase",
                    "sourceContext": "/document/reviews_text/pages/*/Keyphrases/*",
                    "inputs": [
                        {
                            "source": "/document/reviews_text/pages/*/Keyphrases/*",
                            "name": "Keyphrases"
                        }
                    ]
                }
            ]
        }
    ],
    "outputs": [
        {
            "name": "output",
            "targetName": "tableprojection"
        }
    ]
}

使用上述 outputs 节中定义的 tableprojection 节点,我们现在可以使用切片功能将 tableprojection 节点的部分投影到不同的表:With the tableprojection node defined in the outputs section above, we can now use the slicing feature to project parts of the tableprojection node into different tables:

备注

这只是知识存储配置中的一个投影片段。This is only a snippet of the projection within the knowledge store configuration.

"projections": [
    {
        "tables": [
            {
                "tableName": "hotelReviewsDocument",
                "generatedKeyName": "Documentid",
                "source": "/document/tableprojection"
            },
            {
                "tableName": "hotelReviewsPages",
                "generatedKeyName": "Pagesid",
                "source": "/document/tableprojection/pages/*"
            },
            {
                "tableName": "hotelReviewsKeyPhrases",
                "generatedKeyName": "KeyPhrasesid",
                "source": "/document/tableprojection/pages/*/keyphrase/*"
            }
        ]
    }
]

内联整形投影Inline shaping projections

内嵌整形方法不需要整形程序技能,因为投影所需的所有形状只在有必要时才会创建。The inline shaping approach does not require a shaper skill as all shapes needed for the projections are created at the time they are needed. 若要投影与上一个示例相同的数据,可使用如下所示的内联投影选项:To project the same data as the previous example, the inline projection option would look like this:

"projections": [
    {
        "tables": [
            {
                "tableName": "hotelReviewsInlineDocument",
                "generatedKeyName": "Documentid",
                "sourceContext": "/document",     
                "inputs": [
                    {
                        "name": "reviews_text",
                        "source": "/document/reviews_text"
                    },
                    {
                        "name": "reviews_title",
                        "source": "/document/reviews_title"
                    },
                    {
                        "name": "AzureSearch_DocumentKey",
                        "source": "/document/AzureSearch_DocumentKey"
                    }                             
                ]
            },
            {
                "tableName": "hotelReviewsInlinePages",
                "generatedKeyName": "Pagesid",
                "sourceContext": "/document/reviews_text/pages/*",
                "inputs": [
                        {
                    "name": "SentimentScore",
                    "source": "/document/reviews_text/pages/*/Sentiment"
                    },
                    {
                        "name": "LanguageCode",
                        "source": "/document/Language"
                    },
                    {
                        "name": "Page",
                        "source": "/document/reviews_text/pages/*"
                    }
                ]
            },
            {
                "tableName": "hotelReviewsInlineKeyPhrases",
                "generatedKeyName": "KeyPhraseId",
                "sourceContext": "/document/reviews_text/pages/*/Keyphrases/*",
                "inputs": [
                    {
                        "name": "Keyphrases",
                        "source": "/document/reviews_text/pages/*/Keyphrases/*"
                    }
                ]
            }
        ]
    }
]

使用这两种方法后,可以观察如何使用 "sourceContext" 来投影 "Keyphrases" 的值。One observation from both the approaches is how values of "Keyphrases" are projected using the "sourceContext". 包含字符串集合的 "Keyphrases" 节点本身是页文本的子级。The "Keyphrases" node, which contains a collection of strings, is itself a child of the page text. 但是,由于投影需要 JSON 对象并且页是基元(字符串),因此使用了 "sourceContext" 将关键短语包装为具有命名属性的对象。However, because projections require a JSON object and the page is a primitive (string), the "sourceContext" is used to wrap the key phrase into an object with a named property. 使用此技术可以单独投影平整基元。This technique enables even primitives to be projected independently.

后续步骤Next steps

接下来,请创建包含认知技能的第一个技能集。As a next step, create your first skillset with cognitive skills.