zoukankan      html  css  js  c++  java
  • 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
    版权声明:本文为博主原创文章,转载请附上博文链接!

  • 相关阅读:
    marMariaDB & MYSQL flexviews
    tomcat与resin的比较
    nginx 1.4.3能直接升到1.8.1吗
    Docker Compose vs. Dockerfile
    分布式事务 spring 两阶段提交 tcc
    linux下拷贝整个目录
    MySQL :: Fatal error: Can&#039;t change to run as user &#039;mysql&#039;. Please check that the user exists!
    python Drools
    KubeCon CloudNativeCon China 2019
    在mysql中修改表名的sql语句
  • 原文地址:https://www.cnblogs.com/zwei1121/p/11156551.html
Copyright © 2011-2022 走看看