本文整合了看到的几篇博客并结合了笔者自己的尝试,记录下对aiml的浅显理解,想了解的更深入还是要靠自己探索呀!
目录
一、简介
二、原理+源代码解析
三、中文分词尝试
四、注意
五、优势与缺点(个人理解)
AIML,全名为Artificial Intelligence Markup Language(人工智能标记语言),是一种创建自然语言软件代理的XML语言,最初来源于一个名为"A.L.I.C.E."的聊天机器人。
简言之,AIML就是用户通过定义的规则模板进行问答匹配,来实现聊天机器人自动问答的功能
下面展示了一个最基本的例子,仅包含最主要的
你好 您好,很高兴认识您。
当用户输入问题“你好”时,机器人就会匹配到这个pattern,然后将中的内容作为答案返回
标签的详细说明可以参考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方法把解析的
加入到graphmaster对象中 handler.unload方法从读取xml生成的stack里面弹出元素
aiml中的基本知识单元
bot要装载context对象和graphmaster对象,这样,bot就带着aiml中的配置和知识去回答用户提问
(3)用户输入,调用bot对象的respond方法
先利用用户的input生成request对象,request对象是请求对象,属性为original和sentences,original为问句,然后将sentence规范化,赋给request对象
(4)进一步调用重载的respond方法,调用graphmaster的match方法匹配sentence到对应的category,调用process方法,返回标签的内容: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文件时
对应于源码解析中的解析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 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 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]+"); //添加中文字符
经笔者简单测试,可以进行中文模糊匹配
_行不行_ 不可以!*能不能* 能!
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解决很多相同句式的问题;而且,
(2)多种功能标签的辅助
比如
(3)会话机制
基于aiml构建的chatbot支持会话机制,使得机器人具有一定程度的基于上下文语境的多轮对话功能,而且机器人能够区分不同的用户角色。
比如同样的问句“你好”,机器人对于不同人就会回复“你好,张三”、“你好、李四”
2.缺点
因为是基于规则匹配,缺点也很明显
(1)依赖规则的构建复杂程度,以及aiml覆盖知识的多少,规则构建完善、语料大效果自然好。
当针对特定领域的问答时,采用aiml方式构建个性化的标签和采用其他方式比如检索匹配,知识图谱,深度学习技术等等需要评估可行性和效果,可以采用aiml进行辅助,多模块整合
(2)人工的费时费力