Microsoft Bot Framework with LUIS
今年微软的编程之美的主题是“对话即平台”,“人工智能”,要求参赛选手用到Bot Framework与Cognitive Services。
大多数人应该对这两个技术都不怎么熟悉吧,我就在这里写写自己所学会的一点东西,带大家调用LUIS做一个简单的Bot聊天机器人。
打开浏览器,直接搜索Bot Framework,进入官网,点击Documentation,进入如下页面。
把滚动条拉到页面最底下,点击Downloads,进入下载页面
然后我们需要下载的就是Visual Studio Template C# 和Bot Framework Emulator。
下载好Emulator后直接运行安装即可。
(注意要用管理员权限,不然可能会出现每次想打开Emulator都必须重新安装的BUG)。
安装好后它的图标是这样:
下载好C# template以后,我们需要把它复制粘贴到vs2015的相应模板文件里。
一般情况下,这个路径是:我的电脑->我的文档->Visual Studio2015->Templates->ProjectTemplates(注意是“ProjectTemplate”,很多人都误以为ItemProject)->Visual C#
然后我们把sdk粘贴到这里就好了,不用解压。
现在打开vs2015,新建项目,选择C#语言:
拉到最下面,我们会发现多了Bot Application。选择这个模板,创建。
这个模板已经帮我们做好了很多东西,我们先不修改它,直接点击编译。
选择一个你习惯的浏览器(我喜欢chrome),然后点击运行。
这是浏览器会跳转出一个基本页面
把窗口最小化,双击运行Bot Emulator
打开后,最上方的输入窗口会提示你输入Endpoint Url。
回到浏览器显示的那个网页,把那个网页的地址粘贴到最上方的输入窗口。大多数默认的都是:
然后记得要在这个地址后面加上:“/api/massages”。
因为我们现在是本地调试,且对bot 模板内容没有修改,所以下方出现的app ID和app password我们都可以留空不去管它们,直接点击CONNECT。
然而很遗憾,我们会在右下角的log窗口会看到:POST connectECONNREFUSED 127.0.0.1:3979
这个错误是因为我国伟大的防火墙。。。((lll¬ω¬))
就如同因为我国防火墙的存在,你不能直接访问google页面一样,我们也无法直接访问bot终端。而且挂vpn并不能解决这个问题。这个时候就需要ngrok的帮助了。
我们可以把ngrok当成一个链接外面世界和墙内网络的管道,访问bot时,可以通过这个管道访问。
我们先在vs里把运行的程序停止。
然后打开浏览器,输入ngrok,搜索。
找到其官方下载页面,下载ngrok。
进入ngrok的下载路径,解压,运行EXE文件。
这是一个命令行应用程序,直接输入:”ngrok.exe http 80”。
然后就会出现这个界面,你的状态是online说明成功了。
接下来我们重新运行Bot程序,重复我之前所说的操作,在BotEmulator里点击CONNECT:
漂亮,这次的返回值是200,连接成功了!
我们试着在文本输入窗口输入一些东西,比如:你好!
Bot自动回复我们的是:你输入了“你好”,你的输入共2个字符。
(这个回复真是。。。笨笨的(ˉ▽ˉ;)…)
回到vs,先停止程序,然后我们打开RootDialog.cs文件。
为了不让回复那么蠢,我们在MessageReceivedAsync这个函数里用如下代码替换原来的代码:
var activity = await result asActivity;
if (activity.Text.Contains("你好"))
{
await context.PostAsync("你好,老铁");
}elseif(activity.Text.Contains("你叫什么名字"))
{
await context.PostAsync("你就叫我特浪扑吧");
}elseif(activity.Text.Contains("你有对象吗"))
{
await context.PostAsync("不要问这么悲伤的问题啊!扎心了,老铁。。。");
}else
{
await context.PostAsync("你在用脸滚键盘么。。。你发的我看不懂");
}
// calculatesomething for us to return
int length = (activity.Text ??string.Empty).Length;
// return ourreply to the user
await context.PostAsync($"You sent{activity.Text} which was{length} characters");
context.Wait(MessageReceivedAsync);
截个图让大家看的更明白一点:
编译,运行,然后按照我们代码里写的套路在对话框里输入:
很尴尬,我们只能按照提前预设好的套路和bot交流,一旦超出预设的输入,程序就会执行else里的代码,很无语的回复,使我们的用户体验非常不好。
如果要实现用户和bot的简单交流,我们得敲成千上万个if-else语句。等你写出来,黄花菜都凉了。而且这样的代码很不美观,太Low了。
为了提高Bility和效率,接下来我们就要用到LUIS服务了。
Luis全称为:language understand intelligent servis。它利用已经写好的算法,跑神经网络来准确地识别用户的输入。
在浏览器地址栏里输入:luis.ai/
点击登陆。这个是要用microsoft 账户的,还没有的话就快去申请一个。
如果你是初次登陆的话,就会跳转到这样的欢迎界面,按照提示把相关信息填好,accept一些条款,然后continue。
在这个界面,点击NewApp 来创建我们的luis App。
我们给这个app取一个名字,就叫“Niu Bility“好啦。Culture选项,指的是这个app要处理什么语言,这里我们选择中文。在描述部分,我们就随便写写就好了。
在Key to use 这栏,我们选择BootstrapKey,这个可以免费试用30天。最后create!
(注:如果你的account是刚注册的,可能不会出现BootstrapKey,没关系,我们可以以后再管,这时就保留默认就好)
在我们开始构建这个app之前,我们先用一个简单通俗的例子搞懂一些术语:
例句:我想去电影院
对于上面的例子,LUIS把它分为几个部分:
Entities:电影院
Intents:去电影院
Utterance:我想去电影院。
所以,Entities指的是用户具体指代的事物;Intents就是用户的意图、目的;Utterance是用户输入的一段话。
现在我们添加一个Intent:打招呼。
不同人打招呼的方式不尽相同,所以我们要考虑到很多种打招呼的方式,也就是要创建多种不同的Utterance:
点击save,然后再添加一个Intent:询问名字,想一些不同的问名字的语句,save:
我们还可以添加一个讲笑话的Intent。还想添加其他更多Intent的话,就由大家自己去想咯。
(需要提及的是,在intent中会有一个默认的None Intent,这个就相当于我们一开始写的else。因为我们无法完全预知用户的所有意图,所以当Luis经过计算发现没有意图和用户的输入匹配时,它就会返回None这个意图。)
当我们把Intent和Utterance都创建好后,就需要训练我们的app了,让他明白我们刚才输入的Utterance对应的Intent是什么。点击Train!
训练好以后,就可以发布了。在publish页面,点击publish!记得发布的时候,需要在EndPoint Key这里要改为BootstrapKey。
Perfect,我们的app就可以在bot里调用了。
我们此时要先记下两个东西:appID和key。
这两个东西一会儿我们要用到的。先回到vs,在项目名称附近右键,添加一个class,名称为:LuisDialog
下面是代码:
代码里,写“you app id“,”key“ 的地方要替换为刚才记下的那两个app ID和key。
using Microsoft.Bot.Builder.Dialogs;
using Microsoft.Bot.Builder.Luis;
using Microsoft.Bot.Builder.Luis.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Web;
namespace Bot_Application1
{
[LuisModel("your app id","key")]
[Serializable]
publicclassLuisDialog:LuisDialog<object>
{
[LuisIntent("打招呼")]
publicasyncTask Greeting(IDialogContext context,LuisResult result)
{
await context.PostAsync("你好啊,老铁");
context.Wait(MessageReceived);
}
[LuisIntent("询问名字")]
publicasyncTask Name(IDialogContext context,LuisResult result)
{
await context.PostAsync("你就叫我特浪扑吧。");
context.Wait(MessageReceived);
}
[LuisIntent("讲笑话")]
publicasyncTask Amuse(IDialogContext context,LuisResult result)
{
await context.PostAsync("你的存在其实就是一个笑话。");
context.Wait(MessageReceived);
}
[LuisIntent("")]
publicasyncTask none(IDialogContext context,LuisResult result)
{
await context.PostAsync("老铁,发烧就该吃药,不能胡言乱语啊。");
context.Wait(MessageReceived);
}
}
}
再截个图让大家明白点:
然后打开MessagesController.cs文件
把我截图中圈出来的地方改为:
LuisDialog());
然后就可以编译运行了。下面是测试截图:
其实我们看到,LUIS能做的是帮助bot更好的理解用户的意图。而准确获得用户意图的前提是我们预先设定了这些Intents,如果没有意图符合我们的预先设定,同样会有笑话。
但是和if-else比起来,我们的代码更简洁,更有逼格。我们只要不停地训练,完善LUIS app,就可以更好地解决问题。
以上就是我想和大家分享的内容了,如有不当,不正确之处请指出。谢谢。
(注意:luis app有时会因为用户网络问题,或者服务器自身问题,导致无法访问,或者响应缓慢的情况。)