"alexa, ask NiuNiu open the light." 如果你这样说,但是技能不知道你要开哪个灯,这时候技能就应该提示用户“Which light do you open?”, 接着执行下面的动作,这就是多轮对话。

    首先,你需要登录到alexa skill 控制台,创建一个custom skill。

在控制台里面设置你的对话模型。对话模型设置完之后,需要接入endpoint,可以是你自己的服务器,也可以是lambda函数,在这里本人使用lambda函数。

设置对话模型里面几个重要参数:

1、技能调用名,即通过这个名字才能调用到这个技能,就像上面"NiuNiu"就是一个技能调用名。

2、意图,“open”就是一个意图,怎么才能让技能知道你的意图呢?就需要样本话语了。

3、槽位,就是想设置一些关键字,通过这句话能不能获取到相应的关键字;

4、槽位类型,关键字可以看成是一个变量,变量就有很多类型,如int, char等。

    如果你想支持多轮对话,必须要使能槽位填充,即,当技能发现你的对话里面没有包含相应的槽位值时,会提示用户该怎么做?以上步骤网上资料很多就不详细写出来了,最好阅读alexa官方文档。

    其次,前面说了对话模型设置完之后,需要接入endpoint,本人使用lambda函数,这个函数是技能的主要部分,对话模型相当于一个界面,lambda函数才是处理后台逻辑的关键部分。在这里关键讨论多轮对话的实现方式,具体技能是用来干什么的由开发者自己定义。开始以为对话模型设置好了,使能槽位填充就能实现多轮对话了,后来测试发现不是这么回事。通过对官方文档的理解,多轮对话是需要lambda函数进行处理的。多轮对话有三种方式:

1、托管(提示语句由控制台设置);

2、自己控制(提示语句由用户自己设置);

3、托管+自己控制(两种方式结合);

想要简单实现,使用方式1最好。

"alexa, ask NiuNiu open the light.", 这句被alexa云端处理之后,会产生相应的消息传入到lambda函数,lambda函数需要根据传过来的对话状态返回Delegate Directive,如果槽位填满了状态值就是COMPLETED。

代码示例如下:

通过 this.emit(':delegate') 返回delegate directive.
 
const handlers = {
 
    'LedOpen': function () {
 
        if (this.event.request.dialogState === 'STARTED') {
 
            let updatedIntent = this.event.request.intent;
 
            // Pre-fill slots: update the intent object with slot values for which
 
            // you have defaults, then emit :delegate with this updated intent.
 
            updatedIntent.slots.SlotName.value = 'DefaultValue';
 
            this.emit(':delegate', updatedIntent);
 
        } else if (this.event.request.dialogState !== 'COMPLETED'){
 
            this.emit(':delegate');
 
        } else {
 
            // All the slots are filled (And confirmed if you choose to confirm slot/intent)
 
            handlePlanMyTripIntent();
 
        }
 
    }
 
};

这段代码是node.js写的,可以参考https://www.npmjs.com/package/alexa-sdk#dialog-interface。