http://www.cnblogs.com/sonic1abc/p/5941442.html 这边文章是我去年10月看到的,在2017年3月参见微软PowerBI培训中有幸见到博主了。“如何将 Microsoft Bot Framework 链接至微信公共号”该文章详细描述了如何将 微信公众号、Bot、Luis完美结合在一起。整个交互过程如下:

 

接下来就介绍如何把微信和Luis做结合,省去Bot Server这一环节。基本原理图如下:

 接下来看具体实现:

微信开发接入


  •  公众号申请及配置
    • 微信公众号申请步骤此处省略可以到https://mp.weixin.qq.com/申请
    • 需要对微信管理后台启用服务器配置

  • 微信服务器校验
    • 根据微信公众号开发文档提示如下:

    • 检验signature的C#示例代码(采用C# MVC、Senparc.Weixin SDK)
  1 using Senparc.Weixin.MP;
  2 using Senparc.Weixin.MP.Entities.Request;
  3 using System;
  4 using System.Collections.Generic;
  5 using System.IO;
  6 using System.Linq;
  7 using System.Web;
  8 using System.Web.Configuration;
  9 using System.Web.Mvc;
 10 using WeChat.Conduits;
 11  
 12 
 13 
 14 namespace WeChat.Paltform.Controllers
 15 {
 16     using Senparc.Weixin.MP.MvcExtension;
 17     using WeChat.Conduits.MessageHandlers.CustomMessageHandler;
 18     public class WeixinController : Controller
 19     {
 20         public static readonly string Token = WebConfigurationManager.AppSettings["WeixinToken"];//与微信公众账号后台的Token设置保持一致,区分大小写。
 21         public static readonly string EncodingAESKey = WebConfigurationManager.AppSettings["WeixinEncodingAESKey"];//与微信公众账号后台的EncodingAESKey设置保持一致,区分大小写。
 22         public static readonly string AppId = WebConfigurationManager.AppSettings["WeixinAppId"];//与微信公众账号后台的AppId设置保持一致,区分大小写。
 23         readonly Func<string> _getRandomFileName = () => DateTime.Now.ToString("yyyyMMdd-HHmmss") + Guid.NewGuid().ToString("n").Substring(0, 6);
 24         public WeixinController()
 25         {
 26 
 27         }
 28         /// <summary>
 29         /// / 微信后台验证地址(使用Get),微信后台的“接口配置信息”的Url填写如
 30         /// </summary>
 31         /// <param name="postModel"></param>
 32         /// <param name="echostr"></param>
 33         /// <returns></returns>
 34         [HttpGet]
 35         [ActionName("Index")]
 36         public ActionResult Get(PostModel postModel, string echostr)
 37         {
 38             if (CheckSignature.Check(postModel.Signature, postModel.Timestamp, postModel.Nonce, Token))
 39             {
 40                 return Content(echostr); //返回随机字符串则表示验证通过
 41             }
 42             else
 43             {
 44                 return Content("failed:" + postModel.Signature + "," + Senparc.Weixin.MP.CheckSignature.GetSignature(postModel.Timestamp, postModel.Nonce, Token) + "" +
 45                     "如果你在浏览器中看到这句话,说明此地址可以被作为微信公众账号后台的Url,请注意保持Token一致。");
 46             }
 47         }
 48         /// <summary>
 49         /// 用户发送消息后,微信平台自动Post一个请求到这里,并等待响应XML。
 50         /// PS:此方法为简化方法,效果与OldPost一致。
 51         /// v0.8之后的版本可以结合Senparc.Weixin.MP.MvcExtension扩展包,使用WeixinResult,见MiniPost方法。
 52         /// </summary>
 53         [HttpPost]
 54         [ActionName("Index")]
 55         public ActionResult Post(PostModel postModel)
 56         {
 57             if (!CheckSignature.Check(postModel.Signature, postModel.Timestamp, postModel.Nonce, Token))
 58             {
 59                 return Content("参数错误!");
 60             }
 61 
 62             postModel.Token = Token; 
 63             postModel.EncodingAESKey = EncodingAESKey; 
 64             postModel.AppId = AppId;
 65 
 66             
 67             var maxRecordCount = 10;
 68 
 69             var logPath = Server.MapPath(string.Format("~/App_Data/MP/{0}/", DateTime.Now.ToString("yyyy-MM-dd")));
 70             if (!Directory.Exists(logPath))
 71             {
 72                 Directory.CreateDirectory(logPath);
 73             }
 74 
 75             var messageHandler = new CustomMessageHandler(Request.InputStream, postModel, maxRecordCount);
 76 
 77 
 78             try
 79             {
 80                 //测试时可开启此记录,帮助跟踪数据,使用前请确保App_Data文件夹存在,且有读写权限。
 81                 messageHandler.RequestDocument.Save(Path.Combine(logPath, string.Format("{0}_Request_{1}.txt", _getRandomFileName(), messageHandler.RequestMessage.FromUserName)));
 82                 if (messageHandler.UsingEcryptMessage)
 83                 {
 84                     messageHandler.EcryptRequestDocument.Save(Path.Combine(logPath, string.Format("{0}_Request_Ecrypt_{1}.txt", _getRandomFileName(), messageHandler.RequestMessage.FromUserName)));
 85                 }            
 86                 messageHandler.OmitRepeatedMessage = true;
 87 
 88                 //执行微信处理过程
 89                 messageHandler.Execute();
 90  
 91 
 92                 if (messageHandler.ResponseDocument != null)
 93                 {
 94                     messageHandler.ResponseDocument.Save(Path.Combine(logPath, string.Format("{0}_Response_{1}.txt", _getRandomFileName(), messageHandler.RequestMessage.FromUserName)));
 95                 }
 96 
 97                 if (messageHandler.UsingEcryptMessage)
 98                 {
 99                     //记录加密后的响应信息
100                     messageHandler.FinalResponseDocument.Save(Path.Combine(logPath, string.Format("{0}_Response_Final_{1}.txt", _getRandomFileName(), messageHandler.RequestMessage.FromUserName)));
101                 }
102 
103                 return Content(messageHandler.ResponseDocument.ToString());//v0.7-
104             }
105             catch (Exception ex)
106             {
107                 using (TextWriter tw = new StreamWriter(Server.MapPath("~/App_Data/Error_" + _getRandomFileName() + ".txt")))
108                 {
109                     tw.WriteLine("ExecptionMessage:" + ex.Message);
110                     tw.WriteLine(ex.Source);
111                     tw.WriteLine(ex.StackTrace);
112                     //tw.WriteLine("InnerExecptionMessage:" + ex.InnerException.Message);
113 
114                     if (messageHandler.ResponseDocument != null)
115                     {
116                         tw.WriteLine(messageHandler.ResponseDocument.ToString());
117                     }
118 
119                     if (ex.InnerException != null)
120                     {
121                         tw.WriteLine("========= InnerException =========");
122                         tw.WriteLine(ex.InnerException.Message);
123                         tw.WriteLine(ex.InnerException.Source);
124                         tw.WriteLine(ex.InnerException.StackTrace);
125                     }
126 
127                     tw.Flush();
128                     tw.Close();
129                 }
130                 return Content("");
131             }
132         }
133     }
134 }
View Code
    • 微信消息处理代码(微信消息类型有很多种,以下是只贴出文本、语音消息处理)
 1  /// <summary>
 2         /// 处理文字请求
 3         /// </summary>
 4         /// <returns></returns>
 5         public override  IResponseMessageBase OnTextRequest(RequestMessageText requestMessage)
 6         {
 7            
 8 
 9             var responseMessage = base.CreateResponseMessage<ResponseMessageText>();
10             if (requestMessage.Content == "您好" || requestMessage.Content == "你好")
11             {
12                 responseMessage.Content = requestMessage.Content;
13             }
14             else {
15                 responseMessage.Content = LuisService.Instance.PostMessage(requestMessage.Content);
16             }
17  
18             return responseMessage;
19         }
20 
21  /// <summary>
22         /// 处理语音请求
23         /// </summary>
24         /// <param name="requestMessage"></param>
25         /// <returns></returns>
26         public override IResponseMessageBase OnVoiceRequest(RequestMessageVoice requestMessage)
27         {
28        
29             var responseMessage = CreateResponseMessage<ResponseMessageText>();
30 
31             responseMessage.Content = LuisService.Instance.PostMessage(requestMessage.Recognition.ToString());
32            
33             return responseMessage;
34         }
View Code

 Luis简介和应用构建


 

  • Luis介绍      

    牛津计划(Project Oxford)”的最新成果“语义理解智能服务(LUIS)”,作为微软智能云Azure服务,“语义理解智能服务”目前已正式面向公众开放,并且支持汉语应用,开发者无需机器学习或人工智能方面的专业技能,即可在其移动应用中加入自然语言识别能力。开发者可以访问https://www.luis.ai/ 获取更多信息。

    “牛津计划”旨在帮助开发者制作更智能的移动应用,令其方便快捷地在跨平台应用中加入面部、图像、语言、文本等识别功能。一度在国内社交媒体上非常流行的How-Old.net和TwinsOrNot应用,就是以此为基础在几小时内开发出来的。

  • Luis App创建
    • 用自己的微软账号登录后,首先创建App,点击New App进行创建

 

    • 创建完成应用后需要确定应用意图

    意图是指想通过语句表达出来目的或期望的操作。它们是你应用程序主要构建的基础。你现在在需要确定你希望应用程序检测的意图(如:天气查询、股票查询),在网站意图菜单连接中创建意图

 

    • 为意图添加句式

     现在你需要开始为每个意图创建示例,以便及其学习模型了解不同的模式(例如:明天上海会下雨吗?、帮我查一下300170股价)。选择你刚刚添加的意图,然后开始句式添加并保存到你意图

 

 

    • 添加实体

     既然我们已经有意图,我们将继续添加实体。实体是对应用执行任务以及为语义解析提取起着至关重要的作用。下一步就是在意图的句式中标记实体,在你添加的句式中就会突显相关的实体标记

 

    • 训练和测试

     我们基本要完成一用的创建了。现在应该和测试我们所创建的模型和性能了,通过侧菜单转到“训练和测试”页面。并开始测试你的模型。最后发布应用我们可以得到Endpoint Url值我就可以在后端代码中对器进行调用

Luis App调用


 

  • 结合微信输入(语音、文本) + luis 语义理解,先效果图。

 

        

  • LuisAPI定义
 1 using Newtonsoft.Json;
 2 using System;
 3 using System.Collections.Generic;
 4 using System.Linq;
 5 using System.Net.Http;
 6 using System.Text;
 7 using System.Threading.Tasks;
 8 
 9 namespace WeChat.Luis
10 {
11     public class LuisAPI
12     {
13         /// <summary>
14         /// Luis Public app Id
15         /// </summary>
16         private static readonly string URI = "发布后生成的Endpoint url";
17 
18         /// <summary>
19         ///实例化
20         /// </summary>
21         public static LuisAPI Instance
22         {
23             get { return new LuisAPI(); }
24         }
25         /// <summary>
26         /// Get Luis 接口
27         /// </summary>
28         /// <param name="Query"></param>
29         /// <returns></returns>
30         public LuisResponseMessage GetLuis(string Query)
31         {
32             Query = Uri.EscapeDataString(Query);
33             LuisResponseMessage Data = new LuisResponseMessage();
34             using (HttpClient client = new HttpClient())
35             {
36                 string RequestURI = string.Format(URI, Query);
37                 var task = client.GetAsync(RequestURI);
38                 HttpResponseMessage msg = task.Result;
39 
40                 if (msg.IsSuccessStatusCode)
41                 {
42                     var task1 = msg.Content.ReadAsStringAsync();
43                     var JsonDataResponse = task1.Result;
44                     Data = JsonConvert.DeserializeObject<LuisResponseMessage>(JsonDataResponse);
45                 }
46             }
47             return Data;
48         }
49 
50     }
51 }
View Code
  • LuisService定义
 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 using System.Threading.Tasks;
 6 
 7 namespace WeChat.Luis
 8 {
 9    public class LuisService
10     {
11         /// <summary>
12         ///实例化
13         /// </summary>
14         public static LuisService Instance
15         {
16             get { return new LuisService(); }
17         }
18 
19         public string PostMessage(string query)
20         {
21             LuisResponseMessage luisMsg = LuisAPI.Instance.GetLuis(query);
22             if (luisMsg == null )
23                 return LuisInfos.DEFAULT_LUIS;
24 
25             string reponse = "";
26             switch (luisMsg.topScoringIntent.intent)
27             {
28                 case "天气查询":
29                     if (luisMsg.entities == null || luisMsg.entities.Count <= 0)
30                         reponse = "亲你要查询哪个地方的天气信息呢,快把城市的名字发给我吧";
31                     else 
32                         reponse = LuisWeather.Instance.GetWeather(luisMsg.entities[0].entity);
33                     
34                     break;
35                 case "股票查询":
36                     if (luisMsg.entities == null || luisMsg.entities.Count <= 0)
37                         reponse = "亲你需要要查询哪只股票信息呢,快把股票代码发给我吧";
38                     else
39                         reponse = LuisStock.Instance.QueryStock(luisMsg.entities[0].entity);
40 
41 
42                     break;
43                 //case "查询客户信息":
44                 //    reponse = LuisPartner.Default.QueryInfo(luisMsg.entities[0].entity);
45                 //    break;
46                 //case "查覆盖率":
47                 //    reponse = LuisStaConver.Default.QueryInfo(luisMsg.entities[0].entity);
48                 //    break;
49                 default:
50                     reponse = LuisInfos.DEFAULT_LUIS;
51                     break;
52             }
53 
54             return reponse;
55         }
56     }
57 }
View Code
  • 微信消息处理接口调用
/// <summary>
        /// 处理文字请求
        /// </summary>
        /// <returns></returns>
        public override  IResponseMessageBase OnTextRequest(RequestMessageText requestMessage)
        { 
            var responseMessage = base.CreateResponseMessage<ResponseMessageText>();
            if (requestMessage.Content == "您好" || requestMessage.Content == "你好")
            {
                responseMessage.Content = requestMessage.Content;
            }
            else {
                responseMessage.Content = LuisService.Instance.PostMessage(requestMessage.Content);
            }
 
            return responseMessage;
        }
        /// <summary>
        /// 处理语音请求
        /// </summary>
        /// <param name="requestMessage"></param>
        /// <returns></returns>
        public override IResponseMessageBase OnVoiceRequest(RequestMessageVoice requestMessage)
        {
            var responseMessage = CreateResponseMessage<ResponseMessageText>();

            responseMessage.Content = LuisService.Instance.PostMessage(requestMessage.Recognition.ToString());
           
            return responseMessage;
        }
View Code

 

 

 

 

 

 

 

内容来源于网络如有侵权请私信删除
你还没有登录,请先登录注册
  • 还没有人评论,欢迎说说您的想法!