• alicebot


    一、   为什么Alice不支持中文
    因为Alice的question都会被bitoflife.chatterbean.text.Transformations类中的fit函数过滤,而过滤的表达式就是:

    private finalPattern fitting = Pattern.compile("[^A-Z0-9]+");

    只会保留英文字符和数字字符。顺带说一句,因为Alice会将question全部转为大写,所以上面的表达式中没有a-z区间。

    为了让中文不被过滤掉,就将上面的过滤式中添加中文字符。

             privatefinal Pattern fitting = Pattern.compile("[^A-Z0-9u4e00-u9FA5]+")

    二、   Alice支持中文的原理
    先解释一下,Alice对英文支持的原理:

    简而言之:在语料库中,找出匹配的用户question的pattern,再返回pattern对应的template内容作为answer。

    详细点就是:Alice初始化时,将AIML文件中的<pattern>标签的内容根据空格切分,组成一个Graphmaster对象;用户的question也根据空格切分,根据匹配算法在Graphmaster对象中找到匹配的pattern标签,再返回该pattern对应的template内容。

    Graphmaster参考:http://www.alicebot.org/documentation/matching.html

    Alice支持英文中的关键一点就是:英文输入有空格,而中文输入没有空格,Alice就不会切分中文字符,只会把整个中文语句当做英文中一个单词。

    所以支持中文的关键一点就是:为中文语句加空格。

    马上想到了中文分词器,我用的是IK分词器.接下来问题就转化为:怎么为中文语句加空格?在什么地方加空格?

    有两个地方要处理:

    ² 读取AIML文件中的pattern标签时,需要加空格。

    ² 读取用户question时,要加空格。


    三、   代码实践
    IK分词器封装函数
             这是就不多说了,csdn博客多得是IK分词器用法。

    public static StringIKAnalysis(String str) {

    if(str.getBytes().length == str.length()) {
    //如果不包含中文,就直接返回。
    return str;
    }else {
    //由于IK分词器,不支持特殊字符,所以将 * 改为中文字符“这是星号”,中文分词以后再将“这是星号”修正为为 *
    //同理将 _改为中文字符串“这是下划线”,中文分词以后再将“这是下划线”修正为 _
    str= str.replaceAll("\*","这是星号").replaceAll("_","这是下划线");
    }

    StringBuffersb =new StringBuffer();
    try {
    byte[] bt =str.getBytes();
    InputStreamip =new ByteArrayInputStream(bt);
    Readerread =new InputStreamReader(ip);
    //设置为智能分词
    IKSegmenteriks =new IKSegmenter(read,true);
    Lexemet;
    while ((t =iks.next()) !=null) {
    //在每个分词元之后添加空格
    sb.append(t.getLexemeText()+" ");
    }
    //sb.delete(sb.length() - 1, sb.length());
    }catch (IOException e) {
    //TODOAuto-generated catch block
    }

    returnsb.toString().replaceAll("这是星号","*").replaceAll("这是下划线","_");
    }

    读取AIML文件的pattern标签时加空格
             AIML的读取解析工作由bitoflife.chatterbean.aiml.AIMLHandler类完成的。

    修改pushTextNode函数,根据参数来判断是否调用中文分词器。


    /**
    *将一个节点的文本信息压入栈中,并根据参数决定是否调用中文分词器。
    *@param isToSegment 标识是否调用中文分词器
    */
    privatevoidpushTextNode(Boolean isToSegment) {
    Stringpushed =text.toString();
    text.delete(0,text.length());
    if (ignoreWhitespace)
    pushed= pushed.replaceAll("^[\s ]+|[\s ]{2,}| ","");

    if (!"".equals(pushed.trim())){
    if(!isToSegment) {
    stack.push(newText(pushed));
    }else {
    pushed= pushed.toUpperCase();
    stack.push(newText(cn.edu.scut.cs.IKAnalyzer.ChineseSegmenter.IKAnalysis(pushed)));
    }
    }
    }
    在startElement和endElement函数中为pattern和that标签内的中文字符添加空格。将pushTextNode()函数的调用语句改为:

    pushTextNode(qname.toLowerCase().equals("pattern")

                    ||qname.toLowerCase().equals("that"));

    顺带说一句that标签也可能需要中文分词的。

    读取用户question时加空格
             这个很简单,在public void normalization(Sentencesentence)函数中第二行添加调用中文分词函数:

    input =cn.edu.scut.cs.IKAnalyzer.ChineseSegmenter.IKAnalysis(input);
    ---------------------
    作者:zhang-hui
    来源:CSDN
    原文:https://blog.csdn.net/zhang_hui_cs/article/details/22686951
    版权声明:本文为博主原创文章,转载请附上博文链接!

  • 相关阅读:
    Django 07模型层—单表操作(增删改查)
    Django 05(模板-变量、过滤器、 标签 )
    Django 04(url与views相关内容)
    路由基础及反向解析
    Django项目基础
    Django框架导读
    异常处理
    Docker
    Docker基本概念
    Docker架构
  • 原文地址:https://www.cnblogs.com/zwei1121/p/11156551.html
Copyright © 2020-2023  润新知