2018/1/17 更新:olami更新了新版sdk,支持了新的接口,所以不再需要自己编译sdk了,相关的改动已经更新到了码云。


最近olami平台做了一次重大更新,增加了对上下文的支持,这里就研究一下如何用新的方式实现之前提到的上下文功能。

简介

这次更新的主要内容是osl语言中增加了一种特殊的grammar:context grammar。根据文档介绍,context grammar是一种特殊的grammar,作用是补充grammar的功能,通常被用来实现上下文。可以看出,要实现上一篇做到的上下文功能不再需要那么繁琐的方式。接下来就可以一步一步实现上下文功能。

编写grammar

首先,和前面例子类似,新建两个语法模块,为了和之前的区分,一个叫weather2,一个叫navi2。分别给他们加上slot和grammar,这样它们就有了查天气和导航的基本功能:

weather2
// time slot类型为datetime,place slot类型为ext,最短2最长10,高级设置中验证类别选为城市和区县天气1: <time>的天气<{@=query}>天气2: <place>的天气<{@=query}>天气3: (<time><place>|<place><time>)的天气<{@=query}>
navi2
// from和to两个slot设置和weather2中的place相同(不是必须相同)
导航1: 导航去<to><{@=navi}>导航2: (导航从<from>|从<from>导航)(去|到|至)<to><{@=navi}>

编写context grammar

然后,给他们添加上想支持的context grammar:

weather2的context grammar
context1    [查]<time>的
context2    [查]<place>的
context3    <place>的呢
navi2的context grammar
context1    去<to>
context2    从<from>出发
context3    从<from>出发去<to>

加完之后不要忘了发布一下。

修改客户端代码

最后,把之前的测试客户端做一下修改。现在语义平台已经支持了上下文,所以客户端不再需要保存的那些状态,而只需解析语义对应的应用,通过slot和modifier拿对应结果即可(详见文尾代码)。

需要注意的一点是,为了实现整句作为slot的值(如回复“北京”,希望作为slot place的值),我使用了这次更新的接口中的nli_config字段。官方的java client sdk在1.3.0版加入了这个字段的支持,代码中可以直接调用。

新的NliService

和前一篇上下文实现方案中的NliService对比,可以发现少了很多状态的维护,代码变的更简洁了。

package moredemo;import java.io.IOException;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;import ai.olami.cloudService.APIConfiguration;
import ai.olami.cloudService.APIResponse;
import ai.olami.cloudService.APIResponseData;
import ai.olami.cloudService.TextRecognizer;
import ai.olami.nli.NLIResult;
import ai.olami.nli.Semantic;
import app.App;
import app.NaviApp;
import app.WeatherApp;public class NliService {private static final String appkey = "7dec5096f65c4208b98f0e34a6cede8b";private static final String appSercert = "b11814754dea4966b020f64df5ae5e0a";private HashMap<String, App> appService = new HashMap<>();public static String slotname = null;private TextRecognizer recognizer = null;public void init() {APIConfiguration config = new APIConfiguration(appkey, appSercert, APIConfiguration.LOCALIZE_OPTION_SIMPLIFIED_CHINESE);recognizer = new TextRecognizer(config);// 初始化app服务,key与nli系统中的app名称对应,方便使用。appService.put("weather2", new WeatherApp());appService.put("navi2", new NaviApp());}public String process(String input) {String result = null;if (recognizer != null) {try {NLIConfig nliConfig = new NLIConfig();nliConfig.setSlotName(slotname);APIResponse response = recognizer.requestNLI(input, nliConfig);slotname = null;result = handleResponse(response);} catch (NoSuchAlgorithmException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();} catch (Exception e) {e.printStackTrace();}}return result;}private String handleResponse(APIResponse response) {if (response.hasData()) {APIResponseData data = response.getData();if (data.hasNLIResults()) {NLIResult nliResult = data.getNLIResults()[0];String content = nliResult.getDescObject().getReplyAnswer();if (nliResult.getDescObject().getStatus() == 0 && nliResult.hasSemantics()) {Semantic sem = nliResult.getSemantics()[0];String appname = sem.getAppModule();App app = appService.get(appname);if (app != null) {return app.getResult(sem);} else {return "错误:未知服务类型";}} else {return content;}}}return "抱歉,你说的我还不懂";}public static void recordSlotInQuestion(String slotvalue) {slotname = slotvalue;}
}

测试

测试如下几种情形:

导航的上下文:

天气的上下文:

天气和导航对整句做slot的处理:

直接说context grammar的内容会听不懂:

总结

通过测试能够看到,前一句由模块的grammar处理时,匹配context grammar的后一句才会被该模块继续处理。之后输出的是合并好的语义,客户端使用时无需区分context grammar还是grammar,也不用考虑话题切换等问题,直接使用语义取得结果即可。

经过此次更新,可以说olami平台可支持的语义理解功能得到了进一步完善,只要开发者经过细心雕琢,就能提供不输于主流语音助手的体验。context grammar这个概念的增加,使客户端的开发者可以专注于应用功能的开发,而不必纠结于每一句话之后状态如何改变,不同模块的说法互相冲突等问题。

源码地址:

https://gitee.com/stdioh_cn/moredemo2

新的实现上下文对话的方法相关推荐

  1. Android R 通知新特性—人与对话(气泡窗)

    文章目录 对话 Conversation Space Bubbles 通知中心的Bubble 如何弹出Bubble(app端相关) 系统是如何弹出Bubble的(源码相关) Android R 通知新 ...

  2. 【线上直播】人机多轮对话的方法综述

    讲师:庞雨秾 讲师简介: 法狗狗法律人工智能技术总监,伦敦大学玛丽女皇学院认知科学硕士.专注于自然语言处理方面的研究与应用,负责研发了包括处理垂直于法律领域的智能咨询系统.分布式非结构化文本挖掘系统等 ...

  3. Java8 新特性:Lambda 表达式、方法和构造器引用、Stream API、新时间与日期API、注解

    Java8新特性:Lambda 表达式.方法和构造器引用.Stream API.新时间与日期API.注解 1.Java8新特性 1.1.主要的新特性: 1.2.编程风格 2.Lambda 表达式 2. ...

  4. 一种新的高级抖动分离解析方法

    一种新的高级抖动分离解析方法 A new analytic approach for advanced jitter separation 抖动分量的分析是现代通信系统调试中一项越来越重要的任务.一方 ...

  5. maven上解决循环依赖、又不想新加第三模块的方法

    maven上解决循环依赖.又不想新加第三模块的方法 参考文章: (1)maven上解决循环依赖.又不想新加第三模块的方法 (2)https://www.cnblogs.com/yuan951/p/89 ...

  6. php新浪api,php调用新浪短链接API的方法,php调用新浪api_PHP教程

    php调用新浪短链接API的方法,php调用新浪api 本文实例讲述了php调用新浪短链接API的方法.分享给大家供大家参考.具体方法如下: 复制代码 代码如下: //Sina App_Key def ...

  7. 新浪短链api java_php调用新浪短链接API的方法

    本文实例讲述了php调用新浪短链接API的方法.分享给大家供大家参考.具体方法如下: //Sina App_Key define('SINA_APPKEY', '31641035'); functio ...

  8. Java黑皮书课后题第7章:*7.12(倒置数组)7.7节中的reverse方法通过复制到新数组实现倒置。改写方法将参数中传递的数组倒置,并返回该数组。编写一个测试程序,输入10个数字,倒置它们并显示

    7.12(倒置数组)7.7节中的reverse方法通过复制到新数组实现倒置.改写方法将参数中传递的数组倒置,并返回该数组.编写一个测试程序,输入10个数字,倒置它们并显示 题目 题目描述 破题 代码 ...

  9. jQuery 往table添加新内容有以下四个方法:

    Query 添加新内容有以下四个方法: append() - 在被选元素的结尾插入内容 prepend() - 在被选元素的开头插入内容 after() - 在被选元素之后插入内容 before() ...

最新文章

  1. Windows启动exe应用程序,无法正常启动(0xc000007b)的解决办法
  2. 用vs2017编写html,vs2017可以编写java
  3. 函数对象,名称空间与作用域,闭包,装饰器
  4. Java阻塞队列 LinkedBlockingDeque
  5. 修改 Workshop 中 text box 输入内容的颜色
  6. java实现qq抢红包_Java实现抢红包功用
  7. z变换判断稳定性和因果性_图像处理的仿射变换与透视变换
  8. filebeat 配置文件详解
  9. linux Kernel Map
  10. fpga数电基础之--------触发器
  11. [转载] 机器学习模型的保存和调用
  12. BootStrap的基本使用
  13. 批量文件转换:PDG转PDF并合并
  14. 基于FPGA的自动售货机设计(EDA课程设计)(湖南科技大学)
  15. pulse 去马赛克软件_一款号称能去马赛克的软件,却在面对游戏角色时“翻了车”...
  16. linux下的c++filt 命令
  17. Typora一款让你无法拒绝的MarkDown编辑器
  18. JVM成神之路-HotSpot虚拟机-编译原理、JIT、编译优化
  19. 整数分解(java)
  20. Word 中插入高亮代码 | planetB | syntax-highlight-word

热门文章

  1. 从零开始学Go之并发(四):互斥
  2. 42 github 开源代码 ——README.md语法/相关操作等
  3. Python3 局部变量与全局变量作用域
  4. Python语法教程-基础语法01
  5. Code POJ - 1780(栈模拟dfs)
  6. 最小路径和--p64--动态规划
  7. channel(4)定时器
  8. C#错误异常日志记录到文件
  9. 读写文本文件和二进制文件——二进制模式
  10. 登录验证---添加验证码验证,Cookie保存功能