はじめに
LexとLambdaでできる応用テクニック?を書き留めます。
事前にこちらでLambdaとLexを設定しました。
LexとLambdaでできること色々
以下のスロット値の入力のコードについて、できることをまとめます。
フルのコードは、こちらです
Lexの流れは、以下の通りに聞かれます。
発話 → telephoneNumber(電話番号) → date(日付) → age(年齢) → 確認 → yes/no
if slots['telephoneNumber'] is None:
return elicit_slot('telephoneNumber', intent_name, slots)
telephoneNumber = slots['telephoneNumber']['value']['interpretedValue']
if slots['date'] is None:
return elicit_slot('date',intent_name, slots)
date = slots['date']['value']['interpretedValue']
if slots['age'] is None:
return elicit_slot('age',intent_name, slots)
age = slots['age']['value']['interpretedValue']
if int(age) < 20:
return validation_slot(
'age',
'ご利用は20歳以上とさせていただいております。\
年齢を教えて下さい',
intent_name,
slots
)
スロット値をすべてリセット
下記のようLambdaを設定すると、スロット値をすべてリセットできます。
年齢を聞かれた際、スロット値がリセットされ、
telephoneNumber→date→
age(リセット)→telephoneNumber→date→
age(リセット)→telephoneNumber ...
とループします。
通常
発話 → telephoneNumber → date → age → 確認 → yes/no
年齢を聞かれた際に、リセット
発話 → telephoneNumber → date → age(リセット) → telephoneNumber → date → age(リセット)...
return elicit_slot(
'age',
intent_name,
{
"date": None,
"telephoneNumber": None,
"age": None
}
)
Lambda側で1つのスロットに値を入れて、スロット値を聞かれないようにする
以下のようにすると、Lambda側でtelephoneNumberのスロット値に090
を入れることができます。
通常
発話 → telephoneNumber → date → age → 確認 → yes/no
電話番号を事前に入力
発話 → date → age → 確認 → yes/no
return elicit_slot(
'date',
intent_name,
{
"date": None,
"telephoneNumber": {
"shape": "Scalar",
"value": {
"originalValue": "090",
"resolvedValues": [
"090"
],
"interpretedValue": "090"
}
},
"age": None
}
)
↓実際にコードを修正して書いてみます。
originalValue
、resolvedValues
、interpretedValue
の3つに値を入れる必要があります。
telephoneNumber(聞かれない)
→date→age→確認 という流れになります。
もちろんtelephoneNumberのスロット値には、090
が入っています。
# if slots['telephoneNumber'] is None:
# return elicit_slot('telephoneNumber', intent_name, slots)
# telephoneNumber = slots['telephoneNumber']['value']['interpretedValue']
if slots['date'] is None:
return elicit_slot(
'date',
intent_name,
{
"date": None,
"telephoneNumber": {
"shape": "Scalar",
"value": {
"originalValue": "090",
"resolvedValues": [
"090"
],
"interpretedValue": "090"
}
},
"age": None
}
)
date = slots['date']['value']['interpretedValue']
if slots['age'] is None:
return elicit_slot(
'age',
intent_name,
slots
)
age = slots['age']['value']['interpretedValue']
if int(age) < 20:
return validation_slot(
'age',
'ご利用は20歳以上とさせていただいております。\
年齢を教えて下さい',
intent_name,
slots
)
↓事前に入力しておく値をメソッド化してもいいですね。
def input_slots_value(value):
return {
"shape": "Scalar",
"value": {
"originalValue": value,
"resolvedValues": [value],
"interpretedValue": value
}
}
# 省略
# if slots['telephoneNumber'] is None:
# return elicit_slot('telephoneNumber', intent_name, slots)
# telephoneNumber = slots['telephoneNumber']['value']['interpretedValue']
if slots['date'] is None:
return elicit_slot(
'date',
intent_name,
{
"date": None,
"telephoneNumber": input_slots_value(90),
"age": None
}
)
date = slots['date']['value']['interpretedValue']
telephoneNumber = slots['telephoneNumber']['value']['interpretedValue']
if slots['age'] is None:
return elicit_slot(
'age',
intent_name,
slots
)
age = slots['age']['value']['interpretedValue']
if int(age) < 20:
return validation_slot(
'age',
'ご利用は20歳以上とさせていただいております。\
年齢を教えて下さい',
intent_name,
slots
)
Lambda側で2つのスロットに値を入れて、スロット値を聞かれないようにする
下記だと、telephoneNumber(聞かれない)
→date→age(聞かれない)
→確認 という流れになります。
通常
発話 → telephoneNumber → date → age → 確認 → yes/no
電話番号と年齢を事前に入力
発話 → date → 確認 → yes/no
# if slots['telephoneNumber'] is None:
# return elicit_slot('telephoneNumber', intent_name, slots)
# else:
# telephoneNumber = slots['telephoneNumber']['value']['interpretedValue']
if slots['date'] is None:
return elicit_slot(
'date',
intent_name,
{
"date": None,
"telephoneNumber": input_slots_value(90),
"age": None,
}
)
date = slots['date']['value']['interpretedValue']
telephoneNumber = slots['telephoneNumber']['value']['interpretedValue']
if slots['age'] is None:
# ageを入力し、確認プロンプトに移行する
slots = {
"date": input_slots_value(date),
"telephoneNumber": input_slots_value(telephoneNumber),
"age": input_slots_value(40)
}
return confirm_intent( intent_name, slots)
age = slots['age']['value']['interpretedValue']
# if int(age) < 20:
# return validation_slot(
# 'age',
# 'ご利用は20歳以上とさせていただいております。\
# 年齢を教えて下さい',
# intent_name,
# slots
# )
apiキーなどの英数字が混ざった文字列をスロット値に保存する
あるAPIとLex、Lambdaを連携する歳に、アクセスコード(予約コード)を(8j91dcf0rfje4bdaa7ik97c0d2e948pl
)をスロット値に保存する必要があったため、書き留めます。
confirm_intent
でreturnする際に、セッション属性値に値を渡すことができなかったため、スロット値に入れました。
通常
発話 → telephoneNumber → date → alpha(英数字の文字列) → 確認 → yes/no
電話番号とアクセスコードをLambda側で入力
発話 → date → 確認 → yes/no
スロットタイプから、組み込みスロットタイプを使用
のAMAZON.AlphaNumeric
を選択します。
スロットタイプ設定を以下の通りにします。これは、大文字と小文字を含めた英数字に対応します。
正規表現
:[0-9][a-z][A-Z]
APIキーのスロット値は、Lexの受け答えとして、使用しません。
こちらのageの箇所をスロット値alpha
に変えます。
APIキーなので、本来は、確認プロンプトに表示しませんが、以下のように、英数字をスロット値に入れることができました。
ちなみに、AMAZON.AlphaNumeric
は、100文字まで入れられます。
#特定の条件で、強制終了させる(キャンセルさせる)
電話番号を聞かれた際、特定の番号の場合、強制終了させることができます。
下記だと、telephoneNumber(09)
→強制終了 という流れになります。
通常
発話 → telephoneNumber → date → age → 確認 → yes/no
特定の条件で、強制終了させる
発話 → telephoneNumber(09) → no
close( "Failed",
が必要になります。
if slots['telephoneNumber'] is None:
return elicit_slot('telephoneNumber', intent_name, slots)
telephoneNumber = slots['telephoneNumber']['value']['interpretedValue']
# 電話番号が09の場合、強制終了させる
if telephoneNumber == "09":
return close( "Failed", '強制終了です。', intent_name, slots)
if slots['date'] is None:
return elicit_slot(
'date',
intent_name,
slots
)
#省略
特定の条件で、予約完了させる
電話番号を聞かれた際、特定の番号の場合、予約完了させることができます。
下記だと、telephoneNumber(09)
→ 予約完了 という流れになります。
通常
発話 → telephoneNumber → date → age → 確認 → yes/no
特定の条件で、予約完了させる
発話 → telephoneNumber(09) → yes
close( "Fulfilled",
が必要になります。
if slots['telephoneNumber'] is None:
return elicit_slot('telephoneNumber', intent_name, slots)
telephoneNumber = slots['telephoneNumber']['value']['interpretedValue']
# 電話番号が09の場合、予約完了させる
if telephoneNumber == "09":
slots = {
"date": input_slots_value("2022-0227"),
"telephoneNumber": input_slots_value(telephoneNumber),
"age": input_slots_value("fmoeuweoiru93r3320io3wrjo32jr32jo32")
}
return close( "Fulfilled", '予約完了です。', intent_name, slots)
if slots['date'] is None:
return elicit_slot(
'date',
intent_name,
slots
)
#省略
聞き取れなかった場合(解釈できない値)、強制的に予約失敗とする
通常
発話 → telephoneNumber → date → age → 確認 → yes/no
聞き取れなかった場合、強制的に予約失敗させる
発話 → telephoneNumber(09) → date(聞き取れない) → no
if slots['telephoneNumber'] is None:
return elicit_slot('telephoneNumber', intent_name, slots)
telephoneNumber = slots['telephoneNumber']['value']['interpretedValue']
if slots['date'] is None:
return elicit_slot('date',intent_name,slots)
# 聞き取れなかった場合
if slots['date']['value']['resolvedValues'] == []:
return close( "Failed",
'聞き取れませんでした。最初からやり直してください。',
intent_name,
slots
)
date = slots['date']['value']['interpretedValue']
if slots['age'] is None:
#省略
聞き取れなかった場合、lexからlambdaへのslots
内のレスポンス
{
"date": {
"shape": "Scalar",
"value": {
"originalValue": "ttt",
"resolvedValues": []
}
},
"telephoneNumber": {
"shape": "Scalar",
"value": {
"originalValue": "090",
"resolvedValues": [
"090"
],
"interpretedValue": "090"
}
},
"age": null
}
slots['date']['value']['resolvedValues']
:[]
配列が空
slots['date']['value']['originalValue']
:lexが聞き取った言葉
slots['date']['value']['interpretedValue']
:なし
Lexが解釈できなかったということです。
参考