

기계 번역으로 제공되는 번역입니다. 제공된 번역과 원본 영어의 내용이 상충하는 경우에는 영어 버전이 우선합니다.

# 주석 전 및 주석 후 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 형식의 요청을 보내 라벨링 작업과 데이터 객체에 대한 세부 정보를 제공합니다.

다음은 두 가지 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입니다. 이 ARN은 `DescribeLabelingJob` 등과 같은 Ground Truth API 작업을 사용할 때 라벨링 작업을 참조하는 데 사용할 수 있습니다.
+ `dataObject`(JSON 객체): 키에는 입력 매니페스트 파일 또는 Amazon SNS에서 전송한 단일 JSON 행이 포함되어 있습니다. 매니페스트 내 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와 동일한 라벨링 작업에 사용되는 작업자 작업 템플릿에는 `dataObject` 수집을 위해 다음과 같은 Liquid 요소가 포함되어야 합니다.

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

입력 매니페스트 파일이 데이터 객체를 식별하는 데 `source`를 사용한 경우, 작업자 작업 템플릿은 다음을 사용하여 `dataObject`를 수집할 수 있습니다.

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

다음에 나오는 주석 전 Lambda 예제에는 `dataObject`에서 사용되는 키를 식별하고 Lambda의 return 문에서 `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 함수의 예시를 보려면 aws-sagemaker-ground-truth-recipe](https://github.com/aws-samples/aws-sagemaker-ground-truth-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)를 참조하세요.

다음 코드 블록에는 주석 후 요청 스키마가 포함되어 있습니다. 각 파라미터는 다음 글머리표 목록에 설명되어 있습니다.

```
{
    "version": "2018-10-16",
    "labelingJobArn": <string>,
    "labelCategories": [<string>],
    "labelAttributeName": <string>,
    "roleArn" : <string>,
    "payload": {
        "s3Uri": <string>
    }
 }
```
+ `version`(문자열): Ground Truth에서 내부적으로 사용하는 버전 번호입니다.
+ `labelingJobArn`(문자열): 라벨링 작업의 Amazon 리소스 이름, 즉 ARN입니다. 이 ARN은 `DescribeLabelingJob` 등과 같은 Ground Truth API 작업을 사용할 때 라벨링 작업을 참조하는 데 사용할 수 있습니다.
+ `labelCategories`(문자열 목록): 콘솔에서 지정했거나 레이블 범주 구성 파일에 포함시킨 레이블 범주 및 기타 속성을 포함합니다.
+ `labelAttributeName`(문자열): 라벨링 작업의 이름 또는 라벨링 작업을 생성할 때 지정하는 레이블 속성 이름입니다.
+ `roleArn`(문자열): 라벨링 작업을 생성할 때 지정하는 IAM 실행 역할의 Amazon 리소스 이름(ARN)입니다.
+ `payload`(JSON 객체): Amazon S3에 있는 해당 데이터 객체의 주석 데이터 위치를 식별하는 `s3Uri` 키가 포함된 JSON입니다. 아래 두 번째 코드 블록은 이 주석 파일의 예를 보여줍니다.

다음 코드 블록에는 주석 후 요청에 대한 예시가 포함되어 있습니다. 이러한 예시 요청의 각 파라미터는 코드 블록 아래에 설명되어 있습니다.

**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` 키(예: 문자열)를 사용하여 식별되는 경우, 데이터 객체를 식별하는 `content` 키가 `dataObject`에 포함되어 있습니다. 그렇지 않으면 데이터 객체의 위치(예: 링크 또는 S3 URI)가 `s3Uri`로 식별됩니다.
+ `annotations`(JSON 객체 목록): 이 목록에는 해당 `dataObject`에 대해 작업자가 제출한 각 주석을 위한 단일 JSON 객체가 포함되어 있습니다. 단일 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-recipe](https://github.com/aws-samples/aws-sagemaker-ground-truth-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는 데이터를 추가로 처리하지 않습니다.