Amazon Lex槽位全填充后仍触发DialogCodeHook而非FulfillmentCodeHook问题
问题:Amazon Lex槽位填充完成后无法触发FulfillmentCodeHook
原本运行正常的预订试驾Lambda槽位验证代码出现异常:用户填写完所有必填槽位(FirstName、ContactDetails、Date)后,Lex并未触发预期的FulfillmentCodeHook(intent状态为ReadyForFulfillment),而是持续发送DialogCodeHook请求,intent状态始终为InProgress。
预期请求示例
{ "sessionId": "526322052651484", ... "sessionState": { "sessionAttributes": {}, "intent": { "name": "BookTestDrive", "slots": { "ContactDetails": { "shape": "Scalar", "value": { "originalValue": "mail@mail.com", "resolvedValues": [], "interpretedValue": "mail@mail.com" } }, "FirstName": { "shape": "Scalar", "value": { "originalValue": "Buln", "resolvedValues": [ "Bula" ], "interpretedValue": "Buln" } }, "Date": { "shape": "Scalar", "value": { "originalValue": "14-03-2024", "resolvedValues": [ "2024-03-14" ], "interpretedValue": "2024-03-14" } } }, "state": "ReadyForFulfillment", "confirmationState": "None" }, "originatingRequestId": "a13fd06a-bc03-4a80-94f9-8b65e7b2edb2" }, "invocationSource": "FulfillmentCodeHook", ... }
实际收到的请求示例
{ "sessionId": "526322052651839", ... "sessionState": { "sessionAttributes": {}, "activeContexts": [], "intent": { "confirmationState": "None", "name": "BookTestDrive", "slots": { "ContactDetails": { "shape": "Scalar", "value": { "originalValue": "email@mail.com", "resolvedValues": [], "interpretedValue": "email@mail.com" } }, "FirstName": { "shape": "Scalar", "value": { "originalValue": "Bunleap", "resolvedValues": [], "interpretedValue": "Bunleap" } }, "Date": { "shape": "Scalar", "value": { "originalValue": "today", "resolvedValues": [ "2023-07-25" ], "interpretedValue": "2023-07-25" } } }, "state": "InProgress" }, "originatingRequestId": "47dd31f5-0119-42c1-9d22-89bf05d44d86" }, ... "invocationSource": "DialogCodeHook", }
当前Lambda Python代码
import boto3 import random def validate_booking(slots): if not slots['FirstName']: return { 'isValid': False, 'invalidSlot': 'FirstName' } if not slots['ContactDetails']: return { 'isValid': False, 'invalidSlot': 'ContactDetails' } if not slots['Date']: return { 'isValid': False, 'invalidSlot': 'Date' } return {'isValid': True} def lambda_handler(event, context): print(event) bot = event['bot']['name'] slots = event['sessionState']['intent']['slots'] intent = event['sessionState']['intent']['name'] validate_result = validate_booking(slots) dynamodb = boto3.resource('dynamodb') table = dynamodb.Table("CarBookTestDrive") if event['invocationSource'] == 'DialogCodeHook': if not validate_result['isValid']: if 'message' in validate_result: response = { "sessionState": { "dialogAction": { "slotToElicit": validate_result['invalidSlot'], "type": "ElicitSlot" }, "intent": { "name": intent, "slots": slots } }, "messages": [ { "contentType": "PlainText", "content": validate_result['message'] } ] } else: response = { "sessionState": { "dialogAction": { "slotToElicit": validate_result['invalidSlot'], "type": "ElicitSlot" }, "intent": { "name": intent, "slots": slots } } } else: response = { "sessionState": { "dialogAction": { "type": "Delegate" }, "intent": { 'name': intent, 'slots': slots } } } if event['invocationSource'] == 'FulfillmentCodeHook': message = f"Thanks {event['sessionState']['intent']['slots']['FirstName']['value']['interpretedValue']}, We will contact you shortly to confirm the drive test." response = { "sessionState": { "dialogAction": { "type": "Close" }, "intent": { "name": intent, "slots": slots, "state": "Fulfilled" } }, "messages": [ { "contentType": "PlainText", "content": message } ] } table.put_item(Item={ 'TestDriveID': str(random.randint(1000,9999)), 'FirstName': event['sessionState']['intent']['slots']['FirstName']['value']['interpretedValue'], 'ContactDetails': event['sessionState']['intent']['slots']['ContactDetails']['value']['interpretedValue'], 'Date': event['sessionState']['intent']['slots']['Date']['value']['interpretedValue'] }) return response
解决方案
1. 检查Lex控制台Intent配置
- 确认
BookTestDriveIntent已启用Fulfillment,并绑定了正确的Lambda函数。 - 检查Intent的Confirmation prompt是否开启:若开启,需用户确认Intent后才会触发Fulfillment,若流程不需要确认,需关闭该选项。
- 检查各槽位的Slot confirmation prompt:若某个槽位开启了确认,需用户确认槽位内容后流程才会继续,若不需要则关闭。
2. 修改Lambda代码,手动触发Fulfillment
当所有槽位验证通过后,不再返回Delegate类型的DialogAction,而是直接将Intent状态设置为ReadyForFulfillment,告诉Lex可以触发Fulfillment流程:
修改Lambda代码中DialogCodeHook分支的else块:
else: response = { "sessionState": { "intent": { 'name': intent, 'slots': slots, 'state': 'ReadyForFulfillment' } } }
3. 优化资源初始化(可选)
将DynamoDB的初始化代码移到FulfillmentCodeHook分支内,避免不必要的资源加载:
if event['invocationSource'] == 'FulfillmentCodeHook': dynamodb = boto3.resource('dynamodb') table = dynamodb.Table("CarBookTestDrive") # 后续Fulfillment逻辑...
内容的提问来源于stack exchange,提问作者Bunleap
相关产品推荐
相关产品推荐

