根据OLAMI平台开发的日历Demo
来源:互联网 发布:学车电销数据 编辑:程序博客网 时间:2024/06/07 09:04
前言
在自然语言处理中,语义理解一直是个难题。
最近发现OLAMI语义平台提供了自然语言语义理解 API ,而且支持自定义语法,所以决定写一个日历的Demo来看一下效果。
生成语法
想要使用自然语言语义理解 API,首先我们需要提前创建自己的帐号、应用以及编写自己的语法。
创建应用
创建帐号的过程,在这里就不详述了,OLAMI的官网主页上就有注册入口。
创建完帐号之后,登录成功就可以看到如下界面:
点击创建新应用,跳转到如下界面:
在上面的界面分别填写上应用名称、应用类型和应用描述,点击提交就可以创建成功了。
经过测试,除了应用类型只能选择固定的内容,其他两项可以按照自己喜好填写任意字段,在这里,我主要是想开发一个日历程序,所以就以“日期时间”来命名。
编写语法
在登录成功之后看到的页面上,除了创建新应用,还有一个“进入NLI系统”的按钮。
点击之后,就可以进入NLI 自然语言语义互动系统编写语法了。
OLAMI平台对“NLI 自然语言语义互动系统”和“OSL 语法描述语言”都有详细的文档说明。我在这里就只简单的描述一下。
首先,我们可以点击新增,创建一个模块,用来写某一类相关联的语法。例如:可以创建“music”模块用来写音乐相关的语法、“weather”模块用来写天气相关的语法。这样的好处是,对于前面创建的不同应用,可以导入不同的模块语法。(应用导入模块的内容会在后面单独列出来)
我在这里就可以新建一个“date”模块。点击进入模块就可以开始编写语法了。
当然,这里有一个更方便的方法——就是直接导入内置模块的语法。前提条件就是,语法平台提供的内置模块刚好和你需要开发的模块相一致或者相近。
刚好,内置模块里面提供了“date”,可以直接选择导入。
到了这里,还不能算完成了,因为这时候的语法还不能使用,还需要在发布页面点击发布。当看到“发布成功”的提示之后,编写语法的工作才算完成了。
配置模块
在我的应用里面,可以对每一个创建的应用分别配置模块。
我这边只有date模块,勾选上即可。
前面提到的分模块写语法的好处就体现在这里。如果有创建了多个应用,同时又多个模块的语法,就可以根据对应的应用需求去选择对应的语法,而不需要为每一个应用去单独写语法了。
日历Demo
完成了语法的工作之后,就可以开始来应用程序的开发了。
语义理解请求
OLAMI提供了几种不同的API接口,我们这里主要使用“语义理解请求”,接口在“OLAMI 文档中心”都有详细的描述。
在调用接口的时候,需要注意两个参数——appkey和sign。
API 请求参数中的 sign 为一个字符串,其值必须是由以下规则所组合成的字符串所生成的 MD5 值。 your_app_secret + api=api_parameter + appkey=your_app_key + timestamp=current_timestamp + your_app_secret
其中的your_app_key(同appkey)和your_app_secret是从前面创建的应用中获取的。
如下图所示(找到对应的应用之后,点击查看Key即可):
获取到了App Key和App Secret就可以调用接口了,以下是接口调用示例:
public static JSONObject process (String input) { JSONObject NLIresult = new JSONObject(); List<NameValuePair> params = new ArrayList<NameValuePair>(); params.add(new BasicNameValuePair("appkey", Appkey)); //Appkey为上图中的App Key params.add(new BasicNameValuePair("api", nli)); // 值必须是 ‘nli’ long timestamp = Calendar.getInstance().getTimeInMillis(); params.add(new BasicNameValuePair("timestamp", String.valueOf(timestamp))); params.add(new BasicNameValuePair("sign", generateSign(timestamp))); // generateSign方法根据规则生成sign JSONObject request = new JSONObject(); JSONObject data = new JSONObject(); try { data.put("input_type", 1); // input_type具体含义可参照文档,由于这里不需要语音输入,默认填1即可 data.put("text", input); // input为需要解析的语句;例如“今天是几号” request.put("data_type", "stt"); request.put("data", data); } catch (JSONException e1) { e1.printStackTrace(); return NLIresult; } params.add(new BasicNameValuePair("rq", request.toString())); params.add(new BasicNameValuePair("cusid", cusid)); // cusid终端用户识别码;如果是手机应用,上传IMEI即可 CloseableHttpClient httpclient = HttpClients.createDefault(); HttpPost httppost = new HttpPost(url); // 接口url:https://cn.olami.ai/cloudservice/api try { httppost.setEntity(new UrlEncodedFormEntity(params, "UTF-8")); CloseableHttpResponse response = httpclient.execute(httppost); try { HttpEntity entity = response.getEntity(); if (entity != null) { String contnt = EntityUtils.toString(entity); System.out.println("Response content: " + contnt); NLIresult = new JSONObject(contnt); } } finally { response.close(); } } catch (Exception e) { e.printStackTrace(); return NLIresult; } finally { try { httpclient.close(); } catch (Exception e) { e.printStackTrace(); } } return NLIresult;}
语义处理
如果输入的语句能够匹配上对应的语法的话,在调用接口之后,就能够根据对应语法的内容返回语义结构了。
语义结果的详细描述请参考NLI 输出结果。由于我们的模块主要是语义输出,所以主要关心“semantic”字段里面的内容就可以了。
以下是解析Semantic的示例代码:
private static Semantic parseSemantic(JSONObject semantic) { Semantic s = new Semantic(); if (semantic == null || !"ok".equalsIgnoreCase(semantic.optString("status", ""))) return s; JSONObject data = semantic.optJSONObject("data"); JSONArray s_list = data.optJSONArray("nli"); JSONObject s_first = s_list.optJSONObject(0); JSONObject desc_obj = s_first.optJSONObject("desc_obj"); s.status = desc_obj.optInt("status", -1); if (0 != s.status) { s.answer = desc_obj.optString("result", "some error occured"); return s; } JSONObject intention = s_first.optJSONArray("semantic").optJSONObject(0); JSONArray modifier = intention.optJSONArray("modifier"); for (int i = 0; i != modifier.length(); i++) { s.modifiers.add(modifier.optString(i, "")); } JSONArray slots = intention.optJSONArray("slots"); for (int i = 0; i != slots.length(); i++) { JSONObject record = slots.optJSONObject(i); Slot slot = new Slot(); slot.name = record.optString("name", ""); slot.value = record.optString("value", ""); slot.datetime = record.optJSONObject("datetime"); s.slots.put(slot.name, slot); } return s;}class Semantic { String app = ""; String answer = ""; Map<String, Slot> slots = new HashMap(); List<String> modifiers = new ArrayList<>(); // status -1表示未处理的错误;0表示正常输出;其他数值对应不同的系统错误。 int status = -1;}class Slot { String name = ""; String value = ""; JSONObject datetime = new JSONObject();}
根据语义生成最终结果
当获取到了modifiers和slots之后,就可以根据不同modifier所对应的含义和slots的值去获取最终结果了。这个处理过程完全是由自己决定的,输出结果也是任意的。
例如:
输入“今天是几号”,通过调用语义理解的接口之后,在返回的Semantic中包含modifier(query_gregorian)和slot(今天)。
query_gregorian表示的是用户输入的语句意图为查询公历日期。
slot表示用户指定查询的时间为“今天”。
针对上面这个语义,我们当然可以直接回复“14号”,也可以回复“今天是6月14号”,甚至可以返回结果“我不想告诉你今天是几号”。
由于Demo程序处理的语义类别比较多,这里我就不给出具体的示例代码了。大家可以直接去github上查看或者下载源码。里面实现了包括农历计算、时区转换、节假日计算等各种功能。
最终效果展示
为了方便展示,我做了一个简单的展示界面。
可以将需要处理的语句填入“文本输入框”,点击send按钮。
NLI 输出结果会展示在“语义输出框”中。
最终处理结果会展示在“结果输出”中。
- 根据OLAMI平台开发的日历Demo
- 自然语言处理-实际开发:用语义开放平台olami写一个翻译的应用
- 日历开发demo
- 运营平台开发日历
- 基于qualcomm平台的无人机开发demo
- 使用OLAMI自然语言开放平台提供的API接口制作自己的语音助手
- olami开放平台语法(grammar)编写简介
- MAVEN3的安装 淘宝开发平台 TAE2.0 demo java
- 根据工作日历推算工作日的算法
- 带手势滑动的日历Demo
- 基于vue的日历小demo
- Android开发之MVP模式(根据google的demo的修改版)
- 根据年份输出日历
- Duilib 日历demo
- 日历组件demo
- 【PHP】日历Demo
- 简单日历Demo
- 腾讯微博开发平台开发,android平台一个微博的demo,OATUH2.0版本,教程一
- lintcode(653)Add Operators
- codeforces 472A Design Tutorial: Learn from Math
- Spring(一)概况
- SDOI2013 森林
- 【Android】【Framework】MessageQueue
- 根据OLAMI平台开发的日历Demo
- 正则表达式
- Vue中的$set的使用
- 网址收藏
- 子类虚函数调用无效
- RecyclerView的学习理解
- java并发包学习系列:future模式
- J2EE系列之Spring4学习笔记(九)--Spring对JDBC的支持
- Vue豆瓣系列文章