

本文為英文版的機器翻譯版本，如內容有任何歧義或不一致之處，概以英文版為準。

# 在對話期間使用拼寫樣式擷取槽值
<a name="spelling-styles"></a>

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」，您的機器人可能會改為識別「ab**b**123」一詞。如果這是不正確的值，您可以要求使用者提供輸入做為「a as in alpha b as in boy p as in peter one23」。機器人會將輸入解析為「abp123」。

使用逐字拼寫時，您可以使用下列格式：
+ "as in" （蘋果中的 )
+ "for" （適用於蘋果的 )
+ "like" （類似蘋果）

**預設** – 這是使用單字發音擷取位置的自然樣式。例如，它可以自然地擷取名稱，例如 "John Stiles"。如果未指定槽引出樣式，機器人會使用預設樣式。對於 `AMAZON.AlphaNumeric`和 `AMAZON.UKPostal` 程式碼槽類型，預設樣式支援字母輸入的拼字。

如果名稱 "Xiulan" 是使用混合字母和單字 說出，例如 "x as in x-ray i u l as in lion a n"，則槽引出樣式必須設定為spell-by-word寫樣式。spell-by-letter樣式無法辨識。

您應該建立語音界面，以自然的對話風格擷取槽值，以獲得更好的體驗。對於使用自然樣式未正確擷取的輸入，您可以重新提示使用者，並將槽引出樣式設定為spell-by-letter或spell-by-word寫。

您可以針對英文 （美國）、英文 （英國） 和英文 （澳洲） 語言的下列槽類型，使用spell-by-wordspell-by-letter拼寫樣式：
+  [AMAZON.AlphaNumeric](built-in-slot-alphanumeric.md) 
+  [AMAZON.EmailAddress](built-in-slot-email.md) 
+  [AMAZON.FirstName](built-in-slot-first-name.md) 
+  [AMAZON.LastName](built-in-slot-last-name.md) 
+  [AMAZON.UKPostalCode](built-in-slot-uk-postal-code.md) 
+  [自訂插槽類型](custom-slot-types.md) 

## 啟用拼字
<a name="spelling-enable"></a>

當您從使用者引出槽時，您可以在執行時間啟用spell-by-letter和spell-by-word。您可以使用 [PutSession](https://docs.aws.amazon.com/lexv2/latest/APIReference/API_runtime_PutSession.html)、[RecognizeText](https://docs.aws.amazon.com/lexv2/latest/APIReference/API_runtime_RecognizeText.html)、[RecognizeUtterance](https://docs.aws.amazon.com/lexv2/latest/APIReference/API_runtime_RecognizeUtterance.html) 或 [StartConversation](https://docs.aws.amazon.com/lexv2/latest/APIReference/API_runtime_StartConversation.html) 操作來設定拼寫樣式。您也可以使用 Lambda 函數啟用spell-by-letter和spell-by-word寫。

您可以在上述其中一個 API 操作的請求或設定 Lambda 回應時，使用 `sessionState` 欄位`dialogAction`的 欄位來設定拼寫樣式 （如需詳細資訊[AWS LambdaLex V2 的回應格式](lambda-response-format.md)，請參閱 )。只有在對話方塊動作類型為 且要引出的插槽是其中一個支援的插槽類型`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 的範例程式碼
<a name="spelling-example"></a>

如果第一次嘗試解析無法運作的槽值，通常會執行變更拼寫樣式。下列程式碼範例是 Python Lambda 函數，在spell-by-word樣式。

若要使用範例程式碼，您必須具有：
+ 使用一種語言的機器人，英文 (GB) (en\$1GB)。
+ 一個意圖，「CheckAccount」和一個範例表達用語，「我想要檢查我的帳戶」。請務必在意圖定義的**程式碼掛**勾區段中選取**使用 Lambda 函數進行初始化和驗證**。
+ 意圖應該有一個`AMAZON.UKPostalCode`內建類型的槽「PostalCode」。
+ 已定義 Lambda 函數的別名。如需詳細資訊，請參閱[為您的 Amazon Lex V2 機器人建立 AWS Lambda函數](lambda-attach.md)。



```
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
```