aiml简介+源代码解析+中文分词(java)
本文整合了看到的几篇博客并结合了笔者自己的尝试,记录下对aiml的浅显理解,想了解的更深入还是要靠自己探索呀!
目录
一、简介
二、原理+源代码解析
三、中文分词尝试
四、注意
五、优势与缺点(个人理解)
一、简介
AIML,全名为Artificial Intelligence Markup Language(人工智能标记语言),是一种创建自然语言软件代理的XML语言,最初来源于一个名为"A.L.I.C.E."的聊天机器人。
简言之,AIML就是用户通过定义的规则模板进行问答匹配,来实现聊天机器人自动问答的功能
下面展示了一个最基本的例子,仅包含最主要的<category><pattern><template>三种标签
<category><pattern>你好</pattern><template>您好,很高兴认识您。</template> </category>
当用户输入问题“你好”时,机器人就会匹配到这个pattern,然后将<template>中的内容作为答案返回
标签的详细说明可以参考https://www.tutorialspoint.com/aiml/index.htm
二、原理+源代码解析
1.原理
原理参考了春雨里de太阳的AIML知识库数据匹配原理解析这篇博客(感谢!)
一个通常流程是:
首先系统初始化,包括问句规范化配置、加载许多配置属性等然后将aiml问答知识库以树的形式加载到内存,将其拆分成单个词,结构类似trie tree,在java源码中就是Graphmaster对象(节点和子节点来存储知识节点)
然后接受用户输入,将问句规范化,并将其拆成一个个单词
进而查询匹配标签
最后根据最佳匹配,完善模板(比如*填充,index填充等)返回答案
2.源代码解析
代码逻辑:
(1)用Chat类实现会话,工厂创造bot对象
(2)解析aiml,在aiml包下 AimlHandler类,里面包含对多种标签的解析,生成context和graphmaster对象
解析主入口在aliceBotParser的parse方法。
主要通过AimlHandler中的startElement和endElement方法调用pushTextNode()方法,将解析的一个完整标签内容压入stack
然后构造context对象(包含了所有aiml文件的节点、配置和上下文信息,节点存在transformation属性中,配置信息存储在properties属性中),其中transformations对象主要存储的是语句分离器,问句规范化处理信息
同时构造了graphmaster对象,通过newGraphmaster方法把解析的<category>加入到graphmaster对象中
handler.unload方法从读取xml生成的stack里面弹出元素
aiml中的基本知识单元<category></category>主要存储在category对象中,如上图所示,解析aiml文件后,返回存储问答对的Category类型的list,然后作为graphmaster对象的属性
bot要装载context对象和graphmaster对象,这样,bot就带着aiml中的配置和知识去回答用户提问
(3)用户输入,调用bot对象的respond方法
先利用用户的input生成request对象,request对象是请求对象,属性为original和sentences,original为问句,然后将sentence规范化,赋给request对象
(4)进一步调用重载的respond方法,调用graphmaster的match方法匹配sentence到对应的category,调用process方法,返回<template>标签的内容:value.toString
再调用response.append方法,将response对象的original(答案)设置为category的template回复内容
(5)把response添加进context的response链表中,这样会话历史就被存储到context对象中
(6)返回respond的最终返回值:response.original.toString()
三、中文分词尝试
参考了https://blog.csdn.net/zhang_hui_cs/article/details/22686951这篇博客
aiml默认是不支持中文的,如原理中知识节点图所示,知识节点都是按空格切分的,所以aiml支持默认按空格分割的英文,这样才能匹配,而不支持中文,所以支持中文的关键就是将中文分词后加空格分割
因而需要修改的地方有三个:
(1)解析aiml文件时<pattern>和<that>标签内容中文分词空格分割
对应于源码解析中的解析aiml时利用putNextNode方法将标签压栈,修改中文分词即可,我采用了Hanlp,可个性化定制
/*** 中文分词重载, 分词后中间加空格* 然后应用到that和pattern标签* @param isToChineseSegment*/private void pushTextNode(Boolean isToChineseSegment){String pushed = text.toString();text.delete(0, text.length());if (ignoreWhitespace)pushed = pushed.replaceAll("^[\\s\n]+|[\\s\n]{2,}|\n", " ");if(!"".equals(pushed.trim())){if(!isToChineseSegment){stack.push(new Text(pushed));}else{String result = "";List<Term> list = HanLP.segment(pushed);for(Term term:list){result += term.word + " ";}stack.push(new Text(result.trim()));}}}
然后在调用它的startElement和endElement方法中修改
//pushTextNode(); //英文分词pushTextNode(qname.toLowerCase().equals("pattern") ||qname.toLowerCase().equals("that") || qname.toLowerCase().equals("srai")); //中文分词
(2)读取用户question中文分词空格分割
修改Transformation类的normalization方法
public void normalization(Sentence sentence){//String input = breakWords(sentence.getOriginal());//---对用户输入中文分词---String result = breakWords(sentence.getOriginal());String input = "";List<Term> list = HanLP.segment(result);for(Term term:list){input += term.word + " ";}//------------------------input = ' ' + input + ' ';input = input.replaceAll("\\s{2,}", " ");sentence.setOriginal(input);Mapper mapper = new Mapper(input);input = substitute(input, mapper);input = fit(input, mapper);sentence.setMappings(mapper.toArray());sentence.setNormalized(input);}
(3)规范化处理类Transformations中需要修改正则表达式匹配,使其能够匹配中文
//private final Pattern fitting = Pattern.compile("[^A-Z0-9]+"); //正则表达式匹配英文+数字private final Pattern fitting = Pattern.compile("[^A-Z0-9\u4e00-\u9FA5]+"); //添加中文字符
经笔者简单测试,可以进行中文模糊匹配
<category><pattern>_行不行_</pattern><template>不可以!</template></category> <category><pattern>*能不能*</pattern><template>能!</template></category>
四、注意
1. aiml元素属性是大小写敏感的,修改时,pattern元素中的英文都要大写
2. 自定义标签:只需继承TemplateElement类,核心方法是process方法,它的返回值直接作为答案返回给用户
然后在aiml文件中添加
<category><pattern>测试</pattern><template><b/></template></category>
其中B就是自定义的标签类
public class B extends TemplateElement
{/*Constructors*/public B(Attributes attributes){}public B(Object... children){super(children);}/*Methods*/public String process(Match match){return "user-defined";}
}
这样输入“测试”,机器人就会回复“user-defined”
3. bot.respond()往往需要一个session参数,因为面对不同用户时,能够进行区分
五、优势与缺点(个人理解)
1.优势:
第一部分展示的demo例子其实完全可以用问答对构建,然后检索的方式解决,不需要如此复杂。
aiml的优势有以下几点:
(1)支持通配符,即模糊匹配
这就使得aiml可以利用一个category解决很多相同句式的问题;而且,<srai>标签解决了检所匹配问答对扩充时答案的冗余
(2)多种功能标签的辅助
比如<random>,增加了回复的多样性
<if><condition>判断条件
<topic>根据主题匹配
<system>learn</system>学习功能,学习用户输入的正确答案
(3)会话机制
基于aiml构建的chatbot支持会话机制,使得机器人具有一定程度的基于上下文语境的多轮对话功能,而且机器人能够区分不同的用户角色。
比如同样的问句“你好”,机器人对于不同人就会回复“你好,张三”、“你好、李四”
2.缺点
因为是基于规则匹配,缺点也很明显
(1)依赖规则的构建复杂程度,以及aiml覆盖知识的多少,规则构建完善、语料大效果自然好。
当针对特定领域的问答时,采用aiml方式构建个性化的标签和采用其他方式比如检索匹配,知识图谱,深度学习技术等等需要评估可行性和效果,可以采用aiml进行辅助,多模块整合
(2)人工的费时费力
aiml简介+源代码解析+中文分词(java)相关推荐
- 中科院NLPIR中文分词java版
中科院NLPIR中文分词java版 中科院NLPIR中文分词java版
- Ansj中文分词Java开发词性分类
用ansj分词后,只提取满足提交的词性的单词. Ansj下载地址:http://maven.ansj.org/org/ansj/ansj_seg/ 辅助包NLP下载地址:http://maven.an ...
- Ansj中文分词Java开发小记
1.ansj中文分词器:https://github.com/NLPchina/ansj_seg 基于n-Gram+CRF+HMM的中文分词的java实现. 分词速度达到每秒钟大约200万字左右 ...
- Ansj中文分词Java开发自定义和过滤词库
Ansj中文分词应用时,需要自定义词库,比如城中村,分词成城.中.村,需自定义词库,有时,也需要过滤单词.具体代码如下,可以结合执行结果看代码效果. 1.过滤词库 package csc.ansj;i ...
- java将输出的内容存入词典,中文分词JAVA实现(基于已知的词典txt)
这是我第一次写博客,里面有些内容可能描述不当,但是我能保证最后的程序可以在eclipse环境下运行 最近有了作业,要求写中文分词程序,主要是依据一个词典,txt文本,里面是词语,然后要求依据词典,对输 ...
- java nlpir_中科院NLPIR中文分词java版
摘要:为解决中文搜索的问题,最开始使用 版 SCWS ,但是处理人名和地名时,会出现截断人名地名出现错误.开始使用 NLPIR 分词,在分词准确性上效果要比 SCWS 好.本文介绍如何在 系统下 JA ...
- 几种常见的中文分词包的分析与比较
1:中文分词简介 2:Lucence的中文分词 3:庖丁分词简介 4:IK中文分词简介 一:中文分词简介 1:分词算法分类 -----基于字符串匹配的中文分词方法 eg:句子:我来自沈阳航空航天大学 ...
- 2019年了,中文分词到底该怎么做?中文分词十年方法大盘点(附下载)
https://www.toutiao.com/a6655113946241958403/ 2019-02-07 12:41:03 基本上所有的中文自然语言处理任务,第一步都需要先分词.中文分词是中文 ...
- word中文分词 一
前言:这篇笔记算是 word中文分词 java库的入门笔记,记录下word分词的基本配置,和一个由于经验浅而踩的坑. 感谢word分词 的作者,word分词的github地址:http ...
- ictclas4j java_ictclas4j 中科院中文分词系统完成的java源码,能很好的实现 的 ,为文本挖掘提供基础。 Develop 238万源代码下载- www.pudn.com...
文件名称: ictclas4j下载 收藏√ [ 5 4 3 2 1 ] 开发工具: Java 文件大小: 6617 KB 上传时间: 2013-12-06 下载次数: 4 提 供 者: 黄倩 ...
最新文章
- python 换行符的识别问题,Unix 和Windows 中是不一样的
- url,html,javascript中的转义字符
- 【校招面试 之 C/C++】第17题 C 中的malloc相关
- python操作redis中的list
- 基于C#的计时管理器
- cross-entropy函数
- tomcat服务器运行环境,win7怎么配置Tomcat服务器环境|win7系统配置Tomcat服务器环境的方法...
- 船舶定位实时查询系统_港口人员精准定位系统,实时安全管控与智能预警
- 2021 年软件工程现状:Python 或将成为第一大编程语言,中国开源涨势最猛
- Response.AddHeader
- tomcat套接字接受失败_07 | What? 还有本地套接字?
- 雨棚板弹性法计算简图_悬挑雨棚板结构计算小工具Exce版
- CAD迷你看图 for Mac(MiniCAD)
- 2022-2027年中国洗面奶市场规模现状及投资规划建议报告
- 【工业大数据】工业大数据层层深度解析!
- 【物联网】21.物联网开发之先进传感 - RGB-D 传感器
- 《算法竞赛入门经典》 习题 4-1 (Xiangqi, ACM/ICPC Fuzhou 2011, UVa1589,hdoj_4121)
- 宽带和光纤宽带的区别
- Kali Linux(2021.2)系统 安装中文输入法
- 数据分析技术:结构方程模型;想要“追求”,了解是第一步