Java接入UNIT文本对话处理源码详解
荒墨丶迷失 发布于2017-11-22 15:41 浏览:11489 回复:41
5
收藏

应邀一位网友的想法,想实现调用UNIT接口,实现文字对话功能,特整理一下内容分享给大家。

此功能对于大神来说非常简单,但是对于新手理解代码处理逻辑,并且如何解析UNIT返回参数的处理,还是有一定的帮助的

嘿嘿~文章最下方有源码下载地址哟~

如果您还不了解UNIT的使用,请移步到UNIT文档,请认真阅读~

http://ai.baidu.com/docs#/UNIT-sample/top

并且能够训练出该场景的机器人,本文例子就是利用这个天气机器来做对接的。

 

接下来看下对话交互的页面效果,请看下方图片

以上是整体的交互效果,那么现在简单的来说说怎么搭建这个项目的步骤:

1.训练出UNIT场景模型(此处为天气查询场景)

2.导入此例子的源码项目(java开发)

3.修改token配置

4.启动项目即可

按照以上步骤一步一步进行,先看看该项目的包结构

注意:获取token类之后,把token复制到UNIT核心类中,并且还需要记得修改场景ID,以下是核心类的作用:解析UNIT返回的JSON数据,获取我们需要的数据

此处能力有限,只能一步一步利用JSON解析,hhhh~

  //获得返回的json数据
	        String str = HttpUtil.post(talkUrl, accessToken, "application/json", params);
	     	System.out.println(str);
	     	//获得result
	     	JSONObject jsonobject = JSONObject.fromObject(str);
	     	String result = jsonobject.getString("result");
	     	System.out.println(result);
	     	//获得会话session_id
	    	JSONObject jsonobject2 = JSONObject.fromObject(result);
			session_id = jsonobject2.getString("session_id");
			map.put("session_id", session_id);
			//获得动作列表
			String action_list =jsonobject2.getString("action_list");
			JSONArray json = JSONArray.fromObject(action_list); // 首先把字符串转成 JSONArray  对象
			if(json.size()>0){
			    for(int i=0;i<json.size();i++){
			        JSONObject job = json.getJSONObject(i);  // 遍历 jsonarray 数组,把每一个对象转成 json 对象
			        String say = (String) job.get("say");//机器bot返回的话术
			        map.put("say", say);
			        System.out.println(say);
				    String action_id = (String) job.get("action_id");//动作名称,当为fail_action时表示未能命中任何意图
				    map.put("action_id", action_id);
				    if(!"fail_action".equals(action_id)){//命中意图
					    Object object = job.get("action_type");//获得action_type对象  动作详细
				        JSONObject jsona = JSONObject.fromObject(object);//转成json对象
				        String act_type = jsona.getString("act_type");//动作类型,取值clarify/satisfy/guide
		//				    clarify: 澄清 ; satisfy: 满足 ; guide: 引导 ;faqguide: faq引导
		//			    info.setAct_type(act_type);
				        map.put("act_type", act_type);
				        if("satisfy".equals(act_type)){
				    	    //解析意图概要
				    	    String schema =jsonobject2.getString("schema");//获得意图概要
				    	    JSONObject jsonObect = JSONObject.fromObject(schema);
				    	    String current_qu_intent = jsonObect.getString("current_qu_intent");//获得当前意图
				    	    String bot_merged_slots = jsonObect.getString("bot_merged_slots");//词槽列表  
				    	    map.put("current_qu_intent", current_qu_intent);
				    	    map.put("bot_merged_slots", bot_merged_slots);
				        }else{
				        	map.put("mapSchema", null);
				        }
				    }else{
				    	map.put("act_type", null);
				    }
			    }

然后在分享控制层的作用:

1.首先用一个Map接收解析的数据,传到控制层,然后

2.判断是否命中意图,

3.如果命中意图,该意图是否完成还是未完成,

4.既然是命中意图,那么命中的是那个意图,需要做什么样的逻辑处理.

//调用unit分析语音
					Map<String, String> map = UnitService.utterance(session_id, msg);
					//判断是否命中意图
					if(!"fail_action".equals(map.get("action_id"))){
						//判断是否意图结束
						if("satisfy".equals(map.get("act_type"))){
							session_id="";//意图结束,清空session_id
							/**
							 * 以下是意图处理逻辑,根据命中的意图,判断进入当前意图的对话处理  current_qu_intent字段为意图
							 */
							switch (map.get("current_qu_intent")) {
								case "RAIN": //查询是否下雨
									//解析是否刮风的词槽列表
									String companyParams = getCompany(map.get("bot_merged_slots"));
									if(!companyParams.equals("")){
										modelMap.put("companyParams", companyParams);
									}else{
										modelMap.put("companyParams", map.get("raw_query"));
									}
									modelMap.put("queryType", "COMPANY");
									break;
								case "WIND": //查询是否刮风
									//解析是否刮风的词槽列表
									String companyParams2 = getCompany(map.get("bot_merged_slots"));
									if(!companyParams2.equals("")){
										modelMap.put("companyParams", companyParams2);
									}else{
										modelMap.put("companyParams", map.get("raw_query"));
									}
									modelMap.put("queryType", "COMPANY");
									break;
								default:
									break;
								}
						}else{
							//意图未完成 需要传入session_id 用户下一次对话
							session_id = map.get("session_id");
						}
						//返回机器人说的bot  不管意图有没有命中
						modelMap.put("msg", map.get("say"));
					}else{
						modelMap.put("msg", "我好像不太明白");
					}

接下来咋们看前台的一个处理,这是页面上的发送消息的一个函数,作用:

1.获取文本消息,加载到聊天页面样式中

2.ajax调用后台控制层,然后判断是否正常返回数据

3.加载机器回复消息样式

//发送消息
function sendMessage(event, from_name){
	//获得发送的消息
    var msg = $("#message").val();
// 	alert(msg);
    //自己回复的样式加载
	var htmlData =   '<div class="msg_item fn-clear">'
                   + '   <div class="uface"><img src="../images/hetu.jpg" width="40" height="40"  alt=""/></div>'
			       + '   <div class="item_right">'
			       + '     <div class="msg own">' + msg + '</div>'
			       + '     <div class="name_time">' + from_name + ' · 30秒前</div>'
			       + '   </div>'
			       + '</div>';
	$("#message_box").append(htmlData);
	$('#message_box').scrollTop($("#message_box")[0].scrollHeight + 20);
	$("#message").val('');
	
	var session_id = $("#session_id").val();
	$.ajax({
   		type:"POST",
   		url:"${pageContext.request.contextPath}/unit/common.do",
//    	datatype: "json",
   		data:{
   			"session_id":session_id,
   			"msg":msg
   		},
   		success:function(data){
	   		var mes = eval(data);
	   		if (mes.success) {
	   			var msg = data.msg;
	   			var session_id = data.session_id;
	   			$("#session_id").val(session_id);
	   		 	//机器人回复样式加载
	   			var htmlData =   '<div class="msg_item fn-clear">'
	   		                   + '   <div class="uface"><img src="../images/53f442834079a.jpg" width="40" height="40"  alt=""/></div>'
	   					       + '   <div class="item_right">'
	   					       + '     <div class="msg">' + msg + '</div>'
	   					       + '     <div class="name_time">' + '机器人 ' + '· 30秒前</div>'
	   					       + '   </div>'
	   					       + '</div>';
	   			$("#message_box").append(htmlData);
	   			$('#message_box').scrollTop($("#message_box")[0].scrollHeight + 20);
	   			$("#message").val('');
	   			
	   		} else {
	   			alert("返回数据失败");
	   		}
   		},
   		error: function(){
    		//请求出错处理
    		alert("出情况了");
    		}         
  		});
}

经过前台和后台的一些讲解,不知道大家清楚不,如果有任何问题,可以在下方回复我

感谢支持~

附加源码下载:https://gitee.com/liyingming/unitTest

收藏
点赞
5
个赞
共41条回复 最后由爱上主丽叶回复于2018-04-26 12:00
#42爱上主丽叶回复于2018-04-26

ajax老是用不好,老是报错,真是够了。

0
#41人人心人土土回复于2018-04-20
#40 荒墨丶迷失回复
这个时间还有点久了 懵了 哈哈 稍等我想想看~

多谢大神

0
#40荒墨丶迷失回复于2018-04-19
#39 人人心人土土回复
[图片] 1.判断是否是刮风词槽列表的目的是什么呢?后面并没有用到“companyParams”呀? 2.获取的词槽列表中为什么中有一个词槽呢? 3.“queryType”代表什么呢?
展开

这个时间还有点久了 懵了 哈哈 稍等我想想看~

1
#39人人心人土土回复于2018-04-19

1.判断是否是刮风词槽列表的目的是什么呢?后面并没有用到“companyParams”呀?

2.获取的词槽列表中为什么中有一个词槽呢?

3.“queryType”代表什么呢?

0
#38荒墨丶迷失回复于2018-03-22
#36 厦门KP回复
百度有没有开放API来修改词槽、意图、样本,? 不想通过百度后台去管理,想直接通过API来管理
展开

目前UNIT还在不断升级中  等待下一次的升级吧~

1
#37卡农LLLL回复于2018-03-22
#36 厦门KP回复
百度有没有开放API来修改词槽、意图、样本,? 不想通过百度后台去管理,想直接通过API来管理
展开

听说是下一步的计划.会有接口来做你说的这些

0
#36厦门KP回复于2018-03-21

百度有没有开放API来修改词槽、意图、样本,?

不想通过百度后台去管理,想直接通过API来管理

0
#35荒墨丶迷失回复于2018-03-02
#32 sunmenmian回复
想问一下如果对话很多内容一个一个词槽匹配是不是太复杂了?

你好  请问您的具体需求是什么呢  可以通过正则表达 以及对话样本来扩大交互场景的。

1
#32sunmenmian回复于2018-03-02

想问一下如果对话很多内容一个一个词槽匹配是不是太复杂了?

0
#31荒墨丶迷失回复于2018-01-07
#30 goJhou回复
真xx有钱+1

肯定没两位大佬有钱 哈哈  要么看运气公众号抽一个。哈哈哈

1
#30goJhou回复于2018-01-05
#28 荒墨丶迷失回复
就是撒 不如买个reven H吧 也算是高级 板子2.0

真xx有钱+1

0
#29卡农LLLL回复于2018-01-04
#28 荒墨丶迷失回复
就是撒 不如买个reven H吧 也算是高级 板子2.0

............真XX有钱..

0
#28荒墨丶迷失回复于2018-01-03
#27 卡农LLLL回复
没板子集成android的也行撒.

就是撒 不如买个reven H吧 也算是高级 板子2.0

1
#27卡农LLLL回复于2018-01-03
#26 荒墨丶迷失回复
是哇 不过我的板子就是 2.0 哈哈哈

没板子集成android的也行撒.

0
#26荒墨丶迷失回复于2018-01-02
#25 goJhou回复
你看我说什么来着hhh,真的2.0了

是哇 不过我的板子就是 2.0 哈哈哈

0
#25goJhou回复于2018-01-02
#21 荒墨丶迷失回复
这....迭代真快~

你看我说什么来着hhh,真的2.0了

0
#24荒墨丶迷失回复于2018-01-02
#23 静心之王回复
好东西!

恭喜你成功的发现了~

1
#23静心之王回复于2018-01-02

好东西!

0
#22卡农LLLL回复于2017-11-27

貌似今天要发2.0的DuerOS了.

0
#21荒墨丶迷失回复于2017-11-27
#20 goJhou回复
等你板到了,板子2.0就出了

这....迭代真快~

0
TOP
切换版块