

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

# 데모 템플릿: `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>"
           }
         }
       }
     }
   },
     ...
     ...
     ...
]
```

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