信息流的详细信息 - Amazon Lex V1

如果您使用的是 Amazon Lex V2,请改为参阅 Amazon Lex V2 指南

 

如果您使用的是 Amazon Lex V1,我们建议您将机器人升级到 Amazon Lex V2。我们不再向 V1 添加新功能,强烈建议使用 V2 以获得全新的机器人。

本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。

信息流的详细信息

在本练习中,您将使用 Amazon Lex 控制台中提供的测试窗口客户端与 Amazon Lex BookTrip 机器人展开对话。本节介绍以下内容:

数据流:预订酒店目的

本部分介绍了获得每个用户输入后会发生的情况。

  1. 用户:“book a hotel”

    1. 客户端 (控制台) 将向 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 函数首先设置会话属性。

    2. 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 – 所有槽值均设置为空。

    3. 此时,所有槽值均为空值。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 说明后续步骤。

    4. 根据 dialogAction.type,Amazon Lex 决定下一个操作(从用户获取 Location 插槽的数据)。它会根据目的配置针对这个槽选择一项提示消息(“您要住在哪座城市?”),然后向用户发送以下响应:

      JSON 响应包含对话状态、意图名称、消息、响应卡、会话属性、要引发的插槽和其他插槽。

      这些会话属性会被传递到客户端。

      客户端读取响应并显示消息:“您要住在哪座城市?”

  2. 用户:“Moscow”

    1. 客户端向 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 会话属性。

    2. 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

    3. 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

    4. Amazon Lex 发现 dialogAction.type 并通过以下响应向客户端传递信息:

      JSON 响应包含对话状态、意图名称、消息、响应卡、会话属性、要引发的插槽和其他插槽。

      客户端只是显示消息:“目前我们不支持莫斯科作为有效目的地,能否换一个城市?”

  3. 用户:“Chicago”

    1. 客户端将向 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}" } }

    2. 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

    3. 根据 DialogCodeHookinvocationSource 值,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 选择下一个操作。

       

    4. 根据 dialogAction.type,Amazon Lex 选择下一个操作。Amazon Lex 知道它需要更多插槽数据,因此会根据意图配置将下一个未填充的插槽 (CheckInDate) 设为最高优先级。它会根据目的配置针对这个槽选择一项提示消息(“您想要在哪天入住?”),然后向客户端发送回以下响应:

      JSON 响应包含对话状态、意图名称、消息、响应卡、会话属性、要引发的插槽和其他插槽。位置插槽现在填充为“芝加哥”。

      客户端显示消息:“您想在哪天入住?”

  4. 用户交互继续进行(用户提供数据,Lambda 函数验证数据,然后将下一个操作委派给 Amazon Lex)。最后,用户提供所有插槽数据,Lambda 函数验证所有用户输入,然后 Amazon Lex 确定自己获得了所有插槽数据。

    注意

    在本练习中,用户提供所有插槽数据之后,Lambda 函数会计算酒店的预订价格并将其作为另一个会话属性 (currentReservationPrice) 返回。

    此时意图已准备好履行,但 BookHotel 意图配置了一项确认提示,会在 Amazon Lex 履行意图前要求用户确认。因此,在预订酒店之前,Amazon Lex 会向客户端发送以下消息来要求确认:

    JSON 响应包含对话状态、意图名称、消息、响应卡、会话属性、要引发的插槽和其他插槽。现在,所有空插槽都已填充。

    客户端会显示消息:“好的,确定您要在芝加哥住 5 晚,入住日期是 2016-12-18。是否要预订?”

  5. 用户:“yes”

    1. 客户端将向 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" } }
    2. 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

    3. 此时,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 函数添加的新会话属性(不是 currentReservationcurrentReservationPrice)。

      • dialogAction.type — Lambda 函数将此值设置为 Close,表示 Amazon Lex 不需要用户响应。

      • dialogAction.fulfillmentState – 被设置为 Fulfilled 并且包含要传达给用户的相应 message

    4. Amazon Lex 查看 fulfillmentState 并向客户端发送以下响应:

      JSON 响应包含对话状态、意图名称、消息、响应卡、会话属性、要引发的插槽和其他插槽。所有插槽都已填充,会话属性下最后确认的预订字段现已填充。
      注意
      • dialogState — Amazon Lex 将此值设置为 Fulfilled

      • message — 与 Lambda 函数提供的消息相同。

      客户端将显示消息。

数据流:预订汽车目的

本练习中的 BookTrip 自动程序支持两种目的 (BookHotel 和 BookCar)。预订酒店之后,用户可以继续进行对话以便预订汽车。只要会话未超时,客户端就会在每个后续请求中继续发送会话属性 (本示例中为 lastConfirmedReservation)。Lambda 函数可以使用这一信息来初始化 BookCar 意图的插槽数据。这体现了在跨目的数据共享中使用会话属性的过程。

具体来说,当用户选择 BookCar 意图时,Lambda 函数会使用会话属性中的相关信息来预填充 BookCar 意图的插槽(PickUpDate、ReturnDate 和 PickUpCity)。

注意

Amazon Lex 控制台提供清除链接,您可使用此链接清除之前的所有会话属性。

按照以下步骤继续进行对话。

  1. 用户:“also book a car”

    1. 客户端将向 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 会话属性。

    2. 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 — 其中包括意图名称和插槽。此时,所有槽值均为空值。

    3. Lambda 函数发现所有插槽值均为空值,没有任何可以验证的内容。但是函数会使用会话属性来初始化一些槽值 (PickUpDateReturnDatePickUpCity),然后返回以下响应:

      { "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 函数中还包含更多会话属性(currentReservationconfirmationContext)。

      • dialogAction.type 设置为 ConfirmIntent,会通知 Amazon Lex 需要用户回复“是”或“否”(confirmationContext 设置为 AutoPopulate),Lambda 函数知道只有用户回复“是”或“否”才能获取用户对 Lambda 函数执行的初始化(自动预填充插槽数据)的确认。

         

        Lambda 函数还在响应中包含一条 dialogAction.message 中的通知消息,供 Amazon Lex 将其返回客户端。

        注意

        ConfirmIntent (dialogAction.type 的值) 与所有自动程序目的都没有关系。在本示例中,Lambda 函数使用该术语让 Amazon Lex 获取来自用户的“是”或“否”回复。

    4. 根据 dialogAction.type,Amazon Lex 向客户端返回以下响应:

      JSON 响应包含对话状态、意图名称、消息、响应卡、会话属性、要引发的插槽和其他插槽。

      客户端显示消息:“您是否要从 2016-12-18 开始在芝加哥租用这辆汽车 5 天?”

  2. 用户:“yes”

    1. 客户端将向 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\"}" } }
    2. 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

    3. 根据 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?" } } }
    4. Amazon Lex 返回以下响应:

      JSON 响应显示了预订汽车的意图,并显示了一条引发“驾驶员年龄”插槽的消息。

      客户端显示消息“驾驶此次所租汽车的司机多大年龄?” 对话继续进行。