手把手教你利用微软的Bot Framework,LUIS,QnA Maker做一个简单的对话机器人

时间:2021-09-11 22:35:12

最近由于要参加微软亚洲研究院的夏令营,需要利用微软的服务搭建一个对话Bot,以便对俱乐部的情况进行介绍,所以现学了几天,搭建了一个简单的对话Bot,期间参考了大量的资料,尤其是下面的这篇博客:

http://www.cnblogs.com/rocsheh/p/5846009.html

实现的大致效果是可以询问微软俱乐部的相关情况,并且查询天气。效果演示如下:

手把手教你利用微软的Bot Framework,LUIS,QnA Maker做一个简单的对话机器人

下面我会将整个过程进行详细的表述。

1. 什么是Bot Framework?

Bot Framework就是帮你快速搭建智能服务的后端,快速在各种终端和服务上提供服务。包括三大组件。

手把手教你利用微软的Bot Framework,LUIS,QnA Maker做一个简单的对话机器人

Bot Builder SDKs:

这个是Bot的生成器,快速生成一个ASP.NET和Node.js的后端服务,提供了像Dialog、FormFlow帮你管理与用户的会话。

Bot Connector:

这是个Bot的Channel,帮你把你的服务快速发布到各个渠道,比如说Skype,Facebook Messager等等。这样用户就可以在Skype等Channel上使用你的服务了。

Bot Directory:

这个算是Bot 的商店,在这里可以找到各个bot,你也可以把自己的Bot发布出来,从而大家都可以看到你的Bot。

官方网址:https://docs.microsoft.com/zh-cn/bot-framework,用你的微软账户登录就行。

界面如图所示:

手把手教你利用微软的Bot Framework,LUIS,QnA Maker做一个简单的对话机器人

2. 什么是LUIS?

说到LUIS,我们首先谈一下Cognitive Services(认知服务)。

Cognitive Services(认知服务)的前身是Project Oxford(牛津计划),正式发布的时候更名的。这是微软将研究院研究的技术以API和SDK的形式开放给开发者的一系列智能化服务。

主要包括5大类的服务:视觉、语言、语言、知识和搜索。

手把手教你利用微软的Bot Framework,LUIS,QnA Maker做一个简单的对话机器人

其实就包括我们今天要讲的"语言理解(Language Understanding Intelligent Service,简称LUIS)"。

LUIS的官网介绍:https://www.luis.ai,用你的微软账户登录就行。

界面如图所示:

手把手教你利用微软的Bot Framework,LUIS,QnA Maker做一个简单的对话机器人

点击"App"这一栏,咱们先点击"new App"新建一个app。

手把手教你利用微软的Bot Framework,LUIS,QnA Maker做一个简单的对话机器人

新建完成后,点击应用的名称,进入编辑这个应用。

我们先看以下左边的tab,可以看到有仪表盘,意图(Intents),实体(Entities),功能以及发布应用。。。。

手把手教你利用微软的Bot Framework,LUIS,QnA Maker做一个简单的对话机器人

Intents:就是意图,比如咱们现在要提供天气查询的服务,那么咱们就创建一个"查询天气"的Intent。

实体里头有两类:

Entities:实体,比如在查询天气的时候需要有地理位置信息,需要把用户的语言里头的地点提取出来,这个地点就是这个句子里头的实例,咱们创建一个"地点"的实例。

Pre-built Entities(预建实体):这个是预置好的实例,比如说时间,数字等等,我加了一个datetime的预置实例。

在功能里头会有:

Phrase List Features(短语列表功能):固定的一些短语,能够直接识别,比如说航空公司的名字等已知信息

Pattern Features(模式功能):正则表达式,可以匹配出相应的一些字段,比如说航班号。

咱们现在来创建一个能够识别查询天气的语言理解服务。

首先,查询天气需要地点信息,咱们先创建一个"地点"的实例。

点击到“实体”里头,“添加自定义实体”:

手把手教你利用微软的Bot Framework,LUIS,QnA Maker做一个简单的对话机器人

手把手教你利用微软的Bot Framework,LUIS,QnA Maker做一个简单的对话机器人

添加一个“预建实体” datetime:

手把手教你利用微软的Bot Framework,LUIS,QnA Maker做一个简单的对话机器人

再创建一个叫做"查询天气"的Intent。

手把手教你利用微软的Bot Framework,LUIS,QnA Maker做一个简单的对话机器人

点击save之后会出现以下界面:

手把手教你利用微软的Bot Framework,LUIS,QnA Maker做一个简单的对话机器人

在“句式”中,输入几个例子,比如说“北京天气怎么样”,可以多输入几个句子的类型,比如“北京今天有雾霾吗?”等等,没输入完一句按一下回车。

手把手教你利用微软的Bot Framework,LUIS,QnA Maker做一个简单的对话机器人

如果北京等地点信息没有显示标记的话,选中北京两个字,然后选择"地点"标注。然后点击"保存"。

之后点击"发布应用",点击该界面里头的"Train"按钮。

手把手教你利用微软的Bot Framework,LUIS,QnA Maker做一个简单的对话机器人

开始训练,可能需要点时间,你可以做点其他事情。

训练完成之后,Publish按钮,发布成api的形式。

手把手教你利用微软的Bot Framework,LUIS,QnA Maker做一个简单的对话机器人

大家可以看到有“Endpoint url”这个选项,这个url后面加上查询语句就是API了。

如:https://westus.api.cognitive.microsoft.com/luis/v2.0/apps/LUIS_APP_ID?subscription-key=LUIS_subscription-key&timezoneOffset=0.0&verbose=true&q=北京今天天气怎么样?

手把手教你利用微软的Bot Framework,LUIS,QnA Maker做一个简单的对话机器人

把LUIS的ID(就是apps后面那串字符)和subscription-key记下来,后面需要用到。

在URL后面可以输入相关的语句,然后回车,就可以看到返回的json字符串了。

手把手教你利用微软的Bot Framework,LUIS,QnA Maker做一个简单的对话机器人

3. 什么是QnA Maker?

QnA Maker可以创建、训练并发布一个基于问题对的智能匹配,可以通过简单的训练来组织问题对,特别适合处理的就是标准问答的形式,比如“微软学生俱乐部是什么?”“如何加入微软俱乐部?”等等,后面匹配上标准的答案。

官方网址:https://qnamaker.ai

界面如下:

手把手教你利用微软的Bot Framework,LUIS,QnA Maker做一个简单的对话机器人

第一次进入,我们点击Create new Service,进入创建界面。

SERVICE NAME:随便起,我起的BOPdemo。

FAQ URL(S):如果你有相关的URL,可以填写,没有可以不写。样式参考:http://studentclub.msra.cn/bop2017/qa这种格式。

FAQ FILES:如果有相关文件可以直接导入,没有可以不导入,因为最后还可以手动导入。样例文件如下:
手把手教你利用微软的Bot Framework,LUIS,QnA Maker做一个简单的对话机器人

中间记得用tab键隔开。至此,就创建完了。

创建完了之后,你会发现在My services多了一个刚才创建的服务,如下:

手把手教你利用微软的Bot Framework,LUIS,QnA Maker做一个简单的对话机器人

 
 点进去之后,效果如图:
手把手教你利用微软的Bot Framework,LUIS,QnA Maker做一个简单的对话机器人

还可以通过Add new QnA pair添加单独的问题对。添加完了之后别忘了Save and retrain,之后你就可以通过Test进行测试,比如我输入Hi,机器人回复Hello。

通过URL,File以及单独添加的问题对都训练完并且测试满足条件之后,你就可以Publish发布了。

这时你肯定想问,怎么通过自己的代码进行访问啊?我以C#为例:参考文档:https://qnamaker.ai/Documentation/ApiReference

Publish之后,会形成如下HTTP样式:

POST /knowledgebases/<Your KB ID>/generateAnswer HTTP/1.1
Host: https://westus.api.cognitive.microsoft.com/qnamaker/v1.0
Ocp-Apim-Subscription-Key: <Your Subscription key>
Content-Type: application/json
Cache-Control: no-cache
{"question": "Question goes here"}

请求的代码:

string responseString = string.Empty;

var query = “hi”; //User Query
var knowledgebaseId = “YOUR_KNOWLEDGE_BASE_ID”; // Use knowledge base id created.
var qnamakerSubscriptionKey = “YOUR_SUBSCRIPTION_KEY”; //Use subscription key assigned to you. //Build the URI
Uri qnamakerUriBase = new Uri("https://westus.api.cognitive.microsoft.com/qnamaker/v1.0");
var builder = new UriBuilder($"{qnamakerUriBase}/knowledgebases/{knowledgebaseId}/generateAnswer"); //Add the question as part of the body
var postBody = $"{{\"question\": \"{query}\"}}"; //Send the POST request
using (WebClient client = new WebClient())
{
//Set the encoding to UTF8
client.Encoding = System.Text.Encoding.UTF8; //Add the subscription key header
client.Headers.Add("Ocp-Apim-Subscription-Key", qnamakerSubscriptionKey);
client.Headers.Add("Content-Type", "application/json");
responseString = client.UploadString(builder.Uri, postBody);
}

得到的响应格式是JSON,如下:

{ "Answer": "Sample response", "Score": "" }

处理响应的代码:

using Newtonsoft.Json; 

private class QnAMakerResult
{
/// <summary>
/// The top answer found in the QnA Service.
/// </summary>
[JsonProperty(PropertyName = "answer")]
public string Answer { get; set; } /// <summary>
/// The score in range [0, 100] corresponding to the top answer found in the QnA Service.
/// </summary>
[JsonProperty(PropertyName = "score")]
public double Score { get; set; }
}
//De-serialize the response
QnAMakerResult response;
try
{
response = JsonConvert.DeserializeObject< QnAMakerResult >(responseString);
}
catch
{
throw new Exception("Unable to deserialize QnA Maker response string.");
}

4. 开发流程

1) 首先获取Bot Builder SDK和Bot模拟器

可以去https://docs.microsoft.com/en-us/bot-framework/resources-tools-downloads进行参考。

首先,请下载Bot Framework的SDK,建议下载Bot Framework的Visual Studio的模板Bot Application

下载下来的模板(不用解压)请直接放置到C:\Users\你的用户名\Documents\Visual Studio 2017\Templates\ProjectTemplates\Visual C# 下面,这样你在C#下面就可以看到有Bot Application的模板了。

手把手教你利用微软的Bot Framework,LUIS,QnA Maker做一个简单的对话机器人

如果是使用NuGet来下载SDK,请参考:

  1. 右键你的C#项目,选择"Manage NuGet Packages".
  2. 在"Browse"的tab页,输入"Microsoft.Bot.Builder".
  3. 点击"Install"的按钮.

下载模拟器的地址为:https://github.com/Microsoft/BotFramework-Emulator/releases/tag/v3.5.31

选择.exe那个,直接下一步,下一步就行了。

2)创建一个新项目

快速开始,参考:https://docs.microsoft.com/en-us/bot-framework/dotnet/bot-builder-dotnet-quickstart

手把手教你利用微软的Bot Framework,LUIS,QnA Maker做一个简单的对话机器人

手把手教你利用微软的Bot Framework,LUIS,QnA Maker做一个简单的对话机器人

创建完之后,默认就是一个完整的项目,可以直接运行。直接点击运行,会打开一个web页面,地址栏如下:

手把手教你利用微软的Bot Framework,LUIS,QnA Maker做一个简单的对话机器人

打开模拟器输入URL:http://localhost:3979/api/messages

直接点击Connect即可。此时,你输入一段话,对方就会回一段话,显示你发送的内容,并说明这句话有多少字符。

这个基本的模型就建好了。

看一下项目目录,我们需要写的就是在Dialogs文件夹下新建Dialog,每次新增完在Controllers文件夹下的MessagesController.cs中记得更改一下,如图:

手把手教你利用微软的Bot Framework,LUIS,QnA Maker做一个简单的对话机器人

3)将应用发布到Azure云

首先注册中国区Azure云并申请1元订阅。

第一步:搜索引擎输入关键字“世纪互联Azure”,进入世纪互联azure官网,并点击申请试用,如下图红色框所示

手把手教你利用微软的Bot Framework,LUIS,QnA Maker做一个简单的对话机器人

图1:中国区Azure官网页面

第二步:点击申请试用后,弹出链接,填写电话号码与手机收到的验证码。

第三步:填写完验证码后将弹出下图页面,将必要信息填入到网页中。身份证正反面扫描件或者照片均可,建议选手在身份证正反面照片中打上水印,如“仅限申请Azure账户使用”,但不应该遮蔽身份证号码等必要的验证信息。

手把手教你利用微软的Bot Framework,LUIS,QnA Maker做一个简单的对话机器人

图2:Azure试用申请表

第四步:提交之后,你将收到一封邮件(可能稍有延迟)。打开你上图中填写的邮箱,查看主题为“Azure一元试用激活码”的邮件,邮件正文如下图所示:

手把手教你利用微软的Bot Framework,LUIS,QnA Maker做一个简单的对话机器人

图3:Azure一元试用激活码邮件内容

第五步:执行邮件的正文中的第一步“点击进入输入激活码页”

第六步:执行邮件正文中的第二步,创建用户账号并付费完成注册。第七步的具体过程如下:

  • 点击邮件中的链接进入如下界面,填写相关信息,由此生成登录账号。手把手教你利用微软的Bot Framework,LUIS,QnA Maker做一个简单的对话机器人

    图4:填写信息

  • 设置账号密码(密码需要包含大小写字母、符号和数字),并填写手机号获取验证码。手把手教你利用微软的Bot Framework,LUIS,QnA Maker做一个简单的对话机器人

    图5:填写信息

  • 自动跳转登录界面,输入密码登录。手把手教你利用微软的Bot Framework,LUIS,QnA Maker做一个简单的对话机器人

    图6:登录页面

  • 选择支付宝,支付一元钱。手把手教你利用微软的Bot Framework,LUIS,QnA Maker做一个简单的对话机器人

    图7:一元订阅支付页面

第七步:收到主题为“由世纪互联运营的 Windows Azure 购买确认”邮件以及主题为“欢迎使用 Windows Azure Active Directory”表示azure注册成功。具体图片分别如下图8和9所示:

手把手教你利用微软的Bot Framework,LUIS,QnA Maker做一个简单的对话机器人

图8:邮件主题为“由世纪互联运营的 Windows Azure 购买确认”截图

手把手教你利用微软的Bot Framework,LUIS,QnA Maker做一个简单的对话机器人

图9:邮件主题为“欢迎使用 Windows Azure Active Directory”截图

申请完之后,需要用VS链接到中国区Azure,参考:

https://www.azure.cn/documentation/articles/developerdifferences/

也许这一块你还会有其他很多问题,别着急,在http://studentclub.msra.cn/bop2017/qa肯定能找到答案。

回到VS,点击项目名,右键,发布,最后效果:

手把手教你利用微软的Bot Framework,LUIS,QnA Maker做一个简单的对话机器人

此时已经部署到云了。

4)在Bot Framework网站上注册应用

登录 Bot Fraework网站,https://dev.botframework.com/ 如果你还没有账号,请先注册一个。

点击"Register a Bot"https://dev.botframework.com/bots/new 注册一个

填写相关的信息:

"Name":你的bot的名字,比如我的叫做"萌萌"。

"Bot Handle":随便写一串字母,比如我的写"mengmeng",其实就是你的Bot的id。

"Description":你的Bot的描述,会在你的publish之后主页上显示。

下面需要填写你的endpoint,就是你后台服务的地址:https://你的服务器地址/api/messages (刚才咱们发布的template的默认接口)

你需要点击"Create Microsoft App ID and password",创建App ID和Password(注意,切记把这个app password记下来,只显示一次)

下面的必填的一些选项随便填一下就可以了。

点击保存。

在右边的"Channels"里头可以看到"Web Chat",这个网页端的一个channel,已经帮你写好的一个frame,咱们点击"Edit"更新。

生成Web Chat的密钥之后,把密钥复制,点击"I'm done configuring Web Chat"。

5)更新你的后端服务

在你的Web.config里,填上你的botId,刚才创建的App ID和app password。

手把手教你利用微软的Bot Framework,LUIS,QnA Maker做一个简单的对话机器人

打开网站的起始页default.htm

手把手教你利用微软的Bot Framework,LUIS,QnA Maker做一个简单的对话机器人

复制以下代码:

<!DOCTYPE html>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<html>
<head>
<title>小驰</title>
<meta charset="utf-8" />
</head>
<body style="font-family:'Segoe UI'">
<iframe name="myframe" scrolling="auto" width="100%" height="100%"
onload="document.all['myframe'].style.height=myframe.document.body.scrollHeight"
src="https://webchat.botframework.com/embed/mengmeng?s=你 自 己 的 Web Chat 密 钥 " style="height: 502px; max-height: 502px;"></iframe>
</body>
</html>

然后右键项目工程,点击"publish",之后你就可以拥有一个简单的Bot啦。

手把手教你利用微软的Bot Framework,LUIS,QnA Maker做一个简单的对话机器人

注意:此时你再想通过模拟器调试,需要加上app id和password了。

5. 核心代码

github地址:https://github.com/DarrenChanChenChi/Microsoft-Bot

MengmengDialog.cs:

using BOPdemo.Models;
using Microsoft.Bot.Builder.Dialogs;
using Microsoft.Bot.Builder.Luis;
using Microsoft.Bot.Builder.Luis.Models;
using Microsoft.Bot.Connector;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Threading.Tasks;
using System.Web; namespace BOPdemo.Dialogs
{
[LuisModel("c26cbbd3-4ee0-4487-a585-e9c17fd1ac40", "857c6cd0cf2744deb8f91b434379582d")]
[Serializable]
//https://westus.api.cognitive.microsoft.com/luis/v2.0/apps/c26cbbd3-4ee0-4487-a585-e9c17fd1ac40?
//subscription-key=857c6cd0cf2744deb8f91b434379582d&timezoneOffset=0&verbose=true&q=
public class MengmengDialog : LuisDialog<object>
{
public MengmengDialog()
{
}
public MengmengDialog(ILuisService service)
: base(service)
{
}
[LuisIntent("")]
[LuisIntent("None")]
public async Task None(IDialogContext context, LuisResult result)
{
/**string message = $"小驰不知道你在说什么,面壁去。。。我现在只会查询天气。。T_T" + string.Join(", ", result.Intents.Select(i => i.Intent));
await context.PostAsync(message);
context.Wait(MessageReceived);*/
//var activity = await result as Activity; // calculate something for us to return
//int length = (activity.Text ?? string.Empty).Length; // return our reply to the user
//await context.PostAsync($"You sent {activity.Text} which was {length} characters");
//await context.PostAsync("你好"); /**
* 发送
**/
string responseString = string.Empty;
var query = result.Query; //User Query
var knowledgebaseId = "a00256ee-9316-4476-9fcb-0f6f7e10f8b6"; // Use knowledge base id created.
var qnamakerSubscriptionKey = "417cc12cef9a4b64835b84b657dc4d73"; //Use subscription key assigned to you. //Build the URI
Uri qnamakerUriBase = new Uri("https://westus.api.cognitive.microsoft.com/qnamaker/v1.0");
var builder = new UriBuilder($"{qnamakerUriBase}/knowledgebases/{knowledgebaseId}/generateAnswer"); //Add the question as part of the body
var postBody = $"{{\"question\": \"{query}\"}}"; //Send the POST request
using (WebClient client = new WebClient())
{
//Set the encoding to UTF8
client.Encoding = System.Text.Encoding.UTF8; //Add the subscription key header
client.Headers.Add("Ocp-Apim-Subscription-Key", qnamakerSubscriptionKey);
client.Headers.Add("Content-Type", "application/json");
responseString = client.UploadString(builder.Uri, postBody);
}
/**
* 接收
**/
//De-serialize the response
QnAMakerResult response;
try
{
response = JsonConvert.DeserializeObject<QnAMakerResult>(responseString);
}
catch
{
throw new Exception("Unable to deserialize QnA Maker response string.");
} string answer = response.Answer;
if (answer.Equals("No good match found in the KB"))
{
await context.PostAsync("小驰不知道你在说什么,面壁去。。。我现在只会介绍微软俱乐部信息和查询天气。。T_T");
}
else
{
await context.PostAsync(answer);
}
//await context.PostAsync(response.Score+"");
//原来的
context.Wait(MessageReceived);
}
public bool TryToFindLocation(LuisResult result, out String location)
{
location = "";
EntityRecommendation title;
if (result.TryFindEntity("地点", out title))
{
location = title.Entity;
}
else
{
location = "";
}
return !location.Equals("");
}
[LuisIntent("查询天气")]
public async Task QueryWeather(IDialogContext context, LuisResult result)
{
string location = "";
string replyString = "";
if (TryToFindLocation(result, out location))
{
replyString = await GetWeather(location);
await context.PostAsync(replyString);
context.Wait(MessageReceived);
}
else
{
await None(context, result);
}
//else
//{
// await context.PostAsync("亲你要查询哪个地方的天气信息呢,快把城市的名字发给我吧");
//context.Wait(AfterEnterLocation);
//}
} private async Task<string> GetWeather(string cityname)
{
WeatherData weatherdata = await BOPdemoTask.GetWeatherAsync(cityname);
if (weatherdata == null || weatherdata.HeWeatherdataservice30 == null)
{
return string.Format("呃。。。萌萌不知道\"{0}\"这个城市的天气信息", cityname);
}
else
{
HeweatherDataService30[] weatherServices = weatherdata.HeWeatherdataservice30;
if (weatherServices.Length <= ) return string.Format("呃。。。萌萌不知道\"{0}\"这个城市的天气信息", cityname);
Basic cityinfo = weatherServices[].basic;
if (cityinfo == null) return string.Format("呃。。。萌萌目测\"{0}\"这个应该不是一个城市的名字。。不然我咋不知道呢。。。", cityname);
String cityinfoString = "城市信息:" + cityinfo.city + "\n\n"
+ "更新时间:" + cityinfo.update.loc + "\n\n"
+ "经纬度:" + cityinfo.lat + "," + cityinfo.lon + "\n\n";
Aqi cityAirInfo = weatherServices[].aqi;
String airInfoString = "空气质量指数:" + cityAirInfo.city.aqi + "\n\n"
+ "PM2.5 1小时平均值:" + cityAirInfo.city.pm25 + "(ug/m³)\n\n"
+ "PM10 1小时平均值:" + cityAirInfo.city.pm10 + "(ug/m³)\n\n"
+ "二氧化硫1小时平均值:" + cityAirInfo.city.so2 + "(ug/m³)\n\n"
+ "二氧化氮1小时平均值:" + cityAirInfo.city.no2 + "(ug/m³)\n\n"
+ "一氧化碳1小时平均值:" + cityAirInfo.city.co + "(ug/m³)\n\n"; Suggestion citySuggestion = weatherServices[].suggestion;
String suggestionString = "生活指数:" + "\n\n"
+ "穿衣指数:" + citySuggestion.drsg.txt + "\n\n"
+ "紫外线指数:" + citySuggestion.uv.txt + "\n\n"
+ "舒适度指数:" + citySuggestion.comf.txt + "\n\n"
+ "旅游指数:" + citySuggestion.trav.txt + "\n\n"
+ "感冒指数:" + citySuggestion.flu.txt + "\n\n"; Daily_Forecast[] cityDailyForecast = weatherServices[].daily_forecast;
Now cityNowStatus = weatherServices[].now;
String nowStatusString = "天气实况:" + "\n\n"
+ "当前温度(摄氏度):" + cityNowStatus.tmp + "\n\n"
+ "体感温度:" + cityNowStatus.fl + "\n\n"
+ "风速:" + cityNowStatus.wind.spd + "(Kmph)\n\n"
+ "湿度:" + cityNowStatus.hum + "(%)\n\n"
+ "能见度:" + cityNowStatus.vis + "(km)\n\n"; return string.Format("现在{0}天气实况:\n\n{1}", cityname, cityinfoString + nowStatusString + airInfoString + suggestionString);
}
}
}
}

WeatherModel.cs:

using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web; namespace BOPdemo.Models
{
public class WeatherData
{
[JsonProperty(PropertyName = "HeWeather data service 3.0")]
public HeweatherDataService30[] HeWeatherdataservice30 { get; set; }
} public class HeweatherDataService30
{
public Aqi aqi { get; set; }
public Basic basic { get; set; }
public Daily_Forecast[] daily_forecast { get; set; }
public Hourly_Forecast[] hourly_forecast { get; set; }
public Now now { get; set; }
public string status { get; set; }
public Suggestion suggestion { get; set; }
} public class Aqi
{
public City city { get; set; }
} public class City
{
public string aqi { get; set; }
public string co { get; set; }
public string no2 { get; set; }
public string o3 { get; set; }
public string pm10 { get; set; }
public string pm25 { get; set; }
public string qlty { get; set; }
public string so2 { get; set; }
} public class Basic
{
public string city { get; set; }
public string cnty { get; set; }
public string id { get; set; }
public string lat { get; set; }
public string lon { get; set; }
public Update update { get; set; }
} public class Update
{
public string loc { get; set; }
public string utc { get; set; }
} public class Now
{
public Cond cond { get; set; }
public string fl { get; set; }
public string hum { get; set; }
public string pcpn { get; set; }
public string pres { get; set; }
public string tmp { get; set; }
public string vis { get; set; }
public Wind wind { get; set; }
} public class Cond
{
public string code { get; set; }
public string txt { get; set; }
} public class Wind
{
public string deg { get; set; }
public string dir { get; set; }
public string sc { get; set; }
public string spd { get; set; }
} public class Suggestion
{
public Comf comf { get; set; }
public Cw cw { get; set; }
public Drsg drsg { get; set; }
public Flu flu { get; set; }
public Sport sport { get; set; }
public Trav trav { get; set; }
public Uv uv { get; set; }
} public class Comf
{
public string brf { get; set; }
public string txt { get; set; }
} public class Cw
{
public string brf { get; set; }
public string txt { get; set; }
} public class Drsg
{
public string brf { get; set; }
public string txt { get; set; }
} public class Flu
{
public string brf { get; set; }
public string txt { get; set; }
} public class Sport
{
public string brf { get; set; }
public string txt { get; set; }
} public class Trav
{
public string brf { get; set; }
public string txt { get; set; }
} public class Uv
{
public string brf { get; set; }
public string txt { get; set; }
} public class Daily_Forecast
{
public Astro astro { get; set; }
public Cond1 cond { get; set; }
public string date { get; set; }
public string hum { get; set; }
public string pcpn { get; set; }
public string pop { get; set; }
public string pres { get; set; }
public Tmp tmp { get; set; }
public string vis { get; set; }
public Wind1 wind { get; set; }
} public class Astro
{
public string sr { get; set; }
public string ss { get; set; }
} public class Cond1
{
public string code_d { get; set; }
public string code_n { get; set; }
public string txt_d { get; set; }
public string txt_n { get; set; }
} public class Tmp
{
public string max { get; set; }
public string min { get; set; }
} public class Wind1
{
public string deg { get; set; }
public string dir { get; set; }
public string sc { get; set; }
public string spd { get; set; }
} public class Hourly_Forecast
{
public string date { get; set; }
public string hum { get; set; }
public string pop { get; set; }
public string pres { get; set; }
public string tmp { get; set; }
public Wind2 wind { get; set; }
} public class Wind2
{
public string deg { get; set; }
public string dir { get; set; }
public string sc { get; set; }
public string spd { get; set; }
}
}

BOPdemoTask.cs:

using BOPdemo.Models;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using System.Web; namespace BOPdemo
{
public class BOPdemoTask
{
public static async Task<double?> GetStockRateAsync(string StockSymbol)
{
try
{
string ServiceURL = $"http://finance.yahoo.com/d/quotes.csv?s={StockSymbol}&f=sl1d1nd";
string ResultInCSV;
using (WebClient client = new WebClient())
{
ResultInCSV = await client.DownloadStringTaskAsync(ServiceURL).ConfigureAwait(false);
}
var FirstLine = ResultInCSV.Split('\n')[];
var Price = FirstLine.Split(',')[];
if (Price != null && Price.Length >= )
{
double result;
if (double.TryParse(Price, out result))
{
return result;
}
}
return null;
}
catch (WebException ex)
{
//handle your exception here
throw ex;
}
} public static async Task<WeatherData> GetWeatherAsync(string city)
{
try
{
string ServiceURL = $"https://free-api.heweather.com/x3/weather?city={city}&key=e8c9a95d0a0f4d2092def1174c44be17";
string ResultString;
using (WebClient client = new WebClient())
{
client.Encoding = Encoding.UTF8;
ResultString = await client.DownloadStringTaskAsync(ServiceURL).ConfigureAwait(false);
}
WeatherData weatherData = (WeatherData)JsonConvert.DeserializeObject(ResultString, typeof(WeatherData));
return weatherData;
}
catch (WebException ex)
{
//handle your exception here
//throw ex;
return null;
}
}
}
}

QnAMakerResult.cs:

using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web; namespace BOPdemo.Models
{
public class QnAMakerResult
{
/// <summary>
/// The top answer found in the QnA Service.
/// </summary>
[JsonProperty(PropertyName = "answer")]
public string Answer { get; set; } /// <summary>
/// The score in range [0, 100] corresponding to the top answer found in the QnA Service.
/// </summary>
[JsonProperty(PropertyName = "score")]
public double Score { get; set; }
}
}

学习资料:

http://studentclub.msra.cn/bop2017/qa

http://studentclub.msra.cn/bop2017/rules/learning

手把手教你利用微软的Bot Framework,LUIS,QnA Maker做一个简单的对话机器人的更多相关文章

  1. 手把手教你开发chrome扩展一:开发Chrome Extenstion其实很简单

    手把手教你开发chrome扩展一:开发Chrome Extenstion其实很简单   手把手教你开发chrome扩展一:开发Chrome Extenstion其实很简单 手把手教你开发Chrome扩 ...

  2. netty系列之&colon;小白福利!手把手教你做一个简单的代理服务器

    目录 简介 代理和反向代理 netty实现代理的原理 实战 总结 简介 爱因斯坦说过:所有的伟大,都产生于简单的细节中.netty为我们提供了如此强大的eventloop.channel通过对这些简单 ...

  3. 【转】手把手教你利用Jenkins持续集成iOS项目

    前言 众所周知,现在App的竞争已经到了用户体验为王,质量为上的白热化阶段.用户们都是很挑剔的.如果一个公司的推广团队好不容易砸了重金推广了一个APP,好不容易有了一些用户,由于一次线上的bug导致一 ...

  4. 手把手教你利用Jenkins持续集成iOS项目

    前言 众所周知,现在App的竞争已经到了用户体验为王,质量为上的白热化阶段.用户们都是很挑剔的.如果一个公司的推广团队好不容易砸了重金推广了一个APP,好不容易有了一些用户,由于一次线上的bug导致一 ...

  5. 手把手教你利用Docker&plus;jenkins部署你的网站

    更新服务器的安装源为阿里的源,参考链接:https://blog.csdn.net/js_xh/article/details/79166655 安装docker; 1 更新资源 sudo apt-g ...

  6. 手把手教你利用Python自动下载CL社区图片

    需求描述:     最近发现CL社区上好多精华的帖子分享的图片非常棒,好想好想保存下来,但是一张一张地保存太费时间了,因此,造物者思想主义的我就想动手写个工具,实现只要输入帖子的链接,就能把所有的精华 ...

  7. CNN实战篇-手把手教你利用开源数据进行图像识别(基于keras搭建)

    我一直强调做深度学习,最好是结合实际的数据上手,参照理论,对知识的掌握才会更加全面.先了解原理,然后找一匹数据来验证,这样会不断加深对理论的理解. 欢迎留言与交流! 数据来源: cifar10  (其 ...

  8. js利用点击事件做一个简单的计算器

    先放一个样式图: 源代码如下: <!DOCTYPE html> <html> <head> <meta charset="UTF-8"&g ...

  9. 利用JS跨域做一个简单的页面访问统计系统

    其实在大部分互联网web产品中,我们通常会用百度统计或者谷歌统计分析系统,通过在程序中引入特定的JS脚本,然后便可以在这些统计系统中看到自己网站页面具体的访问情况.但是有些时候,由于一些特殊情况,我们 ...

随机推荐

  1. React Native知识11-Props&lpar;属性&rpar;与State&lpar;状态&rpar;

    一:Props(属性) 大多数组件在创建时就可以使用各种参数来进行定制.用于定制的这些参数就称为props(属性).props是在父组件中指定,而且一经指定,在被指定的组件的生命周期中则不再改变 通过 ...

  2. dp与px之间的转换

    代码如下: package com.example.fxvideo.utils; import android.content.Context; public class DensityUtils { ...

  3. &lbrack;转&rsqb;Visual Studio 2008中如何比较二个数据库的架构【Schema】和数据【Data】并同步

    使用场景: 在团队开发中,每一个人都有可能随时更新数据库,这时候数据库中数据和架构等信息都会发生变化.如果更新不及时,就会发生数据错误或数据丢失的风险,影响团队的开发效率和 项目进度,这时候我们该怎么 ...

  4. android的快速开发框架集合

    出自:http://blog.csdn.net/shulianghan/article/details/18046021 1.Afinal  (快速开发框架) 简介:http://www.oschin ...

  5. JS中setTimeout&lpar;&rpar;的使用方法具体解释

    1. SetTimeOut()              1.1 SetTimeOut()语法样例              1.2 用SetTimeOut()运行Function           ...

  6. 学习REST

    REST:Representational State Transfer,资源的表现状态转换.可以理解为对资源的操作.   1. 资源 资源就是业务对象,如图片.文本.歌曲或者客户.交易等.这些是用户 ...

  7. Python 学习 第四篇:动态类型模型

    Python的变量不用声明,赋值之后就可以直接使用,类型是在运行过程中自动确定的,这就是动态类型模型.该模型把变量和对象设计成两个不同的实体,对象是存储数据的地方,对象的类型是由初始值自动决定的,而变 ...

  8. pandas 应用

    类似vlookup import pandas as pd file = pd.read_csv('NIN411PF.CSV', encoding='ANSI') a = pd.DataFrame({ ...

  9. 【Java并发编程】2、无锁编程:lock-free原理;CAS;ABA问题

    转自:http://blog.csdn.net/kangroger/article/details/47867269 定义 无锁编程是指在不使用锁的情况下,在多线程环境下实现多变量的同步.即在没有线程 ...

  10. A Brief Overview of Deep Learning

    A Brief Overview of Deep Learning (This is a guest post by Ilya Sutskever on the intuition behind de ...