如果您使用的是 Amazon Lex V2,请改为参阅 Amazon Lex V2 指南。
如果您使用的是 Amazon Lex V1,我们建议您将机器人升级到 Amazon Lex V2。我们不再向 V1 添加新功能,强烈建议使用 V2 以获得全新的机器人。
本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。
信息流的详细信息
在本练习中,您将使用 Amazon Lex 控制台中提供的测试窗口客户端与 Amazon Lex BookTrip 机器人展开对话。本节介绍以下内容:
-
客户端与 Amazon Lex 之间的数据流。
本节假定客户端使用
PostText
运行时 API 向 Amazon Lex 发送请求,并显示相应的请求和响应详细信息。有关PostText
运行时 API 的更多信息,请参阅 PostText。注意
有关客户端和 Amazon Lex(客户端在其中使用
PostContent
API)之间的信息流示例,请参阅步骤 2a (可选):查看语音信息流的详细信息 (控制台) 。 -
Amazon Lex 与 Lambda 函数之间的数据流。有关更多信息,请参阅Lambda 函数输入事件和响应格式。
数据流:预订酒店目的
本部分介绍了获得每个用户输入后会发生的情况。
-
用户:“book a hotel”
-
客户端 (控制台) 将向 Amazon Lex 发送以下 PostText 请求:
POST /bot/
BookTrip
/alias/$LATEST
/user/wch89kjqcpkds8seny7dly5x3otq68j3
/text "Content-Type":"application/json" "Content-Encoding":"amz-1.0" { "inputText":"book a hotel", "sessionAttributes":{} }请求 URI 和正文都向 Amazon Lex 提供信息:
-
请求 URI — 提供机器人名称 (BookTrip)、机器人别名 ($LATEST) 和用户名称。后面的
text
表示它是一个PostText
API 请求 (而不是PostContent
)。 -
请求正文 – 包括用户输入 (
inputText
) 和空sessionAttributes
。最初这是一个空对象,Lambda 函数首先设置会话属性。
-
-
Amazon Lex 会从
inputText
中检测意图 (BookHotel)。此意图配置有 Lambda 函数作为代码挂钩,以用于用户数据初始化/验证。因此,Amazon Lex 会通过传递以下信息作为事件参数来调用 Lambda 函数(请参阅输入事件格式):{ "messageVersion":"1.0", "invocationSource":"DialogCodeHook", "userId":"wch89kjqcpkds8seny7dly5x3otq68j3", "sessionAttributes":{ }, "bot":{ "name":"BookTrip", "alias":null, "version":"$LATEST" }, "outputDialogMode":"Text", "currentIntent":{ "name":"BookHotel", "slots":{ "RoomType":null, "CheckInDate":null, "Nights":null, "Location":null }, "confirmationStatus":"None" } }
除了客户端发送的信息以外,Amazon Lex 还包含以下额外数据:
-
messageVersion
— Amazon Lex 当前只支持 1.0 版。 -
invocationSource
— 表明 Lambda 函数调用的目的。在本示例中,它会执行用户数据初始化和验证(此时 Amazon Lex 知道用户尚未提供履行意图所需的所有插槽数据)。 -
currentIntent
– 所有槽值均设置为空。
-
-
此时,所有槽值均为空值。Lambda 函数没有任何内容需要验证。Lambda 函数会向 Amazon Lex 返回以下响应。有关响应格式的信息,请参阅响应格式。
{ "sessionAttributes":{ "currentReservation":"{\"ReservationType\":\"Hotel\",\"Location\":null,\"RoomType\":null,\"CheckInDate\":null,\"Nights\":null}" }, "dialogAction":{ "type":"Delegate", "slots":{ "RoomType":null, "CheckInDate":null, "Nights":null, "Location":null } } }
注意
-
currentReservation
— Lambda 函数包含此会话属性。其值为当前槽信息和预订类型。只有 Lambda 函数和客户端可以更新这些会话属性。Amazon Lex 只是传递这些值。
-
dialogAction.type
— 通过将此值设置为Delegate
,Lambda 函数将下一个操作的责任委派给 Amazon Lex。如果 Lambda 函数在用户数据验证过程中检测到任何内容,就会向 Amazon Lex 说明后续步骤。
-
-
根据
dialogAction.type
,Amazon Lex 决定下一个操作(从用户获取Location
插槽的数据)。它会根据目的配置针对这个槽选择一项提示消息(“您要住在哪座城市?”),然后向用户发送以下响应:这些会话属性会被传递到客户端。
客户端读取响应并显示消息:“您要住在哪座城市?”
-
-
用户:“Moscow”
-
客户端向 Amazon Lex 发送以下
PostText
请求(为便于阅读而添加了换行符):POST /bot/
BookTrip
/alias/$LATEST
/user/wch89kjqcpkds8seny7dly5x3otq68j3
/text "Content-Type":"application/json" "Content-Encoding":"amz-1.0" { "inputText":"Moscow", "sessionAttributes":{ "currentReservation":"{\"ReservationType\":\"Hotel\", \"Location\":null, \"RoomType\":null, \"CheckInDate\":null, \"Nights\":null}" } }除了
inputText
以外,客户端还会发送其收到的相同currentReservation
会话属性。 -
Amazon Lex 首先会根据当前意图来解读
inputText
(服务记得它已经向特定用户询问了关于Location
插槽的信息)。它会更新当前意图的插槽值并使用以下事件来调用 Lambda 函数:{ "messageVersion": "1.0", "invocationSource": "DialogCodeHook", "userId": "wch89kjqcpkds8seny7dly5x3otq68j3", "sessionAttributes": { "currentReservation": "{\"ReservationType\":\"Hotel\",\"Location\":null,\"RoomType\":null,\"CheckInDate\":null,\"Nights\":null}" }, "bot": { "name": "BookTrip", "alias": null, "version": "$LATEST" }, "outputDialogMode": "Text", "currentIntent": { "name": "BookHotel", "slots": { "RoomType": null, "CheckInDate": null, "Nights": null, "Location": "Moscow" }, "confirmationStatus": "None" } }
注意
-
invocationSource
仍然是DialogCodeHook
。在此步骤中,我们只验证用户数据。 -
Amazon Lex 只是向 Lambda 函数传递会话属性。
-
对于
currentIntent.slots
,Amazon Lex 已经将Location
插槽更新为Moscow
。
-
-
Lambda 函数执行用户数据验证,并确定
Moscow
是一个无效地点。注意
在本练习中,Lambda 函数具有一个简单的有效城市列表,而
Moscow
不在此列表中。在生产应用中,您可以使用后端数据库来获取这一信息。它会将插槽值重置回空值,并让 Amazon Lex 通过发送以下响应来再次提示用户提供另一个值:
{ "sessionAttributes": { "currentReservation": "{\"ReservationType\":\"Hotel\",\"Location\":\"Moscow\",\"RoomType\":null,\"CheckInDate\":null,\"Nights\":null}" }, "dialogAction": { "type": "ElicitSlot", "intentName": "BookHotel", "slots": { "RoomType": null, "CheckInDate": null, "Nights": null, "Location": null }, "slotToElicit": "Location", "message": { "contentType": "PlainText", "content": "We currently do not support Moscow as a valid destination. Can you try a different city?" } } }
注意
-
currentIntent.slots.Location
被重置为空值。 -
dialogAction.type
设置为ElicitSlot
,这会让 Amazon Lex 通过提供以下响应来再次提示用户:-
dialogAction.slotToElicit
– 要将用户提供的数据用到的槽。 -
dialogAction.message
- 传达给用户的message
。
-
-
-
Amazon Lex 发现
dialogAction.type
并通过以下响应向客户端传递信息:客户端只是显示消息:“目前我们不支持莫斯科作为有效目的地,能否换一个城市?”
-
-
用户:“Chicago”
-
客户端将向 Amazon Lex 发送以下
PostText
请求:POST /bot/
BookTrip
/alias/$LATEST
/user/wch89kjqcpkds8seny7dly5x3otq68j3
/text "Content-Type":"application/json" "Content-Encoding":"amz-1.0" { "inputText":"Chicago", "sessionAttributes":{ "currentReservation":"{\"ReservationType\":\"Hotel\", \"Location\":\"Moscow\", \"RoomType\":null, \"CheckInDate\":null, \"Nights\":null}" } } -
Amazon Lex 知道上下文,即引发
Location
插槽的数据。在这个上下文中,它知道inputText
值用于Location
槽。然后,它通过发送以下事件来调用 Lambda 函数:{ "messageVersion": "1.0", "invocationSource": "DialogCodeHook", "userId": "wch89kjqcpkds8seny7dly5x3otq68j3", "sessionAttributes": { "currentReservation": "{\"ReservationType\":\"Hotel\",\"Location\":Moscow,\"RoomType\":null,\"CheckInDate\":null,\"Nights\":null}" }, "bot": { "name": "BookTrip", "alias": null, "version": "$LATEST" }, "outputDialogMode": "Text", "currentIntent": { "name": "BookHotel", "slots": { "RoomType": null, "CheckInDate": null, "Nights": null, "Location": "Chicago" }, "confirmationStatus": "None" } }
Amazon Lex 通过将
Location
插槽设置为Chicago
来更新currentIntent.slots
。 -
根据
DialogCodeHook
的invocationSource
值,Lambda 函数会执行用户数据验证。它会将Chicago
识别为有效的插槽值,相应更新会话属性,然后向 Amazon Lex 返回以下响应。{ "sessionAttributes": { "currentReservation": "{\"ReservationType\":\"Hotel\",\"Location\":\"Chicago\",\"RoomType\":null,\"CheckInDate\":null,\"Nights\":null}" }, "dialogAction": { "type": "Delegate", "slots": { "RoomType": null, "CheckInDate": null, "Nights": null, "Location": "Chicago" } } }
注意
-
currentReservation
— Lambda 函数通过将Location
设置为Chicago
来更新这一会话属性。 -
dialogAction.type
– 被设置为Delegate
。用户数据有效,Lambda 函数指示 Amazon Lex 选择下一个操作。
-
-
根据
dialogAction.type
,Amazon Lex 选择下一个操作。Amazon Lex 知道它需要更多插槽数据,因此会根据意图配置将下一个未填充的插槽 (CheckInDate
) 设为最高优先级。它会根据目的配置针对这个槽选择一项提示消息(“您想要在哪天入住?”),然后向客户端发送回以下响应:客户端显示消息:“您想在哪天入住?”
-
-
用户交互继续进行(用户提供数据,Lambda 函数验证数据,然后将下一个操作委派给 Amazon Lex)。最后,用户提供所有插槽数据,Lambda 函数验证所有用户输入,然后 Amazon Lex 确定自己获得了所有插槽数据。
注意
在本练习中,用户提供所有插槽数据之后,Lambda 函数会计算酒店的预订价格并将其作为另一个会话属性 (
currentReservationPrice
) 返回。此时意图已准备好履行,但 BookHotel 意图配置了一项确认提示,会在 Amazon Lex 履行意图前要求用户确认。因此,在预订酒店之前,Amazon Lex 会向客户端发送以下消息来要求确认:
客户端会显示消息:“好的,确定您要在芝加哥住 5 晚,入住日期是 2016-12-18。是否要预订?”
-
用户:“yes”
-
客户端将向 Amazon Lex 发送以下
PostText
请求:POST /bot/
BookTrip
/alias/$LATEST
/user/wch89kjqcpkds8seny7dly5x3otq68j3
/text "Content-Type":"application/json" "Content-Encoding":"amz-1.0" { "inputText":"Yes", "sessionAttributes":{ "currentReservation":"{\"ReservationType\":\"Hotel\", \"Location\":\"Chicago\", \"RoomType\":\"queen\", \"CheckInDate\":\"2016-12-18\", \"Nights\":\"5\"}", "currentReservationPrice":"1195" } } -
Amazon Lex 将解释确认当前意图的上下文中的
inputText
。Amazon Lex 知道用户希望继续预订。此时 Amazon Lex 会通过发送以下事件来调用 Lambda 函数,从而履行意图。通过将事件中的invocationSource
设置为FulfillmentCodeHook
,它向 Lambda 函数发送信息。Amazon Lex 也将confirmationStatus
设置为Confirmed
。{ "messageVersion": "1.0", "invocationSource": "FulfillmentCodeHook", "userId": "wch89kjqcpkds8seny7dly5x3otq68j3", "sessionAttributes": { "currentReservation": "{\"ReservationType\":\"Hotel\",\"Location\":\"Chicago\",\"RoomType\":\"queen\",\"CheckInDate\":\"2016-12-18\",\"Nights\":\"5\"}", "currentReservationPrice": "956" }, "bot": { "name": "BookTrip", "alias": null, "version": "$LATEST" }, "outputDialogMode": "Text", "currentIntent": { "name": "BookHotel", "slots": { "RoomType": "queen", "CheckInDate": "2016-12-18", "Nights": "5", "Location": "Chicago" }, "confirmationStatus": "Confirmed" } }
注意
-
invocationSource
— 此时,Amazon Lex 将此值设置为FulfillmentCodeHook
,指示 Lambda 函数履行意图。 -
confirmationStatus
– 被设置为Confirmed
。
-
-
此时,Lambda 函数履行 BookHotel 意图,Amazon Lex 完成预订,然后返回以下响应:
{ "sessionAttributes": { "lastConfirmedReservation": "{\"ReservationType\":\"Hotel\",\"Location\":\"Chicago\",\"RoomType\":\"queen\",\"CheckInDate\":\"2016-12-18\",\"Nights\":\"5\"}" }, "dialogAction": { "type": "Close", "fulfillmentState": "Fulfilled", "message": { "contentType": "PlainText", "content": "Thanks, I have placed your reservation. Please let me know if you would like to book a car rental, or another hotel." } } }
注意
-
lastConfirmedReservation
— 是 Lambda 函数添加的新会话属性(不是currentReservation
和currentReservationPrice
)。 -
dialogAction.type
— Lambda 函数将此值设置为Close
,表示 Amazon Lex 不需要用户响应。 -
dialogAction.fulfillmentState
– 被设置为Fulfilled
并且包含要传达给用户的相应message
。
-
-
Amazon Lex 查看
fulfillmentState
并向客户端发送以下响应:注意
-
dialogState
— Amazon Lex 将此值设置为Fulfilled
。 -
message
— 与 Lambda 函数提供的消息相同。
客户端将显示消息。
-
-
数据流:预订汽车目的
本练习中的 BookTrip 自动程序支持两种目的 (BookHotel 和 BookCar)。预订酒店之后,用户可以继续进行对话以便预订汽车。只要会话未超时,客户端就会在每个后续请求中继续发送会话属性 (本示例中为 lastConfirmedReservation
)。Lambda 函数可以使用这一信息来初始化 BookCar 意图的插槽数据。这体现了在跨目的数据共享中使用会话属性的过程。
具体来说,当用户选择 BookCar 意图时,Lambda 函数会使用会话属性中的相关信息来预填充 BookCar 意图的插槽(PickUpDate、ReturnDate 和 PickUpCity)。
注意
Amazon Lex 控制台提供清除链接,您可使用此链接清除之前的所有会话属性。
按照以下步骤继续进行对话。
-
用户:“also book a car”
-
客户端将向 Amazon Lex 发送以下
PostText
请求:POST /bot/
BookTrip
/alias/$LATEST
/user/wch89kjqcpkds8seny7dly5x3otq68j3
/text "Content-Type":"application/json" "Content-Encoding":"amz-1.0" { "inputText":"also book a car", "sessionAttributes":{ "lastConfirmedReservation":""{\"ReservationType\":\"Hotel\", \"Location\":\"Chicago\", \"RoomType\":\"queen\", \"CheckInDate\":\"2016-12-18\", \"Nights\":\"5\"}" } }客户端会发送
lastConfirmedReservation
会话属性。 -
Amazon Lex 从
inputText
中检测意图 (BookCar)。此意图也被配置为调用 Lambda 函数来执行初始化和用户数据验证。Amazon Lex 使用以下事件调用 Lambda 函数:{ "messageVersion": "1.0", "invocationSource": "DialogCodeHook", "userId": "wch89kjqcpkds8seny7dly5x3otq68j3", "sessionAttributes": { "lastConfirmedReservation": "{\"ReservationType\":\"Hotel\",\"Location\":\"Chicago\",\"RoomType\":\"queen\",\"CheckInDate\":\"2016-12-18\",\"Nights\":\"5\"}" }, "bot": { "name": "BookTrip", "alias": null, "version": "$LATEST" }, "outputDialogMode": "Text", "currentIntent": { "name": "BookCar", "slots": { "PickUpDate": null, "ReturnDate": null, "DriverAge": null, "CarType": null, "PickUpCity": null }, "confirmationStatus": "None" } }
注意
-
messageVersion
— Amazon Lex 当前只支持 1.0 版。 -
invocationSource
– 表明调用的目的是执行初始化和用户数据验证。 -
currentIntent
— 其中包括意图名称和插槽。此时,所有槽值均为空值。
-
-
Lambda 函数发现所有插槽值均为空值,没有任何可以验证的内容。但是函数会使用会话属性来初始化一些槽值 (
PickUpDate
、ReturnDate
和PickUpCity
),然后返回以下响应:{ "sessionAttributes": { "lastConfirmedReservation": "{\"ReservationType\":\"Hotel\",\"Location\":\"Chicago\",\"RoomType\":\"queen\",\"CheckInDate\":\"2016-12-18\",\"Nights\":\"5\"}", "currentReservation": "{\"ReservationType\":\"Car\",\"PickUpCity\":null,\"PickUpDate\":null,\"ReturnDate\":null,\"CarType\":null}", "confirmationContext": "AutoPopulate" }, "dialogAction": { "type": "ConfirmIntent", "intentName": "BookCar", "slots": { "PickUpCity": "Chicago", "PickUpDate": "2016-12-18", "ReturnDate": "2016-12-22", "CarType": null, "DriverAge": null }, "message": { "contentType": "PlainText", "content": "Is this car rental for your 5 night stay in Chicago on 2016-12-18?" } } }
注意
-
除了
lastConfirmedReservation
以外,Lambda 函数中还包含更多会话属性(currentReservation
和confirmationContext
)。 -
当
dialogAction.type
设置为ConfirmIntent
,会通知 Amazon Lex 需要用户回复“是”或“否”(confirmationContext 设置为 AutoPopulate),Lambda 函数知道只有用户回复“是”或“否”才能获取用户对 Lambda 函数执行的初始化(自动预填充插槽数据)的确认。Lambda 函数还在响应中包含一条
dialogAction.message
中的通知消息,供 Amazon Lex 将其返回客户端。注意
ConfirmIntent
(dialogAction.type
的值) 与所有自动程序目的都没有关系。在本示例中,Lambda 函数使用该术语让 Amazon Lex 获取来自用户的“是”或“否”回复。
-
-
根据
dialogAction.type
,Amazon Lex 向客户端返回以下响应:客户端显示消息:“您是否要从 2016-12-18 开始在芝加哥租用这辆汽车 5 天?”
-
-
用户:“yes”
-
客户端将向 Amazon Lex 发送以下
PostText
请求:POST /bot/
BookTrip
/alias/$LATEST
/user/wch89kjqcpkds8seny7dly5x3otq68j3
/text "Content-Type":"application/json" "Content-Encoding":"amz-1.0" { "inputText":"yes", "sessionAttributes":{ "confirmationContext":"AutoPopulate", "currentReservation":"{\"ReservationType\":\"Car\", \"PickUpCity\":null, \"PickUpDate\":null, \"ReturnDate\":null, \"CarType\":null}", "lastConfirmedReservation":"{\"ReservationType\":\"Hotel\", \"Location\":\"Chicago\", \"RoomType\":\"queen\", \"CheckInDate\":\"2016-12-18\", \"Nights\":\"5\"}" } } -
Amazon Lex 读取
inputText
并了解上下文(要求用户确认自动填充)。Amazon Lex 通过发送以下事件来调用 Lambda 函数:{ "messageVersion": "1.0", "invocationSource": "DialogCodeHook", "userId": "wch89kjqcpkds8seny7dly5x3otq68j3", "sessionAttributes": { "confirmationContext": "AutoPopulate", "currentReservation": "{\"ReservationType\":\"Car\",\"PickUpCity\":null,\"PickUpDate\":null,\"ReturnDate\":null,\"CarType\":null}", "lastConfirmedReservation": "{\"ReservationType\":\"Hotel\",\"Location\":\"Chicago\",\"RoomType\":\"queen\",\"CheckInDate\":\"2016-12-18\",\"Nights\":\"5\"}" }, "bot": { "name": "BookTrip", "alias": null, "version": "$LATEST" }, "outputDialogMode": "Text", "currentIntent": { "name": "BookCar", "slots": { "PickUpDate": "2016-12-18", "ReturnDate": "2016-12-22", "DriverAge": null, "CarType": null, "PickUpCity": "Chicago" }, "confirmationStatus": "Confirmed" } }
由于用户回复“是”,所以 Amazon Lex 将
confirmationStatus
设置为Confirmed
。 -
根据
confirmationStatus
,Lambda 函数确定预填充的值正确无误。Lambda 函数执行以下操作:-
将
currentReservation
会话属性更新为已经预填充的槽值。 -
将
dialogAction.type
设置为ElicitSlot
-
将
slotToElicit
值设置为DriverAge
。
发送的响应如下:
{ "sessionAttributes": { "currentReservation": "{\"ReservationType\":\"Car\",\"PickUpCity\":\"Chicago\",\"PickUpDate\":\"2016-12-18\",\"ReturnDate\":\"2016-12-22\",\"CarType\":null}", "lastConfirmedReservation": "{\"ReservationType\":\"Hotel\",\"Location\":\"Chicago\",\"RoomType\":\"queen\",\"CheckInDate\":\"2016-12-18\",\"Nights\":\"5\"}" }, "dialogAction": { "type": "ElicitSlot", "intentName": "BookCar", "slots": { "PickUpDate": "2016-12-18", "ReturnDate": "2016-12-22", "DriverAge": null, "CarType": null, "PickUpCity": "Chicago" }, "slotToElicit": "DriverAge", "message": { "contentType": "PlainText", "content": "How old is the driver of this car rental?" } } }
-
-
Amazon Lex 返回以下响应:
客户端显示消息“驾驶此次所租汽车的司机多大年龄?” 对话继续进行。
-