

本文属于机器翻译版本。若本译文内容与英语原文存在差异，则一律以英文原文为准。

# 使用自定义标签工作流程处理数据 AWS Lambda
<a name="sms-custom-templates-step3"></a>

在本主题中，您可以了解在创建自定义标注工作流程时如何部署可选的 [AWS Lambda](https://aws.amazon.com/lambda/) 函数。您可以指定两种类型的 Lambda 函数与自定义标注工作流程配合使用。
+ *注释前 Lambda*：在将每个数据对象发送给工作人员之前，此函数启动并预处理发送给标注作业的每个数据对象。
+ *注释后 Lambda*：该函数在工作人员提交任务后处理结果。如果为每个数据对象指定多个工作人员，则该函数可能包含用于合并注释的逻辑。

如果您是 Lambda 和 Ground Truth 的新用户，我们建议您按照以下方式使用本节中的页面：

1. 首先，查看[使用注释前和注释后 Lambda 函数使用 Lambda 函数](sms-custom-templates-step3-lambda-requirements.md)。

1. 然后，使用 [添加与 Ground Trut AWS Lambda h 一起使用所需的权限](sms-custom-templates-step3-lambda-permissions.md) 页面了解在 Ground Truth 自定义标注作业中使用注释前和注释后 Lambda 函数的安全和权限要求。

1. 接下来，您需要访问 Lambda 控制台或使用 Lambda APIs 来创建您的函数。使用[使用 Ground Truth 模板创建 Lambda 函数](sms-custom-templates-step3-lambda-create.md)部分以了解如何创建 Lambda 函数。

1. 要了解如何测试 Lambda 函数，请参阅[测试注释前和注释后 Lambda 函数](sms-custom-templates-step3-lambda-test.md)。

1. 创建预处理和后处理 Lambda 函数后，从 Ground Truth 控制台中自定义 HTML 代码编辑器后的 **Lambda 函数**部分选择它们。要了解如何在 `CreateLabelingJob` API 请求中使用这些函数，请参阅[创建标注作业 (API)](sms-create-labeling-job-api.md)。

有关包含注释前和注释后 Lambda 函数示例的自定义标注工作流教程，请参阅 [演示模板：使用 `crowd-bounding-box` 的映像注释](sms-custom-templates-step2-demo1.md)。

**Topics**
+ [使用注释前和注释后 Lambda 函数](sms-custom-templates-step3-lambda-requirements.md)
+ [添加与 Ground Trut AWS Lambda h 一起使用所需的权限](sms-custom-templates-step3-lambda-permissions.md)
+ [使用 Ground Truth 模板创建 Lambda 函数](sms-custom-templates-step3-lambda-create.md)
+ [测试注释前和注释后 Lambda 函数](sms-custom-templates-step3-lambda-test.md)

# 使用注释前和注释后 Lambda 函数
<a name="sms-custom-templates-step3-lambda-requirements"></a>

使用这些主题可以了解发送到注释前和注释后 Lambda 函数的请求语法，以及 Ground Truth 在自定义标注工作流程中使用的所需响应语法。

**Topics**
+ [注释前 Lambda](#sms-custom-templates-step3-prelambda)
+ [注释后 Lambda](#sms-custom-templates-step3-postlambda)

## 注释前 Lambda
<a name="sms-custom-templates-step3-prelambda"></a>

在将标注任务发送给工作人员之前，可以可选的调用注释前 Lambda 函数。

Ground Truth 向您的 Lambda 函数发送一个 JSON 格式的请求，以提供有关标注作业和数据对象的详细信息。

以下是 2 个 JSON 格式请求示例。

------
#### [ Data object identified with "source-ref" ]

```
{
    "version": "2018-10-16",
    "labelingJobArn": <labelingJobArn>
    "dataObject" : {
        "source-ref": <s3Uri>
    }
}
```

------
#### [ Data object identified with "source" ]

```
{
    "version": "2018-10-16",
    "labelingJobArn": <labelingJobArn>
    "dataObject" : {
        "source": <string>
    }
}
```

------

 以下列表包含注释前请求模式。每个参数的说明如下。
+ `version`（字符串）：这是 Ground Truth 内部使用的版本号。
+ `labelingJobArn`（字符串）：这是标注作业的 Amazon 资源名称 (ARN)。在使用 Ground Truth API 操作（如 `DescribeLabelingJob`）时，此 ARN 可用于引用标注作业。
+ `dataObject`（JSON 对象）：该键包含单一 JSON 行，可以来自您的输入清单文件，也可以来自 Amazon SNS。清单中的 JSON 行对象的大小最多可达 100 千字节，并且包含各种数据。对于非常基本的图像注释作业，`dataObject` JSON 可能只包含一个 `source-ref` 键，用于标识要注释的图像。如果数据对象（例如，一行文本）直接包含在输入清单文件中，则用 `source` 标识数据对象。如果您创建验证或调整作业，则此行可能包含来自前一个标注作业的标签数据和元数据。

以下标签示例显示了注释前请求的示例。这些示例请求中的每个参数都在选项卡式表下面进行了说明。

------
#### [ Data object identified with "source-ref" ]

```
{
    "version": "2018-10-16",
    "labelingJobArn": "arn:aws:sagemaker:us-west-2:111122223333:labeling-job/<labeling_job_name>"
    "dataObject" : {
        "source-ref": "s3://input-data-bucket/data-object-file-name"
    }
}
```

------
#### [ Data object identified with "source" ]

```
{
    "version": "2018-10-16",
    "labelingJobArn": "arn:aws:sagemaker:<aws_region>:111122223333:labeling-job/<labeling_job_name>"
    "dataObject" : {
        "source": "Sue purchased 10 shares of the stock on April 10th, 2020"
    }
}
```

------

作为返回对象，Ground Truth 需要如下格式的响应：

**Example 预期的返回数据**  

```
{
    "taskInput": <json object>,
    "isHumanAnnotationRequired": <boolean> # Optional
}
```

在前面的示例中，`<json object>` 需要包含自定义工作人员任务模板所需的*所有*数据。如果您正在执行一个边界框任务，其中指令始终保持不变，那么可能只是图像文件的 HTTP(S) 或 Amazon S3 资源。如果执行的是情绪分析任务，并且不同的对象可能有不同的选择，那么是作为字符串的对象引用和作为字符串数组的选项。

**`isHumanAnnotationRequired` 的含义**  
该值是可选的，因为它默认为 `true`。显式设置该值的主要使用案例是当您想要将此数据对象从人工标注范围中排除时。

如果清单中的对象多种多样，有些需要人工注释，有些则不需要，那么可以在每个数据对象中包含 `isHumanAnnotationRequired` 值。您可以在注释前 Lambda 中添加逻辑，以动态确定对象是否需要注释，并相应地设置该布尔值。

### 注释前 Lambda 函数的示例
<a name="sms-custom-templates-step3-prelambda-example"></a>

下面的基本注释前 Lambda 函数从初始请求访问 `dataObject` 中的 JSON 对象，并在 `taskInput` 参数中返回该对象。

```
import json

def lambda_handler(event, context):
    return {
        "taskInput":  event['dataObject']
    }
```

假设输入清单文件使用 `"source-ref"` 来标识数据对象，那么在与此注释前 Lambda 相同的标注作业中使用的工作人员任务模板必须包含类似下面的 Liquid 元素，以摄取 `dataObject`：

```
{{ task.input.source-ref | grant_read_access }}
```

如果输入清单文件使用 `source` 来标识数据对象，那么工作任务模板可以通过以下方式摄取 `dataObject`：

```
{{ task.input.source }}
```

下面的注释前 Lambda 示例包含一个逻辑，用于识别 `dataObject` 中使用的键，并在 Lambda 的返回语句中使用 `taskObject` 指向该数据对象。

```
import json

def lambda_handler(event, context):

    # Event received
    print("Received event: " + json.dumps(event, indent=2))

    # Get source if specified
    source = event['dataObject']['source'] if "source" in event['dataObject'] else None

    # Get source-ref if specified
    source_ref = event['dataObject']['source-ref'] if "source-ref" in event['dataObject'] else None

    # if source field present, take that otherwise take source-ref
    task_object = source if source is not None else source_ref

    # Build response object
    output = {
        "taskInput": {
            "taskObject": task_object
        },
        "humanAnnotationRequired": "true"
    }

    print(output)
    # If neither source nor source-ref specified, mark the annotation failed
    if task_object is None:
        print(" Failed to pre-process {} !".format(event["labelingJobArn"]))
        output["humanAnnotationRequired"] = "false"

    return output
```

## 注释后 Lambda
<a name="sms-custom-templates-step3-postlambda"></a>

当所有工作人员都注释了数据对象或达到 [https://docs.aws.amazon.com/sagemaker/latest/APIReference/API_HumanLoopConfig.html#SageMaker-Type-HumanLoopConfig-TaskAvailabilityLifetimeInSeconds](https://docs.aws.amazon.com/sagemaker/latest/APIReference/API_HumanLoopConfig.html#SageMaker-Type-HumanLoopConfig-TaskAvailabilityLifetimeInSeconds)（以先到者为准）时，Ground Truth 将这些注释发送到您的注释后 Lambda。此 Lambda 通常用于[注释整合](sms-annotation-consolidation.md)。

**注意**  
要查看合并后 Lambda 函数的示例，[请参阅-recipe 存储](https://github.com/aws-samples/aws-sagemaker-ground-truth-recipe/blob/master/aws_sagemaker_ground_truth_sample_lambda/annotation_consolidation_lambda.py)库[aws-sagemaker-ground-truth中的](https://github.com/aws-samples/aws-sagemaker-ground-truth-recipe) GitHub annotation\$1consolidation\$1lambda.py。

以下代码块包含注释后请求模式。下面的项目符号列表中描述了每个参数。

```
{
    "version": "2018-10-16",
    "labelingJobArn": <string>,
    "labelCategories": [<string>],
    "labelAttributeName": <string>,
    "roleArn" : <string>,
    "payload": {
        "s3Uri": <string>
    }
 }
```
+ `version`（字符串）：Ground Truth 内部使用的版本号。
+ `labelingJobArn`（字符串）：标注作业的 Amazon 资源名称 (ARN)。在使用 Ground Truth API 操作（如 `DescribeLabelingJob`）时，此 ARN 可用于引用标注作业。
+ `labelCategories`（字符串列表）：包括在控制台中指定或包含在标签类别配置文件中的标签类别和其他属性。
+ `labelAttributeName`（字符串）：标注作业的名称或创建标注作业时指定的标签属性名称。
+ `roleArn`（字符串）：您在创建标注作业时指定的 IAM 执行角色的 Amazon 资源名称 (ARN)。
+ `payload`（JSON 对象）：包含 `s3Uri` 键的 JSON，该键标识该数据对象的注释数据在 Amazon S3 中的位置。下面的第二个代码块显示了此注释文件的示例。

以下代码块包含注释后请求的示例。此示例请求中的每个参数都在代码块下面进行了说明。

**Example 注释后 Lambda 请求**  

```
{
    "version": "2018-10-16",
    "labelingJobArn": "arn:aws:sagemaker:us-west-2:111122223333:labeling-job/labeling-job-name",
    "labelCategories": ["Ex Category1","Ex Category2", "Ex Category3"],
    "labelAttributeName": "labeling-job-attribute-name",
    "roleArn" : "arn:aws:iam::111122223333:role/role-name",
    "payload": {
        "s3Uri": "s3://amzn-s3-demo-bucket/annotations.json"
    }
 }
```

**注意**  
如果没有工作人员处理数据对象并且已经达到 `TaskAvailabilityLifetimeInSeconds`，则数据对象被标记为失败，并且不包括在注释后 Lambda 调用中。

下面的代码块包含负载模式。这是由注释后 Lambda 请求 `payload` JSON 对象中的 `s3Uri` 参数指示的文件。例如，如果前面的代码块是注释后 Lambda 请求，则下面的注释文件位于 `s3://amzn-s3-demo-bucket/annotations.json`。

下面的项目符号列表中描述了每个参数。

**Example 注释文件**  

```
[
    {
        "datasetObjectId": <string>,
        "dataObject": {
            "s3Uri": <string>,
            "content": <string>
        },
        "annotations": [{
            "workerId": <string>,
            "annotationData": {
                "content": <string>,
                "s3Uri": <string>
            }
       }]
    }
]
```
+ `datasetObjectId`（字符串）：标识 Ground Truth 为发送到标注作业的每个数据对象分配的唯一 ID。
+ `dataObject`（JSON 对象）：标注的数据对象。如果数据对象包含在输入清单文件中并使用 `source` 键（例如，字符串）进行标识，则 `dataObject` 包括一个用于标识数据对象的 `content` 键。否则，数据对象的位置（例如，链接或 S3 URI）用 `s3Uri` 标识。
+ `annotations`（JSON 对象列表）：此列表包含单一 JSON 对象，用于表示工作人员为该 `dataObject` 提交的每个注释。单一 JSON 对象包含唯一的 `workerId`，可用于标识提交该注释的工作人员。`annotationData` 键包含下列值之一：
  + `content`（字符串）：包含注释数据。
  + `s3Uri`（字符串）：包含一个 S3 URI，用于标识注释数据的位置。

下表包含了您可以在不同类型注释的负载中找到的内容示例。

------
#### [ Named Entity Recognition Payload ]

```
[
    {
      "datasetObjectId": "1",
      "dataObject": {
        "content": "Sift 3 cups of flour into the bowl."
      },
      "annotations": [
        {
          "workerId": "private.us-west-2.ef7294f850a3d9d1",
          "annotationData": {
            "content": "{\"crowd-entity-annotation\":{\"entities\":[{\"endOffset\":4,\"label\":\"verb\",\"startOffset\":0},{\"endOffset\":6,\"label\":\"number\",\"startOffset\":5},{\"endOffset\":20,\"label\":\"object\",\"startOffset\":15},{\"endOffset\":34,\"label\":\"object\",\"startOffset\":30}]}}"
          }
        }
      ]
    }
]
```

------
#### [ Semantic Segmentation Payload ]

```
[
    {
      "datasetObjectId": "2",
      "dataObject": {
        "s3Uri": "s3://amzn-s3-demo-bucket/gt-input-data/images/bird3.jpg"
      },
      "annotations": [
        {
          "workerId": "private.us-west-2.ab1234c5678a919d0",
          "annotationData": {
            "content": "{\"crowd-semantic-segmentation\":{\"inputImageProperties\":{\"height\":2000,\"width\":3020},\"labelMappings\":{\"Bird\":{\"color\":\"#2ca02c\"}},\"labeledImage\":{\"pngImageData\":\"iVBOR...\"}}}"
          }
        }
      ]
    }
  ]
```

------
#### [ Bounding Box Payload ]

```
[
    {
      "datasetObjectId": "0",
      "dataObject": {
        "s3Uri": "s3://amzn-s3-demo-bucket/gt-input-data/images/bird1.jpg"
      },
      "annotations": [
        {
          "workerId": "private.us-west-2.ab1234c5678a919d0",
          "annotationData": {
            "content": "{\"boundingBox\":{\"boundingBoxes\":[{\"height\":2052,\"label\":\"Bird\",\"left\":583,\"top\":302,\"width\":1375}],\"inputImageProperties\":{\"height\":2497,\"width\":3745}}}"
          }
        }
      ]
    }
 ]
```

------

注释后 Lambda 函数可能包含类似下面的逻辑，以循环访问请求中包含的所有注释。有关完整示例，请参阅 [aws-sagemaker-ground-truth-](https://github.com/aws-samples/aws-sagemaker-ground-truth-recipe) recipe GitHub 存储库[中的 annotation\$1consolidation\$1lambda.py](https://github.com/aws-samples/aws-sagemaker-ground-truth-recipe/blob/master/aws_sagemaker_ground_truth_sample_lambda/annotation_consolidation_lambda.py)。在此 GitHub示例中，您必须添加自己的注释合并逻辑。

```
for i in range(len(annotations)):
    worker_id = annotations[i]["workerId"]
    annotation_content = annotations[i]['annotationData'].get('content')
    annotation_s3_uri = annotations[i]['annotationData'].get('s3uri')
    annotation = annotation_content if annotation_s3_uri is None else s3_client.get_object_from_s3(
        annotation_s3_uri)
    annotation_from_single_worker = json.loads(annotation)

    print("{} Received Annotations from worker [{}] is [{}]"
            .format(log_prefix, worker_id, annotation_from_single_worker))
```

**提示**  
对数据运行合并算法时，可以使用 AWS 数据库服务来存储结果，也可以将处理后的结果传回 Ground Truth。您返回给 Ground Truth 的数据会以合并注释清单的形式存储在 S3 存储桶中，该存储桶是在标注作业配置过程中指定用于输出的。

作为返回对象，Ground Truth 需要如下格式的响应：

**Example 预期的返回数据**  

```
[
   {        
        "datasetObjectId": <string>,
        "consolidatedAnnotation": {
            "content": {
                "<labelattributename>": {
                    # ... label content
                }
            }
        }
    },
   {        
        "datasetObjectId": <string>,
        "consolidatedAnnotation": {
            "content": {
                "<labelattributename>": {
                    # ... label content
                }
            }
        }
    }
    .
    .
    .
]
```
此时，除了 `datasetObjectId` 之外，您发送到 S3 存储桶的所有数据都在 `content` 对象中。

在 `content` 中返回注释时，会在作业的输出清单中生成一个条目，如下所示：

**Example 输出清单中的标签格式**  

```
{  "source-ref"/"source" : "<s3uri or content>", 
   "<labelAttributeName>": {
        # ... label content from you
    },   
   "<labelAttributeName>-metadata": { # This will be added by Ground Truth
        "job_name": <labelingJobName>,
        "type": "groundTruth/custom",
        "human-annotated": "yes", 
        "creation_date": <date> # Timestamp of when received from Post-labeling Lambda
    }
}
```

由于自定义模板及其所收集数据的潜在复杂性，Ground Truth 不会对数据进行进一步处理。

# 添加与 Ground Trut AWS Lambda h 一起使用所需的权限
<a name="sms-custom-templates-step3-lambda-permissions"></a>

您可能需要配置以下部分或全部内容，才能在 Ground Truth 中创建和使用 AWS Lambda 。
+ 您需要向 IAM 角色或用户（统称为 IAM 实体）授予使用创建标注前和注释后 Lambda 函数的权限 AWS Lambda，并在创建标签任务时选择它们。
+ 配置标注作业时指定的 IAM 执行角色需要调用注释前和注释后 Lambda 函数的权限。
+ 注释后 Lambda 函数可能需要获得访问 Amazon S3 的权限。

使用以下部分了解如何创建 IAM 实体并授予上述权限。

**Topics**
+ [授予创建和选择 AWS Lambda 函数的权限](#sms-custom-templates-step3-postlambda-create-perms)
+ [授予 IAM 执行角色调用 AWS Lambda 函数的权限](#sms-custom-templates-step3-postlambda-execution-role-perms)
+ [授予注释后 Lambda 访问注释的权限](#sms-custom-templates-step3-postlambda-perms)

## 授予创建和选择 AWS Lambda 函数的权限
<a name="sms-custom-templates-step3-postlambda-create-perms"></a>

如果您不需要精细权限来开发注释前和注释后的 Lambda 函数，则可以将托管`AWSLambda_FullAccess`策略附加 AWS 到用户或角色。该策略授予使用所有 Lambda 功能的广泛权限，以及在 Lambda 与之交互的其他 AWS 服务中执行操作的权限。

要为安全敏感的用例创建更精细的策略，请参阅 AWS Lambda 开发人员指南中的文档中针对 [Lambda 的基于身份的 IAM 策略，了解如何创建适合](https://docs.aws.amazon.com/lambda/latest/dg/access-control-identity-based.html)您的用例的 IAM 策略。

**使用 Lambda 控制台的策略**

如果您想授予 IAM 实体使用 Lambda 控制台的权限，请参阅开发人员指南中的[使用 Lambda 控制台](https://docs.aws.amazon.com/lambda/latest/dg/security_iam_id-based-policy-examples.html#security_iam_id-based-policy-examples-console)。 AWS Lambda 

此外，如果您希望用户能够 AWS Serverless Application Repository 在 Lambda 控制台中使用访问和部署 Ground Truth 入门预注释和标注后函数，则必须指定要部署函数*`<aws-region>`*的位置（这应该与用于创建标签任务的 AWS 区域相同），并将以下策略添加到 IAM 角色。

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": [
                "serverlessrepo:ListApplicationVersions",
                "serverlessrepo:GetApplication",
                "serverlessrepo:CreateCloudFormationTemplate"
            ],
            "Resource": "arn:aws:serverlessrepo:us-east-1:838997950401:applications/aws-sagemaker-ground-truth-recipe"
        },
        {
            "Sid": "VisualEditor1",
            "Effect": "Allow",
            "Action": "serverlessrepo:SearchApplications",
            "Resource": "*"
        }
    ]
}
```

------

**在 Ground Truth 控制台中查看 Lambda 函数的策略**

要授予 IAM 实体在用户创建自定义标注作业时在 Ground Truth 控制台中查看 Lambda 函数的权限，该实体必须具有[授予 IAM 使用亚马逊 G SageMaker round Truth 控制台的权限](sms-security-permission-console-access.md)中所述的权限，包括[自定义标注工作流权限](sms-security-permission-console-access.md#sms-security-permissions-custom-workflow)部分中所述权限。

## 授予 IAM 执行角色调用 AWS Lambda 函数的权限
<a name="sms-custom-templates-step3-postlambda-execution-role-perms"></a>

如果您将 IAM 托管策略[AmazonSageMakerGroundTruthExecution](https://console.aws.amazon.com/iam/home?#/policies/arn:aws:iam::aws:policy/AmazonSageMakerGroundTruthExecution)添加到用于创建标签任务的 IAM 执行角色，则该角色有权列出和调用函数名称中包含以下字符串之一的 Lambda 函数：`GtRecipe`、、、`SageMaker``Sagemaker``sagemaker`、或。`LabelingFunction`

如果注释前或注释后 Lambda 函数名称不包括上一段中的任何术语，或者您需要比 `AmazonSageMakerGroundTruthExecution` 托管策略中更细粒度的权限，您可以添加与下面类似的策略，以授予执行角色调用注释前和注释后函数的权限。

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "lambda:InvokeFunction",
            "Resource": [
                "arn:aws:lambda:us-east-1:111122223333:function:<pre-annotation-lambda-name>",
                "arn:aws:lambda:us-east-1:111122223333:function:<post-annotation-lambda-name>"
            ]
        }
    ]
}
```

------

## 授予注释后 Lambda 访问注释的权限
<a name="sms-custom-templates-step3-postlambda-perms"></a>

如[注释后 Lambda](sms-custom-templates-step3-lambda-requirements.md#sms-custom-templates-step3-postlambda)中所述，注释后 Lambda 请求包括注释数据在 Amazon S3 中的位置。此位置由 `payload` 对象中的 `s3Uri` 字符串标识。要处理传入的注释，即使是简单的传递函数，也需要为注释后 [Lambda 执行角色](https://docs.aws.amazon.com/lambda/latest/dg/lambda-intro-execution-role.html)分配必要的权限，以便从 Amazon S3 读取文件。

您可以通过多种方式配置 Lambda 以访问 Amazon S3 中的注释数据。两种常见的方法是：
+ 允许 Lambda 执行角色担任注释后 Lambda 请求`roleArn`中标识的 SageMaker AI 执行角色。此 SageMaker AI 执行角色用于创建标签任务，并且可以访问存储注释数据的 Amazon S3 输出存储桶。
+ 授予 Lambda 执行角色直接访问 Amazon S3 输出存储桶的权限。

使用以下部分了解如何配置这些选项。

**向 Lambda 授予担任 SageMaker AI 执行角色的权限**

要允许 Lambda 函数担任 SageMaker AI 执行角色，您必须将策略附加到 Lambda 函数的执行角色，并修改 SageMaker AI 执行角色的信任关系以允许 Lambda 担任该角色。

1. 将以@@ [下 IAM 策略附加](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_manage-attach-detach.html)到您的 Lambda 函数的执行角色，以代入中确定的 SageMaker AI 执行角色。`Resource`将 `222222222222` 替换为 [AWS 账户 ID](https://docs.aws.amazon.com/general/latest/gr/acct-identifiers.html)。将 `sm-execution-role` 替换为代入角色的名称。

------
#### [ JSON ]

****  

   ```
   {
       "Version":"2012-10-17",		 	 	 
       "Statement": {
           "Effect": "Allow",
           "Action": "sts:AssumeRole",
           "Resource": "arn:aws:iam::222222222222:role/sm-execution-role"
       }
   }
   ```

------

1. [修改 SageMaker AI 执行角色的信任策略](https://docs.aws.amazon.com/IAM/latest/UserGuide/roles-managingrole-editing-console.html#roles-managingrole_edit-trust-policy)以包括以下内容`Statement`。将 `222222222222` 替换为 [AWS 账户 ID](https://docs.aws.amazon.com/general/latest/gr/acct-identifiers.html)。将 `my-lambda-execution-role` 替换为代入角色的名称。

------
#### [ JSON ]

****  

   ```
   {
       "Version":"2012-10-17",		 	 	 
       "Statement": [
           {
               "Effect": "Allow",
               "Principal": {
                   "AWS": "arn:aws:iam::222222222222:role/my-lambda-execution-role"
               },
               "Action": "sts:AssumeRole"
           }
       ]
   }
   ```

------

**授予 Lambda 执行角色访问 S3 的权限**

您可以将类似于以下内容的策略添加到注释后 Lambda 函数执行角色，以授予其 S3 读取权限。*amzn-s3-demo-bucket*替换为您在创建标注任务时指定的输出存储桶的名称。

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "s3:GetObject"
            ],
            "Resource": "arn:aws:s3:::amzn-s3-demo-bucket/*"
        }
    ]
}
```

------

要在 Lambda 控制台中为 Lambda 执行角色添加 S3 读取权限，请使用以下过程。

**将 S3 读取权限添加到注释后 Lambda：**

1. 在 Lambda 控制台中打开[**函数**页面](https://console.aws.amazon.com/lambda/home#/functions)。

1. 选择注释后函数的名称。

1. 选择**配置**，然后选择**权限**。

1. 选择**角色名称**，该角色的摘要页面就会在 IAM 控制台的新标签页中打开。

1. 选择**附加策略**。

1. 请执行以下操作之一：
   + 搜索并选择 **`AmazonS3ReadOnlyAccess`** 以授予函数读取账户中所有存储桶和对象的权限。
   + 如果需要更细粒度的权限，请选择**创建策略**并使用上一节中的策略示例来创建策略。请注意，创建策略后必须导航回执行角色摘要页面。

1. 如果使用了 `AmazonS3ReadOnlyAccess` 托管策略，请选择**附加策略**。

   如果您创建了新策略，请导航回 Lambda 执行角色摘要页面并附加刚创建的策略。

# 使用 Ground Truth 模板创建 Lambda 函数
<a name="sms-custom-templates-step3-lambda-create"></a>

您可以使用 Lambda 控制台、或使用您选择的支持的编程语言的 AWS CLI AWS 软件开发工具包创建 Lambda 函数。使用 AWS Lambda 开发者指南详细了解以下每个选项：
+ 要了解如何使用控制台创建 Lambda 函数，请参阅[使用控制台创建 Lambda 函数](https://docs.aws.amazon.com/lambda/latest/dg/getting-started-create-function.html)。
+ 要了解如何使用创建 Lambda 函数 AWS CLI，请参阅在命令行界面中使用 [AWS Lambda](https://docs.aws.amazon.com/lambda/latest/dg/gettingstarted-awscli.html)。 AWS 
+ 选择目录中的相关章节，了解用您选择的语言使用 Lambda 的更多信息。例如，选择[使用 Python](https://docs.aws.amazon.com/lambda/latest/dg/lambda-python.html)，了解有关将 Lambda 与 适用于 Python (Boto3) 的 AWS SDK结合使用的更多信息。

*Ground Truth 通过 AWS Serverless Application Repository （SAR）配方提供注释前和注释后的模板。*使用以下过程在 Lambda 控制台中选择 Ground Truth 配方。

**使用 Ground Truth SAR 配方创建注释前和注释后 Lambda 函数：**

1. 在 Lambda 控制台上打开[**函数**页面](https://console.aws.amazon.com/lambda/home#/functions)。

1. 选择**创建函数**。

1. 选择**浏览无服务器应用程序存储库**。

1. 在搜索文本框中，输入 **aws-sagemaker-ground-truth-recipe**，然后选择该应用程序。

1. 选择**部署**。应用程序的部署可能需要几分钟时间。

   部署应用程序后，Lambda 控制台的**函数**部分会显示 `serverlessrepo-aws-sagema-GtRecipePreHumanTaskFunc-<id>` 和 `serverlessrepo-aws-sagema-GtRecipeAnnotationConsol-<id>` 这两个函数。

1. 选择其中一个函数，然后在**代码**部分添加自定义逻辑。

1. 完成更改后，选择**部署**来部署这些函数。

# 测试注释前和注释后 Lambda 函数
<a name="sms-custom-templates-step3-lambda-test"></a>

您可以在 Lambda 控制台中测试注释前和注释后 Lambda 函数。如果您是 Lambda 的新用户，可以使用《 AWS Lambda 开发人员指南》中的[使用控制台创建 Lambda 函数](https://docs.aws.amazon.com/lambda/latest/dg/getting-started-create-function.html#gettingstarted-zip-function)教程，了解如何在控制台中测试或*调用*您的 Lambda 函数。您可以使用本页上的章节来学习如何测试通过 AWS Serverless Application Repository (SAR) 提供的 Ground Truth 注释前和注释后模板。

**Topics**
+ [先决条件](#sms-custom-templates-step3-lambda-test-pre)
+ [测试注释前 Lambda 函数](#sms-custom-templates-step3-lambda-test-pre-annotation)
+ [测试注释后 Lambda 函数](#sms-custom-templates-step3-lambda-test-post-annotation)

## 先决条件
<a name="sms-custom-templates-step3-lambda-test-pre"></a>

您必须执行以下操作才能使用本页上描述的测试。
+ 您需要访问 Lambda 控制台，还需要创建和调用 Lambda 函数的权限。要了解如何设置这些权限，请参阅[授予创建和选择 AWS Lambda 函数的权限](sms-custom-templates-step3-lambda-permissions.md#sms-custom-templates-step3-postlambda-create-perms)。
+ 如果您尚未部署 Ground Truth SAR 配方，请使用[使用 Ground Truth 模板创建 Lambda 函数](sms-custom-templates-step3-lambda-create.md)中的步骤进行部署。
+ 要测试注释后 Lambda 函数，您必须在 Amazon S3 中拥有一个包含示例注释数据的数据文件。对于简单的测试，您可以将以下代码复制并粘贴到一个文件中，将此文件另存为 `sample-annotations.json` 并[将此文件上传到 Amazon S3](https://docs.aws.amazon.com/AmazonS3/latest/userguide/upload-objects.html)。请注意此文件的 S3 URI，您需要此信息来配置注释后 Lambda 测试。

  ```
  [{"datasetObjectId":"0","dataObject":{"content":"To train a machine learning model, you need a large, high-quality, labeled dataset. Ground Truth helps you build high-quality training datasets for your machine learning models."},"annotations":[{"workerId":"private.us-west-2.0123456789","annotationData":{"content":"{\"crowd-entity-annotation\":{\"entities\":[{\"endOffset\":8,\"label\":\"verb\",\"startOffset\":3},{\"endOffset\":27,\"label\":\"adjective\",\"startOffset\":11},{\"endOffset\":33,\"label\":\"object\",\"startOffset\":28},{\"endOffset\":51,\"label\":\"adjective\",\"startOffset\":46},{\"endOffset\":65,\"label\":\"adjective\",\"startOffset\":53},{\"endOffset\":74,\"label\":\"adjective\",\"startOffset\":67},{\"endOffset\":82,\"label\":\"adjective\",\"startOffset\":75},{\"endOffset\":102,\"label\":\"verb\",\"startOffset\":97},{\"endOffset\":112,\"label\":\"verb\",\"startOffset\":107},{\"endOffset\":125,\"label\":\"adjective\",\"startOffset\":113},{\"endOffset\":134,\"label\":\"adjective\",\"startOffset\":126},{\"endOffset\":143,\"label\":\"object\",\"startOffset\":135},{\"endOffset\":169,\"label\":\"adjective\",\"startOffset\":153},{\"endOffset\":176,\"label\":\"object\",\"startOffset\":170}]}}"}}]},{"datasetObjectId":"1","dataObject":{"content":"Sift 3 cups of flour into the bowl."},"annotations":[{"workerId":"private.us-west-2.0123456789","annotationData":{"content":"{\"crowd-entity-annotation\":{\"entities\":[{\"endOffset\":4,\"label\":\"verb\",\"startOffset\":0},{\"endOffset\":6,\"label\":\"number\",\"startOffset\":5},{\"endOffset\":20,\"label\":\"object\",\"startOffset\":15},{\"endOffset\":34,\"label\":\"object\",\"startOffset\":30}]}}"}}]},{"datasetObjectId":"2","dataObject":{"content":"Jen purchased 10 shares of the stock on Janurary 1st, 2020."},"annotations":[{"workerId":"private.us-west-2.0123456789","annotationData":{"content":"{\"crowd-entity-annotation\":{\"entities\":[{\"endOffset\":3,\"label\":\"person\",\"startOffset\":0},{\"endOffset\":13,\"label\":\"verb\",\"startOffset\":4},{\"endOffset\":16,\"label\":\"number\",\"startOffset\":14},{\"endOffset\":58,\"label\":\"date\",\"startOffset\":40}]}}"}}]},{"datasetObjectId":"3","dataObject":{"content":"The narrative was interesting, however the character development was weak."},"annotations":[{"workerId":"private.us-west-2.0123456789","annotationData":{"content":"{\"crowd-entity-annotation\":{\"entities\":[{\"endOffset\":29,\"label\":\"adjective\",\"startOffset\":18},{\"endOffset\":73,\"label\":\"adjective\",\"startOffset\":69}]}}"}}]}]
  ```
+ 您必须使用中的[授予注释后 Lambda 访问注释的权限](sms-custom-templates-step3-lambda-permissions.md#sms-custom-templates-step3-postlambda-perms)说明向注释后 Lambda 函数的执行角色授予权限，以代 SageMaker 入您用于创建标签任务的 AI 执行角色。注释后 Lambda 函数使用 SageMaker AI 执行角色来访问 S3 中的注解数据文件`sample-annotations.json`。



## 测试注释前 Lambda 函数
<a name="sms-custom-templates-step3-lambda-test-pre-annotation"></a>

使用以下过程来测试在部署 Gro AWS Serverless Application Repository und Truth (SAR) 配方时创建的预注解 Lambda 函数。

**测试 Ground Truth SAR 配方注释前 Lambda 函数**

1. 在 Lambda 控制台中打开[**函数**页面](https://console.aws.amazon.com/lambda/home#/functions)。

1. 选择从 Ground Truth SAR 配方中部署的注释前函数。此函数的名称类似于 `serverlessrepo-aws-sagema-GtRecipePreHumanTaskFunc-<id>`。

1. 在**代码来源**部分中，选择**测试**旁边的箭头。

1. 选择**配置测试事件**。

1. 保持选中**创建新测试事件**选项。

1. 在**事件模板**下，选择 G **SageMakerround Truth PreHumanTask**。

1. 为您的测试指定**事件名称**。

1. 选择**创建**。

1. 再次选择**测试**旁边的箭头，您应该会看到您创建的测试已选中，在事件名称旁用点表示。如果未选中，请选择该测试。

1. 选择**测试**来运行测试。

运行测试后，您可以看到**执行结果**。在**函数日志**中，您应该会看到类似于以下内容的响应：

```
START RequestId: cd117d38-8365-4e1a-bffb-0dcd631a878f Version: $LATEST
Received event: {
  "version": "2018-10-16",
  "labelingJobArn": "arn:aws:sagemaker:us-east-2:123456789012:labeling-job/example-job",
  "dataObject": {
    "source-ref": "s3://sagemakerexample/object_to_annotate.jpg"
  }
}
{'taskInput': {'taskObject': 's3://sagemakerexample/object_to_annotate.jpg'}, 'isHumanAnnotationRequired': 'true'}
END RequestId: cd117d38-8365-4e1a-bffb-0dcd631a878f
REPORT RequestId: cd117d38-8365-4e1a-bffb-0dcd631a878f	Duration: 0.42 ms	Billed Duration: 1 ms	Memory Size: 128 MB	Max Memory Used: 43 MB
```

在此响应中，我们可以看到 Lambda 函数的输出与所需的注释前响应语法匹配：

```
{'taskInput': {'taskObject': 's3://sagemakerexample/object_to_annotate.jpg'}, 'isHumanAnnotationRequired': 'true'}
```

## 测试注释后 Lambda 函数
<a name="sms-custom-templates-step3-lambda-test-post-annotation"></a>

使用以下过程来测试在部署 Gro AWS Serverless Application Repository und Truth (SAR) 配方时创建的注释后 Lambda 函数。

**测试 Ground Truth SAR 配方注释后 Lambda**

1. 在 Lambda 控制台中打开[**函数**页面](https://console.aws.amazon.com/lambda/home#/functions)。

1. 选择从 Ground Truth SAR 配方中部署的注释后函数。此函数的名称类似于 `serverlessrepo-aws-sagema-GtRecipeAnnotationConsol-<id>`。

1. 在**代码来源**部分中，选择**测试**旁边的箭头。

1. 选择**配置测试事件**。

1. 保持选中**创建新测试事件**选项。

1. 在**事件模板**下，选择 G **SageMakerround Truth AnnotationConsolidation**。

1. 为您的测试指定**事件名称**。

1. 对提供的模板代码进行如下修改：
   + 将中的 `roleArn` Amazon 资源名称 (ARN) 替换为您用于创建标签任务的 SageMaker AI 执行角色的 ARN。
   + 将 `s3Uri` 中的 S3 URI 替换为添加到 Amazon S3 的 `sample-annotations.json` 文件的 URI。

   进行这些修改后，您的测试应类似于以下内容：

   ```
   {
     "version": "2018-10-16",
     "labelingJobArn": "arn:aws:sagemaker:us-east-2:123456789012:labeling-job/example-job",
     "labelAttributeName": "example-attribute",
     "roleArn": "arn:aws:iam::222222222222:role/sm-execution-role",
     "payload": {
       "s3Uri": "s3://your-bucket/sample-annotations.json"
     }
   }
   ```

1. 选择**创建**。

1. 再次选择**测试**旁边的箭头，您应该会看到您创建的测试已选中，在事件名称旁用点表示。如果未选中，请选择该测试。

1. 选择**测试**来运行测试。

运行测试后，您应该会在**函数日志**中看到 `-- Consolidated Output --` 部分，其中包含 `sample-annotations.json` 中包括的所有注释的列表。