聊天机器人越来越受欢迎。 Facebook正在努力提供一个构建Messenger机器人的框架,该框架将允许企业所有者完全在Facebook的消息传递应用程序内部建立其客户支持。 订购披萨 ,安排您的下一次医生就诊,还是只是想为下一次旅行找到最便宜的航班? 在消息传递应用程序中查找机器人联系人,并像在好友列表中询问人类联系人一样,询问您需要什么。

Facebook消息产品副总裁David Marcus在11月的Web Summit上发表了有关Facebook参与聊天机器人的演讲,很明显,Facebook制定了使客户和企业所有者不仅将客户支持集成到Messenger聊天中而且将其集成到客户聊天中的宏伟计划。还有一些您通常希望是网页或应用程序中的表单的交互(例如,订购食物,配置下一次购车等 )。

在本教程中,我们将使用Electron和Microsoft Bot Framework (MBF)创建用于日常Scrum会议的Skype机器人。

那里有什么?

从技术角度看,当前最流行的框架似乎是Microsoft Bot Framework,它使您可以将bot与基本上所有流行的聊天连接起来。

但是,还有其他选择:

  • Facebook的Messenger平台 (仅限Facebook Messenger)。
  • Pandorabots平台
  • Imperson的对话机器人
  • api.ai

关于我们的机器人

我们将创建配置GUI,以创建Scrum团队并使用Electron添加成员,然后使用MBF创建一个机器人,该机器人将从配置中读取信息,并向所有添加的用户提示三个Scrum日常会议问题。 当每个人都提供答案后,该漫游器会将会议摘要发送给团队中的所有参与者。

橄榄球机器人?

不,我们不是制造橄榄球机器人。 对于那些不熟悉scrum的人,这里是TL; DR

Scrum是一种方法,由针对敏捷开发过程(例如,软件开发团队)的预定义规则和最佳实践组成,特别是针对大约3至6人的团队(非常粗糙且变化很大)。 这些规则/最佳实践可以包括以下内容(再次,非常粗略,并且变化很大,因为每个团队都根据自己的需要对其进行了一些调整):

  • 如何创建任务以及应指定什么
  • 用于根据团队完成任务所需的先前时间计算团队可以多快交付产品迭代的度量。
  • 每个团队成员的定义角色
    • 产品负责人:做主的人; 与客户讨论正在开发的产品,并根据客户的需求创建用户案例(任务的奇特名称),然后由开发人员自由选择
    • 开发人员 :技术人员
    • Scrum master :坐在您的脖子后面,确保整个团队的行为均符合Scrum规则
  • 促进团队沟通 ,尤其是面对面的沟通
  • 团队应举行的会议
    • 这些会议多久举行一次
    • 在那些会议上应该讨论什么

这些会议之一是每日Scrum会议。 通常,每个团队成员都是在早上做第一件事,向每个团队的其他成员提供他们在前一天所做的工作以及所取得的进展的最新信息。 此外,每个团队成员都将透露他们今天计划做的事情,以及最后但并非最不重要的任何障碍,尤其是那些会阻碍任务进一步发展的障碍。

日常Scrum会议通常是“实时”进行的,但是对于具有不同时区和/或不同位置的远程团队而言,这可能会带来问题。 这就是我们制造的机器人进来的地方。

Configurator GUI

先决条件:

  • 节点JS
  • npm
    • botbuilder
    • 重新调整
    • fs-extra
  • JavaScript(ES6)
  • 的HTML
  • 约曼发电机
    • 发生器电子

僵尸程序和配置程序的所有代码都可以在本文随附的存储库中找到 。

样板

如果您不熟悉Electron,最好阅读一下这篇文章 (至少介绍性的段落),该文章描述了Electron的基础知识以及它迅速流行的原因。 即将出现的许多新的桌面应用程序都在使用Electron (例如Slack,Visual Studio Code)。

要设置样板代码,我们将使用Yeoman生成器 。

转到要您的项目驻留的文件夹,然后运行以下命令

npm install -g yo generator-electron

这将在您的计算机上全局安装Electron软件包。 从这一点开始,您可以在任意位置调用电子发生器,这是我们的下一步:

yo electron

这将为您提供运行“ Hello World” Electron应用程序所需的所有文件。 它将自动运行npm install ,因此,在Yeoman完成后,您可以运行:

npm start

并且您应该看到一个新的应用程序窗口弹出。

入口点

index.js是应用程序的入口点。 我建议您打开该文件,然后自己看看是否发生了什么。

function createMainWindow() {const win = new electron.BrowserWindow({width: 600,height: 400});win.loadURL(`file://${__dirname}/index.html`);win.on('closed', onClosed);return win;
}

createMainWindow()将通过调用BrowserWindow类的构造函数来创建主窗口(显然是上尉),在这里您可以提供一些窗口选项,例如宽度,高度,背景颜色等等 。

此函数中要注意的重要事项是win.loadURL方法。 为什么这很重要? 在这里,我们可以看到应用程序的内容实际上只是HTML文件而已! 没有魔术,也没有新功能或框架来学习制作桌面应用程序。 它所需要的只是Web开发人员的专业知识,因此也使我们所有Web开发人员都成为了桌面应用程序开发人员!

const app = electron.app;app.on("window-all-closed", () => {// ...
});app.on('activate', () => {// ...
});app.on('ready', () => {// ...
});

Electron为我们提供了事件的回调,请参见此处的完整列表。

  • ready –如果您熟悉jQuery,则ready事件将类似于jQuery(document).ready()

  • 启动 -启动发出的每个应用程序窗口投入集中时间。

  • windows-all- closed-在关闭应用程序的所有窗口时触发,这使得它可以进行任何清理。 请谨慎使用此代码,因为在某些情况下它不会被调用 (例如,如果您从代码中调用app.quit() ,或者用户按下了Cmd + Q)。

应用逻辑

入口点文件index.js包含应用程序启动和退出的特定代码,并且更用于全局设置。 我们不在此放置应用程序逻辑。 正如我们已经看到的,应用程序本身就是一个HTML文件。 因此,让我们进入index.html并为配置器GUI添加一些元素。

<!doctype html>
<html><head><meta charset="utf-8"><title>Electron boilerplate</title><link rel="stylesheet" href="index.css"></head><body><div class="container"><section class="main"><h2>Teams</h2><div><select id="teams"><option>Select a team...</option></select><input type="text" id="newTeamName" placeholder="New team name..."/><button id="addTeam" disabled type="button">+</button></div><div id="members"></div><button id="addMember" type="button">+</button><p id="message"></p><button id="save" type="button">Save</button></section><footer></footer></div><script src="app.js"></script></body>
</html>

用此代码替换当前的HTML文件。 在正文的最后,我们添加了对app.js脚本的引用,这是我们的应用逻辑所在。 请记住,Electron窗口不过是嵌入其中的浏览器窗口,因此在开发过程中,您可以使用标准快捷方式来重新运行代码(F5,Ctrl + R)并打开类似Chrome的开发人员工具(F12)。

在项目的根目录中添加一个新文件,将其命名为app.js ,然后从此处粘贴代码。 这里没有新的事情发生,只有好的旧JavaScript。

对于持久数据,我们将使用一个简单的JSON文件,足以满足我们的需求。 如果您想扩展应用程序,则必须用数据库解决方案代替。

有一个用于添加新团队的按钮,然后在每个团队内部我们可以添加成员。 每个成员在Skype上均以其用户名表示。 稍后,当我们开始制作机器人本身时,您会看到机器人模拟器内置了一个聊天客户端,用于测试。 该用户的用户名是user

另外,我们可以通过从下拉列表中选择团队名称来加载团队。 在每个团队的底部,都有一个输入框,表示我们应该进行每日Scrum会议的一天中的时间。 我们将此值保存为时间戳,表示从午夜到会议时间的秒数。

现在让我们启动配置器,并尝试添加一个团队和一个名为“ user”的用户。

现在,我们可以从下拉列表中选择添加的团队,并向其中添加一些用户。

重要说明:您必须添加具有用户名user的用户,因为仿真器无法更改名称,而该名称是硬编码的。 为了使机器人能够在测试时识别我们,它必须是user

将时间设置为00:00(或其他时间),然后点击保存

检查您的teams.json文件,这应该是其内容:

{"alpha": {"members": {"user": {},"almir bijedic": {}},"time": 0}
}

稍后将由机器人使用。

机器人

Microsoft Bot框架

MBF SDK有两个版本:C#和Node.js。 我们将使用Node版本。 该机器人通过REST API工作 ,您可以手动调用它,也可以使用提供的开源SDK 。 在本教程中,我们将使用SDK,因为它要快得多。 如果需要将机器人与现有应用程序集成在一起,或者由于某种原因而无法使用Node.js / C#,则使用自定义函数调用API 可能是一个更好的选择。

要在本地测试该机器人,有两种选择:

  1. 使用ConsoleConnector ,它允许您通过命令行与机器人对话,或者
  2. 将ChatConnector类与restify (或其他方式)一起使用以运行本地服务器,并运行Microsoft提供的bot仿真器,该仿真器充当本地计算机上的虚拟用户。

我们将选择第二个选项,即“更真实”。

路线

构建聊天机器人的主要类称为UniversalBot 。 值得一提的是, UniversalCallBot也存在,它可以让您进行呼叫,但是在本教程中我们不会对此进行介绍。 此外,聊天机器人的重点是允许用户无需调用即可进行交互,因为似乎我们更喜欢发短信而不是call 。

为了确定漫游器如何回答来自用户的传入消息,我们使用路由。 这与常规的Web应用程序非常相似,例如:

// bot is an instance of UniversalBot
bot.dialog("/", function (session) {session.send("Hello World");
});

请注意,这里的botUniversalBot类的实例。

每次用户向机器人发送任何消息时,这都会向用户发送“ Hello World”。

bot.dialog()具有两个参数:路由,以及在该路由处于活动状态时执行的函数。 在瀑布模型对话框的情况下(瀑布将在下一节中说明),第二个参数可以是一个函数数组 ,然后将依次执行另一个函数,从而与用户进行交互。

最初设定

现在将是一个很好的尝试时间。 回到您的Electron项目,并在名为bot内部添加一个新文件夹。 在该文件夹内运行npm init并填写基本信息,您唯一需要输入的内容就是app.js作为入口点, node app.js作为开始脚本。 完成后,在bot文件夹的根目录中创建一个新文件app.js

现在,我们需要为我们的机器人安装依赖项。

npm install --save botbuilder restify fs-extra

接下来,转到我们在bot文件夹中创建的app.js文件,并包含我们需要的库。

// app.jsvar restify = require("restify"),builder = require("botbuilder"),fse = require("fs-extra");

我们需要创建一个Restify服务器,该服务器将侦听某个端口上的传入连接。

// app.js// Setup Restify Server
var server = restify.createServer();
server.listen(process.env.port || process.env.PORT || 3978, function () {console.log("%s listening to %s", server.name, server.url);
});

现在,我们将把Restify服务器连接到MBF bot REST服务。

// Create chat bot
var connector = new builder.ChatConnector({appId: process.env.MICROSOFT_APP_ID,appPassword: process.env.MICROSOFT_APP_PASSWORD
});
var bot = new builder.UniversalBot(connector);
server.post("/api/messages", connector.listen());

您可以将MICROSOFT_APP_IDMICROSOFT_APP_PASSWORD环境变量用于Node以提供您的登录凭据。 用于对Microsoft Bot目录进行身份验证。

注意: ChatConnector的替代方法ConsoleConnector ,它将在正在运行的应用程序的控制台中要求输入。 这种方法不需要我们稍后要安装的模拟器

最后但并非最不重要的一点是,在根路由上添加一个简单的对话框,该对话框仅输出“ Hello World! 给用户。

bot.dialog("/", function(session) {session.send("Hello World!");
});

让我们从ChatConnector角度来看这一切是如何工作的,因为这可能会使我们在使用ChatConnector进行操作时有些困惑,以及为什么我们需要重新调整服务器。

用户将您的漫游器添加为Skype联系人。

  1. 用户从他们的Skype客户端向机器人发送消息。 该消息将发送到Skype的服务器,然后路由到您先前注册的机器人。
  2. 在注册过程中,您为bot提供了一个https端点,该端点指向运行bot代码的服务器。 因此,Skype的服务器将消息的所有详细信息转发到您的Restify服务器。
  3. ChatConnector从Restify服务器接收此请求并相应地处理它(按您的预期)。
  4. 然后,Bot Framework SDK会根据您的需求生成响应并将其发送回服务器。 注册期间,您指定了APP ID和密码,以便您的机器人访问Skype服务器。 该机器人在步骤2中收到了REST API的位置以及消息。
  5. Skype的服务器识别响应并将消息转发给用户。

为了测试我们刚刚制作的这个简单的机器人,我们必须下载并安装模拟器,该模拟器既充当客户端Skype应用程序(用户),又充当Skype REST API服务器,这是上图的左侧。

转至仿真器页面并下载,安装和运行它。

现在,我们需要为模拟器提供运行我们的机器人代码的端点。

返回bot文件夹并运行npm start 。 您应该会看到以下内容:

restify listening to http://[::]:3978

您可以通过提供PORT Node环境变量或通过在文件开头更改硬编码回退值3978来更改此端口。

这是本地主机上端口3978上的端点。因此,我们将其放入仿真器中。 此外,别忘了我们在/ api / messages路由上进行监听。

将Microsoft应用ID和密码保留为空; 由于我们在本地运行测试,因此不需要这样做。 单击连接

现在您可以尝试该机器人了。 您将始终收到Hello World消息,因为这是我们到目前为止已配置的全部。

我们将需要一个比这更聪明的机器人。 在下一部分中,我们将实现以下路线:

  • / –仅当已经注册的用户在Scrum会议之间向机器人发送消息时,才使用根对话框路由。 我们添加它的唯一目的是向用户显示正在发生的事情,并且即使我们不在Scrum会议或注册中,该机器人仍在侦听。
  • /firstRun –我们需要以某种方式注册用户并保存其地址,以便以后能够向他们发送消息。
  • /dailyScrumDialog –将使用setInterval()运行一个计时器,该计时器将检查所有团队的每日站立会议的时间。 如果有一个小组的会议时间到了,请查找所有在该bot中注册的用户(通过注册,我们表示已经在配置器中添加到该团队中的用户,并且他们还将该bot作为Skype上的联系人添加了并且他们已经向漫游器发送了至少一条消息)。
  • /report –这里最简单的对话框,仅用于将会议报告发送给团队的所有成员。 这将由另一个运行setInterval()函数来触发,该函数检查团队中的每个成员是否都已完成对三个问题的回答。 如果是,请将每个人的答案发送给每个团队成员。

瀑布

瀑布是最基本的bot对话类型。 它确实像听起来的那样:它顺流而下,不回头。 我们将函数数组作为第二个参数传递给机器人的dialog函数。 在上一步有提示的情况下,每个功能都会一个接一个地执行。

builder.Prompts.text(session, "Message to send")是从用户请求输入的主要方式。 用户响应后,将执行数组中的下一个函数。 这次它有两个参数:会话对象和包含用户消息的结果对象。

bot.dialog("/", [function (session) {builder.Prompts.text(session, "Hey there, how are you doing?");},function (session, results) {console.log(results.response); // This will print out whatever the user sent as a messagesession.send("Great! Thank you for letting me know.")}
]);

用新对话框替换以前的根对话框,然后尝试一下。

请注意,我们还可以保存和保留用户数据。

bot.dialog("/", [function (session) {if (session.userData.howIsHe) {session.send(session.userData.howIsHe);} else {builder.Prompts.text(session, "Hey there, how are you doing?");}},function (session, results) {session.userData.howIsHe = results.response;session.send("Great! Thank you for letting me know.")}
]);

运行此命令将保存用户的响应,然后在每条下一条消息上向他们发送响应。

对话框堆栈

如前所述,该漫游器通过对话框来组织聊天。 与用户的对话开始后,机器人将默认对话框推入堆栈顶部。 然后,我们可以使用以下功能之一重新路由到其他对话框和/或结束它们。

session.beginDialog(route,args,next)

此函数停止当前对话框,将具有指定路由的对话框添加到堆栈顶部,一旦完成新调用的对话框,它将返回到上一个对话框中beginDialog()位置。

session.endDialog()

当我们调用endDialog() ,当前对话框将从堆栈中弹出,然后返回到堆栈上的下一个对话框。

session.endDialogWithResult(args)

endDialog()相同,不同之处在于我们可以传递一些变量以供调用对话框(堆栈中的下一个对话框)使用。

session.replaceDialog(route,args,next)

如果我们希望一旦新一个完成返回到先前的对话框,我们可以使用replaceDialog()代替beginDialog()

session.cancelDialog(dialogId,replaceWithId,replaceWithArgs)

取消对话框将导致对话框从堆栈中弹出(取消),直到到达具有提供的ID的对话框为止,然后对话框也将取消,并将控制权返回给原始调用者。 然后,该调用者还可以检查results.resumed变量以检测取消。

此外,除了返回原始调用方外,还可以通过提供对话框的ID来替换它。

session.endConversation()

这是取消所有对话框的便捷方法。 基本上就像调用session.cancelDialog(0) (0是堆栈中第一个对话框的ID,因此所有对话框将被取消)。 当您还想清除用户的会话数据时,这非常方便。

首次运行中间件

在用户启动与僵尸程序的对话之前,僵尸程序无法与Skype用户交谈(或与此有关的任何其他聊天平台-不要忘记MBF与多个聊天客户端配合使用)。 有道理不是吗? 主要是为了避免垃圾邮件。

为了能够启动对话框,我们需要用户的地址(包含用户ID和对话ID的对象),因此,我们需要某种先运行逻辑来存储用户的地址供以后使用。

MBF为我们提供了一个中间件,我们可以使用该中间件来指示我们要将用户定向到第一次启动对话框的路径。

var version = 1.0;
bot.use(builder.Middleware.firstRun({ version: version, dialogId: "*:/firstRun" }));

这将引导用户首次注册到“ firstRun”路由,然后我们必须对其进行定义。

bot.dialog("/firstRun", [function (session, args) {if (session.userData.user && session.userData.team) {session.userData["BotBuilder.Data.FirstRunVersion"] = version;session.replaceDialog("/dailyScrum");} else {builder.Prompts.text(session, "Hello... What's your team name?");}},function (session, results) {// We'll save the users name and send them an initial greeting. All// future messages from the user will be routed to the root dialog.var teams = readTeamsFromFile();var providedTeamName = results.response.toLowerCase();var user = session.message.user.name.toLowerCase();if (teams[providedTeamName] && Object.keys(teams[providedTeamName].members).indexOf(user) > -1) {teams[providedTeamName].members[user].address = session.message.address;writeTeamsToFile(teams);session.userData.user = user;session.userData.team = providedTeamName;session.send("Hi %s, you are now registered for the %s team daily scrum. We will contact you at the time of the meeting, which is at %s", user, providedTeamName, timeToString(teams[providedTeamName].time));} else {session.send("Wrong team! Try again :D (%s)", user);session.replaceDialog("/firstRun");}}
]);function readTeamsFromFile() {return fse.readJsonSync("./data/teams.json");
}function writeTeamsToFile(teams) {fse.outputJsonSync("./data/teams.json", teams);
}function timeToString(time) {return pad(parseInt(time / 60 / 60 % 24)) + ":" + pad(parseInt(time / 60) % 60)
}function pad(num) {var s = "0" + num;return s.substr(s.length - 2);
}

我们在第二个参数数组中提供了两个函数,这些函数将被顺序调用。 用户提供对第一个的响应后,将调用第二个。 在这种情况下,我们使用builder.Prompts.text(session, message))提示用户输入名称,然后在下一个中,通过使用团队名称搜索JSON处理提供的团队名称。 如果找到了团队名称,我们会将用户的名称添加到JSON并发送一条消息,通知用户他现在已经注册,并会在Scrum时间提示。

除了/ firstRun对话框,我们还有一些帮助程序功能。

readTeamsFromFile()将从JSON readTeamsFromFile()文件返回一个JSON对象。

writeTeamsTofile()将一个对象作为参数(在本例中为JSON团队)并将其写回到磁盘。

timeToString将UNIX时间戳记作为参数,并以字符串形式返回解析的时间。

pad用于将其他零附加到字符串(例如1小时3分钟应为01:30,而不是1:30)。

将前两个代码段添加到我们的bot/app.js ,并添加以下代码以包含npm中的fs-extra库,让我们尝试一下。

var restify = require("restify"),builder = require("botbuilder"),fse = require("fs-extra");

通过仿真器发送消息之前,请确保退出仿真器并重新启动它(仿真器的Delete User Data功能有一个错误)。

现在,您可以进入data/teams.json文件,您将看到我们已将仿真器用户的地址另存为一个对象。

{"alpha": {"members": {"user": {"address": {"id": "3hk7agejfgehaaf26","channelId": "emulator","user": {"id": "default-user","name": "User"},"conversation": {"id": "5kaf6861ll4a7je6"},"bot": {"id": "default-bot"},"serviceUrl": "http://localhost:54554","useAuth": false}}},"time": 0}
}

我们还应该使用根对话框来做一些更有意义的事情。 一旦用户完成/firstRun ,我们应该输出某种消息以使用户知道正在发生的事情。

bot.dialog("/", function(session) {// this is a hack in order to avoid this issue// https://github.com/Microsoft/BotBuilder/issues/1837if (!session.userData.team || !session.userData.user) {session.replaceDialog("/firstRun");} else {session.send("Hello there, it's not yet scrum time. I'll get back to you later.");}
});

中间件

首次运行的中间件只是普通的中间件,与其他任何中间件一样,默认情况下在框架中实现。 我们还可以创建一个自定义的中间件功能。 在与Skype用户聊天期间,对话ID可能会更改,因此,我们希望在从用户收到的每条消息上更新地址(包含对话ID)。 该地址将随每条消息一起传递,因此让我们将其添加到我们的app.js

bot.use({botbuilder: function (session, next) {if (session.userData.team && session.userData.user) {var teams = readTeamsFromFile();teams[session.userData.team].members[session.userData.user].address = session.message.address;writeTeamsToFile(teams);}next();}
});

我们通过使用UniversalBot类的use函数添加中间件。 它必须包含一个带有botbuilder键的对象,该对象的值是一个带有两个参数的函数:会话和next函数。

我们通过检查会话的userData对象中是否设置了team和user变量来检查是否已经注册了该用户。 如果是,请使用新地址更新JSON文件中的地址。

计时器

下一步是添加一个功能,该功能将每隔x秒检查是否有一个团队的每日Scrum会议时间到了。 在会议即将召开的情况下,如果我们有地址(用户已通过“ / firstRun”注册),则通过与团队中的每个成员发起对话来开始与团队中的每个成员的“ / dailyScrum”路线。 如果没有地址,那么很遗憾,我们必须跳过此用户,仅在第一次运行完成时提示他们。

setInterval(function() {var teams = readTeamsFromFile();Object.keys(teams).forEach(function(team) {if (shouldStartScrum(team)) {teamsTmp[team] = { members: {} };Object.keys(teams[team].members).forEach(function(member) {if (teams[team].members[member].address) {bot.beginDialog(teams[team].members[member].address, "/dailyScrum", {team, member});}});}});
}, 3 * 1000);function shouldStartScrum(team) {var teams = readTeamsFromFile();if (teams[team].time < 24 * 60 * 60 && getTimeInSeconds() > teams[team].time) {var nextTime = Math.round(new Date().getTime()/1000) - getTimeInSeconds() + 24 * 60 * 60 + teams[team].time;teams[team].time = nextTime;writeTeamsToFile(teams);return true;} else if (Math.round(new Date().getTime()/1000) > teams[team].time) {var nextTime = 24 * 60 * 60 + teams[team].time;teams[team].time = nextTime;writeTeamsToFile(teams);return true;}return false;
}function getTimeInSeconds() {var d = new Date();return d.getHours() * 60 * 60 + d.getMinutes() * 60;
}

我们还必须在文件顶部添加teamsTmp全局变量,以便将团队中每个成员的答案保留在内存中以生成报告。

var teamsTmp = {};

请注意shouldStartScrum函数,该函数检查时间戳记是否在JSON文件中,该文件充当我们在Electron配置器和bot之间的存储和链接。 我不建议将其用于生产环境。 这仅是为了本教程的目的,是为了显示Bot Framework的功能而制作一个简单的调度程序。

每日Scrum对话框

到目前为止,我们已经掌握了所有知识,这很简单,那就是在行中添加另一个包含三个问题的瀑布对话框,并将每个答案的数据保存到一个临时变量中,以便稍后我们可以生成报告。 这是由先前创建的计时器启动的对话框。

/* Add a dailyScrum dialog, which is called when it's a time for a daily scrum meeting, prompting the user in a waterfall fashion dialog */
bot.dialog("/dailyScrum", [// 1st question of the dailyfunction (session) {builder.Prompts.text(session, "What did you do yesterday?");},/* After the users answer the 1st question, the waterfall dialog progresses to the next function, with the 2nd question, but checking that the input for the previous question was not an empty string. If yes return the user to the first question by calling replaceDialog */function(session, results) {if (results.response.length > 0) {teamsTmp[session.userData.team].members[session.userData.user] = { q1: results.response };builder.Prompts.text(session, "What will you do today?");} else {session.send("It can't be that you did nothing %s! Let's try this again.", session.userData.user);session.replaceDialog("/dailyScrum");}},// 3rd questionfunction(session, results) {teamsTmp[session.userData.team].members[session.userData.user].q2 = results.response ;builder.Prompts.text(session, "Are there any impediments in your way?");},/* Finalize and schedule a report for the user. After the user has answered the third and last daily scrum question, set the isDone variable for that user to true */function(session, results) {teamsTmp[session.userData.team].members[session.userData.user].q3 = results.response;teamsTmp[session.userData.team].members[session.userData.user].isDone = true;session.send("Got it! Thank you. When all the members finished answering you will receive a summary.");/* If the user is the first to finish for the team, create a checker function for the whole team, whichwill periodically check whether everyone from the team finished, if yes, send all the users in the teama report */if (!teamsTmp[session.userData.team].checker) {teamsTmp[session.userData.team].checker = setInterval(function() {if (isEverybodyDone(session.userData.team)) {teamsTmp[session.userData.team].isDone = true;clearInterval(teamsTmp[session.userData.team].checker);var teams = fse.readJsonSync("./data/teams.json");Object.keys(teamsTmp[session.userData.team].members).forEach(function(member) {bot.beginDialog(teams[session.userData.team].members[member].address, "/report", { report: createReport(session.userData.team) });});session.endDialog();}}, 1000);}session.endDialog();}
]);function isEverybodyDone(team) {var everybodyDone = true;Object.keys(teamsTmp[team].members).forEach(function (x) {if (!teamsTmp[team].members[x].isDone) {everybodyDone = false;}});return everybodyDone;
}function createReport(team) {// change to membersvar report = "_"+ team + "_<br />";report += "___________<br />";Object.keys(teamsTmp[team].members).forEach(function(member) {report += "**User:** " + member + "<br />";report += "**What did " + member + " do yesterday:** " + teamsTmp[team].members[member].q1 + "<br />";report += "**What will " + member + " do today:** " + teamsTmp[team].members[member].q2 + "<br />";report += "**Impediments for " + member + ":** " + teamsTmp[team].members[member].q3 + "<br />";report += "___________<br />";});return report;
}

要格式化消息,您可以使用markdown。

将其添加到bot.use(builder.Middleware.firstRun ...

请注意,在每日Scrum对话的最后,我们使用setInterval()添加了另一个函数,该函数在团队的第一个成员完成时将开始跟踪团队中的其他所有人是否都已完成回答。 完成每个人的工作后,它将与每个团队成员开始一个新的对话框,并向他们发送生成的报告,该报告将添加为我们的最后一个对话路径。

bot.dialog("/report", function(session, args) {session.send(args.report);session.endDialog();
});

请注意,我们将报表作为参数传递给begin对话框函数,然后可以从调用的对话框中的args参数中再次读取该报表。

演示版

现在该尝试一下了。 我建议您退出并重新启动仿真器和bot脚本,以确保重置用户数据并且脚本中的最新代码正在运行。

此外,请在JSON文件中更改Scrum的时间,以便确保触发会议,而不是等待先前保存的下一次时间。

尝试对机器人说些什么,它会提示您输入团队名称。

启动模拟器或类似操作时,scrum的时间已“过去”,因此,如果模拟器没有立即提示您出现问题,请设置时间(直接在JSON文件中或通过Electron配置器)设为0,这将迫使漫游器今天再次开始会议。

更改此设置后,应立即通过3步瀑布式每日Scrum对话框提示您。

为了与多个用户一起尝试,我们必须将其部署在能够通过SSL提供服务的服务器上,因为这是Microsoft Bot Directory的要求。

下一步

我们只是真正地了解了MBF所能提供的功能。 以下是一些值得进一步研究的内容,可以使您的机器人更上一层楼。

路易斯

Microsoft Bot Framework提供的功能远不止于此。 一些有趣的事情包括LUIS(语言理解智能服务) ,该语言使用从Cortana和BING中获取的数据来生成试图理解用户想要说的AI的人工智能。

意图对话框

意图对话框是一个更简单的示例,它与我们使用的普通对话框相似,但是代替路由,它们使用了正则表达式作为第一个参数。 基于正则表达式,您可以尝试发现用户的意图,并对识别出的意图做一些特定的事情。 例如:

// example from https://docs.botframework.com/en-us/node/builder/chat/IntentDialog/
var intents = new builder.IntentDialog();
bot.dialog("/", intents);intents.matches(/^echo/i, [function (session) {builder.Prompts.text(session, "What would you like me to say?");},function (session, results) {session.send("Ok... %s", results.response);}
]);

我发现非常有用的是Microsoft提供的示例存储库:

https://github.com/Microsoft/BotBuilder-Samples

那就是所有的人

我们已经介绍了Electron,Scrum,bot框架的对话框堆栈,对话框的瀑布类型,消息传输中间件的基础知识,以及如何在没有用户初始请求的情况下与用户随机地发起对话框。

感谢您关注本教程。 将来,我们将看到越来越多的聊天机器人(希望不会太多吗?!)。 如果您有任何意见,建议或问题,请在下面发表评论。

本文由Vildan Softic和Camilo Reyes进行了同行评审。 感谢所有SitePoint的同行评审人员使SitePoint内容达到最佳状态!

From: https://www.sitepoint.com/skype-bot-electron-microsoft-bot-framework/

使用Electron和Microsoft Bot Framework制作Skype Bot相关推荐

  1. electron 图标制作_使用Electron和Microsoft Bot Framework制作Skype Bot

    electron 图标制作 聊天机器人越来越受欢迎. Facebook正在致力于提供一个构建Messenger机器人的框架,该框架将允许企业所有者完全在Facebook的消息传递应用程序内部建立其客户 ...

  2. 如何将 Microsoft Bot Framework 链接至微信公共号

    说到 Microsoft Bot Framework 其实微软发布了已经有一段时间了,有很多朋友可能还不太了解,微软Bot的功能今天我给大家简单的介绍一下,Bot Framework的开发基础以及如何 ...

  3. Microsoft Bot Framework 上手

    因为这前使用过MS Bot Frameowrk 做过开发, 最近心血来潮想做(挖坑)一个小的bot. 今天带领大家使用MS Bot Framework创建Hello World. 首先,我们要创建项目 ...

  4. 使用Bot Service创建Bot Framework

    创建Bot Service:进入至Azure控制台中,新建Bot Service,如不知道Bot Service在哪个选项中,可以先查找Bot Service再创建 在弹出的查询结果中,选择Bot S ...

  5. Microsoft .NET Framework 4.6.1

    适用于操作系统平台:Windows 7 SP1.Windows 8.Windows 8.1.Windows 10.Windows Server 2008 R2 SP1.Windows Server 2 ...

  6. .net framework 4.0安装_Win 7无法安装Microsoft .NET Framework 4.6.2

    Win 7无法安装Microsoft .NET Framework 4.6.2 造冰箱的大熊猫@cnblogs 2018/9/6 在Windows 7 64位计算机上安装某个软件时,安装程序提示需先安 ...

  7. IIS异常:CS0016: 未能写入输出文件“c:\WINDOWS\Microsoft.NET\Framework\.。。”--“拒绝访问...

    CS0016: 未能写入输出文件"c:/WINDOWS/Microsoft.NET/Framework/v2.0.50727/Temporary ASP.NET Files/........ ...

  8. 没有对“C:/WINDOWS/Microsoft.NET/Framework/v2.0.50727/Temporary ASP.NET Files”的写访问权限...

    没有对"C:/WINDOWS/Microsoft.NET/Framework/v2.0.50727/Temporary ASP.NET Files"的写访问权限. 出现此问题,在网 ...

  9. 使用 Microsoft .NET Framework 精简版中的 MessageWindow 类

     使用 Microsoft .NET Framework 精简版中的 MessageWindow 类 收藏 Alex Yakhnin IntelliProg, Inc. 2003年3月 适用于:    ...

  10. You must use the Role Management Tool to install or configure Microsoft .NET Framework 3.5 SP1

    今天在Windows Server 2008 下安装SQL SERVER 2008时,碰到如下错误: You must use the Role Management Tool to install ...

最新文章

  1. 2019成考计算机几时出成绩,2019年成人高考成绩什么时候出来?如何查询
  2. openlayers之style符号化
  3. ubtunu打开firefox_如何在Firefox(在Lubuntu中)中打开“apt”链接?
  4. 【语音增强】基于matlab GUI维纳滤波语音增强【含Matlab源码 298期】
  5. MySql绿色版安装和配置
  6. ie11无法使用,卸载后无法安装,错误代码0x8000ffff
  7. Wondershare Flash Gallery Factory
  8. 计算机怎么搜索隐藏的网络,电脑如何连接隐藏wifi 笔记本电脑如何添加隐藏wifi?-192路由网...
  9. 计算机 睡眠 无法打印,台式机睡眠后打不开怎么办
  10. uhuntu五笔输入法fcitx安装
  11. 如何入职京东、华为、IBM等大厂?你需要学懂这门语言
  12. 互联网晚报 | 1月24日 星期一 | 快手与11家省市春晚达成合作;京东首个数字人客服芊言上岗;拉菲虎年限定红酒上线虹宇宙...
  13. linux 下跑通pointnet++网络模型
  14. 全球7大经典火车地铁营销案例
  15. OSChina 周二乱弹 —— 金 冈刂 犭良
  16. 机原自检——第4章 平面机构的力分析
  17. 刷个openwrt,并加入改写的802.1X认证客户端(iNode认证)
  18. 依托EcoStruxure架构 施耐德电气发力数据中心全面创新
  19. linux内核 can总线,Linux Canbus调试笔记
  20. html5 矢量 插件,Sketchpad:HTML5创作工具

热门文章

  1. 中科大一所学校撑起中国人工智能半壁江山
  2. 嵌入式学习笔记-迅为4412开发板实现一键开关机休眠唤醒
  3. 爱在心中【tarjan + 缩点】
  4. 2021年百度智能云服务器最新租用价格表
  5. 转行软件测试两个多月,感觉很迷茫,下一步该如何提高自己?
  6. mysql如何还原数据库
  7. centos6.5重置密码
  8. 向量积(叉积)和数量积(点积)的区别和联系之解析
  9. hmailserver mysql密码_mysql+hmailserver+roundcube修改密码
  10. java nginx 502_Nginx 502 Bad Gateway错误的解决方案