alicebot

1、   爲何Alice不支持中文
由於Alice的question都會被bitoflife.chatterbean.text.Transformations類中的fit函數過濾,而過濾的表達式就是:html

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

只會保留英文字符和數字字符。順帶說一句,由於Alice會將question所有轉爲大寫,因此上面的表達式中沒有a-z區間。app

爲了讓中文不被過濾掉,就將上面的過濾式中添加中文字符。函數

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

 

2、   Alice支持中文的原理
先解釋一下,Alice對英文支持的原理:spa

簡而言之:在語料庫中,找出匹配的用戶question的pattern,再返回pattern對應的template內容做爲answer。.net

詳細點就是:Alice初始化時,將AIML文件中的<pattern>標籤的內容根據空格切分,組成一個Graphmaster對象;用戶的question也根據空格切分,根據匹配算法在Graphmaster對象中找到匹配的pattern標籤,再返回該pattern對應的template內容。orm

Graphmaster參考:http://www.alicebot.org/documentation/matching.htmlhtm

 

Alice支持英文中的關鍵一點就是:英文輸入有空格,而中文輸入沒有空格,Alice就不會切分中文字符,只會把整個中文語句當作英文中一個單詞。對象

因此支持中文的關鍵一點就是:爲中文語句加空格。

立刻想到了中文分詞器,我用的是IK分詞器.接下來問題就轉化爲:怎麼爲中文語句加空格?在什麼地方加空格?

有兩個地方要處理:

² 讀取AIML文件中的pattern標籤時,須要加空格。

² 讀取用戶question時,要加空格。


3、   代碼實踐
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\n]+|[\\s\n]{2,}|\n","");

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)函數中第二行添加調用中文分詞函數:

相關文章
相關標籤/搜索