利用 assistant_如何使用Dialogflow对Google Assistant操作实施本地履行

唐兴思
2023-12-01

利用 assistant

NB: this blog covers Actions on Google node.js deployments only, and presumes some basic prior knowledge of Actions on Google/ Dialogflow

注意:此博客仅涵盖Google node.js部署上的操作,并假定您对Google / Dialogflow上的操作具有一些基本的先验知识

Hello, world!

你好,世界!

问题陈述 (Problem statement)

I’ve been getting into Actions on Google quite a bit of late — enjoying myself thoroughly — My learning has been primarily designing small “party tricks” that I can amuse visitors with. I’ve been doing the same with Alexa too, but since I’m a lot more familiar with the Google Cloud Platform and Firebase especially, I have prototyped more on Google.

我已经很晚才进入Google的Actions -充分享受自己的乐趣-我的学习主要是设计一些小的“聚会技巧”,我可以使访客感兴趣。 我也一直在使用Alexa,但是由于我对Google Cloud PlatformFirebase更加熟悉,因此我在Google上制作了更多原型。

Actions and working with the Google Assistant often requires server side logic to handle the interaction with the desired level of personalisation or customization. This is called “fulfillment”.

操作和使用Google Assistant常常需要服务器端逻辑来以所需的个性化或自定义级别处理交互。 这称为“实现”。

The development cycle for fulfillment can be a bit tedious because you need to push your server code to the cloud each time, to see if it’s working. Every time we make changes that we want to test, we need to push code to Firebase and give it 30–60 seconds to propagate. It’s like web dev before hot reloads — ugh! So 2011.

实现的开发周期可能有点繁琐,因为您需要每次将服务器代码推送到云中,以查看其是否正常运行。 每次我们进行要测试的更改时,都需要将代码推送到Firebase,并使其传播30-60秒。 就像是在热重载之前的Web开发人员—嗯! 所以2011

体系结构摘要 (Summary of the Architecture)

I won’t go into the details of building Actions for the Assistant, as there is plenty out there to help you with that. But a high level overview of the system now will help you understand the problem statement that inspired this blog.

我将不介绍为助手构建动作的详细信息,因为那里有很多可以帮助您的内容。 但是,现在对该系统进行高级概述将有助于您理解启发该博客的问题陈述。

Here is a diagram from Google that explains how Actions/ Assistant interactions are processed.

这是Google的图表,解释了如何处理动作/助手交互。

A user’s interaction gets picked up by the device, converted to text that is parsed by the device, and passed to a DialogFlow agent which is a NLUengine. That then works out the “intent” of the user’s statement (“phrase” or “utterance”). That intent then gets matched to code that “fulfills” the intent of the user, then returns a response that is (hopefully) appropriate and acceptable.

用户的交互被设备拾取,转换为由设备解析的文本,然后传递给DialogFlow代理,后者是NLU引擎。 然后得出用户陈述的“意图”(“短语”或“话语”)。 然后,将该意图与“满足”用户意图的代码进行匹配,然后返回(希望)适当且可接受的响应。

If you have studied the picture, you will see that a request is made in the last column, which denotes Firebase. What it really denotes is a back-end server that has a HTTP webhook that receives ‘requests’ for fulfillment and then works out how to respond appropriately. Architecturally, the Dialogflow NLU agent sends a POST request to the server webhook, which then gets processed by the server using SDKs.

如果您已经研究了图片,那么您将在最后一列(表示Firebase)中看到一个请求。 它真正表示的是具有HTTP Webhook的后端服务器,该Webhook接收要实现的“请求”,然后确定如何适当地响应。 在结构上,Dialogflow NLU代理将POST请求发送到服务器Webhook,然后由服务器使用SDK对其进行处理。

The back end server that processes requests and responses is easily hosted on Firebase Cloud Functions (of course, Google makes it easy to use their stack — that’s just good business!).

处理请求和响应的后端服务器很容易托管在Firebase Cloud Functions上 (当然Google可以轻松使用它们的堆栈-很好!)。

Also, a locally run server will generate a webhook endpoint like http://localhost:3000, which is not accessible to Google Assistant’s POST requests.

另外,本地运行的服务器将生成一个Webhook终结点,例如http:// localhost:3000, Google Assistant的POST请求无法访问该终结点。

解决方案声明-本地实现开发服务器! (Solution Statement — local fulfillment dev server!)

There are three steps to this solution:

此解决方案包括三个步骤:

  1. Create the back-end fulfillment server as an Express server.

    将后端履行服务器创建为Express服务器

  2. Handle Dialogflow requests and responses as an Express endpoint. The default Firebase Cloud Functions server users the Actions on Google Nodejs Client Library which has built-in functionality to receive HTTP POST requests from the Dialogflow agent. But that won’t work outside the Firebase environment (i.e. on our local development server). So we need to deploy our fulfillment server an an Express app.

    将Dialogflow请求和响应作为Express端点处理。 默认的Firebase Cloud Functions服务器使用内置功能从Dialogflow代理接收HTTP POST请求的Google Nodejs客户端库上操作 。 但这在Firebase环境之外(即在我们的本地开发服务器上)不起作用。 因此,我们需要将履行服务器部署为Express应用程序。

  3. use the Ngrok Node package to create a temporary HTTP endpoint that tunnels HTTP requests through to our local:3000 (or whatever port you use) server.

    使用Ngrok Node包创建一个临时HTTP终结点,该终结点将 HTTP请求通过隧道传输到我们的local:3000(或您使用的任何端口)服务器。

I will not go into the steps of setting up your basic code for a simple nodejs fulfillment server — the Dialogflow/ Actions on Google docs help you with all that. But I do provide here the snippets that show you how to convert that Dialogflow App into an Express App, and what your package.json needs to look like.

我不会介绍为简单的nodejs履行服务器设置基本代码的步骤-Google文档上的Dialogflow /操作可帮助您完成所有这些工作。 但我在这里提供了一些片段,向您展示了如何将Dialogflow应用程序转换为Express应用程序,以及package.json外观。

Let’s start with the basic setup for the Dialogflow node.js client. We will call it the Dialogflow App.

让我们从Dialogflow node.js客户端的基本设置开始。 我们将其称为Dialogflow应用。

const {
  dialogflow,
  BasicCard
} = require("actions-on-google");


// Instantiate the Dialogflow client.
const app = dialogflow({ debug: true });


// Handlers go here..
app.intent("Default Welcome Intent", conv => {
   // handler for this intent
});

app.intent("Say_Something_Silly", conv => {
   // handler for this intent
});


module.exports = app;

This is the app that ‘handles’ the intents. The above code is just scaffolding. Export the app, and import it in functions/index.js.

这是“处理”意图的应用程序。 上面的代码只是脚手架。 导出应用程序,并将其导入到functions/index.js

index.js is the entry point in our functions folder, which contains the cloud functions we push up to Firebase Cloud Functions. In this file we create the Express App, and import the DialogflowApp object, and then pass it in to the Express route that will receive the HTTP POST requests from Dialogflow. Note that we need the body-parser npm package as the HTTP requests are JSON.

index.jsfunctions文件夹中的入口点,其中包含我们推送到Firebase Cloud Functions的云函数。 在此文件中,我们创建Express App,并导入DialogflowApp对象,然后将其传递到Express路由,该路由将从Dialogflow接收HTTP POST请求。 请注意 ,由于HTTP请求是JSON,因此我们需要body-parser npm软件包。

"use strict";

const express = require("express");
const bodyParser = require("body-parser");
const functions = require("firebase-functions");


// clients
const dialogFlowApp = require("./DialogflowApp");
const expressApp = express().use(bodyParser.json());

// EXPRESS APP fulfillment route (POST). The entire dialogFlowApp object (incl its handlers) is the callback handler for this route.
expressApp.post("/", dialogFlowApp);


//  EXPRESS APP test route (GET)
expressApp.get("/", (req, res) => {
  res.send("CONFIRMED RECEIPT OF GET.");
});



/*
 *   LOCAL NGROK SERVER LOGIC. ENSURE that you "export IS_LOCAL_DEV=true" in terminal prior to start
 */
if (process.env.IS_LOCAL_DEV) {
  const PORT = 8000;
  expressApp.listen(PORT, () =>
    console.log(`*** SERVER RUNNING LOCALLY ON PORT ${PORT} ***`)
  );
} else {
  console.log("*** NOT LOCALLY SERVED - OR - LOCAL ENV VAR NOT SET  ****");
}

//EXPORT either of the following two endpoints:  one express app, one dialogflow app
exports.fulfillmentExpressServer = functions.https.onRequest(expressApp);
exports.dialogflowFirebaseFulfillment = functions.https.onRequest(dialogFlowApp);

The key parts of this code are that we create a POST route that takes, as the handler-callback, our DialogflowApp object. I created a GET route just to make quick browser GET requests to test the endpoint is working. But Dialogflow only uses the POST route.

该代码的关键部分是我们创建一个POST路由,该路由将DialogflowApp对象作为处理程序回调。 我创建了一个GET路由,只是为了向浏览器发出快速的GET请求以测试端点是否正常工作。 但是Dialogflow仅使用POST路由。

Note that I’ve made two exports here. One is the Express app and the other is the dialogflow App itself. This creates to Firebase functions with two endpoints which are identified by the property attached to the exportsobject. One endpoint will be <……/fulfillmentExpressServer> and the other will be <……/dialogflowFirebaseFulfillment>.

请注意 ,我在这里进行了两次导出。 一个是Express应用程序,另一个是dialogflow应用程序本身。 这将为Firebase创建具有两个终结点的函数,这两个终结点由附加到exports对象的属性标识。 一个端点为<……/ fulfillmentExpressServer>,另一个端点为<……/ dialogflowFirebaseFulfillment>。

I can use either of these HTTP endpoints for fulfillment, once I’m done developing locally and have pushed the final code up to Firebase Cloud Functions.

一旦完成本地开发并将最终代码推送到Firebase Cloud Functions,我就可以使用这两个HTTP端点来实现。

NGROK用于本地开发服务器隧道 (NGROK for the local development server tunneling)

There is some funny looking code in there on line 26. On my Mac terminal, I use export IS_LOCAL_DEV=true before I start the server locally. That codeblock on line 26 basically starts the server listening locally, which is notneeded when we push the code up to Cloud Functions — it is for the local server only.

第26行上有一些有趣的代码。在我的Mac终端上,在本地启动服务器之前,我使用export IS_LOCAL_DEV=true 。 上线26的代码块基本上启动服务器监听本地,这时候我们推码达云功能不需要 -这是仅在本地服务器。

"dependencies": {
    "actions-on-google": "^2.0.0",
    "body-parser": "^1.18.3",
    "express": "^4.16.4",
    "firebase-functions": "^2.2.0"
  },
"devDependencies": {
    "ngrok": "^3.1.1"
  },
"scripts": {
    "lint": "eslint .",
    "serve": "firebase serve --only functions",
    "shell": "firebase experimental:functions:shell",
    "start": "npm run shell",
    "deploy": "firebase deploy --only functions",
    "logs": "firebase functions:log",
    "tunnel": "ngrok http 8000",
    "dev": "nodemon index.js"
  },

Which brings me to the above configuration in package.json. In the scripts property, you can see one called tunnel. Note the port number 8000 there. That can be set to anything you like, but make sure that the code in index.jsthat sets the PORT constant (line 27 in the Gist) is the same port number.

这使我进入了package.json中的上述配置。 在scripts属性中,您可以看到一个名为tunnel 。 注意那里的端口号8000。 可以将其设置为任何您喜欢的名称,但是请确保index.js中设置PORT常量(Gist中的第27行)的代码是相同的端口号。

Before you run the code, check the following:

在运行代码之前,请检查以下内容:

  1. You’ve set your environment variable and the code matches it — in my case I used IS_LOCAL_DEV=true

    您已经设置了环境变量,并且代码与之匹配—在我的情况下,我使用了IS_LOCAL_DEV=true

  2. Your port numbers match in index.js and the tunnel script

    您的端口号在index.jstunnel脚本中匹配

Then you open two terminal windows and run the following:

然后打开两个终端窗口并运行以下命令:

npm run dev and npm run tunnel

npm run devnpm run tunnel

In the terminal that ran the tunnel (ngrok) you will see something like this:

在运行隧道的终端(ngrok)中,您将看到以下内容:

Note the two ‘Forwarding’ addresses. They’re identical, except one is https. Either works. That is your endpoint, assuming your POST route is / and not /<some path>. If you’ve added a path to the POST handler then you need to add that path to the Forwarding address.

请注意两个“转发”地址。 它们是相同的,除了一个是https。 无论哪种。 假设您的POST路由是/而不是/<some path>. ,这就是您的端点/<some path>. 如果您已将路径添加到POST处理程序,则需要将该路径添加到转发地址。

Note that every time you run ngrok it generates a new, temporary URL for you. Therefore, you need to update your Dialogflow fulfillment webhook every time you run npm run tunnel.

请注意 ,每次您运行ngrok时,它都会为您生成一个新的临时URL。 因此,每次运行npm run tunnel时,都需要更新Dialogflow实现Webhook。

And there you go. No more pushing every little change in code to Firebase Cloud Functions and waiting a minute or two before testing. Develop on the fly, and with nodemon, your server restarts and you can keep testing as you code!

然后你去。 无需再将代码中的每一个微小变化都推送给Firebase Cloud Functions,而在测试前等待一两分钟。 动态开发,并使用nodemon,服务器将重新启动,并且您可以在编写代码时继续进行测试!



I can be contacted on Twitter: @ZubinPratap

可以通过Twitter与我联系:@ZubinPratap

And if you are a code newbie, and find this overwhelming, that is natural. You’re jumping too far ahead. I made that mistake too, and it cost me too much.

而且,如果您是代码新手,并且觉得不知所措,那是很自然的。 你跳得太远了。 我也犯了这个错误,花了我太多的钱。

If you want to learn to code, or are overwhelmed by it, I encourage you to take a look at my course on Udemy. It teaches you how to learn to code rather than how to code. Coding is easy, but learning to code is not. If you want a promo code go here.

如果您想学习编码或对此感到不知所措,建议您阅读有关Udemy的课程 。 它教您如何学习编码而不是编码。 编码很容易,但是学习编码却不容易。 如果您想要促销代码,请转到此处

翻译自: https://www.freecodecamp.org/news/how-to-implement-local-fulfillment-for-google-assistant-actions-using-dialogflow-1b3b3a13075f/

利用 assistant

 类似资料: