대화 중에 맞춤법 스타일을 사용하여 슬롯 값 캡처하기 - 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 in x-ray i u l as lion a n)”) 슬롯 유도 스타일을 스타일로 설정해야 합니다. spell-by-word spell-by-letter 스타일에서는 인식할 수 없습니다.

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

영어 (미국), 영어 (영국) spell-by-word 및 영어 (호주) 언어로 다음과 같은 슬롯 유형을 사용하고 spell-by-letter 스타일을 지정할 수 있습니다.

맞춤법 활성화

사용자로부터 spell-by-letter 슬롯을 끌어낼 때 spell-by-word 런타임에 활성화합니다. PutSession, RecognizeTextRecognizeUtterance, 또는 연산을 사용하여 철자 스타일을 설정할 수 있습니다. StartConversation Lambda spell-by-letter 함수를 활성화하고 spell-by-word 사용할 수도 있습니다.

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

다음 JSON 코드는 스타일을 사용하도록 설정된 dialogAction 필드를 보여줍니다. spell-by-word

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

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

참고

콘솔을 통해 스타일을 spell-by-letter 활성화하거나 spell-by-word 끌어낼 수 없습니다.

Lambda와 Lex V2를 사용하는 예제 코드

일반적으로 맞춤법 스타일 변경은 작동하지 않는 슬롯 값을 처음 시도할 때 수행됩니다. 다음 코드 예제는 슬롯을 해결하기 위한 두 번째 시도에서 스타일을 사용하는 spell-by-word Python Lambda 함수입니다.

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

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

  • 한 가지 인텐트, CheckAccount "“내 계정을 확인하고 싶습니다”라는 샘플 발언 하나가 있습니다. 의도 정의의 코드 후크 섹션에서 초기화 및 검증에 Lambda 함수 사용이 선택되어 있는지 확인하세요.

  • 인텐트에는 AMAZON.UKPostalCode 빌트인 유형의 슬롯 "PostalCode“이 하나 있어야 합니다.

  • Lambda 함수가 정의된 별칭. 자세한 내용은 만들기 AWS 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