├── .gitignore ├── ReadMe.md ├── __init__.py ├── cache ├── corpus.txt └── query.txt ├── chat.png ├── chat.py ├── getQA.py ├── matcher ├── BM-25 │ ├── __init__.py │ ├── invdx.py │ ├── main.py │ ├── parse.py │ ├── query.py │ └── rank.py ├── __init__.py ├── aimlMatcher.py ├── bm25Matcher.py ├── levenshteinMatcher.py ├── rules │ ├── Common_conversation.aiml │ ├── OrdinaryQuestion.aiml │ ├── bad.aiml │ ├── bye.aiml │ ├── funny.aiml │ ├── personname.aiml │ ├── tools.aiml │ └── tuling.aiml ├── rulesMapper.py └── vectorMatcher.py ├── stopwords ├── chinese_sw.txt ├── specialMarks.txt └── stopwords.txt ├── train_w2v.py └── userdict └── user_dict.csv /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | /cache/*.csv 3 | /model/ 4 | /corpus/*.csv 5 | /notebook/ -------------------------------------------------------------------------------- /ReadMe.md: -------------------------------------------------------------------------------- 1 | ## 基于相似问法的闲聊场景对话机器人(Version 2) 2 | 3 | --- 4 | ## ChatBot运行步骤: 5 | 6 | Step 1. 在根目录下新建corpus文件夹,将[语料文件][1]下载并解压到corpus文件夹 (密码:0n2x) 7 | 8 | Step 2. 在根目录下新建model文件夹,将训练好的[词向量文件][2]下载并解压到model文件夹 (egg9) 9 | 10 | Step 3. 运行getQA.py获得所需的运行文件,这里已经有训练好的_词向量模型_,所以getQA运行时会 11 | 直接加载,并获得chat所需的所有文件。 12 | 13 | Step 4. 运行chat.py进行问答测试 14 | 15 | > 几种对话匹配策略 16 | > - aiml 自定义对话模板 17 | > - vectorMatcher 句子词向量加权表示的余弦相似度 18 | > - levenshteinMatcher 编辑距离匹配 19 | > - BM-25 相似匹配(暂未使用) 20 | 21 | 22 | --- 23 | 24 | ## 对话结果 25 | 26 | ![chatresult](chat.png) 27 | 28 | 29 | <-old version-> 30 | 31 | #### 与Version 1的不同 32 | 33 | - 扩充了机器人的语料库(闲谈逸致,文理类,生活相关,职场职业,城市问题,教育类,情感类,旅游景点,电影,考试相关,名人巨星,生活常识,歌曲歌词,国家相关) 34 | 35 | --- 36 | 37 | > 2017/09/07 <-new version-> 38 | > 将相似匹配算法移到了matcher 39 | > 增加了BM-25匹配算法 40 | --- 41 | [1]:http://pan.baidu.com/s/1kVFwrpP 42 | [2]:http://pan.baidu.com/s/1dFzZxc9 43 | -------------------------------------------------------------------------------- /__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/StephenLee2016/simple-chatbot/348d4b81a7406d2ab0e04b137e5b9f146281f01a/__init__.py -------------------------------------------------------------------------------- /cache/query.txt: -------------------------------------------------------------------------------- 1 | 京巴 2 | 周杰伦 3 | 周杰伦 演唱会 4 | -------------------------------------------------------------------------------- /chat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/StephenLee2016/simple-chatbot/348d4b81a7406d2ab0e04b137e5b9f146281f01a/chat.png -------------------------------------------------------------------------------- /chat.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | __author__ = 'jrlimingyang@jd.com' 3 | 4 | import numpy as np 5 | import json 6 | import random 7 | import jieba 8 | import pandas as pd # 这里选择pandas存储矩阵,numpy无法解决索引问题,后续解决 9 | from matcher import aimlMatcher 10 | from matcher import vectorMatcher 11 | from matcher import levenshteinMatcher 12 | import logging 13 | 14 | import sys 15 | reload(sys) 16 | sys.setdefaultencoding('utf-8') 17 | logger = logging.getLogger('chat.py') 18 | 19 | 20 | # 获得问题回答 21 | def get_response(response_frame, inputs_str): 22 | ''' 23 | for index in list(response_index): 24 | yield id2sent[str(index)] 25 | ''' 26 | 27 | if response_frame is None: 28 | return u'这句话我还无法回答...' 29 | else: 30 | lm = levenshteinMatcher 31 | response_frame['leven'] = response_frame[1].apply(lambda x: lm.levenstein_ratio(inputs_str, str(x))) 32 | 33 | # 这里用levenshtein ratio进行过滤,只选大于0.8的匹配度的问题 34 | response_frame = response_frame[response_frame['leven'] > 0.6] 35 | try: 36 | response_frame = response_frame.sort_values(by='cosine',ascending=False) 37 | if response_frame.shape[0] > 3: 38 | i = random.randint(0,3) 39 | 40 | if '_RBT_NAME_' in response_frame.iloc[i,0]: 41 | return response_frame.iloc[i,0].replace('_RBT_NAME_', '小京灵') 42 | else: 43 | return response_frame.iloc[i,0] 44 | else: 45 | if '_RBT_NAME_' in response_frame.iloc[0,0]: 46 | return response_frame.iloc[0,0].replace('_RBT_NAME_', '小京灵') 47 | else: 48 | return response_frame.iloc[0,0] 49 | except: 50 | return u'这个问题我不知道如何回答哦~~' 51 | 52 | 53 | if __name__ == '__main__': 54 | 55 | sent_vec = pd.read_csv('./cache/sentence2vec.csv', header=None, sep='|', error_bad_lines=True) 56 | vec_model = vectorMatcher.load_w2vModel() 57 | mybot = aimlMatcher.get_rules() 58 | T = jieba.initialize() 59 | jieba.load_userdict('./userdict/user_dict.csv') 60 | 61 | while True: 62 | # 获取用户的输入 63 | inputs_str = raw_input(u'Me > ') 64 | inputs_seg = ' '.join(jieba.cut(inputs_str)) 65 | # cosine 相似度 66 | cosine_sim = vectorMatcher.match(inputs_seg, sent_vec, vec_model) 67 | sent_vec['cosine'] = cosine_sim 68 | # print sent_vec.head() 69 | 70 | try: 71 | # 保留余弦相似度top10 72 | response_frame = sent_vec.sort_values(by='cosine', ascending=False)[:10] 73 | # print response_frame 74 | except: 75 | response_frame = None 76 | 77 | # 获得回答 78 | if '#NoMatchingTemplate' not in aimlMatcher.match(inputs_seg, mybot): 79 | response = aimlMatcher.match(inputs_seg, mybot) 80 | else: 81 | print '模板无结果,从相似匹配获得结果' 82 | response = get_response(response_frame, inputs_str) 83 | print (u'ChatBot > %s'%response) 84 | 85 | # 需要把之前计算的概率值去掉,要不然计算相似度时候维度不同 86 | sent_vec = sent_vec.iloc[:, 0:202] -------------------------------------------------------------------------------- /getQA.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | # __author__=='jrlimingyang@jd.com' 3 | import os 4 | import re 5 | import jieba 6 | import codecs 7 | import numpy as np 8 | import pandas as pd 9 | from train_w2v import train 10 | from gensim.models import KeyedVectors 11 | 12 | import logging 13 | logging.basicConfig(format='%(asctime)s: %(levelname)s: %(message)s', level=logging.INFO) 14 | 15 | import sys 16 | reload(sys) 17 | sys.setdefaultencoding('utf-8') 18 | 19 | ''' 20 | 1.将对话数据拆成question、answer两个文件 21 | 2.将question转换成sentence vector 22 | 3.获得训练vector model的数据 23 | ''' 24 | 25 | def get_qa(file_path): 26 | ''' 27 | :param file_path:原始语料路径 28 | :return: question 和 answer 29 | ''' 30 | corpus = pd.read_csv(file_path, error_bad_lines=True) 31 | # domain = ['闲谈逸致','文理类','生活相关','职场职业','城市问题','教育类','情感类','旅游景点','电影','考试相关','名人巨星','生活常识','歌曲歌词','国家相关'] 32 | # corpus = corpus[corpus[3].isin(domain)] 33 | # corpus = corpus[[10,0]] 34 | # corpus.columns = ['question','answer'] 35 | corpus['question_seg'] = corpus['question'].apply(lambda x: _remove_stopwords(' '.join(jieba.cut(str(x))))) 36 | corpus.index = range(0,corpus.shape[0]) 37 | 38 | return corpus 39 | 40 | 41 | def sentence2vec(corpus, vec_model): 42 | ''' 43 | :param sentence: 44 | :param vec_model: 训练好的词向量模型 45 | :return: 句子的向量化表示 46 | ''' 47 | vecFrame = pd.DataFrame(np.zeros((corpus.shape[0],200))) 48 | corpus['sent2vec'] = corpus['question'].apply(lambda x: ' '.join(jieba.cut(str(x)))) 49 | 50 | for index, row in corpus.iterrows(): 51 | sentVec = np.zeros((1, 200)) 52 | if (index+1) % 1000 == 0: 53 | logging.info(u'%s lines complete'%(index+1)) 54 | word_count = 0 55 | 56 | for word in row['sent2vec'].split(' '): 57 | try: 58 | word_count += 1 59 | sentVec += vec_model[word] 60 | except Exception: 61 | pass 62 | 63 | vecFrame.iloc[index,:] = sentVec[0]/float(word_count) 64 | with open(os.path.join(os.getcwd(),'cache/corpus.txt'), 'w') as f: 65 | for index, row in corpus.iterrows(): 66 | f.write('# '+ str(index)) 67 | f.write('\n') 68 | f.write(row[2]) 69 | f.write('\n') 70 | del corpus['sent2vec'] 71 | corpus = pd.concat([corpus,vecFrame], axis=1) 72 | return corpus 73 | 74 | 75 | def _remove_stopwords(segwords): 76 | stopwords = [stopword for stopword in codecs.open(os.path.join(os.getcwd(), 'stopwords/stopwords.txt'), 'r', 'utf-8').read()] 77 | wordlist = '' 78 | for word in segwords.split(' '): 79 | if word not in stopwords: 80 | wordlist += word + ' ' 81 | return wordlist 82 | 83 | def get_vector_data(corpus): 84 | ''' 85 | :param file_path: 原始语料路径 86 | :return: 分词后的预料数据,用于vector model训练 87 | ''' 88 | #corpus = pd.read_csv(file_path, header=None, error_bad_lines=True) 89 | 90 | vec_data = corpus['question'] + corpus['answer'] 91 | vec_data = vec_data.apply(lambda x: _remove_stopwords(' '.join(jieba.cut(str(x))))) 92 | return vec_data 93 | 94 | def main(): 95 | # 训练闲聊模型需要的数据问题件路径 96 | corpus_path = './corpus/corpus_1509417971.2.csv' 97 | # 需要保存的向量数据路径 98 | vector_path = './corpus/vec_data.csv' 99 | 100 | corpus = get_qa(corpus_path) 101 | # 如果vector model 存在则直接载入 102 | # 这里有一点小trick,如果语料发生了变化,那么词向量是否需要重新训练其实是需要看效果而定 103 | # 假如需要重新训练词向量模型,只需要将model文件夹下的四个文件删除,然后重新运行程序就行 104 | if os.path.exists('./model/all.zh.text.vector'): 105 | vec_model = KeyedVectors.load_word2vec_format('./model/all.zh.text.vector') 106 | else: 107 | vec_data = get_vector_data(corpus) 108 | vec_data.to_csv(vector_path, index=None, header=None, encoding='utf-8') 109 | vec_model = train(vector_path) 110 | 111 | 112 | sent2vec = sentence2vec(corpus, vec_model) 113 | del sent2vec['question_seg'] 114 | # 存储转化好的sentence向量 115 | sent2vec.to_csv('./cache/sentence2vec.csv', index=None, sep='|', header=None) 116 | 117 | 118 | if __name__ == '__main__': 119 | main() -------------------------------------------------------------------------------- /matcher/BM-25/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/StephenLee2016/simple-chatbot/348d4b81a7406d2ab0e04b137e5b9f146281f01a/matcher/BM-25/__init__.py -------------------------------------------------------------------------------- /matcher/BM-25/invdx.py: -------------------------------------------------------------------------------- 1 | # -*- coding;utf-8 -*- 2 | __author__ = 'jrlimingyang@jd.com' 3 | 4 | class InvertedIndex: 5 | def __init__(self): 6 | self.index = dict() 7 | 8 | def __contains__(self, item): 9 | return item in self.index 10 | 11 | def __getitem__(self, item): 12 | return self.index[item] 13 | 14 | def add(self, word, docid): 15 | if word in self.index: 16 | if docid in self.index[word]: 17 | self.index[word][docid] += 1 18 | else: 19 | self.index[word][docid] = 1 20 | else: 21 | d = dict() 22 | d[docid] = 1 23 | self.index[word] = d 24 | 25 | # Frequency of word in document 26 | def get_document_frequency(self, word, docid): 27 | if word in self.index: 28 | if docid in self.index[word]: 29 | return self.index[word][docid] 30 | else: 31 | raise LookupError('%s not in document %s' % (str(word), str(docid))) 32 | else: 33 | raise LookupError('%s not in index' % str(word)) 34 | 35 | # Frequency of word in index, i.e. number of documents that contain word 36 | def get_index_frequency(self, word): 37 | if word in self.index: 38 | return len(self.index[word]) 39 | else: 40 | raise LookupError('%s not in index' % word) 41 | 42 | class DocumentLengthTable: 43 | def __init__(self): 44 | self.table = dict() 45 | 46 | def __len__(self): 47 | return len(self.table) 48 | 49 | def add(self, docid, length): 50 | self.table[docid] = length 51 | 52 | def get_length(self, docid): 53 | if docid in self.table: 54 | return self.table[docid] 55 | else: 56 | raise LookupError('%s not found in table' % str(docid)) 57 | 58 | def get_average_length(self): 59 | sum = 0 60 | for length in self.table.itervalues(): 61 | sum += length 62 | return float(sum) / float(len(self.table)) 63 | 64 | def build_data_structures(corpus): 65 | idx = InvertedIndex() 66 | dlt = DocumentLengthTable() 67 | for docid in corpus: 68 | # build inverted index 69 | for word in corpus[docid]: 70 | idx.add(str(word), str(docid)) 71 | 72 | # build document length table 73 | length = len(corpus[str(docid)]) 74 | dlt.add(docid, length) 75 | 76 | return idx, dlt -------------------------------------------------------------------------------- /matcher/BM-25/main.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | __author__ = 'jrlimingyang@jd.com' 3 | 4 | from parse import * 5 | from query import QueryProcessor 6 | import operator 7 | 8 | def main(): 9 | qp = QueryParser(filename='C:\\Users\\jrlimingyang\\PycharmProjects\\chatbot-version2\\cache\\query.txt') 10 | cp = CorpusParser(filename='C:\\Users\\jrlimingyang\\PycharmProjects\\chatbot-version2\\cache\\corpus.txt') 11 | qp.parse() 12 | queries = qp.get_queries() 13 | cp.parse() 14 | corpus = cp.get_corpus() 15 | proc = QueryProcessor(queries, corpus) 16 | results = proc.run() 17 | qid = 0 18 | for result in results: 19 | sorted_x = sorted(result.iteritems(), key=operator.itemgetter(1)) 20 | sorted_x.reverse() 21 | index = 0 22 | for i in sorted_x[:10]: 23 | tmp = (qid, qid, i[0], index, i[1]) 24 | print '{:>1}\tQ{:>1}\t{:>4}\t{:>2}\t{:>12}\tL-BM25'.format(*tmp) 25 | index += 1 26 | qid += 1 27 | 28 | if __name__ == '__main__': 29 | main() 30 | -------------------------------------------------------------------------------- /matcher/BM-25/parse.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | __author__ = 'jrlimingyang@jd.com' 3 | 4 | import codecs 5 | import re 6 | 7 | class CorpusParser: 8 | def __init__(self, filename): 9 | self.filename = filename 10 | self.regex = re.compile('^#\s*\d+') 11 | self.corpus = dict() 12 | 13 | def parse(self): 14 | with codecs.open(self.filename, 'r') as f: 15 | s = ''.join(f.readlines()) 16 | blobs = s.split('#')[1:] 17 | for x in blobs: 18 | text = x.split() 19 | docid = text.pop(0) 20 | self.corpus[docid] = text 21 | 22 | def get_corpus(self): 23 | return self.corpus 24 | 25 | class QueryParser: 26 | def __init__(self, filename): 27 | self.filename = filename 28 | self.queries = [] 29 | 30 | def parse(self): 31 | with codecs.open(self.filename, 'r' ) as f: 32 | lines = ''.join(f.readlines()) 33 | self.queries = [x.rstrip().split() for x in lines.split('\n')[:-1]] 34 | 35 | def get_queries(self): 36 | return self.queries 37 | 38 | if __name__ == '__main__': 39 | qp = QueryParser('./data/queries.txt') 40 | print qp.get_queries() -------------------------------------------------------------------------------- /matcher/BM-25/query.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | __author__ = 'jrlimingyang@jd.com' 3 | 4 | from invdx import build_data_structures 5 | from rank import score_BM25 6 | import operator 7 | 8 | 9 | class QueryProcessor: 10 | def __init__(self, queries, corpus): 11 | self.queries = queries 12 | self.index, self.dlt = build_data_structures(corpus) 13 | 14 | def run(self): 15 | results = [] 16 | for query in self.queries: 17 | results.append(self.run_query(query)) 18 | #results.append(self.run_query(self.queries)) 19 | return results 20 | 21 | def run_query(self, query): 22 | query_result = dict() 23 | for term in query: 24 | if term in self.index: 25 | doc_dict = self.index[term] 26 | for docid, freq in doc_dict.iteritems(): 27 | score = score_BM25(n=len(doc_dict), f=freq, qf=1, r=0, N=len(self.dlt), 28 | dl=self.dlt.get_length(docid), avdl=self.dlt.get_average_length()) 29 | if docid in query_result: 30 | query_result[docid] += score 31 | else: 32 | query_result[docid] = score 33 | return query_result -------------------------------------------------------------------------------- /matcher/BM-25/rank.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | __author__ = 'jrlimingyang@jd.com' 3 | 4 | from math import log 5 | 6 | k1 = 1.2 7 | k2 = 100 8 | b = 0.75 9 | R = 0.0 10 | 11 | def score_BM25(n,f, qf, r, N, dl, avdl): 12 | K = compute_K(dl, avdl) 13 | first = log(((r + 0.5)/(R - r + 0.5)) / ((n - r + 0.5)/(N - n - R + r + 0.5))) 14 | second = ((k1 + 1) * f) / (K + f) 15 | third = ((k2 + 1) * qf) / (k2 + qf) 16 | return first * second * third 17 | 18 | def compute_K(dl, avdl): 19 | return k1 * ((1-b) + b * (float(dl)/float(avdl))) -------------------------------------------------------------------------------- /matcher/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/StephenLee2016/simple-chatbot/348d4b81a7406d2ab0e04b137e5b9f146281f01a/matcher/__init__.py -------------------------------------------------------------------------------- /matcher/aimlMatcher.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | __author__ = 'jrlimingyang@jd.com' 3 | 4 | 5 | from matcher.rulesMapper import get_rules 6 | 7 | 8 | def add_rules(): 9 | mybot = get_rules() 10 | return mybot 11 | 12 | def match(inputs_seg, mybot): 13 | return mybot.respond(inputs_seg) 14 | -------------------------------------------------------------------------------- /matcher/bm25Matcher.py: -------------------------------------------------------------------------------- 1 | # -*- coding;utf-8 -*- 2 | __author__ = 'jrlimingyang@jd.com' 3 | 4 | import math 5 | 6 | 7 | # TO-DO: 下一步将bm-25将入进来 8 | class bestMatchingMatcher(): 9 | pass -------------------------------------------------------------------------------- /matcher/levenshteinMatcher.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | __author__ = 'jrlimingyang@jd.com' 3 | 4 | def levenstein_ratio(s1, s2): 5 | # 这里用两个字符串的编辑距离比 6 | # 用ratio可以将距离归一化 7 | m, n = len(s1), len(s2) 8 | colsize, matrix = m + 1, [] 9 | for i in range((m + 1) * (n + 1)): 10 | matrix.append(0) 11 | for i in range(colsize): 12 | matrix[i] = i 13 | for i in range(n + 1): 14 | matrix[i * colsize] = i 15 | for i in range(n + 1)[1:n + 1]: 16 | for j in range(m + 1)[1:m + 1]: 17 | cost = 0 18 | if s1[j - 1] == s2[i - 1]: 19 | cost = 0 20 | else: 21 | cost = 2 22 | minValue = matrix[(i - 1) * colsize + j] + 1 23 | if minValue > matrix[i * colsize + j - 1] + 1: 24 | minValue = matrix[i * colsize + j - 1] + 1 25 | if minValue > matrix[(i - 1) * colsize + j - 1] + cost: 26 | minValue = matrix[(i - 1) * colsize + j - 1] + cost 27 | matrix[i * colsize + j] = minValue 28 | return (m + n - matrix[n * colsize + m])/float(m + n) -------------------------------------------------------------------------------- /matcher/rules/Common_conversation.aiml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | * 5 | 9 | 10 | 11 | 12 | 找不到答案 13 | 22 | 23 | 24 | 25 | 26 | 27 | 34 | 35 | 36 | 37 | 你好 38 | 47 | 48 | 49 | HI 50 | HI * 51 | HELLO 52 | HELLO * 53 | * 你好 54 | 您好 * 55 | 56 | 57 | 你好 * 58 | 82 | 83 | 84 | 85 | 夸奖 86 | 94 | 95 | 96 | 97 | 问候 98 | 106 | 107 | 108 | 109 | 晚安 110 | 117 | 118 | 119 | 晚安 * 120 | * 晚安 121 | 122 | 123 | 句子长度过长 124 | 131 | 132 | -------------------------------------------------------------------------------- /matcher/rules/OrdinaryQuestion.aiml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | * 的 * 是 5 | 12 | 13 | 14 | 15 | * 的 * 是 * 16 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /matcher/rules/bad.aiml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 你 个 * 6 | 16 | 17 | 18 | 19 | 愚蠢 20 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /matcher/rules/bye.aiml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 再见 5 | 15 | 16 | 17 | 再见 * 18 | * 再见 19 | 88 20 | * 拜拜 21 | 拜拜 * 22 | 拜拜 23 | 24 | 25 | 好的 26 | 33 | 34 | 35 | 嗯嗯 * 36 | * 好的 37 | 嗯 * 38 | * 好吧 39 | 40 | 41 | 好的 * 42 | 43 | -------------------------------------------------------------------------------- /matcher/rules/personname.aiml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | * 是 谁 5 | 11 | 12 | 13 | 14 | 15 | * 的 * 是 谁 16 | 23 | 24 | 25 | 26 | * 的 * 是 谁 * 27 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /matcher/rules/tools.aiml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 查 时间 5 | 8 | 9 | 今天 几号 10 | 现在 几点 * 11 | 现在 几点 12 | 13 | 14 | * 查 * 到 * 的 * 15 | 25 | 26 | 27 | 28 | * 查一下 * 到 * 的 * 29 | 38 | 39 | 40 | 41 | 42 | 天气 43 | 46 | 47 | 今天天气 * 48 | 今天天气 49 | 今天 * 天气 50 | * 天气 * 51 | 52 | -------------------------------------------------------------------------------- /matcher/rulesMapper.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | __author__ = 'jrlimingyang@jd.com' 3 | 4 | import os, sys 5 | import aiml 6 | 7 | 8 | def add_rules(): 9 | rule_path = os.getcwd() 10 | mybot = aiml.Kernel() 11 | 12 | # 加载aiml规则模板 13 | mybot.learn(rule_path + '/matcher/rules/Common_conversation.aiml') 14 | mybot.learn(rule_path + '/matcher/rules/bye.aiml') 15 | mybot.learn(rule_path + '/matcher/rules/tuling.aiml') 16 | #mybot.learn(rule_path + '/matcher/rules/tools.aiml') 17 | #mybot.learn(rule_path + '/matcher/rules/bad.aiml') 18 | #mybot.learn(rule_path + '/matcher/rules/funny.aiml') 19 | #mybot.learn(rule_path + '/matcher/rules/OrdinaryQuestion.aiml') 20 | 21 | #mybot.learn(rule_path + '/matcher/rules/persionname.aiml') 22 | 23 | return mybot 24 | 25 | def get_rules(): 26 | mybot = add_rules() 27 | return mybot -------------------------------------------------------------------------------- /matcher/vectorMatcher.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | __author__ = 'jrlimingyang@jd.com' 3 | 4 | import os 5 | import gensim 6 | import jieba 7 | import numpy as np 8 | from sklearn.metrics.pairwise import cosine_similarity 9 | import logging 10 | logging.basicConfig(format='%(asctime)s : %(levelname)s : %(message)s', level=logging.INFO) 11 | 12 | def load_w2vModel(): 13 | ''' 14 | 加载 pre-trained 词向量模型 15 | 用来将句子向量化 16 | ''' 17 | assert os.path.exists('./model/all.zh.text.vector') 18 | logging.info(u'开始加载 pre-trained 向量模型...') 19 | vec_model = gensim.models.KeyedVectors.load_word2vec_format('./model/all.zh.text.vector') 20 | logging.info(u'模型加载完毕') 21 | return vec_model 22 | 23 | def input2vec(inputs_str, vec_model): 24 | ''' 25 | 用户输入转化为向量表示 26 | ''' 27 | sent_vec = np.zeros((1,200)) 28 | 29 | vocab_num = 0 30 | for word in inputs_str.split(' '): 31 | try: 32 | vocab_num += 1 33 | sent_vec += vec_model[word] 34 | except Exception: 35 | pass 36 | return sent_vec / float(vocab_num) 37 | 38 | def match(inputs_str, sent_vec, vec_model): 39 | ''' 40 | 句子向量化的处理方式就是简单的加权平均 41 | 可以用其他的方式继续优化 42 | ''' 43 | input_vec = input2vec(inputs_str, vec_model) 44 | cosine = cosine_similarity(input_vec, sent_vec.iloc[:, 2::])[0] 45 | 46 | return cosine -------------------------------------------------------------------------------- /stopwords/chinese_sw.txt: -------------------------------------------------------------------------------- 1 | 啊 2 | 阿 3 | 哎 4 | 哎呀 5 | 哎喲 6 | 哎呦 7 | 唉 8 | 俺 9 | 有點 10 | 有点 11 | 一直 12 | 俺們 13 | 按 14 | 按照 15 | 吧 16 | 吧噠 17 | 吧嗒 18 | 把 19 | 罷了 20 | 罢了 21 | 被 22 | 本 23 | 本著 24 | 比 25 | 比方 26 | 比如 27 | 鄙人 28 | 彼 29 | 彼此 30 | 最近 31 | 老是 32 | 邊 33 | 边 34 | 別 35 | 別的 36 | 別說 37 | 别说 38 | 並 39 | 并 40 | 並且 41 | 并且 42 | 不比 43 | 不成 44 | 不單 45 | 不单 46 | 不但 47 | 不獨 48 | 不独 49 | 不管 50 | 不光 51 | 不過 52 | 不过 53 | 不僅 54 | 不仅 55 | 不拘 56 | 不論 57 | 不论 58 | 不怕 59 | 不然 60 | 不如 61 | 不特 62 | 不惟 63 | 不問 64 | 不问 65 | 不只 66 | 朝 67 | 朝著 68 | 趁 69 | 趁著 70 | 趁着 71 | 乘 72 | 衝 73 | 除 74 | 除此之外 75 | 除非 76 | 除了 77 | 此 78 | 此間 79 | 此间 80 | 此外 81 | 從 82 | 从 83 | 從而 84 | 从而 85 | 打 86 | 待 87 | 但 88 | 但是 89 | 當 90 | 当 91 | 當著 92 | 当着 93 | 得 94 | 的 95 | 的話 96 | 的话 97 | 等 98 | 等等 99 | 地 100 | 第 101 | 叮咚 102 | 對 103 | 对 104 | 對於 105 | 对于 106 | 多 107 | 多少 108 | 而 109 | 而況 110 | 而且 111 | 而是 112 | 而外 113 | 而言 114 | 而已 115 | 爾後 116 | 尔后 117 | 而后 118 | 反過來 119 | 反过来 120 | 反過來說 121 | 反过来说 122 | 反之 123 | 非但 124 | 非徒 125 | 否則 126 | 否则 127 | 嘎 128 | 嘎登 129 | 咯噔 130 | 該 131 | 该 132 | 趕 133 | 赶 134 | 個 135 | 个 136 | 各 137 | 各個 138 | 各个 139 | 各位 140 | 各種 141 | 各种 142 | 各自 143 | 給 144 | 给 145 | 根據 146 | 根据 147 | 跟 148 | 故 149 | 故此 150 | 固然 151 | 關於 152 | 关于 153 | 管 154 | 歸 155 | 归 156 | 果然 157 | 果真 158 | 過 159 | 过 160 | 哈 161 | 哈哈 162 | 呵 163 | 和 164 | 何 165 | 何處 166 | 何处 167 | 何況 168 | 何况 169 | 何時 170 | 何时 171 | 嘿 172 | 哼 173 | 哼唷 174 | 呼哧 175 | 乎 176 | 嘩 177 | 還是 178 | 还是 179 | 還有 180 | 还有 181 | 換句話說 182 | 换句话说 183 | 換言之 184 | 换言之 185 | 或 186 | 或是 187 | 或者 188 | 極了 189 | 极了 190 | 及 191 | 及其 192 | 及至 193 | 即 194 | 即便 195 | 即或 196 | 即令 197 | 即若 198 | 即使 199 | 幾 200 | 几 201 | 幾時 202 | 几时 203 | 己 204 | 既 205 | 既然 206 | 既是 207 | 繼而 208 | 继而 209 | 加之 210 | 假如 211 | 假若 212 | 假使 213 | 鑑於 214 | 终于 215 | 將 216 | 将 217 | 較 218 | 较 219 | 較之 220 | 较之 221 | 叫 222 | 接著 223 | 結果 224 | 结果 225 | 借 226 | 緊接著 227 | 紧接着 228 | 進而 229 | 进而 230 | 盡 231 | 儘管 232 | 尽管 233 | 經 234 | 经 235 | 經過 236 | 经过 237 | 就 238 | 就是 239 | 就是說 240 | 據 241 | 据 242 | 具體地說 243 | 具体地说 244 | 具體說來 245 | 具体说来 246 | 開始 247 | 开始 248 | 開外 249 | 开外 250 | 靠 251 | 咳 252 | 可 253 | 可見 254 | 可见 255 | 可是 256 | 可以 257 | 況且 258 | 况且 259 | 啦 260 | 來 261 | 来 262 | 來著 263 | 来着 264 | 离 265 | 例如 266 | 哩 267 | 连 268 | 连同 269 | 两者 270 | 了 271 | 临 272 | 另 273 | 另外 274 | 另一方面 275 | 论 276 | 嘛 277 | 吗 278 | 慢说 279 | 漫说 280 | 冒 281 | 么 282 | 每 283 | 每当 284 | 们 285 | 莫若 286 | 某 287 | 某个 288 | 某些 289 | 拿 290 | 哪 291 | 哪边 292 | 哪儿 293 | 哪个 294 | 哪里 295 | 哪年 296 | 哪怕 297 | 哪天 298 | 哪些 299 | 哪样 300 | 那 301 | 那边 302 | 那儿 303 | 那个 304 | 那会见 305 | 那里 306 | 那么 307 | 那么些 308 | 那么样 309 | 那时 310 | 那些 311 | 那样 312 | 乃 313 | 乃至 314 | 呢 315 | 能 316 | 你 317 | 你們 318 | 您 319 | 宁 320 | 宁可 321 | 宁肯 322 | 宁愿 323 | 哦 324 | 啪嗒 325 | 旁人 326 | 呸 327 | 凭借 328 | 凭 329 | 其 330 | 其次 331 | 其二 332 | 其他 333 | 其它 334 | 其一 335 | 其余 336 | 其中 337 | 起 338 | 起见 339 | 非但 340 | 恰恰相反 341 | 前后 342 | 前者 343 | 且 344 | 然而 345 | 然后 346 | 然则 347 | 让 348 | 人家 349 | 任 350 | 任何 351 | 任凭 352 | 如 353 | 如此 354 | 如果 355 | 如何 356 | 如其 357 | 如若 358 | 如上所述 359 | 若 360 | 若非 361 | 若是 362 | 啥 363 | 上下 364 | 尚且 365 | 设若 366 | 设使 367 | 甚而 368 | 甚么 369 | 甚至 370 | 省得 371 | 时候 372 | 什么 373 | 什么样 374 | 使得 375 | 是 376 | 是的 377 | 首先 378 | 谁 379 | 谁知 380 | 顺 381 | 顺著 382 | 似的 383 | 虽 384 | 虽然 385 | 虽说 386 | 虽则 387 | 随 388 | 随著 389 | 所 390 | 所以 391 | 他 392 | 他们 393 | 他人 394 | 它 395 | 它们 396 | 她 397 | 她们 398 | 倘 399 | 倘或 400 | 倘然 401 | 倘若 402 | 倘使 403 | 騰 404 | 替 405 | 通过 406 | 同 407 | 同时 408 | 哇 409 | 萬一 410 | 往 411 | 望 412 | 为 413 | 为何 414 | 为了 415 | 为什么 416 | 为着 417 | 喂 418 | 嗡嗡 419 | 我 420 | 我们 421 | 呜 422 | 呜呼 423 | 无论 424 | 毋宁 425 | 嘻 426 | 嚇 427 | 相对而言 428 | 像 429 | 向 430 | 向着 431 | 嘘 432 | 呀 433 | 焉 434 | 沿 435 | 沿著 436 | 要 437 | 要不 438 | 要不然 439 | 要不是 440 | 要么 441 | 要是 442 | 也 443 | 也罢 444 | 也好 445 | 一 446 | 一般 447 | 一旦 448 | 一方面 449 | 一来 450 | 一切 451 | 一样 452 | 一则 453 | 依 454 | 依照 455 | 矣 456 | 以 457 | 以便 458 | 以及 459 | 以免 460 | 以至 461 | 以至于 462 | 以致 463 | 抑或 464 | 因 465 | 因此 466 | 因而 467 | 因为 468 | 呦 469 | 用 470 | 由 471 | 由此可见 472 | 由于 473 | 有 474 | 有的 475 | 有关 476 | 有些 477 | 又 478 | 于 479 | 于是 480 | 于是乎 481 | 与 482 | 与此同时 483 | 与否 484 | 与其 485 | 越是 486 | 云云 487 | 哉 488 | 再说 489 | 再者 490 | 在 491 | 在下 492 | 咱 493 | 咱们 494 | 则 495 | 怎 496 | 怎么 497 | 怎么办 498 | 怎么样 499 | 怎样 500 | 咋 501 | 照 502 | 照着 503 | 者 504 | 这 505 | 这边 506 | 这儿 507 | 这个 508 | 这会儿 509 | 这就是说 510 | 这里 511 | 这么 512 | 这么点儿 513 | 这么些 514 | 这么样 515 | 这时 516 | 这些 517 | 这样 518 | 正如 519 | 吱 520 | 之 521 | 之类 522 | 之所以 523 | 之一 524 | 只是 525 | 只限 526 | 只要 527 | 只有 528 | 至 529 | 至于 530 | 诸位 531 | 著 532 | 著呢 533 | 自 534 | 自从 535 | 自个儿 536 | 自各儿 537 | 自己 538 | 自家 539 | 自身 540 | 综上所述 541 | 总的来看 542 | 总的来说 543 | 总而言之 544 | 总之 545 | 纵 546 | 纵令 547 | 纵然 548 | 纵使 549 | 遵照 550 | 作为 551 | 兮 552 | 呃 553 | 呗 554 | 咚 555 | 咦 556 | 喏 557 | 啐 558 | 喔唷 559 | 嗬 560 | 嗯 561 | 噯 562 | ~ 563 | ! 564 | . 565 | : 566 | " 567 | ' 568 | ( 569 | ) 570 | * 571 | A 572 | 白 573 | 社会主义 574 | -- 575 | .. 576 | >> 577 | [ 578 | ] 579 | < 580 | > 581 | / 582 | \ 583 | | 584 | - 585 | _ 586 | + 587 | = 588 | & 589 | ^ 590 | % 591 | # 592 | @ 593 | ` 594 | ; 595 | $ 596 | ( 597 | ) 598 | —— 599 | — 600 | ¥ 601 | · 602 | ... 603 | ' 604 | ' 605 | 〉 606 | 〈 607 | … 608 |   609 | 0 610 | 1 611 | 2 612 | 3 613 | 4 614 | 5 615 | 6 616 | 7 617 | 8 618 | 9 619 | 0 620 | 1 621 | 2 622 | 3 623 | 4 624 | 5 625 | 6 626 | 7 627 | 8 628 | 9 629 | 二 630 | 三 631 | 四 632 | 五 633 | 六 634 | 七 635 | 八 636 | 九 637 | 零 638 | > 639 | < 640 | @ 641 | # 642 | $ 643 | % 644 | ︿ 645 | & 646 | * 647 | + 648 | ~ 649 | | 650 | [ 651 | ] 652 | 「 653 | 」 654 | 『 655 | 』 656 | 【 657 | 】 658 | { 659 | } 660 | 啊哈 661 | 啊呀 662 | 啊呦 663 | 哎呦 664 | 我艹 665 | 卧槽 666 | 窝草 667 | 我屮艸芔茻 668 | 艹 669 | 草泥马 670 | 挨次 671 | 挨个 672 | 挨家挨户 673 | 挨门挨户 674 | 挨门逐户 675 | 挨着 676 | 按理 677 | 按期 678 | 按时 679 | 按说 680 | 暗地里 681 | 暗中 682 | 暗自 683 | 昂然 684 | 八成 685 | 白白 686 | 半 687 | 梆 688 | 保管 689 | 保险 690 | 饱 691 | 背地里 692 | 背靠背 693 | 倍感 694 | 倍加 695 | 本人 696 | 本身 697 | 甭 698 | 比起 699 | 比如说 700 | 比照 701 | 毕竟 702 | 必 703 | 必定 704 | 必将 705 | 必須 706 | 便 707 | 別人 708 | 并非 709 | 并肩 710 | 并沒 711 | 并沒有 712 | 并排 713 | 并无 714 | 勃然 715 | 不 716 | 不必 717 | 不常 718 | 不大 719 | 不但...而且 720 | 不得 721 | 不得不 722 | 不得了 723 | 不得已 724 | 不迭 725 | 不定 726 | 不对 727 | 不妨 728 | 不管怎样 729 | 不会 730 | 不仅...而且 731 | 不仅仅 732 | 不仅仅是 733 | 不经意 734 | 不可开交 735 | 不可抗拒 736 | 不力 737 | 不了 738 | 不料 739 | 不满 740 | 不免 741 | 不能不 742 | 不起 743 | 不巧 744 | 不然的话 745 | 不日 746 | 不少 747 | 不胜 748 | 不时 749 | 不是 750 | 不同 751 | 不能 752 | 不要 753 | 不外 754 | 不外乎 755 | 不下 756 | 不限 757 | 不消 758 | 不已 759 | 不亦乐乎 760 | 不由得 761 | 不再 762 | 不择手段 763 | 不怎么 764 | 不曾 765 | 不知不觉 766 | 不止 767 | 不止一次 768 | 不至于 769 | 才 770 | 才能 771 | 策略地 772 | 差不多 773 | 差一点 774 | 常 775 | 常常 776 | 常言道 777 | 常言说 778 | 常言说得好 779 | 长此下去 780 | 长话短说 781 | 长期以来 782 | 长线 783 | 敞开儿 784 | 彻夜 785 | 陈年 786 | 趁便 787 | 趁机 788 | 趁热 789 | 趁势 790 | 趁早 791 | 成年 792 | 成年累月 793 | 成心 794 | 乘机 795 | 乘胜 796 | 乘势 797 | 乘隙 798 | 乘虛 799 | 诚然 800 | 迟早 801 | 充分 802 | 充其极 803 | 充其量 804 | 抽冷子 805 | 臭 806 | 初 807 | 出 808 | 出来 809 | 出去 810 | 除此 811 | 除此而外 812 | 除此以外 813 | 除开 814 | 除去 815 | 除卻 816 | 除外 817 | 处处 818 | 川流不息 819 | 传 820 | 传说 821 | 传闻 822 | 串行 823 | 纯 824 | 纯粹 825 | 此后 826 | 此中 827 | 次第 828 | 匆匆 829 | 从不 830 | 从此 831 | 从此以后 832 | 从古到今 833 | 从古至今 834 | 从今以后 835 | 从来 836 | 从轻 837 | 从速 838 | 从头 839 | 从未 840 | 从无到有 841 | 从小 842 | 从新 843 | 从严 844 | 从优 845 | 从早到晚 846 | 从中 847 | 从重 848 | 湊巧 849 | 粗 850 | 存心 851 | 达旦 852 | 打从 853 | 打开天窗说亮话 854 | 大 855 | 大不了 856 | 大大 857 | 大抵 858 | 大都 859 | 大多 860 | 大凡 861 | 大概 862 | 大家 863 | 大举 864 | 大略 865 | 大面儿上 866 | 大事 867 | 大体 868 | 大体上 869 | 大约 870 | 大张旗鼓 871 | 大致 872 | 呆呆地 873 | 带 874 | 殆 875 | 待到 876 | 单 877 | 单纯 878 | 单单 879 | 但愿 880 | 弹指之间 881 | 当场 882 | 当儿 883 | 当即 884 | 当口儿 885 | 当然 886 | 当庭 887 | 当头 888 | 当下 889 | 当真 890 | 当中 891 | 倒不如 892 | 倒不如说 893 | 倒是 894 | 到处 895 | 到底 896 | 到了儿 897 | 到目前为止 898 | 到头 899 | 到头來 900 | 得起 901 | 得天独厚 902 | 的确 903 | 等到 904 | 叮当 905 | 顶多 906 | 定 907 | 动不动 908 | 动辄 909 | 陡然 910 | 都 911 | 独 912 | 独自 913 | 断然 914 | 顿时 915 | 多次 916 | 多多 917 | 多多少少 918 | 多多益善 919 | 多亏 920 | 多年來 921 | 多年前 922 | 而后 923 | 而论 924 | 而又 925 | 尔等 926 | 二话不说 927 | 二话沒说 928 | 反倒 929 | 反倒是 930 | 反而 931 | 反手 932 | 反之亦然 933 | 反之则 934 | 方 935 | 方才 936 | 方能 937 | 放量 938 | 非常 939 | 非得 940 | 分期 941 | 分期分批 942 | 分头 943 | 奋勇 944 | 愤然 945 | 风雨无阻 946 | 逢 947 | 弗 948 | 甫 949 | 嘎嘎 950 | 该当 951 | 概 952 | 赶快 953 | 赶早不赶晚 954 | 敢 955 | 敢情 956 | 敢于 957 | 刚 958 | 刚才 959 | 刚好 960 | 刚巧 961 | 高低 962 | 格外 963 | 隔日 964 | 隔夜 965 | 個人 966 | 各式 967 | 更 968 | 更加 969 | 更进一步 970 | 更为 971 | 公然 972 | 共 973 | 共总 974 | 够瞧的 975 | 姑且 976 | 古来 977 | 故而 978 | 故意 979 | 固 980 | 怪 981 | 怪不得 982 | 惯常 983 | 光 984 | 光是 985 | 归根到底 986 | 归根结底 987 | 过于 988 | 毫不 989 | 毫无 990 | 毫无保留地 991 | 毫无例外 992 | 好在 993 | 何必 994 | 何当 995 | 何妨 996 | 何苦 997 | 何乐而不为 998 | 何须 999 | 何止 1000 | 很 1001 | 很多 1002 | 很少 1003 | 轟然 1004 | 后来 1005 | 呼啦 1006 | 忽地 1007 | 忽然 1008 | 互 1009 | 互相 1010 | 哗啦 1011 | 话说 1012 | 还 1013 | 恍然 1014 | 会 1015 | 豁然 1016 | 活 1017 | 伙同 1018 | 或多或少 1019 | 或许 1020 | 基本 1021 | 基本上 1022 | 基于 1023 | 极 1024 | 极大 1025 | 极度 1026 | 极端 1027 | 极力 1028 | 极其 1029 | 极为 1030 | 急匆匆 1031 | 即将 1032 | 即刻 1033 | 即是说 1034 | 几度 1035 | 几番 1036 | 几乎 1037 | 几经 1038 | 既...又 1039 | 加上 1040 | 加以 1041 | 间或 1042 | 简而言之 1043 | 简言之 1044 | 简直 1045 | 见 1046 | 将才 1047 | 将近 1048 | 将要 1049 | 交口 1050 | 较比 1051 | 较为 1052 | 接连不断 1053 | 接下来 1054 | 皆可 1055 | 截然 1056 | 截至 1057 | 藉以 1058 | 藉此 1059 | 藉以 1060 | 区时 1061 | 仅 1062 | 仅仅 1063 | 进来 1064 | 进去 1065 | 近 1066 | 近几年来 1067 | 近来 1068 | 近年来 1069 | 尽管如此 1070 | 尽可能 1071 | 尽快 1072 | 尽量 1073 | 尽然 1074 | 尽如人意 1075 | 尽心竭力 1076 | 尽心尽力 1077 | 尽早 1078 | 精光 1079 | 经常 1080 | 竟 1081 | 竟然 1082 | 究竟 1083 | 就此 1084 | 就地 1085 | 就算 1086 | 居然 1087 | 局外 1088 | 举凡 1089 | 据称 1090 | 据此 1091 | 据实 1092 | 据说 1093 | 据我所知 1094 | 据悉 1095 | 具体来说 1096 | 绝不 1097 | 绝非 1098 | 绝 1099 | 绝不 1100 | 绝顶 1101 | 絕對 1102 | 絕非 1103 | 均 1104 | 喀 1105 | 看 1106 | 看來 1107 | 看起來 1108 | 看上去 1109 | 看樣子 1110 | 可好 1111 | 可能 1112 | 恐怕 1113 | 快 1114 | 快要 1115 | 來不及 1116 | 來得及 1117 | 來講 1118 | 來看 1119 | 攔腰 1120 | 牢牢 1121 | 老 1122 | 老大 1123 | 老老實實 1124 | 老是 1125 | 累次 1126 | 累年 1127 | 理當 1128 | 理該 1129 | 理應 1130 | 歷 1131 | 立 1132 | 立地 1133 | 立刻 1134 | 立馬 1135 | 立時 1136 | 聯袂 1137 | 連連 1138 | 連日 1139 | 連日來 1140 | 連聲 1141 | 連袂 1142 | 臨到 1143 | 另方面 1144 | 另行 1145 | 另一個 1146 | 路經 1147 | 屢 1148 | 屢次 1149 | 屢次三番 1150 | 屢屢 1151 | 縷縷 1152 | 率爾 1153 | 率然 1154 | 略 1155 | 略加 1156 | 略微 1157 | 略為 1158 | 論說 1159 | 馬上 1160 | 蠻 1161 | 滿 1162 | 沒 1163 | 沒有 1164 | 每逢 1165 | 每每 1166 | 每時每刻 1167 | 猛然 1168 | 猛然間 1169 | 莫 1170 | 莫不 1171 | 莫非 1172 | 莫如 1173 | 默默地 1174 | 默然 1175 | 吶 1176 | 那末 1177 | 奈 1178 | 難道 1179 | 難得 1180 | 難怪 1181 | 難說 1182 | 內 1183 | 年復一年 1184 | 凝神 1185 | 偶而 1186 | 偶爾 1187 | 怕 1188 | 砰 1189 | 碰巧 1190 | 譬如 1191 | 偏偏 1192 | 乒 1193 | 平素 1194 | 頗 1195 | 迫於 1196 | 撲通 1197 | 其後 1198 | 其實 1199 | 奇 1200 | 齊 1201 | 起初 1202 | 起來 1203 | 起首 1204 | 起頭 1205 | 起先 1206 | 豈 1207 | 豈非 1208 | 豈止 1209 | 迄 1210 | 恰逢 1211 | 恰好 1212 | 恰恰 1213 | 恰巧 1214 | 恰如 1215 | 恰似 1216 | 千 1217 | 千万 1218 | 千万千万 1219 | 切 1220 | 切不可 1221 | 切莫 1222 | 切切 1223 | 切勿 1224 | 亲口 1225 | 亲身 1226 | 亲手 1227 | 亲眼 1228 | 亲自 1229 | 顷 1230 | 顷刻 1231 | 顷刻间 1232 | 顷刻之间 1233 | 请勿 1234 | 穷年累月 1235 | 取道 1236 | 权时 1237 | 全都 1238 | 全力 1239 | 全年 1240 | 全然 1241 | 全身心 1242 | 然 1243 | 人人 1244 | 仍 1245 | 仍旧 1246 | 仍然 1247 | 日复一日 1248 | 日见 1249 | 日渐 1250 | 日益 1251 | 日臻 1252 | 如常 1253 | 如此等等 1254 | 如次 1255 | 如今 1256 | 如期 1257 | 如前所述 1258 | 如上 1259 | 如下 1260 | 汝 1261 | 三番两次 1262 | 三番五次 1263 | 三天两头 1264 | 瑟瑟 1265 | 沙沙 1266 | 上 1267 | 上来 1268 | 上去 1269 | 帮 1270 | 好像 1271 | 几个 1272 | 想要 1273 | 觉得 1274 | 直到 1275 | -------------------------------------------------------------------------------- /stopwords/specialMarks.txt: -------------------------------------------------------------------------------- 1 | , 2 | ? 3 | 、 4 | 。 5 | “ 6 | ” 7 | 《 8 | . 9 | 》 10 | ! 11 | , 12 | , 13 | : 14 | ; 15 | ? 16 | ■ 17 | □ 18 | / 19 | % 20 | \ 21 | > 22 | ﹏ 23 | < 24 |  ̄ 25 | ★ 26 | ☆ 27 | ! 28 | ? 29 | ○ 30 | ′ 31 | ⊙ 32 | ` 33 | o 34 | ~ 35 | = 36 | ' 37 | ( 38 | * 39 | ) 40 | -------------------------------------------------------------------------------- /stopwords/stopwords.txt: -------------------------------------------------------------------------------- 1 | ! 2 | @ 3 | % 4 | # 5 | ^ 6 | & 7 | * 8 | ( 9 | ) 10 | - 11 | _ 12 | = 13 | + 14 | \ 15 | | 16 | / 17 | ? 18 | < 19 | > 20 | , 21 | . 22 | ! 23 | , 24 | 。 25 | ? 26 | 、 27 | 《 28 | 》 29 | …… 30 | -------------------------------------------------------------------------------- /train_w2v.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | # __author__ = 'jrlimingyang' 3 | 4 | import logging 5 | import os.path 6 | import sys 7 | import multiprocessing 8 | 9 | from gensim.corpora import WikiCorpus 10 | from gensim.models import Word2Vec 11 | from gensim.models.word2vec import LineSentence 12 | 13 | 14 | 15 | def train(corpus_path): 16 | path = './' 17 | program = os.path.basename(path + 'train_w2v.py') 18 | logger = logging.getLogger(program) 19 | 20 | logging.basicConfig(format='%(asctime)s: %(levelname)s: %(message)s') 21 | logging.root.setLevel(level=logging.INFO) 22 | inp, outp1, outp2 = corpus_path, path + 'model/all.zh.text.model', path + 'model/all.zh.text.vector' 23 | model = Word2Vec(LineSentence(inp), size=200, window=5, min_count=2, 24 | workers=multiprocessing.cpu_count()) 25 | model.save(outp1) 26 | model.wv.save_word2vec_format(outp2, binary=False) 27 | 28 | return model 29 | 30 | -------------------------------------------------------------------------------- /userdict/user_dict.csv: -------------------------------------------------------------------------------- 1 | _RBT_NAME_ --------------------------------------------------------------------------------