

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

# 사용자 지정 레이블 지정 워크플로
<a name="sms-custom-templates"></a>

이 주제는 사용자 지정 레이블 지정 템플릿을 사용하는 Ground Truth 레이블 지정 작업을 설정하는 데 도움이 됩니다. 사용자 지정 레이블 지정 템플릿을 사용하면 작업자가 데이터에 레이블을 지정하는 데 사용할 사용자 지정 작업자 포털 UI를 생성할 수 있습니다. 템플릿은 HTML, CSS, JavaScript, [Liquid 템플릿 언어](https://shopify.github.io/liquid/) 및 [군중 HTML 요소](https://docs.aws.amazon.com/sagemaker/latest/dg/sms-ui-template-reference.html)를 사용하여 생성할 수 있습니다.

## 개요
<a name="sms-custom-templates-overview"></a>

Ground Truth에서 사용자 지정 레이블 지정 워크플로를 처음 생성하는 경우 다음 목록은 필요한 단계에 대한 상위 수준 요약입니다.

1. *작업 인력 설정* - 사용자 지정 레이블 지정 워크플로를 생성하려면 인력이 필요합니다. 이 주제에서는 인력 구성에 대해 설명합니다.

1. *사용자 지정 템플릿 생성* - 사용자 지정 템플릿을 생성하려면 입력 매니페스트 파일의 데이터를 템플릿의 변수에 올바르게 매핑해야 합니다.

1. *선택적 처리 Lambda 함수 사용* - 입력 매니페스트의 데이터가 작업자 템플릿에 추가되는 방식과 작업자 주석이 작업의 출력 파일에 기록되는 방식을 제어합니다.

또한 이 주제에는 사용자 지정 레이블 지정 템플릿을 사용하는 방법을 더 잘 이해하는 데 도움이 되는 세 가지 엔드 투 엔드 데모가 있습니다.

**참고**  
아래 링크의 예에는 주석 전 및 주석 후 Lambda 함수가 모두 포함됩니다. 이러한 Lambda 함수는 선택 사항입니다.
+ [데모 템플릿: `crowd-bounding-box`를 사용한 이미지 주석](sms-custom-templates-step2-demo1.md)
+ [데모 템플릿: `crowd-classifier`를 사용하여 의도(intent) 라벨링](sms-custom-templates-step2-demo2.md)
+ [Amazon SageMaker Ground Truth를 사용하여 사용자 지정 데이터 레이블링 워크플로 구축](https://aws.amazon.com/blogs/machine-learning/build-a-custom-data-labeling-workflow-with-amazon-sagemaker-ground-truth/)

**Topics**
+ [개요](#sms-custom-templates-overview)
+ [인력 설정](sms-custom-templates-step1.md)
+ [사용자 지정 작업자 작업 템플릿 생성하기](sms-custom-templates-step2.md)
+ [Liquid를 사용하여 자동화 추가](sms-custom-templates-step2-automate.md)
+ [를 사용하여 사용자 지정 레이블 지정 워크플로에서 데이터 처리 AWS Lambda](sms-custom-templates-step3.md)
+ [데모 템플릿: `crowd-bounding-box`를 사용한 이미지 주석](sms-custom-templates-step2-demo1.md)
+ [데모 템플릿: `crowd-classifier`를 사용하여 의도(intent) 라벨링](sms-custom-templates-step2-demo2.md)
+ [API를 사용하여 사용자 지정 워크플로 생성](sms-custom-templates-step4.md)

# 인력 설정
<a name="sms-custom-templates-step1"></a>

이 단계에서는 콘솔을 사용하여 사용하려는 작업자 유형을 설정하고 설정한 작업자 유형에 대해 필요한 하위 항목을 선택합니다. 여기서는 [시작하기: Ground Truth로 경계 상자 레이블 지정 작업 생성](sms-getting-started.md) 섹션에서 이 지점까지의 단계들을 이미 완료했고 **사용자 지정 라벨링 작업**을 **작업 유형**으로 선택했다고 가정합니다.

**작업 인력을 구성하려면**

1. 먼저, **작업자 유형**에서 옵션을 선택합니다. 현재 사용 가능한 세 가지 유형은 다음과 같습니다.
   + **퍼블릭**은 Amazon Mechanical Turk에서 제공하는 독립적 계약업체의 온디맨드 작업 인력을 사용합니다. 이들에게는 작업당 비용이 지불됩니다.
   + **프라이빗**은 조직 내부에 보관해야 하는 데이터를 처리하기 위해 자체 직원 또는 계약업체를 사용합니다.
   + **공급업체는** AWS Marketplace를 통해 제공되는 데이터 레이블 지정 서비스 제공을 전문으로 하는 타사 공급업체를 사용합니다.

1. **퍼블릭** 옵션을 선택하면 **데이터세트 객체당 작업자 수**를 설정하라는 메시지가 표시됩니다. 두 명 이상의 작업자에게 같은 객체에 대해 동일한 작업을 수행하도록 하면 결과의 정확성을 높일 수 있습니다. 기본값은 3개입니다. 필요한 정확도에 따라 작업자 수를 늘리거나 줄일 수 있습니다.

   또한 드롭다운 메뉴를 사용하여 **작업당 가격**을 설정하라는 메시지도 표시됩니다. 이 메뉴는 작업을 완료하는 데 걸리는 시간을 기준으로 가격대를 추천합니다.

   이 옵션을 결정하기 위해서는 먼저 **프라이빗** 작업 인력을 사용하여 작업에 대한 단기 테스트를 실행하는 것이 좋습니다. 이 테스트를 통해 작업을 완료하는 데 걸리는 실제 시간을 예측할 수 있습니다. 그런 다음 **작업당 가격** 메뉴에서 예측 범위를 선택합니다. 평균 시간이 5분을 초과하면 작업을 더 작은 단위로 분할하는 것을 고려해 보세요.

## 다음
<a name="templates-step1-next"></a>

[사용자 지정 작업자 작업 템플릿 생성하기](sms-custom-templates-step2.md)

# 사용자 지정 작업자 작업 템플릿 생성하기
<a name="sms-custom-templates-step2"></a>

사용자 지정 레이블 지정 작업을 생성하려면 작업자 작업 템플릿을 업데이트하고 매니페스트 파일의 입력 데이터를 템플릿에 사용된 변수에 매핑하고 출력 데이터를 Amazon S3에 매핑해야 합니다. Liquid 자동화를 사용하는 고급 기능에 대한 자세한 내용은 [Liquid를 사용하여 자동화 추가](sms-custom-templates-step2-automate.md) 섹션을 참조하세요.

다음 섹션에서는 각 필수 단계에 대해 설명합니다.

## 작업자 작업 템플릿
<a name="sms-custom-templates-step2-template"></a>

*작업자 작업 템플릿*은 Ground Truth에서 작업자 사용자 인터페이스(UI)를 사용자 지정하는 데 사용하는 파일입니다. HTML, CSS, JavaScript, [Liquid 템플릿 언어](https://shopify.github.io/liquid/) 및 [군중 HTML 요소](https://docs.aws.amazon.com/sagemaker/latest/dg/sms-ui-template-reference.html)를 사용하여 작업자 작업 템플릿을 생성할 수 있습니다. Liquid는 템플릿을 자동화하는 데 사용됩니다. 군중 HTML 요소를 사용하여 일반적인 주석 도구를 포함하고 Ground Truth에 제출할 로직을 제공합니다.

다음 항목을 사용하여 작업자 작업 템플릿을 생성하는 방법을 알아보세요. [GitHub](https://github.com/aws-samples/amazon-sagemaker-ground-truth-task-uis)에서 Ground Truth 작업자 작업 템플릿 예시의 리포지토리를 볼 수 있습니다.

### SageMaker AI 콘솔에서 기본 작업자 작업 템플릿 사용
<a name="sms-custom-templates-step2-base"></a>

Ground Truth 콘솔의 템플릿 편집기를 사용하여 템플릿 생성을 시작할 수 있습니다. 이 편집기에는 미리 설계된 여러 기본 템플릿이 포함되어 있습니다. HTML 및 Crowd HTML 요소 코드에 대한 자동 채우기를 지원합니다.

**Ground Truth 사용자 지정 템플릿 편집기에 액세스하는 방법:**

1. [레이블 지정 작업 생성(콘솔)](sms-create-labeling-job-console.md)의 지침을 따르세요.

1. 그런 다음 레이블링 작업 **작업 유형**에 대해 **사용자 지정**을 선택합니다.

1. **다음**을 선택하면 **사용자 지정 레이블 지정 설정** 섹션에서 템플릿 편집기와 기본 템플릿에 액세스할 수 있습니다.

1. (선택 사항) **템플릿** 아래의 드롭다운 메뉴에서 기본 템플릿을 선택합니다. 템플릿을 처음부터 새로 만들려면 드롭다운 메뉴에서 **사용자 지정**을 선택하여 템플릿의 틀만 최소한으로 사용합니다.

다음 섹션을 사용하여 콘솔에서 로컬로 개발된 템플릿을 시각화하는 방법을 알아봅니다.

#### 로컬에서 작업자 작업 템플릿 시각화
<a name="sms-custom-template-step2-UI-local"></a>

콘솔을 사용하여 템플릿이 수신 데이터를 처리하는 방법을 테스트해야 합니다. 템플릿의 HTML 및 사용자 지정 요소의 모양과 느낌을 테스트하려면 브라우저를 사용할 수 있습니다.

**참고**  
변수는 구문 분석되지 않습니다. 콘텐츠를 로컬에서 보는 동안 이를 샘플 콘텐츠로 교체해야 할 수 있습니다.

다음 예제 코드 조각은 사용자 지정 HTML 요소를 렌더링하는 데 필요한 코드를 로드합니다. 콘솔이 아니라 원하는 편집기에서 템플릿의 모양 및 느낌을 개발하려면 이 방법을 사용하세요.

**Example**  

```
<script src="https://assets.crowd.aws/crowd-html-elements.js"></script>
```

### 간단한 HTML 작업 샘플 생성
<a name="sms-custom-templates-step2-sample"></a>

이제 기본 작업자 작업 템플릿이 있으므로 이 주제를 사용하여 간단한 HTML 기반 작업 템플릿을 생성할 수 있습니다.

다음은 입력 매니페스트 파일의 예제 항목입니다.

```
{
  "source": "This train is really late.",
  "labels": [ "angry" , "sad", "happy" , "inconclusive" ],
  "header": "What emotion is the speaker feeling?"
}
```

HTML 작업 템플릿에서는 입력 매니페스트 파일의 변수를 템플릿에 매핑해야 합니다. 예제 입력 매니페스트의 변수는 다음 구문 **task.input.source**, **task.input.labels**및 **task.input.header**를 사용하여 매핑됩니다.

다음은 트윗 분석을 위한 간단한 HTML 작업자 작업 템플릿의 예입니다. 모든 작업이 `<crowd-form> </crowd-form>` 요소로 시작하고 끝납니다. 표준 HTML `<form>` 요소처럼 모든 양식 코드는 이 요소 사이에 있어야 합니다. Ground Truth는 사전 주석 Lambda를 구현하지 않는 한 템플릿에 지정된 컨텍스트에서 작업자의 작업을 직접 생성합니다. Ground Truth에서 반환한 `taskInput` 객체 또는 [주석 전 Lambda](sms-custom-templates-step3-lambda-requirements.md#sms-custom-templates-step3-prelambda)는 템플릿의 `task.input` 객체입니다.

간단한 트윗 분석 작업의 경우 `<crowd-classifier>` 요소를 사용합니다. 이 작업에는 다음 속성이 필요합니다.
+ *name* - 출력 변수의 이름입니다. 작업자 주석은 출력 매니페스트의 이 변수 이름에 저장됩니다.
+ *categories* - 가능한 답변의 JSON 형식 어레이
+ *header* - 주석 도구의 제목

`<crowd-classifier>` 요소에는 다음 세 가지 하위 요소가 필요합니다.
+ *<classification-target>* - 위의 `categories` 속성에서 지정한 옵션을 기반으로 작업자가 분류할 텍스트
+ *<full-instructions>* - 도구의 "View full instructions(전체 지침 보기)" 링크에서 확인할 수 있는 지침 비워둘 수 있지만 더 나은 결과를 얻기 위해서는 적절한 지침을 제공하는 것이 좋습니다.
+ *<short-instructions>* - 도구의 사이드바에 나타나는 작업에 대한 보다 간단한 설명 비워둘 수 있지만 더 나은 결과를 얻기 위해서는 적절한 지침을 제공하는 것이 좋습니다.

이 도구의 간단한 버전의 모양은 다음과 같습니다. 변수**\$1\$1 task.input.source \$1\$1**는 입력 매니페스트 파일의 소스 데이터를 지정합니다. **\$1\$1 task.input.labels \$1 to\$1json \$1\$1**은 배열을 JSON 표현으로 변환하기 위한 변수 필터의 예시입니다. `categories` 속성은 JSON이어야 합니다.

**Example 샘플 입력 매니페스트 json과 함께 `crowd-classifier` 사용**  

```
<script src="https://assets.crowd.aws/crowd-html-elements.js"></script>
<crowd-form>
  <crowd-classifier
    name="tweetFeeling"
    categories="='{{ task.input.labels | to_json }}'"
    header="{{ task.input.header }}'"
  >
     <classification-target>
       {{ task.input.source }}
     </classification-target>

    <full-instructions header="Sentiment Analysis Instructions">
      Try to determine the sentiment the author
      of the tweet is trying to express.
      If none seem to match, choose "cannot determine."
    </full-instructions>

    <short-instructions>
      Pick the term that best describes the sentiment of the tweet.
    </short-instructions>

  </crowd-classifier>
</crowd-form>
```

Ground Truth 라벨링 작업 생성 워크플로에서 코드를 복사하여 편집기에 붙여 넣고 도구를 미리 보거나 [CodePen에서 이 코드의 데모](https://codepen.io/MTGT/full/OqBvJw)를 볼 수 있습니다.

 [https://codepen.io/MTGT/full/OqBvJw](https://codepen.io/MTGT/full/OqBvJw) 

## 입력 데이터, 외부 자산 및 작업 템플릿
<a name="sms-custom-templates-step2-template-input"></a>

다음 섹션에서는 외부 자산 사용, 입력 데이터 형식 요구 사항 및 주석 전 Lambda 함수 사용을 고려해야 하는 경우를 설명합니다.

### 입력 데이터 형식 요구 사항
<a name="sms-custom-template-input-manifest"></a>

사용자 지정 Ground Truth 레이블 지정 작업에 사용할 입력 매니페스트 파일을 생성할 때는 Amazon S3에 데이터를 저장해야 합니다. 입력 매니페스트 파일도 사용자 지정 Ground Truth 레이블 지정 작업을 실행할 동일한 AWS 리전 에 저장해야 합니다. 또한, Ground Truth에서 사용자 지정 레이블 지정 작업을 실행하는 데 사용하는 IAM 서비스 역할에 액세스할 수 있는 모든 Amazon S3 버킷에 저장할 수 있습니다.

입력 매니페스트 파일은 새 줄로 구분된 JSON 또는 JSON 줄 형식을 사용해야 합니다. 각 행은 표준 줄 바꿈인 **\$1n** 또는 **\$1r\$1n**으로 구분됩니다. 각 줄은 유효한 JSON 객체여야 합니다.

또한 매니페스트 파일의 각 JSON 객체에는 `source-ref` 또는 `source` 키 중 하나가 포함되어야 합니다. 키 값은 다음과 같이 해석됩니다.
+ `source-ref` – 객체의 소스는 값에 지정된 Amazon S3 객체입니다. 객체가 바이너리 객체(예: 이미지)인 경우 이 값을 사용하세요.
+ `source` – 객체의 소스가 이 값입니다. 객체가 문자 값일 때 이 값을 사용하세요.

입력 매니페스트 파일 형식 지정에 대한 자세한 내용은 [매니페스트 파일 입력](sms-input-data-input-manifest.md) 섹션을 참조하세요.

### 주석 전 Lambda 함수
<a name="sms-custom-template-input-lambda"></a>

선택적으로 *사전 주석 Lambda* 함수를 지정하여 레이블 지정 전에 입력 매니페스트 파일의 데이터가 처리되는 방식을 관리할 수 있습니다. `isHumanAnnotationRequired` 키-값 페어를 지정한 경우 사전 주석 Lambda 함수를 사용해야 합니다. Ground Truth가 사전 주석 Lambda 함수에 JSON 형식의 요청을 보내면 다음 스키마를 사용합니다.

**Example `source-ref` 키-값 페어로 식별된 데이터 객체**  

```
{
  "version": "2018-10-16",
  "labelingJobArn": arn:aws:lambda:us-west-2:555555555555:function:my-function
  "dataObject" : {
    "source-ref": s3://input-data-bucket/data-object-file-name
  }
}
```

**Example `source` 키-값 페어로 식별된 데이터 객체**  

```
{
      "version": "2018-10-16",
      "labelingJobArn" : arn:aws:lambda:us-west-2:555555555555:function:my-function
      "dataObject" : {
        "source": Sue purchased 10 shares of the stock on April 10th, 2020
      }
    }
```

다음은 를 `isHumanAnnotationRequired` 사용할 때 Lambda 함수에서 예상되는 응답입니다.

```
{
  "taskInput": {
    "source": "This train is really late.",
    "labels": [ "angry" , "sad" , "happy" , "inconclusive" ],
    "header": "What emotion is the speaker feeling?"
  },
  "isHumanAnnotationRequired": False
}
```

### 외부 자산 사용
<a name="sms-custom-template-step2-UI-external"></a>

Amazon SageMaker Ground Truth 사용자 지정 템플릿을 사용하면 외부 스크립트 및 스타일 시트를 포함할 수 있습니다. 예를 들어, 다음 코드 블록은 `https://www.example.com/my-enhancement-styles.css`에 있는 스타일 시트를 템플릿에 추가하는 방법을 보여줍니다.

**Example**  

```
<script src="https://www.example.com/my-enhancment-script.js"></script>
<link rel="stylesheet" type="text/css" href="https://www.example.com/my-enhancement-styles.css">
```

오류가 발생하면 원본 서버가 자산과 함께 올바른 MIME 유형 및 인코딩 헤더를 보내고 있는지 확인하세요.

예를 들어, 원격 스크립트의 MIME 및 인코딩 유형은 다음과 같습니다: `application/javascript;CHARSET=UTF-8`.

원격 스타일 시트의 MIME 및 인코딩 유형: `text/css;CHARSET=UTF-8`.

## 출력 데이터 및 작업 템플릿
<a name="sms-custom-templates-step2-template-output"></a>

다음 섹션에서는 사용자 지정 레이블 지정 작업의 출력 데이터와 주석 후 Lambda 함수 사용을 고려해야 하는 경우를 설명합니다.

### 출력 데이터
<a name="sms-custom-templates-data"></a>

사용자 지정 레이블 지정 작업이 완료되면 레이블 지정 작업이 생성될 때 지정된 Amazon S3 버킷에 데이터가 저장됩니다. 데이터는 `output.manifest` 파일에 저장됩니다.

**참고**  
*labelAttributeName*은 자리 표시자 변수입니다. 입력에서 라벨링 작업의 이름 또는 라벨링 작업을 생성할 때 지정하는 레이블 속성 이름입니다.
+ `source` 또는 `source-ref` - 문자열 또는 S3 URI 작업자에게 레이블을 지정하도록 요청했습니다.
+ `labelAttributeName` – [주석 후 Lambda 함수](sms-custom-templates-step3-lambda-requirements.md#sms-custom-templates-step3-postlambda)의 통합 레이블 내용이 포함된 사전입니다. 주석 후 Lambda 함수가 지정되지 않은 경우 이 사전은 비어 있습니다.
+ `labelAttributeName-metadata` – Ground Truth에 추가된 사용자 지정 레이블 지정 작업의 메타데이터입니다.
+ `worker-response-ref` – 데이터가 저장되는 버킷의 S3 URI입니다. 주석 후 Lambda 함수가 지정된 경우 이 키-값 페어는 표시되지 않습니다.

이 예제에서 JSON 객체는 가독성을 위해 형식이 지정되어 있고, 실체 출력 파일에서 JSON 객체는 단일 행에 있습니다.

```
{
  "source" : "This train is really late.",
  "labelAttributeName" : {},
  "labelAttributeName-metadata": { # These key values pairs are added by Ground Truth
    "job_name": "test-labeling-job",
    "type": "groundTruth/custom",
    "human-annotated": "yes",
    "creation_date": "2021-03-08T23:06:49.111000",
    "worker-response-ref": "s3://amzn-s3-demo-bucket/test-labeling-job/annotations/worker-response/iteration-1/0/2021-03-08_23:06:49.json"
  }
}
```

### 주석 후 Lambda를 사용하여 작업자의 결과 통합
<a name="sms-custom-templates-consolidation"></a>

기본적으로 Ground Truth는 Amazon S3에서 처리되지 않은 작업자 응답을 저장합니다. 응답 처리 방식을 더 세밀하게 제어하려면 *주석 후 Lambda 함수*를 지정할 수 있습니다. 예를 들어 여러 작업자가 동일한 데이터 객체에 레이블을 지정한 경우 주석 후 Lambda 함수를 사용하여 주석을 통합할 수 있습니다. 주석 후 Lambda 함수 생성에 대한 자세한 내용은 [주석 후 Lambda](sms-custom-templates-step3-lambda-requirements.md#sms-custom-templates-step3-postlambda) 섹션을 참조하세요.

주석 후 Lambda 함수를 사용하려면 `CreateLabelingJob` 요청에서 [https://docs.aws.amazon.com//sagemaker/latest/APIReference/API_AnnotationConsolidationConfig.html](https://docs.aws.amazon.com//sagemaker/latest/APIReference/API_AnnotationConsolidationConfig.html)의 일부로 지정해야 합니다.

주석 통합의 작동 방식에 대한 자세한 내용은 [주석 통합](sms-annotation-consolidation.md) 섹션을 참조하세요.

# Liquid를 사용하여 자동화 추가
<a name="sms-custom-templates-step2-automate"></a>

Amazon의 사용자 지정 템플릿 시스템은 자동화를 위해 [Liquid](https://shopify.github.io/liquid/)를 사용합니다. Liquid는 오픈 소스 인라인 마크업 언어입니다. Liquid에서 단일 중괄호와 퍼센트 기호 사이에 있는 텍스트는 제어 흐름 또는 반복과 같은 작업을 수행하는 지침 또는 *태그*입니다. 이중 중괄호 사이에 있는 텍스트는 변수 또는 변수의 값을 출력하는 *객체*입니다.

Liquid는 가장 일반적으로 입력 매니페스트 파일에서 가져온 데이터를 구분 분석하고 작업을 생성하기 위해 관련 변수를 가져오는 데 사용됩니다. Ground Truth는 사전 주석 Lambda가 지정되지 않는 한 작업을 자동으로 생성합니다. Ground Truth 또는 에서 반환하는 `taskInput` 객체[주석 전 Lambda](sms-custom-templates-step3-lambda-requirements.md#sms-custom-templates-step3-prelambda)는 템플릿의 `task.input` 객체입니다.

입력 매니페스트 내 속성이 `event.dataObject`로 템플릿에 전달됩니다.

**Example 매니페스트 데이터 객체**  

```
{
  "source": "This is a sample text for classification",
  "labels": [ "angry" , "sad" , "happy" , "inconclusive" ],
  "header": "What emotion is the speaker feeling?"
}
```

**Example 변수를 사용하는 샘플 HTM**  

```
<crowd-classifier 
  name='tweetFeeling'
  categories='{{ task.input.labels | to_json }}'
  header='{{ task.input.header }}' >
<classification-target>
  {{ task.input.source }}
</classification-target>
```

위에서 `labels` 속성에 ` | to_json`이 추가되는 데 유의하세요 이것은 입력 매니페이스를 배열의 JSON 표현으로 변환하는 필터입니다. 변수 필터는 다음 섹션에서 설명합니다.

다음 목록에는 템플릿 입력 데이터 처리를 자동화하는 데 유용할 수 있는 두 가지 유형의 Liquid 태그가 포함되어 있습니다. 다음 태그 유형 중 하나를 선택하면 Liquid 설명서로 리디렉션됩니다.
+ [제어 흐름](https://shopify.github.io/liquid/tags/control-flow/): `if/else`, `unless`, `case/when`과 같은 프로그래밍 로직 연산자를 포함합니다.
+ [반복](https://shopify.github.io/liquid/tags/iteration/): for 루프와 같은 명령문을 사용하여 코드 블록을 반복적으로 실행할 수 있습니다.

  Liquid 요소를 사용하여 for 루프를 만드는 HTML 템플릿의 예시는 GitHub의 [translation-review-and-correction.liquid.html](https://github.com/aws-samples/amazon-sagemaker-ground-truth-task-uis/blob/8ae02533ea5a91087561b1daecd0bc22a37ca393/text/translation-review-and-correction.liquid.html)을 참조하세요.

자세한 내용 및 설명서는 [Liquid 홈페이지](https://shopify.github.io/liquid/)를 참조하세요.

## 변수 필터
<a name="sms-custom-templates-step2-automate-filters"></a>

Ground Truth는 표준 [Liquid 필터](https://shopify.github.io/liquid/filters/abs/) 및 작업 이외에 몇 가지 추가 필터를 제공합니다. 필터는 변수 이름 뒤에 파이프(`|`) 문자를 삽입한 후 필터 이름을 지정하여 적용됩니다. 필터는 다음 형식으로 함께 묶을 수 있습니다.

**Example**  

```
{{ <content> | <filter> | <filter> }}
```

### Autoescape 및 explicit escape
<a name="sms-custom-templates-step2-automate-filters-autoescape"></a>

기본적으로 입력은 변수 텍스트와 HTML 간에 혼동을 피하기 위해 이스케이프된 HTML입니다. 이스케이프가 완료된 템플릿의 소스를 보다 분명하게 읽을 수 있도록 `escape` 필터를 명시적으로 추가할 수 있습니다.

### escape\$1once
<a name="sms-custom-templates-step2-automate-escapeonce"></a>

`escape_once`는 코드를 이미 이스케이프한 경우 이후에 해당 코드가 다시 이스케이프되지 않도록 합니다. 예를 들어, &amp;는 &amp;amp;가 되지 않습니다.

### skip\$1autoescape
<a name="sms-custom-templates-step2-automate-skipautoescape"></a>

`skip_autoescape`는 콘텐츠가 HTML로 사용되는 경우 유용합니다. 예를 들어, 경계 상자에 대한 전체 지침에 텍스트 단락 몇 개와 이미지 몇 개가 있을 수 있습니다.

**드물게 `skip_autoescape` 사용**  
템플릿을 사용할 때, 전달 항목에 대해 엄격한 제어 권한이 없는 한 `skip_autoescape`로 함수 코드나 마크업을 전달하지 않는 것이 좋습니다. 사용자 입력을 전달하는 경우 작업자가 교차 사이트 스크립팅 공격에 노출되도록 할 수 있습니다.

### to\$1json
<a name="sms-custom-templates-step2-automate-tojson"></a>

`to_json`은 JSON(JavaScript Object Notation)에 제공하는 항목을 인코딩합니다. 객체를 제공하는 경우 직렬화합니다.

### grant\$1read\$1access
<a name="sms-custom-templates-step2-automate-grantreadaccess"></a>

`grant_read_access`는 S3 URI를 가져와 해당 리소스에 대해 수명이 짧은 액세스 토큰을 사용하여 HTTPS URL로 인코딩합니다. 따라서 작업자에게 S3 버킷에 저장된 사진, 오디오 또는 비디오 객체를 표시할 수 있습니다. 그렇지 않으면 이러한 객체는 공개적으로 액세스할 수 없습니다.

### s3\$1presign
<a name="sms-custom-templates-step2-automate-s3"></a>

 `s3_presign` 필터는 `grant_read_access` 필터와 동일한 방식으로 작동합니다. `s3_presign`는 Amazon S3 URI를 가져와 해당 리소스에 대한 수명이 짧은 액세스 토큰을 사용하여 HTTPS URL로 인코딩합니다. 이를 통해 작업자가 공개적으로 액세스할 수 없는 S3 버킷에 저장된 사진, 오디오 또는 비디오 객체를 표시할 수 있습니다.

**Example 변수 필터 중**  
입력  

```
auto-escape: {{ "Have you read 'James & the Giant Peach'?" }}
explicit escape: {{ "Have you read 'James & the Giant Peach'?" | escape }}
explicit escape_once: {{ "Have you read 'James &amp; the Giant Peach'?" | escape_once }}
skip_autoescape: {{ "Have you read 'James & the Giant Peach'?" | skip_autoescape }}
to_json: {{ jsObject | to_json }}                
grant_read_access: {{ "s3://amzn-s3-demo-bucket/myphoto.png" | grant_read_access }}
s3_presign: {{ "s3://amzn-s3-demo-bucket/myphoto.png" | s3_presign }}
```

**Example**  
출력  

```
auto-escape: Have you read &#39;James &amp; the Giant Peach&#39;?
explicit escape: Have you read &#39;James &amp; the Giant Peach&#39;?
explicit escape_once: Have you read &#39;James &amp; the Giant Peach&#39;?
skip_autoescape: Have you read 'James & the Giant Peach'?
to_json: { "point_number": 8, "coords": [ 59, 76 ] }
grant_read_access: https://s3.amazonaws.com/amzn-s3-demo-bucket/myphoto.png?<access token and other params>
s3_presign: https://s3.amazonaws.com/amzn-s3-demo-bucket/myphoto.png?<access token and other params>
```

**Example 자동화된 분류 템플릿.**  
간단한 텍스트 분류 샘플을 자동화하려면 트윗 텍스트를 변수로 바꿉니다.  
아래 텍스트 분류 템플릿에는 자동화가 추가되어 있습니다. 변경/추가된 내용은 굵게 강조 표시되어 있습니다.  

```
<script src="https://assets.crowd.aws/crowd-html-elements.js"></script>
<crowd-form>
  <crowd-classifier 
    name="tweetFeeling"
    categories="['positive', 'negative', 'neutral', 'cannot determine']"
    header="Which term best describes this tweet?" 
  >
    <classification-target>
       {{ task.input.source }}
    </classification-target>

    <full-instructions header="Analyzing a sentiment">
      Try to determine the feeling the author 
      of the tweet is trying to express. 
      If none seem to match, choose "other."
    </full-instructions>

    <short-instructions>
      Pick the term best describing the sentiment 
      of the tweet. 
    </short-instructions>

  </crowd-classifier>
</crowd-form>
```
이전 샘플에 있던 트윗 텍스트는 이제 객체로 바뀝니다. `entry.taskInput` 객체는 `source`(또는 주석 전 Lambda에서 지정한 다른 이름)를 텍스트에 대한 속성 이름으로 사용하고, 이것은 이중 중괄호 사이에 있기 때문에 HTML에 직접 삽입됩니다.

# 를 사용하여 사용자 지정 레이블 지정 워크플로에서 데이터 처리 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 Truth와 AWS Lambda 함께 사용하는 데 필요한 권한 추가](sms-custom-templates-step3-lambda-permissions.md) 페이지를 통해 Ground Truth 사용자 지정 라벨링 작업에서 주석 전 및 주석 후 Lambda 함수를 사용하기 위한 보안 및 권한 요구 사항에 대해 알아봅니다.

1. 다음으로, Lambda 콘솔을 방문하거나 Lambda의 API를 사용하여 함수를 생성해야 합니다. [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 Truth와 AWS Lambda 함께 사용하는 데 필요한 권한 추가](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 형식의 요청을 보내 라벨링 작업과 데이터 객체에 대한 세부 정보를 제공합니다.

다음은 두 가지 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는 데이터를 추가로 처리하지 않습니다.

# Ground Truth와 AWS Lambda 함께 사용하는 데 필요한 권한 추가
<a name="sms-custom-templates-step3-lambda-permissions"></a>

Ground Truth를 통해 AWS Lambda 를 생성하여 사용하려면 다음 중 일부 또는 전체를 구성해야 할 수 있습니다.
+ 를 사용하여 주석 전 및 주석 후 Lambda 함수를 생성하고 레이블 지정 작업을 생성할 때 선택할 수 AWS Lambda있는 IAM 역할 또는 사용자(집합적으로 IAM 엔터티) 권한을 부여해야 합니다.
+ 라벨링 작업이 구성될 때 지정된 IAM 실행 역할에는 주석 전 및 주석 후 Lambda 함수를 호출할 수 있는 권한이 필요합니다.
+ 주석 후 Lambda 함수에는 Amazon S3에 액세스할 수 있는 권한이 필요할 수 있습니다.

다음 섹션을 통해 위에서 설명한 IAM 엔티티 생성 및 권한 부여 방법을 알아보세요.

**Topics**
+ [AWS Lambda 함수를 생성하고 선택할 수 있는 권한 부여](#sms-custom-templates-step3-postlambda-create-perms)
+ [AWS Lambda 함수를 호출할 수 있는 IAM 실행 역할 권한 부여](#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 함수를 개발하는 데 세분화된 권한이 필요하지 않은 경우 AWS 관리형 정책을 `AWSLambda_FullAccess` 사용자 또는 역할에 연결할 수 있습니다. 이 정책은 모든 Lambda 기능을 사용할 수 있는 광범위한 권한과 Lambda가 상호 작용하는 다른 AWS 서비스에서 작업을 수행할 수 있는 권한을 부여합니다.

보안에 민감한 사용 사례에 대해 보다 세분화된 정책을 생성하려면 AWS Lambda 개발자 안내서의 [Lambda에 대한 자격 증명 기반 IAM 정책](https://docs.aws.amazon.com/lambda/latest/dg/access-control-identity-based.html) 설명서를 참조하여 사용 사례에 맞는 IAM 정책을 생성하는 방법을 알아보세요.

**Lambda 콘솔 사용 정책**

IAM 엔터티에 Lambda 콘솔을 사용할 수 있는 권한을 부여하려면 AWS Lambda 개발자 안내서[의 Lambda 콘솔 사용을](https://docs.aws.amazon.com/lambda/latest/dg/security_iam_id-based-policy-examples.html#security_iam_id-based-policy-examples-console) 참조하세요.

또한 사용자가 Lambda 콘솔에서를 사용하여 Ground Truth 스타터 주석 전 및 주석 후 함수 AWS Serverless Application Repository 에 액세스하고 배포할 수 있게 하려면 함수를 배포할 *`<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 함수를 확인하기 위한 정책**

사용자가 사용자 지정 라벨링 작업을 생성할 때 Ground Truth 콘솔에서 Lambda 함수를 볼 수 있는 권한을 IAM 엔터티에 부여하려면 해당 엔터티가 [사용자 지정 레이블 워크플로 권한](sms-security-permission-console-access.md#sms-security-permissions-custom-workflow) 섹션에서 설명하는 권한을 포함하여 [Amazon SageMaker Ground Truth 콘솔을 사용하는 IAM 권한 부여](sms-security-permission-console-access.md) 섹션에 설명된 권한이 있어야 합니다.

## AWS Lambda 함수를 호출할 수 있는 IAM 실행 역할 권한 부여
<a name="sms-custom-templates-step3-postlambda-execution-role-perms"></a>

라벨링 작업을 생성하는 데 사용된 IAM 실행 역할에 IAM 관리형 정책 [AmazonSageMakerGroundTruthExecution](https://console.aws.amazon.com/iam/home?#/policies/arn:aws:iam::aws:policy/AmazonSageMakerGroundTruthExecution)을 추가하면, 이 역할은 함수 이름에 `GtRecipe`, `SageMaker`, `Sagemaker`, `sagemaker` 또는 `LabelingFunction` 문자열 중 하나를 사용하여 Lambda 함수를 나열하고 호출할 권한을 가집니다.

주석 전 또는 주석 후 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` 문자열로 식별됩니다. 수신 시 주석을 처리하려면 간단한 전달 함수라 하더라도 Amazon S3에서 파일을 읽을 수 있도록 주석 후 [Lambda 실행 역할](https://docs.aws.amazon.com/lambda/latest/dg/lambda-intro-execution-role.html)에 필수 권한을 할당해야 합니다.

Amazon S3의 주석 데이터에 액세스하도록 Lambda를 구성하는 방법은 여러 가지가 있습니다. 일반적인 두 가지 방법은 다음과 같습니다.
+ Lambda 실행 역할이 주석 후 Lambda 요청의 `roleArn`에서 식별된 SageMaker AI 실행 역할을 맡도록 허용합니다. 이 SageMaker AI 실행 역할은 레이블링 작업을 생성하는 데 사용되며 주석 데이터가 저장되는 Amazon S3 출력 버킷에 액세스할 수 있습니다.
+ Lambda 실행 역할에 Amazon S3 출력 버킷에 직접 액세스할 수 있는 권한을 부여합니다.

다음 섹션을 통해 이러한 옵션을 구성하는 방법을 알아보세요.

**Lambda에 SageMaker AI 실행 역할을 맡을 수 있는 권한 부여**

Lambda 함수가 SageMaker AI 실행 역할을 맡도록 허용하려면 Lambda 함수의 실행 역할에 정책을 연결하고 Lambda가 이를 수임할 수 있도록 SageMaker AI 실행 역할의 신뢰 관계를 수정해야 합니다.

1. [다음 IAM 정책을 Lambda 함수의 실행 역할에 연결](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_manage-attach-detach.html)하여 `Resource`에서 식별된 SageMaker AI 실행 역할을 수임합니다. `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. 다음 `Statement`를 포함하도록 SageMaker AI 실행 역할의 [신뢰 정책을 수정](https://docs.aws.amazon.com/IAM/latest/UserGuide/roles-managingrole-editing-console.html#roles-managingrole_edit-trust-policy)합니다. `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 읽기 권한을 추가하려면 다음 절차를 따르세요.

**주석 후 Lambda에 S3 읽기 권한을 추가합니다.**

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 SDK를 사용하여 Lambda 함수를 생성할 수 있습니다. AWS Lambda 개발자 안내서를 사용하여 다음 각 옵션에 대해 자세히 알아보세요.
+ 콘솔을 사용하여 Lambda 함수를 생성하는 방법을 알아보려면 [콘솔로 Lambda 함수 생성](https://docs.aws.amazon.com/lambda/latest/dg/getting-started-create-function.html) 섹션을 참조하세요.
+ 를 사용하여 Lambda 함수를 생성하는 방법을 알아보려면 명령줄 인터페이스에서 Lambda 사용을 AWS CLI참조하세요. [AWSAWS](https://docs.aws.amazon.com/lambda/latest/dg/gettingstarted-awscli.html) 
+ 목차에서 관련 섹션을 선택하여 원하는 언어로 Lambda를 사용해 작업하는 방법에 대해 자세히 알아보세요. 예를 들어, [Python 작업](https://docs.aws.amazon.com/lambda/latest/dg/lambda-python.html)을 선택하여 Lambda를 AWS SDK for Python (Boto3)와 함께 사용하는 방법에 대해 자세히 알아볼 수 있습니다.

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)의 지침에 따라 레이블링 작업을 생성하는 데 사용되는 SageMaker AI 실행 역할을 수임하는 권한을 주석 후 Lambda 함수의 실행 역할에 부여해야 합니다. 주석 후 Lambda 함수는 SageMaker AI 실행 역할을 이용하여 S3의 주석 데이터 파일인 `sample-annotations.json`에 액세스합니다.



## 주석 전 Lambda 함수 테스트
<a name="sms-custom-templates-step3-lambda-test-pre-annotation"></a>

다음 절차에 따라 Ground Truth AWS Serverless Application Repository (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. **이벤트 템플릿**에서 **SageMaker Ground 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>

다음 절차에 따라 Ground Truth AWS Serverless Application Repository (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. **이벤트 템플릿**에서 **SageMaker Ground 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. **테스트**를 선택하여 테스트를 실행합니다.

테스트를 실행한 후에는 `sample-annotations.json`에 포함된 모든 주석의 목록을 포함하고 있는 **함수 로그**의 `-- Consolidated Output --` 섹션이 표시됩니다.

# 데모 템플릿: `crowd-bounding-box`를 사용한 이미지 주석
<a name="sms-custom-templates-step2-demo1"></a>

Amazon SageMaker Ground Truth 콘솔의 작업 유형으로 사용자 지정 템플릿을 선택하면 **사용자 지정 라벨링 작업 패널**이 열립니다. 여기에서 여러 기본 템플릿을 선택할 수 있습니다. 템플릿은 가장 일반적인 작업 몇 가지를 제시하며 사용자 지정 라벨링 작업의 템플릿을 생성할 때 작업할 샘플을 제공합니다. 콘솔을 사용하지 않거나 추가 리소스가 필요한 경우 [Amazon SageMaker AI Ground Truth 샘플 작업 UI](https://github.com/aws-samples/amazon-sagemaker-ground-truth-task-uis)에서 다양한 레이블링 작업 유형의 데모 템플릿 리포지토리를 확인할 수 있습니다.

이 데모는 **BoundingBox** 템플릿에서 사용할 수 있습니다. 또한이 데모는 작업 전후에 데이터를 처리하는 데 필요한 AWS Lambda 함수와 함께 작동합니다. 위의 Github 리포지토리에서 AWS Lambda 함수와 함께 작동하는 템플릿을 찾으려면 템플릿`{{ task.input.<property name> }}`에서를 찾습니다.

**Topics**
+ [입문용 경계 상자 사용자 지정 템플릿](#sms-custom-templates-step2-demo1-base-template)
+ [경계 상자 사용자 지정 템플릿](#sms-custom-templates-step2-demo1-your-own-template)
+ [매니페스트 파일](#sms-custom-templates-step2-demo1-manifest)
+ [주석 전 Lambda 함수](#sms-custom-templates-step2-demo1-pre-annotation)
+ [주석 후 Lambda 함수](#sms-custom-templates-step2-demo1-post-annotation)
+ [라벨링 작업의 출력](#sms-custom-templates-step2-demo1-job-output)

## 입문용 경계 상자 사용자 지정 템플릿
<a name="sms-custom-templates-step2-demo1-base-template"></a>

제공된 입문용 경계 상자 템플릿입니다.

```
<script src="https://assets.crowd.aws/crowd-html-elements.js"></script>

<crowd-form>
  <crowd-bounding-box
    name="boundingBox"
    src="{{ task.input.taskObject | grant_read_access }}"
    header="{{ task.input.header }}"
    labels="{{ task.input.labels | to_json | escape }}"
  >

    <!-- The <full-instructions> tag is where you will define the full instructions of your task. -->
    <full-instructions header="Bounding Box Instructions" >
      <p>Use the bounding box tool to draw boxes around the requested target of interest:</p>
      <ol>
        <li>Draw a rectangle using your mouse over each instance of the target.</li>
        <li>Make sure the box does not cut into the target, leave a 2 - 3 pixel margin</li>
        <li>
          When targets are overlapping, draw a box around each object,
          include all contiguous parts of the target in the box.
          Do not include parts that are completely overlapped by another object.
        </li>
        <li>
          Do not include parts of the target that cannot be seen,
          even though you think you can interpolate the whole shape of the target.
        </li>
        <li>Avoid shadows, they're not considered as a part of the target.</li>
        <li>If the target goes off the screen, label up to the edge of the image.</li>
      </ol>
    </full-instructions>

    <!-- The <short-instructions> tag allows you to specify instructions that are displayed in the left hand side of the task interface.
    It is a best practice to provide good and bad examples in this section for quick reference. -->
    <short-instructions>
      Use the bounding box tool to draw boxes around the requested target of interest.
    </short-instructions>
  </crowd-bounding-box>
</crowd-form>
```

이 사용자 지정 템플릿은 [Liquid 템플릿 언어](https://shopify.github.io/liquid/)를 사용하고 이중 중괄호 사이에 있는 각 항목은 변수입니다. 주석 전 AWS Lambda 함수는 라는 객체를 제공해야 하며 `taskInput` 해당 객체의 속성은 템플릿`{{ task.input.<property name> }}`에서와 같이 액세스할 수 있습니다.

## 경계 상자 사용자 지정 템플릿
<a name="sms-custom-templates-step2-demo1-your-own-template"></a>

일례로 이전의 이미지 분류 작업에서 어떤 동물이 있는지 아는 대규모 동물 사진 모음이 있다고 합시다. 이제 여기에 경계 상자를 그리려고 합니다.

입문용 샘플에는 `taskObject`, `header`, `labels` 등 3가지 변수가 있습니다.

이러한 각 변수는 경계 상자의 여러 부분을 나타냅니다.
+ `taskObject`는 주석을 달 사진의 HTTP(S) URL 또는 S3 URI입니다. 추가된 `| grant_read_access`는 S3 URI를 리소스에 대한 단기 액세스가 가능한 HTTPS URL로 변환하는 필터입니다. HTTP(S) URL을 사용하는 경우에는 필요하지 않습니다.
+ `header`는 라벨링할 사진 위에 표시되는 텍스트입니다(예: "사진 속 새 주위에 상자를 그려보세요").
+ `labels`은 `['item1', 'item2', ...]`로 표시되는 어레이입니다. 이러한 항목은 작업자가 자신이 그린 여러 상자에 할당할 수 있는 레이블로, 하나 이상일 수 있습니다.

각 변수 이름은 주석 전 Lambda의 응답에 있는 JSON 객체에서 가져오고, 위의 이름은 단순히 제안 항목에 불과하며, 변수 이름은 합리적이고 팀 내에서 코드 가독성을 향상시킬 수 있는 것이면 뭐든 사용할 수 있습니다.

**필요한 경우 변수 사용**  
필드가 변경되지 않으면 템플릿에서 변수를 제거한 다음 텍스트로 바꿀 수 있습니다. 그렇지 않으면 매니페스트의 각 객체에서 텍스트를 값으로 반복하거나 주석 전 Lambda 함수로 코딩해야 합니다.

**Example : 최종 사용자 지정 경계 상자 템플릿**  
간단한 설명을 위해 이 템플릿에는 변수, 라벨링이 하나씩 있고 매우 기본적인 지침이 있습니다. 매니페스트의 각 데이터 객체에 "동물" 속성이 있다고 가정하면, 값을 템플릿의 두 부분에서 재사용할 수 있습니다.  

```
<script src="https://assets.crowd.aws/crowd-html-elements.js"></script>
<crowd-form>
  <crowd-bounding-box
    name="boundingBox"
    labels="[ '{{ task.input.animal }}' ]"
    src="{{ task.input.source-ref | grant_read_access }}"
    header="Draw a box around the {{ task.input.animal }}."
  >
    <full-instructions header="Bounding Box Instructions" >
      <p>Draw a bounding box around the {{ task.input.animal }} in the image. If 
      there is more than one {{ task.input.animal }} per image, draw a bounding 
      box around the largest one.</p>
      <p>The box should be tight around the {{ task.input.animal }} with 
      no more than a couple of pixels of buffer around the 
      edges.</p>
      <p>If the image does not contain a {{ task.input.animal }}, check the <strong>
      Nothing to label</strong> box.
    </full-instructions>
    <short-instructions>
      <p>Draw a bounding box around the {{ task.input.animal }} in each image. If 
      there is more than one {{ task.input.animal }} per image, draw a bounding 
      box around the largest one.</p>
    </short-instructions>
  </crowd-bounding-box>
</crowd-form>
```
`{{ task.input.animal }}`는 템플릿 전체에서 재사용할 수 있습니다. 매니페스트에서 모든 동물 이름이 대문자로 시작하는 경우 `{{ task.input.animal | downcase }}`를 사용하여 Liquid의 기본 제공 필터 중 하나를 해당 이름이 소문자로 표시되어야 하는 문장에 통합할 수 있습니다.

## 매니페스트 파일
<a name="sms-custom-templates-step2-demo1-manifest"></a>

매니페스트 파일이 템플릿에서 사용하는 변수 값을 제공해야 합니다. 주석 전 Lambda에서 매니페스트 데이터 중 일부를 변환할 수 있지만 필요하지 않은 경우 오류가 발생할 약간의 위험을 감수하면 Lambda가 더 빠르게 실행됩니다. 다음은 템플릿에 대한 샘플 매니페스트 파일입니다.

```
{"source-ref": "<S3 image URI>", "animal": "horse"}
{"source-ref": "<S3 image URI>", "animal" : "bird"}
{"source-ref": "<S3 image URI>", "animal" : "dog"}
{"source-ref": "<S3 image URI>", "animal" : "cat"}
```

## 주석 전 Lambda 함수
<a name="sms-custom-templates-step2-demo1-pre-annotation"></a>

작업 설정의 일부로 매니페스트 항목을 처리하고 템플릿 엔진에 전달하기 위해 호출할 수 있는 AWS Lambda 함수의 ARN을 제공합니다.

**Lambda 함수 이름 지정**  
함수 이름 지정에서 모범 사례는 `SageMaker`, `Sagemaker`, `sagemaker`, `LabelingFunction` 등 4개 문자열 중 하나를 함수 이름의 일부로 사용하는 것입니다. 이는 주석 전 및 주석 후 함수에 모두 적용됩니다.

콘솔을 사용할 때 계정이 소유한 AWS Lambda 함수가 있는 경우 이름 지정 요구 사항을 충족하는 함수의 드롭다운 목록이 제공되어 하나를 선택할 수 있습니다.

이 매우 기본적인 예제에서는, 매니페스트의 정보를 추가적인 처리 없이 전달만 합니다. 이 샘플 주석 전 함수는 Python 3.7용으로 작성된 것입니다.

```
import json

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

매니페스트의 JSON 객체는 `event` 객체의 하위 항목으로 제공됩니다. `taskInput` 객체 내부의 속성은 템플릿에서 변수로 사용될 수 있으므로 단순히 `taskInput` 값을 `event['dataObject']`로 설정하면 개별적으로 복사할 필요 없이 매니페스트 객체의 모든 값이 템플릿으로 전달됩니다. 템플릿으로 더 많은 값을 보내려면 `taskInput` 객체에 해당 값을 추가합니다.

## 주석 후 Lambda 함수
<a name="sms-custom-templates-step2-demo1-post-annotation"></a>

작업 설정의 일부로 작업자가 작업을 완료할 때 양식 데이터를 처리하기 위해 호출할 수 있는 AWS Lambda 함수의 ARN을 제공합니다. 원하는 대로 간단하거나 복잡할 수 있습니다. 수신될 때 답변을 통합하고 채점하려는 경우 선택한 채점 및/또는 통합 알고리즘을 적용할 수 있습니다. 오프라인 처리를 위해 원시 데이터를 저장하려는 경우 이는 옵션입니다.

**주석 후 Lambda에 권한 부여**  
주석 데이터는 `payload` 객체의 `s3Uri` 문자열에서 지정한 파일에 있습니다. 수신 시 주석을 처리하려면 간단한 전달 함수라 하더라도 주석 파일을 읽을 수 있도록 Lambda에 `S3ReadOnly` 액세스 권한을 할당해야 합니다.  
Lambda를 생성하기 위한 콘솔 페이지에서 **실행 역할** 패널로 스크롤합니다. **1개 이상의 템플릿에서 새로운 역할을 생성하세요**를 선택합니다. 역할 이름을 지정합니다. **정책 템플릿** 드롭다운에서 **Amazon S3 객체 읽기 전용 권한**을 선택합니다. Lambda를 저장하면 역할이 저장되어 선택됩니다.

다음 샘플은 Python 2.7에서 작성되었습니다.

```
import json
import boto3
from urlparse import urlparse

def lambda_handler(event, context):
    consolidated_labels = []

    parsed_url = urlparse(event['payload']['s3Uri']);
    s3 = boto3.client('s3')
    textFile = s3.get_object(Bucket = parsed_url.netloc, Key = parsed_url.path[1:])
    filecont = textFile['Body'].read()
    annotations = json.loads(filecont);
    
    for dataset in annotations:
        for annotation in dataset['annotations']:
            new_annotation = json.loads(annotation['annotationData']['content'])
            label = {
                'datasetObjectId': dataset['datasetObjectId'],
                'consolidatedAnnotation' : {
                'content': {
                    event['labelAttributeName']: {
                        'workerId': annotation['workerId'],
                        'boxesInfo': new_annotation,
                        'imageSource': dataset['dataObject']
                        }
                    }
                }
            }
            consolidated_labels.append(label)
    
    return consolidated_labels
```

주석 후 Lambda는 일반적으로 이벤트 객체에서 작업 결과 배치를 수신합니다. 이러한 배치는 Lambda가 반복해야 하는 `payload` 객체입니다. 다시 보내는 항목은 [API 계약](sms-custom-templates-step3.md)을 충족하는 객체입니다.

## 라벨링 작업의 출력
<a name="sms-custom-templates-step2-demo1-job-output"></a>

작업 출력은 지정한 대상 S3 버킷에서 라벨링 작업 후 이름을 지정한 폴더에서 찾습니다. `manifests`라는 하위 폴더에 있습니다.

경계 상자 작업의 경우 출력 매니페스트의 출력은 아래 데모와 약간 유사합니다. 이 예제는 인쇄를 위해 정리되었습니다. 실제 출력은 레코드당 단일 행입니다.

**Example : 출력 매니페스트의 JSON**  

```
{
  "source-ref":"<URL>",
  "<label attribute name>":
    {
       "workerId":"<URL>",
       "imageSource":"<image URL>",
       "boxesInfo":"{\"boundingBox\":{\"boundingBoxes\":[{\"height\":878, \"label\":\"bird\", \"left\":208, \"top\":6, \"width\":809}], \"inputImageProperties\":{\"height\":924, \"width\":1280}}}"},
  "<label attribute name>-metadata":
    {
      "type":"groundTruth/custom",
      "job_name":"<Labeling job name>",
      "human-annotated":"yes"
    },
  "animal" : "bird"
}
```
어떻게 원래 매니페스트의 추가 `animal` 속성이 `source-ref` 및 라벨링 데이터와 동일한 수준에서 출력 매니페스트로 전달되었는지 보세요. 템플릿에서 사용되었는지 여부와 상관없이 입력 매니페스트의 모든 속성이 출력 매니페스트로 전달됩니다.

# 데모 템플릿: `crowd-classifier`를 사용하여 의도(intent) 라벨링
<a name="sms-custom-templates-step2-demo2"></a>

사용자 지정 템플릿을 선택하면 **사용자 지정 라벨링 작업 패널**이 열립니다. 여기에서 보다 일반적인 작업 몇 가지를 제시하는 여러 입문용 템플릿을 선택할 수 있습니다. 템플릿은 사용자 지정 라벨링 작업의 템플릿을 빌드하는 출발점을 제공합니다.

이 데모에서는 `crowd-classifier` 요소를 사용하는 **의도 감지** 템플릿과 작업 전후에 데이터를 처리하는 데 필요한 AWS Lambda 함수를 사용해 봅니다.

**Topics**
+ [입문용 의도 감지 사용자 지정 템플릿](#sms-custom-templates-step2-demo2-base-template)
+ [의도 감지 사용자 지정 템플릿](#sms-custom-templates-step2-demo2-your-template)
+ [주석 전 Lambda 함수](#sms-custom-templates-step2-demo2-pre-lambda)
+ [주석 후 Lambda 함수](#sms-custom-templates-step2-demo2-post-lambda)
+ [라벨링 작업 출력](#sms-custom-templates-step2-demo2-job-output)

## 입문용 의도 감지 사용자 지정 템플릿
<a name="sms-custom-templates-step2-demo2-base-template"></a>

시작점으로 제공되는 의도 감지 템플릿입니다.

```
<script src="https://assets.crowd.aws/crowd-html-elements.js"></script>

<crowd-form>
  <crowd-classifier
    name="intent"
    categories="{{ task.input.labels | to_json | escape }}"
    header="Pick the most relevant intention expressed by the below text"
  >
    <classification-target>
      {{ task.input.utterance }}
    </classification-target>
    
    <full-instructions header="Intent Detection Instructions">
        <p>Select the most relevant intention expressed by the text.</p>
        <div>
           <p><strong>Example: </strong>I would like to return a pair of shoes</p>
           <p><strong>Intent: </strong>Return</p>
        </div>
    </full-instructions>

    <short-instructions>
      Pick the most relevant intention expressed by the text
    </short-instructions>
  </crowd-classifier>
</crowd-form>
```

이 사용자 지정 템플릿은 [Liquid 템플릿 언어](https://shopify.github.io/liquid/)를 사용하고 이중 중괄호 사이에 있는 각 항목은 변수입니다. 주석 전 AWS Lambda 함수는 이라는 객체를 제공해야 하며 `taskInput` 해당 객체의 속성은 템플릿`{{ task.input.<property name> }}`에서와 같이 액세스할 수 있습니다.

## 의도 감지 사용자 지정 템플릿
<a name="sms-custom-templates-step2-demo2-your-template"></a>

입문용 템플릿에는 `crowd-classifier` 요소 열기 태그의 `task.input.labels` 속성 변수와, `classification-target` 리전 콘텐츠의 `task.input.utterance` 변수가 있습니다.

다른 텍스트 언어(utterance)로 다른 레이블 세트를 제공할 필요가 없는 한, 변수를 피하고 텍스트를 사용하는 것만으로도 처리 시간이 절약되고 오류 가능성이 낮아집니다. 이 데모에 사용되는 템플릿은 변수를 제거하며, `to_json`등과 같은 필터와 변수는 [`crowd-bounding-box` 데모]() 자료에서 자세히 설명합니다.

### 요소 스타일 지정
<a name="sms-custom-templates-step2-demo2-instructions"></a>

이러한 사용자 지정 요소에서 자주 간과되는 두 부분은 `<full-instructions>` 영역과 `<short-instructions>` 영역입니다. 적절한 지침은 좋은 결과를 가져옵니다.

이러한 영역을 포함하는 요소에서는 작업자 화면 왼쪽 창의 "지침" 창에 `<short-instructions>`가 자동으로 나타납니다. `<full-instructions>`는 창 창단의 "View full instructions(전체 지침 보기)" 링크에서 연결됩니다. 링크를 클릭하면 자세한 지침이 들어 있는 창이 열립니다.

이 섹션에서 HTML, CSS 및 JavaScript를 사용할 수 있을 뿐만 아니라, 작업자가 더 빠르고 정확하게 작업을 완료하도록 도와주는 강력한 지침과 예를 제공할 수 있습니다.

**Example JSFiddle을 사용한 샘플 테스트해 보기**  
[https://jsfiddle.net/MTGT_Fiddle_Manager/bjc0y1vd/35/](https://jsfiddle.net/MTGT_Fiddle_Manager/bjc0y1vd/35/)  
 [예제 `<crowd-classifier>` 작업](https://jsfiddle.net/MTGT_Fiddle_Manager/bjc0y1vd/35/)을 테스트해 보세요. 이 예제는 JSFiddle로 렌더링되었으므로 모든 템플릿 변수는 하드 코딩 값으로 대체됩니다. "전체 지침 보기" 링크를 클릭하여 확장 CSS 스타일이 지정된 예제들을 볼 수 있습니다. 프로젝트에 따라 CSS를 직접 변경하여 실험해 보거나, 샘플 이미지를 추가하거나, 확장된 JavaScript 기능을 추가할 수 있습니다.

**Example : 최종 사용자 지정 의도 감지 템플릿**  
이 템플릿은 [예제 `<crowd-classifier>` 작업](https://jsfiddle.net/MTGT_Fiddle_Manager/bjc0y1vd/35/)을 사용하지만 `<classification-target>`에 대한 변수가 포함되어 있습니다. 일련의 여러 라벨링 작업 간에 일관된 CSS 디자인을 유지하려면 일반 HTML 문서에서와 같은 방식으로 `<link rel...>` 요소를 사용하여 외부 스타일시트를 포함시키면 됩니다.  

```
<script src="https://assets.crowd.aws/crowd-html-elements.js"></script>

<crowd-form>
  <crowd-classifier
    name="intent"
    categories="['buy', 'eat', 'watch', 'browse', 'leave']"
    header="Pick the most relevant intent expressed by the text below"
  >
    <classification-target>
      {{ task.input.source }}
    </classification-target>
    
    <full-instructions header="Emotion Classification Instructions">
      <p>In the statements and questions provided in this exercise, what category of action is the speaker interested in doing?</p>
          <table>
            <tr>
              <th>Example Utterance</th>
              <th>Good Choice</th>
            </tr>
            <tr>
              <td>When is the Seahawks game on?</td>
              <td>
                eat<br>
                <greenbg>watch</greenbg>
                <botchoice>browse</botchoice>
              </td>
            </tr>
            <tr>
              <th>Example Utterance</th>
              <th>Bad Choice</th>
            </tr>
            <tr>
              <td>When is the Seahawks game on?</td>
              <td>
                buy<br>
                <greenbg>eat</greenbg>
                <botchoice>watch</botchoice>
              </td>
            </tr>
          </table>
    </full-instructions>

    <short-instructions>
      What is the speaker expressing they would like to do next?
    </short-instructions>  
  </crowd-classifier>
</crowd-form>
<style>
  greenbg {
    background: #feee23;
    display: block;
  }

  table {
    *border-collapse: collapse; /* IE7 and lower */
    border-spacing: 0; 
  }

  th, tfoot, .fakehead {
    background-color: #8888ee;
    color: #f3f3f3;
    font-weight: 700;
  }

  th, td, tfoot {
      border: 1px solid blue;
  }

  th:first-child {
    border-radius: 6px 0 0 0;
  }

  th:last-child {
    border-radius: 0 6px 0 0;
  }

  th:only-child{
    border-radius: 6px 6px 0 0;
  }

  tfoot:first-child {
    border-radius: 0 0 6px 0;
  }

  tfoot:last-child {
    border-radius: 0 0 0 6px;
  }

  tfoot:only-child{
    border-radius: 6px 6px;
  }

  td {
    padding-left: 15px ;
    padding-right: 15px ;
  }

  botchoice {
    display: block;
    height: 17px;
    width: 490px;
    overflow: hidden;
    position: relative;
    background: #fff;
    padding-bottom: 20px;
  }

  botchoice:after {
    position: absolute;
    bottom: 0;
    left: 0;  
    height: 100%;
    width: 100%;
    content: "";
    background: linear-gradient(to top,
       rgba(255,255,255, 1) 55%, 
       rgba(255,255,255, 0) 100%
    );
    pointer-events: none; /* so the text is still selectable */
  }
</style>
```

**Example : 매니페스트 파일**  
이와 같은 텍스트 분류 작업에 대해 매니페스트 파일을 직접 준비하려면 다음과 같은 방식으로 데이터를 포맷합니다.  

```
{"source": "Roses are red"}
{"source": "Violets are Blue"}
{"source": "Ground Truth is the best"}
{"source": "And so are you"}
```

이것은 "[데모 템플릿: `crowd-bounding-box`를 사용한 이미지 주석](sms-custom-templates-step2-demo1.md)" 데모에 사용되는 매니페스트 파일(`source` 대신 `source-ref`가 속성 이름으로 사용됨)과 다릅니다. `source-ref` 사용은 HTTP로 변환되어야 하는 이미지 또는 기타 파일의 S3 URI를 지정합니다. 그렇지 않을 경우 `source`를 위의 텍스트 문자열과 같이 사용해야 합니다.

## 주석 전 Lambda 함수
<a name="sms-custom-templates-step2-demo2-pre-lambda"></a>

작업 설정의 일부로 매니페스트 항목을 처리하고 템플릿 엔진에 전달하기 위해 호출할 수 AWS Lambda 있는의 ARN을 제공합니다.

이 Lambda 함수는 함수 이름의 일부로 `SageMaker`, `Sagemaker`, `sagemaker`, `LabelingFunction` 등의 네 가지 문자열 중 하나가 필요합니다.

이는 주석 전 및 주석 후 Lambda에 모두 적용됩니다.

콘솔을 사용할 때 계정이 소유한 Lambda가 있는 경우 명명 요구 사항을 충족하는 함수의 드롭다운 목록이 제공되어 함수를 선택할 수 있습니다.

변수가 하나 뿐인 매우 기본적인 이 샘플에서 함수는 주로 전달 함수입니다. 다음은 Python 3.7을 사용하는 라벨링 전처리 Lambda 샘플입니다.

```
import json

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

`event`의 `dataObject` 속성은 매니페스트에 있는 데이터 객체의 속성을 포함합니다.

이 간단한 전달 함수 데모에서는 변수 하나를 `taskInput` 값으로 간단히 전달합니다. 해당 값을 포함하는 속성을 `event['dataObject']` 객체에 추가하면, HTML 템플릿에서 `{{ task.input.<property name> }}` 형식의 Liquid 변수로 제공됩니다.

## 주석 후 Lambda 함수
<a name="sms-custom-templates-step2-demo2-post-lambda"></a>

작업 설정의 일부로 작업자가 작업을 완료했을 때 양식 데이터를 처리하기 위해 호출할 수 있는 Lambda 함수의 ARN을 제공합니다. 원하는 대로 간단하거나 복잡할 수 있습니다. 데이터가 수신될 때 답변을 통합하고 채점하려는 경우 선택한 채점 또는 통합 알고리즘을 적용할 수 있습니다. 오프라인 처리를 위해 원시 데이터를 저장하려는 경우 이는 옵션입니다.

**주석 후 Lambda 함수 권한 설정**  
주석 데이터는 `payload` 객체의 `s3Uri` 문자열에서 지정한 파일에 있습니다. 수신 시 주석을 처리하려면 간단한 전달 함수라 하더라도 주석 파일을 읽을 수 있도록 Lambda에 `S3ReadOnly` 액세스 권한을 할당해야 합니다.  
Lambda를 생성하기 위한 콘솔 페이지에서 **실행 역할** 패널로 스크롤합니다. **1개 이상의 템플릿에서 새로운 역할을 생성하세요**를 선택합니다. 역할 이름을 지정합니다. **정책 템플릿** 드롭다운에서 **Amazon S3 객체 읽기 전용 권한**을 선택합니다. Lambda를 저장하면 역할이 저장되어 선택됩니다.

다음 샘플은 Python 3.7용입니다.

```
import json
import boto3
from urllib.parse import urlparse

def lambda_handler(event, context):
    consolidated_labels = []

    parsed_url = urlparse(event['payload']['s3Uri']);
    s3 = boto3.client('s3')
    textFile = s3.get_object(Bucket = parsed_url.netloc, Key = parsed_url.path[1:])
    filecont = textFile['Body'].read()
    annotations = json.loads(filecont);
    
    for dataset in annotations:
        for annotation in dataset['annotations']:
            new_annotation = json.loads(annotation['annotationData']['content'])
            label = {
                'datasetObjectId': dataset['datasetObjectId'],
                'consolidatedAnnotation' : {
                'content': {
                    event['labelAttributeName']: {
                        'workerId': annotation['workerId'],
                        'result': new_annotation,
                        'labeledContent': dataset['dataObject']
                        }
                    }
                }
            }
            consolidated_labels.append(label)

    return consolidated_labels
```

## 라벨링 작업 출력
<a name="sms-custom-templates-step2-demo2-job-output"></a>

주석 후 Lambda는 일반적으로 이벤트 객체에서 작업 결과 배치를 수신합니다. 이러한 배치는 Lambda가 반복해야 하는 `payload` 객체입니다.

작업 출력은 지정한 대상 S3 버킷에서 라벨링 작업 후 이름을 지정한 폴더에서 찾습니다. `manifests`라는 하위 폴더에 있습니다.

의도 감지 작업의 경우 출력 매니페스트의 출력은 아래 데모와 비슷합니다. 이 예는 인간이 읽기 쉽도록 정리되고 띄어쓰기가 적용되었습니다. 실제 출력은 기계 판독용으로 압축됩니다.

**Example : 출력 매니페스트의 JSON**  

```
[
  {
    "datasetObjectId":"<Number representing item's place in the manifest>",
     "consolidatedAnnotation":
     {
       "content":
       {
         "<name of labeling job>":
         {     
           "workerId":"private.us-east-1.XXXXXXXXXXXXXXXXXXXXXX",
           "result":
           {
             "intent":
             {
                 "label":"<label chosen by worker>"
             }
           },
           "labeledContent":
           {
             "content":"<text content that was labeled>"
           }
         }
       }
     }
   },
  "datasetObjectId":"<Number representing item's place in the manifest>",
     "consolidatedAnnotation":
     {
       "content":
       {
         "<name of labeling job>":
         {     
           "workerId":"private.us-east-1.6UDLPKQZHYWJQSCA4MBJBB7FWE",
           "result":
           {
             "intent":
             {
                 "label": "<label chosen by worker>"
             }
           },
           "labeledContent":
           {
             "content": "<text content that was labeled>"
           }
         }
       }
     }
   },
     ...
     ...
     ...
]
```

사용자 지정 템플릿을 생성하고 사용하는 데 도움이 될 것입니다.

# API를 사용하여 사용자 지정 워크플로 생성
<a name="sms-custom-templates-step4"></a>

사용자 지정 UI 템플릿(2단계) 및 처리 Lambda 함수(3단계)를 생성한 경우 템플릿은 `<FileName>.liquid.html`이라는 파일 이름 형식으로 Amazon S3 버킷에 저장해야 합니다. [https://docs.aws.amazon.com/sagemaker/latest/APIReference/API_CreateLabelingJob.html](https://docs.aws.amazon.com/sagemaker/latest/APIReference/API_CreateLabelingJob.html) 작업을 사용하여 작업을 구성합니다. S3에서 `<filename>.liquid.html` 파일에 저장된 사용자 지정 템플릿([사용자 지정 작업자 작업 템플릿 생성하기](sms-custom-templates-step2.md))의 위치를[https://docs.aws.amazon.com/sagemaker/latest/APIReference/API_HumanTaskConfig.html](https://docs.aws.amazon.com/sagemaker/latest/APIReference/API_HumanTaskConfig.html) 객체 내[https://docs.aws.amazon.com/sagemaker/latest/APIReference/API_UiConfig.html](https://docs.aws.amazon.com/sagemaker/latest/APIReference/API_UiConfig.html) 객체의 `UiTemplateS3Uri` 필드에 대한 값으로 사용합니다.

에 설명된 AWS Lambda 작업의 경우 주석 [를 사용하여 사용자 지정 레이블 지정 워크플로에서 데이터 처리 AWS Lambda](sms-custom-templates-step3.md)후 작업의 ARN이 `AnnotationConsolidationLambdaArn` 필드 값으로 사용되고 주석 전 작업이의 값으로 사용됩니다. `PreHumanTaskLambdaArn.` 