Amazon Lex V1开启Lambda初始化验证时触发响应处理错误
问题原因
报错核心是开启Initialization and validation选项后,Lambda在DialogCodeHook阶段返回给Lex的响应不符合格式规范,具体有三个问题:
- 调用
elicitSlot方法时漏传必填参数:你定义的elicitSlot方法共接收5个入参,其中slotToElicit是必填参数,用来指定要引导用户填写的槽位名,但实际调用时只传了4个参数,导致返回结构中slotToElicit字段为undefined,Lex无法正常解析响应。 - 无兜底返回逻辑:用户首次发送"Hi"触发Greeting意图时,
user_name和std_name两个槽位均为空(运行日志中打印的两个null可以佐证),无法进入std_name == 'student'的判断分支,函数执行完成后没有调用callback返回任何内容,Lambda返回空响应给Lex,直接触发服务端解析错误。仅开启Fulfillment阶段时功能正常,是因为Fulfillment的触发条件是所有槽位均已填充完成,不会走到空返回分支。 - message字段格式错误:Lex V1要求响应中的message字段必须是包含
contentType和content属性的对象,直接传入字符串的话,就算参数传全也会触发格式校验失败。
修复步骤
- 补全响应工具方法,修正字段格式,补充DialogCodeHook阶段常用的Delegate、Close响应类型,保证返回结构完全符合Lex V1的响应规范。
- 给DialogCodeHook分支增加全场景判断逻辑,按槽位填充状态返回对应响应,所有分支必须调用callback返回结果,禁止出现函数执行完无返回的情况。
- 调用ElicitSlot时必须传入要引导填充的槽位名,不能缺省参数;如果不需要自定义槽位引导逻辑,可以直接返回Delegate类型响应,让Lex按默认配置引导用户填槽。
- 学生身份判断分支如果要直接返回提示语,不要用ElicitSlot类型,改用Close类型返回最终结果即可——ElicitSlot的作用是让用户填写指定槽位,不能用来发送最终回复。
修正后参考代码
响应工具方法(lexResponse.js):
module.exports.elicitSlot = function (sessionAttributes, intentName, slots, slotToElicit, message) { return { sessionAttributes, dialogAction: { type: 'ElicitSlot', intentName, slots, slotToElicit, // 修正message格式,符合Lex要求 message: { contentType: 'PlainText', content: message } }, }; }; module.exports.delegate = function (sessionAttributes, slots) { return { sessionAttributes, dialogAction: { type: 'Delegate', slots } }; }; module.exports.close = function (sessionAttributes, fulfillmentState, message) { return { sessionAttributes, dialogAction: { type: 'Close', fulfillmentState, message: { contentType: 'PlainText', content: message } } }; };
Greeting意图处理逻辑(greeting.js):
const lexResponse = require('./lexResponse'); module.exports = function(intentRequest, callback){ const slots = intentRequest.currentIntent.slots; const source = intentRequest.invocationSource; const intentName = intentRequest.currentIntent.name; const userName = slots.user_name; const std_name = slots.std_name; if(source === 'DialogCodeHook'){ // 用户名槽位为空,引导用户输入姓名 if (!userName) { callback(lexResponse.elicitSlot( intentRequest.sessionAttributes, intentName, slots, 'user_name', '请问你叫什么名字?' )); return; } // 身份槽位为空,引导用户选择身份 if (!std_name) { callback(lexResponse.elicitSlot( intentRequest.sessionAttributes, intentName, slots, 'std_name', '请问你的身份是学生还是教授?' )); return; } // 身份为学生时直接返回对应提示 if(std_name === 'student'){ callback(lexResponse.close( intentRequest.sessionAttributes, 'Fulfilled', "I can help you with your modules and assignments!" )); return; } // 其他场景交给Lex默认逻辑流转 callback(lexResponse.delegate(intentRequest.sessionAttributes, slots)); return; } // Fulfillment阶段逻辑可在此处补充,同样保证所有分支都有callback返回 };
内容的提问来源于stack exchange,提问作者Yosra Bader
相关产品推荐
相关产品推荐

