맞춤법 스타일을 사용하여 슬롯 값 캡처 - Amazon Lex

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

맞춤법 스타일을 사용하여 슬롯 값 캡처

Amazon Lex V2는 이름, 성, 이메일 주소 또는 영숫자 식별자와 같은 사용자별 정보를 캡처할 수 있는 기본 제공 슬롯을 제공합니다. 예를 들어 AMAZON.LastName 슬롯을 사용하여 ‘Jackson’ 또는 ‘Garcia’와 같은 성을 캡처할 수 있습니다. 하지만 Amazon Lex V2는 ‘Xiulan’과 같이 발음하기 어렵거나 특정 지역에서 흔하지 않은 성과 혼동할 수 있습니다. 이러한 이름을 캡처하려면 사용자에게 문자별 맞춤법 또는 단어별 맞춤법 스타일로 입력하도록 요청할 수 있습니다.

Amazon Lex V2는 사용할 수 있는 세 가지 슬롯 유도 스타일을 제공합니다. 슬롯 유도 스타일을 설정하면 Amazon Lex V2가 사용자의 입력을 해석하는 방식이 변경됩니다.

문자별 맞춤법 – 이 스타일을 사용하면 봇이 전체 문구 대신 철자를 듣도록 지시할 수 있습니다. 예를 들어, ‘Xiulan’과 같은 성을 캡처하려면 사용자에게 한 번에 한 글자씩 성을 입력하라고 지시할 수 있습니다. 봇은 철자를 캡처하여 글자를 한 단어로 해석합니다. 예를 들어, 사용자가 “x i u l a n”이라고 말하면 봇은 성을 ‘xiulan’으로 캡처합니다.

단어별 맞춤법 – 음성 대화, 특히 전화를 사용할 때는 ‘t’, ‘b’, ‘p’와 같이 비슷하게 들리는 글자가 몇 개 있습니다. 영숫자 값이나 철자 이름을 캡처하여 잘못된 값이 나오는 경우 사용자에게 문자와 함께 식별할 수 있는 단어를 입력하라는 메시지를 표시할 수 있습니다. 예를 들어 예약 ID 요청에 대한 음성 응답이 ‘abp123’이면 봇이 대신 ‘abb123’이라는 문구를 인식할 수 있습니다. 값이 잘못된 경우 사용자에게 “alpha의 a, boy의 b, peter의 p, 1 2 3"과 같이 입력하도록 요청할 수 있습니다. 봇은 입력을 ‘abp123’으로 해석합니다.

단어별 맞춤법을 사용하는 경우 다음 형식을 사용할 수 있습니다.

  • "as in" (a as in apple)

  • "for" (a for apple)

  • "like" (a like apple)

기본값 – 단어 발음을 사용하는 자연스러운 슬롯 캡처 스타일입니다. 예를 들어, “John Stiles”와 같은 이름을 자연스럽게 캡처할 수 있습니다. 슬롯 유도 스타일이 지정되지 않은 경우 봇은 기본 스타일을 사용합니다. AMAZON.AlphaNumericAMAZON.UKPostal 코드 슬롯 유형의 경우 기본 스타일은 문자별 맞춤법 입력을 지원합니다.

‘xiulan’이라는 이름을 문자와 단어를 혼합하여 사용하는 경우(예: “x as in x-ray i u l as in lion a n”) 슬롯 유도 스타일을 단어 단위 스타일로 설정해야 합니다. 문자별 맞춤법 스타일에서는 인식하지 못합니다.

더 나은 경험을 위해 자연스러운 대화 스타일로 슬롯 값을 캡처하는 음성 인터페이스를 만들어야 합니다. 자연스러운 스타일을 사용하여 올바르게 캡처되지 않은 입력의 경우 사용자에게 다시 메시지를 표시하고 슬롯 유도 스타일을 문자별 또는 단어별 맞춤법으로 설정할 수 있습니다.

영어(미국), 영어(영국) 및 영어(호주) 언어의 다음 슬롯 유형에 대해 단어별 및 맞춤법별 스타일을 사용할 수 있습니다.

맞춤법 활성화

사용자로부터 슬롯을 유도할 때는 런타임에 문자별 맞춤법 및 단어별 맞춤법을 활성화합니다. PutSession, RecognizeText, RecognizeUtterance 또는 StartConversation 작업을 사용하여 맞춤법 스타일을 설정할 수 있습니다. Lambda 함수를 사용하여 문자별 맞춤법 및 단어별 맞춤법을 활성화할 수도 있습니다.

앞서 언급한 API 작업 중 하나를 요청하거나 Lambda 응답을 구성할 때 sessionState 필드의 dialogAction 필드를 사용하여 맞춤법 스타일을 설정합니다 (자세한 내용은 응답 형식 준비 참조). 대화 작업 유형이 ElicitSlot이고 유도할 슬롯이 지원되는 슬롯 유형 중 하나인 경우에만 스타일을 설정할 수 있습니다.

다음 JSON 코드는 맞춤법 스타일을 사용하도록 설정된 dialogAction 필드를 보여줍니다.

"dialogAction": { "slotElicitationStyle": "SpellByWord", "slotToElicit": "BookingId", "type": "ElicitSlot" }

slotElicitationStyle 필드는 SpellByLetter, SpellByWord 또는 Default로 설정할 수도 있습니다. 값을 지정하지 않으면 값이 Default로 설정됩니다.

참고

콘솔을 통해 문자별 맞춤법 또는 단어별 맞춤법 유도 스타일을 활성화할 수 없습니다.

예제 코드

일반적으로 맞춤법 스타일 변경은 작동하지 않는 슬롯 값을 처음 시도할 때 수행됩니다. 다음 코드 예제는 슬롯을 해석하려는 두 번째 시도에서 단어별 맞춤법 스타일을 사용하는 Python Lambda 함수입니다.

예제 코드를 사용하려면 다음이 필요합니다.

  • 영어(영국)(en_GB)라는 한 가지 언어를 사용하는 봇입니다.

  • 한 가지 의도는 “계좌를 확인하고 싶어요”라는 샘플 발화 하나가 있는 “CheckAccount”입니다. 의도 정의의 코드 후크 섹션에서 초기화 및 검증에 Lambda 함수 사용이 선택되어 있는지 확인하십시오.

  • 의도에는 AMAZON.UKPostalCode 기본 제공 유형의 “PostalCode” 슬롯이 하나 있어야 합니다.

  • Lambda 함수가 정의된 별칭. 자세한 내용은 Lambda 함수를 생성하고 봇 별칭에 연결 섹션을 참조하세요.

import json import time import os import logging logger = logging.getLogger() logger.setLevel(logging.DEBUG) # --- Helpers that build all of the responses --- def get_slots(intent_request): return intent_request['sessionState']['intent']['slots'] def get_session_attributes(intent_request): sessionState = intent_request['sessionState'] if 'sessionAttributes' in sessionState: return sessionState['sessionAttributes'] return {} def get_slot(intent_request, slotName): slots = get_slots(intent_request) if slots is not None and slotName in slots and slots[slotName] is not None: logger.debug('resolvedValue={}'.format(slots[slotName]['value']['resolvedValues'])) return slots[slotName]['value']['resolvedValues'] else: return None def elicit_slot(session_attributes, intent_request, slots, slot_to_elicit, slot_elicitation_style, message): return {'sessionState': {'dialogAction': {'type': 'ElicitSlot', 'slotToElicit': slot_to_elicit, 'slotElicitationStyle': slot_elicitation_style }, 'intent': {'name': intent_request['sessionState']['intent']['name'], 'slots': slots, 'state': 'InProgress' }, 'sessionAttributes': session_attributes, 'originatingRequestId': 'REQUESTID' }, 'sessionId': intent_request['sessionId'], 'messages': [ message ], 'requestAttributes': intent_request['requestAttributes'] if 'requestAttributes' in intent_request else None } def build_validation_result(isvalid, violated_slot, slot_elicitation_style, message_content): return {'isValid': isvalid, 'violatedSlot': violated_slot, 'slotElicitationStyle': slot_elicitation_style, 'message': {'contentType': 'PlainText', 'content': message_content} } def GetItemInDatabase(postal_code): """ Perform database check for transcribed postal code. This is a no-op check that shows that postal_code can't be found in the database. """ return None def validate_postal_code(intent_request): postal_code = get_slot(intent_request, 'PostalCode') if GetItemInDatabase(postal_code) is None: return build_validation_result( False, 'PostalCode', 'SpellByWord', "Sorry, I can't find your information. " + "To try again, spell out your postal " + "code using words, like a as in apple." ) return {'isValid': True} def check_account(intent_request): """ Performs dialog management and fulfillment for checking an account with a postal code. Besides fulfillment, the implementation for this intent demonstrates the following: 1) Use of elicitSlot in slot validation and re-prompting. 2) Use of sessionAttributes to pass information that can be used to guide a conversation. """ slots = get_slots(intent_request) postal_code = get_slot(intent_request, 'PostalCode') session_attributes = get_session_attributes(intent_request) if intent_request['invocationSource'] == 'DialogCodeHook': # Validate the PostalCode slot. If any aren't valid, # re-elicit for the value. validation_result = validate_postal_code(intent_request) if not validation_result['isValid']: slots[validation_result['violatedSlot']] = None return elicit_slot( session_attributes, intent_request, slots, validation_result['violatedSlot'], validation_result['slotElicitationStyle'], validation_result['message'] ) return close( intent_request, session_attributes, 'Fulfilled', {'contentType': 'PlainText', 'content': 'Thanks' } ) def close(intent_request, session_attributes, fulfillment_state, message): intent_request['sessionState']['intent']['state'] = fulfillment_state return { 'sessionState': { 'sessionAttributes': session_attributes, 'dialogAction': { 'type': 'Close' }, 'intent': intent_request['sessionState']['intent'], 'originatingRequestId': 'xxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx' }, 'messages': [ message ], 'sessionId': intent_request['sessionId'], 'requestAttributes': intent_request['requestAttributes'] if 'requestAttributes' in intent_request else None } # --- Intents --- def dispatch(intent_request): """ Called when the user specifies an intent for this bot. """ intent_name = intent_request['sessionState']['intent']['name'] response = None # Dispatch to your bot's intent handlers if intent_name == 'CheckAccount': response = check_account(intent_request) return response # --- Main handler --- def lambda_handler(event, context): """ Route the incoming request based on the intent. The JSON body of the request is provided in the event slot. """ # By default, treat the user request as coming from # Eastern Standard Time. os.environ['TZ'] = 'America/New_York' time.tzset() logger.debug('event={}'.format(json.dumps(event))) response = dispatch(event) logger.debug("response={}".format(json.dumps(response))) return response