集成Alexa与Voiceflow – CodesCode

如何将Alexa和Voiceflow集成,将注意力放在对话设计而非编码上这将帮助你提升对话品质!

Alexa有很多功能,但是创建复杂对话并不容易。Voiceflow是一个无需编写代码就能创建复杂对话的工具。该集成允许您在Voiceflow中创建对话,然后部署到Alexa。

因此,在这个仓库中,你将找到一个使用Alexa Skills Kit SDK for Node.js和调用Voiceflow的对话管理器API集成Alexa和Voiceflow的简单示例。

先决条件

  1. 您需要在Voiceflow上拥有一个账户
  2. 您需要在Alexa Developer上拥有一个账户
  3. 您的计算机上需要安装Node.js和npm/yarn

Voiceflow项目

在Voiceflow上,您需要创建一个项目并创建一段对话。您可以按照Voiceflow快速入门创建一段简单的对话。在Voiceflow中,您唯一需要关心的是设计对话。

在这个示例中,我们将创建一段简单的对话,询问用户关于Pokemon的信息。对话将会是这样的:

NLU

Voiceflow拥有一个内置的NLU,由于我们将使用对话管理器API调用Voiceflow,因此我们需要在Voiceflow和Alexa上设计我们的NLU。

按照示例,我们将创建一个名为info_intent的意图和一个名为pokemon的插槽,该插槽将被用户要了解的Pokemon的名称填充:

对话管理器API

对话管理器API是一个REST API,可以让您与Voiceflow进行交互。您可以在这里找到文档。

DM API会自动创建和管理对话状态。对DM API的相同请求可能会产生不同的响应,这取决于您的图表逻辑和API之前收到的请求。

DM API的终端是:https://general-runtime.voiceflow.com/state/user/%7BuserID%7D/interact

可以发送不同类型的请求。要查看所有请求类型的列表,请查看下面的action字段的文档。

要启动对话,您应该发送一个启动请求。然后,要传递给您的用户响应,您应该发送一个文本请求。如果您拥有自己的NLU匹配,那么您可能想直接发送一个意图请求。

这里有一个请求的示例:

curl --request POST \     --url 'https://general-runtime.voiceflow.com/state/user/{userID}/interact?logs=off' \     --header 'accept: application/json' \     --header 'content-type: application/json' \     --header 'Authorization: VF.DM.96ds3423ds9423fs87492fds79792gf343' \     --data '{  "action": {    "type": "launch"  },  "config": {    "tts": false,    "stripSSML": true,    "stopAll": true,    "excludeTypes": [      "block",      "debug",      "flow"    ]  }}'

如您所见,您需要传递userIDAuthorization头。该userID是您想与之交互的用户ID。Authorization头是您可以在Voiceflow项目设置中找到的API密钥。

您可以在voiceflow/project.vf中找到我在本示例中使用的Voiceflow项目。

Alexa技能

要创建一个Alexa技能,您需要前往Alexa Developer并创建一个新的技能。请按照Alexa Developer控制台快速入门创建一个简单的技能。

NLU

我们需要在我们的Alexa Skill中复制Voiceflow NLU(意图和实体)。

正如您所看到的,我们正在使用SearchQuery类型。此类型用于获取用户输入并直接发送到Voiceflow。您可以在这里找到有关该类型的更多信息。

Lambda代码

Alexa Skill代码将是通用的,这意味着该Alexa Skill代码可以与任何Voiceflow项目一起使用。为此,我们将实现一个Lambda函数,该函数将调用Voiceflow对话管理器API。我们将使用Alexa Skills Kit SDK for Node.js和Axios来调用API。

我们只需要调整两个处理程序,即LaunchRequestHandlerListenerIntentHandlerLaunchRequestHandler用于启动对话,而ListenerIntentHandler用于将用户输入发送到Voiceflow。

让我们从LaunchRequestHandler开始:

const LaunchRequestHandler = {    canHandle(handlerInput) {        return Alexa.getRequestType(handlerInput.requestEnvelope) === 'LaunchRequest';    },    async handle(handlerInput) {        let chatID = Alexa.getUserId(handlerInput.requestEnvelope).substring(0, 8);        const messages = await utils.interact(chatID, {type: "launch"});        return handlerInput.responseBuilder            .speak(messages.join(" "))            .reprompt(messages.join(" "))            .getResponse();    }};

当技能启动时,将调用此处理程序。我们将获取用户ID并使用launch操作调用Voiceflow对话管理器API。然后,我们将返回响应。

以下交互将由ListenerIntentHandler处理:

const ListenerIntentHandler = {    canHandle(handlerInput) {        return Alexa.getRequestType(handlerInput.requestEnvelope) === 'IntentRequest'    },    async handle(handlerInput) {        let chatID = Alexa.getUserId(handlerInput.requestEnvelope).substring(0, 8);        const intent = Alexa.getIntentName(handlerInput.requestEnvelope);        const entitiesDetected = utils.alexaDetectedEntities(handlerInput.requestEnvelope);        const request = {             type: "intent",             payload: {                 intent: {                    name: intent                },                entities: entitiesDetected            }        };        const messages = await utils.interact(chatID, request);        return handlerInput.responseBuilder            .speak(messages.join(" "))            .reprompt(messages.join(" "))            .getResponse();    }};

当用户说出某个内容时,将调用此处理程序。我们将获取用户输入,并使用intent操作调用Voiceflow对话管理器API。由于NLU推理由Alexa完成,我们需要获取检测到的实体和检测到的意图,并将它们发送到Voiceflow。然后,我们将返回响应。

为了获取检测到的实体,我们将使用以下函数:

module.exports.alexaDetectedEntities = function alexaDetectedEntities(alexaRequest) {    let entities = [];    const entitiesDetected = alexaRequest.request.intent.slots;    for ( const entity of Object.values(entitiesDetected)) {        entities.push({            name: entity.name,            value: entity.value        });    }    return entities;}

您可以在lambda/utils.js中找到此函数的代码。

最后,我们必须确保将这些处理程序添加到skill中:

exports.handler = Alexa.SkillBuilders.custom()    .addRequestHandlers(        LaunchRequestHandler,        ListenerIntentHandler,        HelpIntentHandler,        CancelAndStopIntentHandler,        FallbackIntentHandler,        SessionEndedRequestHandler,        IntentReflectorHandler)    .addErrorHandlers(        ErrorHandler)    .withCustomUserAgent('sample/hello-world/v1.2')

在上述处理程序中,您可以看到我们使用了名为utils.interact的函数。此函数将调用Voiceflow对话管理器API。您可以在lambda/utils.js中找到该函数的代码:

const axios = require('axios');const VF_API_KEY = "VF.DM.96ds3423ds9423fs87492fds79792gf343";module.exports.interact = async function interact(chatID, request) {    let messages = [];    console.log(`request: `+JSON.stringify(request));    const response = await axios({        method: "POST",        url: `https://general-runtime.voiceflow.com/state/user/${chatID}/interact`,        headers: {            Authorization: VF_API_KEY        },        data: {            request        }    });    for (const trace of response.data) {        switch (trace.type) {            case "text":            case "speak":                {                    // remove break lines                    messages.push(this.filter(trace.payload.message));                    break;                }            case "end":                {                    messages.push("再见!");                    break;                }        }    }    console.log(`response: `+messages.join(","));    return messages;};

这个函数将返回一个消息数组。我们将使用这个数组来构建回应。我们还添加了一些代码来移除换行和奇怪的字符:

module.exports.filter = function filter(string) {    string = string.replace(/\'/g, '\'')    string = string.replace(/(<([^>]+)>)/ig, "")    string = string.replace(/\&/g, ' and ')    string = string.replace(/[&\\#,+()$~%*?<>{}]/g, '')    string = string.replace(/\s+/g, ' ').trim()    string = string.replace(/ +(?= )/g,'')    return string;};

通过这段代码,我们已经完成了 Alexa 技能。你可以在 lambda/index.js 中找到 Lambda 函数的代码。

测试

一旦你创建了 Alexa 技能和 Voiceflow 项目,你就可以进行测试。你可以使用 Alexa 模拟器进行测试,也可以使用真实设备进行测试。

按照我们使用的例子,你可以使用以下句子来请求有关 Pokemon 的信息,以测试 Alexa 技能:

结论

正如你所见,将 Alexa 与 Voiceflow 集成非常简单。你可以在 Voiceflow 中创建复杂的对话,然后将其部署到 Alexa 上。这样,你的重点将放在对话上,而不是代码上!

希望你喜欢这个教程。

你可以在这里找到这个教程的代码。

愉快编码!


Leave a Reply

Your email address will not be published. Required fields are marked *