├── ChatUtils.py ├── README.html ├── README.md ├── WordSegment ├── __pycache__ │ └── utils.cpython-35.pyc ├── dict │ ├── dict_small.txt │ └── dict_test.txt ├── segs │ ├── __pycache__ │ │ └── bmseg.cpython-35.pyc │ ├── bmseg.py │ ├── mmseg.py │ └── rmmseg.py ├── test_seg.py └── utils.py ├── __pycache__ ├── ChatUtils.cpython-35.pyc ├── chatdb.cpython-35.pyc ├── chatjsonctl.cpython-35.pyc ├── chatjsondb.cpython-35.pyc └── utils.cpython-35.pyc ├── chatdb.py ├── chatjsonctl.py ├── chatjsondb.py ├── chatsession.py ├── coms ├── he_20161205 100616 ├── he_20161205 100754 ├── he_20161205 101011 ├── li_20161130 202248 ├── wang_20161205 101447 ├── wang_20161205 110120 ├── wang_20161205 110653 ├── zhang_20161130 171327 ├── zhang_20161130 171804 ├── zhang_20161130 172203 ├── zhang_20161130 202041 ├── zhang_20161201 135449 ├── zhang_20161201 135556 ├── zhang_20161201 135718 ├── zhang_20161201 140525 └── zhang_20161205 100042 ├── data ├── ReadMe.md ├── ans2que ├── ans2que.json ├── ans2que_he.json ├── ans2que_li.json ├── ans2que_wang.json ├── ans2que_xuman.json ├── ans2que_zhang.json ├── answer ├── answer_he.json ├── answer_li.json ├── answer_wang.json ├── answer_xuman.json ├── answer_zhang.json ├── data_helper.py ├── ids_zhang ├── question ├── question.json ├── question_he.json ├── question_li.json ├── question_wang.json ├── question_xuman.json └── question_zhang.json ├── model ├── __pycache__ │ ├── ans2que.cpython-35.pyc │ ├── answer.cpython-35.pyc │ └── question.cpython-35.pyc ├── ans2que.py ├── answer.py └── question.py └── web ├── __pycache__ └── settings.cpython-35.pyc ├── app.py ├── settings.py ├── static ├── chat.css ├── favicon.ico ├── index.css ├── login.css └── logo.png └── templates ├── ans_add.html ├── ans_score.html ├── login.html ├── que_add.html └── que_ask.html /ChatUtils.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | '辅助类' 4 | 5 | __author__='litterzhang' 6 | 7 | import random 8 | from model.answer import Answer 9 | 10 | # 模糊回答,先写死,之后写入文件,多种模糊回答 11 | __blur_anss = [ 12 | { 13 | 'id' : 0, 14 | 'type' : 0, 15 | 'seed' : 0, 16 | 'deg' : 0, 17 | 'content' : '完全听不懂你在说什么~', 18 | }, 19 | { 20 | 'id' : 0, 21 | 'type' : 0, 22 | 'seed' : 0, 23 | 'deg' : 0, 24 | 'content' : '一脸懵逼~', 25 | }, 26 | { 27 | 'id' : 0, 28 | 'type' : 0, 29 | 'seed' : 0, 30 | 'deg' : 0, 31 | 'content' : '来啊!互相伤害啊!', 32 | }, 33 | { 34 | 'id' : 0, 35 | 'type' : 0, 36 | 'seed' : 0, 37 | 'deg' : 0, 38 | 'content' : '不明觉厉!!', 39 | }, 40 | ] 41 | 42 | # 默认回答 43 | def default_ans(): 44 | ans = Answer(-1, -1, -1, -1, '欢迎!小伙子们在火炉旁挤挤,留个位子出来~') 45 | return ans 46 | 47 | def default_ans_json(): 48 | ans = Answer(-1, -1, -1, -1, '欢迎!小伙子们在火炉旁挤挤,留个位子出来~') 49 | return ans.toString() 50 | 51 | # 计算相似度 52 | def sim_calc(words_s, words_d): 53 | words_d = [list(x) for x in words_d] 54 | words_d = list(filter(lambda x: x[2]!='bd', words_d)) 55 | 56 | cnt_same = 0 57 | for word in words_s: 58 | if word in words_d: 59 | cnt_same += 1 60 | word_same = cnt_same/(len(words_s)+len(words_d)-cnt_same) 61 | 62 | return word_same 63 | 64 | # 获取一个模糊回答 65 | def blur_ans(): 66 | index = random.randint(0, len(__blur_anss)-1) 67 | _ans = __blur_anss[index] 68 | ans = Answer(_ans.get('id', 0), _ans.get('type', 0), _ans.get('seed', 0), _ans.get('deg', 0), _ans.get('content', 'oh no!我的系统出故障了!')) 69 | return ans 70 | 71 | def blur_ans_json(): 72 | index = random.randint(0, len(__blur_anss)-1) 73 | _ans = __blur_anss[index] 74 | ans = Answer(_ans.get('id', 0), _ans.get('type', 0), _ans.get('seed', 0), _ans.get('deg', 0), _ans.get('content', 'oh no!我的系统出故障了!')) 75 | return ans.toString() 76 | 77 | def search_ans_json(anss, times=-1, ans_seed=-1, ans_type=-1): 78 | if not anss: 79 | return default_ans_json(), 0 80 | # 第一次回答问题,尝试打乱数组,达到随机回答的目的 81 | # if times==0: 82 | random.shuffle(anss) 83 | anss = sorted(anss, key=lambda x: x['ans']['deg']) 84 | 85 | # 修正times 86 | deg_max = max([x['ans']['deg'] for x in anss]) 87 | if times > deg_max: 88 | times = deg_max 89 | if times < 0: 90 | times = 0 91 | 92 | # 找到所有符合条件的回答 93 | anss_res = list() 94 | for ans in anss: 95 | if ans_seed==-1 and ans_type==-1: 96 | if ans['ans']['deg']==times: 97 | anss_res.append(ans) 98 | elif ans_seed==-1: 99 | if ans['ans']['type']==ans_type or ans['ans']['type']==2: 100 | if ans['ans']['deg']==times: 101 | anss_res.append(ans) 102 | elif ans_type==-1: 103 | if ans['ans']['seed']==ans_seed or ans['ans']['seed']==-1: 104 | if ans['ans']['deg']==times: 105 | anss_res.append(ans) 106 | else: 107 | if (ans['ans']['type']==ans_type and ans['ans']['seed']==ans_seed) or (ans['ans']['type']==2 and ans['ans']['seed']==-1): 108 | if ans['ans']['deg']==times: 109 | anss_res.append(ans) 110 | if not anss_res: 111 | return default_ans_json(), 0 112 | 113 | # 在符合条件的回答中进行概率随机 114 | pro_base = 10 115 | pro_key = [x['score'] for x in anss_res] 116 | pro_key = [x + pro_base if x > 0 else pro_base for x in pro_key] 117 | 118 | pro_ran = random.random()*sum(pro_key) 119 | pro_cnt = 0 120 | for i in range(len(pro_key)): 121 | if pro_ran>=pro_cnt and pro_ran deg_max: 139 | times = deg_max 140 | if times < 0: 141 | times = 0 142 | 143 | # 找到所有符合条件的回答 144 | anss_res = list() 145 | for ans in anss: 146 | if ans_seed==-1 and ans_type==-1: 147 | if ans['ans'].deg==times: 148 | anss_res.append(ans) 149 | elif ans_seed==-1: 150 | if ans['ans'].type==ans_type or ans['ans'].type==2: 151 | if ans['ans'].deg==times: 152 | anss_res.append(ans) 153 | elif ans_type==-1: 154 | if ans['ans'].seed==ans_seed or ans['ans'].seed==-1: 155 | if ans['ans'].deg==times: 156 | anss_res.append(ans) 157 | else: 158 | if (ans['ans'].type==ans_type and ans['ans'].seed==ans_seed) or (ans['ans'].type==2 and ans['ans'].seed==-1): 159 | if ans['ans'].deg==times: 160 | anss_res.append(ans) 161 | if not anss_res: 162 | return default_ans(), 0 163 | 164 | # 在符合条件的回答中进行概率随机 165 | pro_base = 10 166 | pro_key = [x['score'] for x in anss_res] 167 | pro_key = [x + pro_base if x > 0 else pro_base for x in pro_key] 168 | 169 | pro_ran = random.random()*sum(pro_key) 170 | pro_cnt = 0 171 | for i in range(len(pro_key)): 172 | if pro_ran>=pro_cnt and pro_ranREADME

聊天机器人

1018 |

智能聊天机器人!期待在语境上做一些突破,为聊天机器人添加:情绪、个性!

1019 |

ToDo List

1020 |
    1021 |
  1. 记录对话,随机回答(完成)
  2. 1022 |
  3. 根据对话,固定回答(完成)
  4. 1023 |
  5. 1024 |

    学习对话,反问学习(进行中)
    1025 | 学习计划方案
    1026 | a. 设定新建问题相似度阈值sim_new,若相似度大于sim_new,不创建新问题;反之创建新问题,并要求设定问题类型。

    1027 |

    b. 设定匹配旧问题答案相似度阈值sim_old,若相似度大于sim_old,将匹配到的问题答案关联到新问题上;否则不关联答案。

    1028 |

    c. 给出答案。若答案为模糊答案或者默认答案,要求新增1或n个答案,关联答案到问题;若答案为匹配答案,要求打分,可以新增1或n个答案,关联答案到问题。

    1029 |

    d. 存储问答库

    1030 |
  6. 1031 |
  7. 1032 |

    语料库添加方式优化,支持自动id编号,自动对应

    1033 |
  8. 1034 |
-------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 聊天机器人 2 | 智能聊天机器人!期待在语境上做一些突破,为聊天机器人添加:情绪、个性! 3 | 4 | ## ToDo List 5 | 1. 记录对话,随机回答(完成) 6 | 2. 根据对话,固定回答(完成) 7 | 3. 学习对话,反问学习(完成) 8 | ![学习计划方案](http://thumbnail0.baidupcs.com/thumbnail/f15c3f7172302101af26b94a7f1a6749?fid=1880885688-250528-926991618690474&time=1479114000&rt=sh&sign=FDTAER-DCb740ccc5511e5e8fedcff06b081203-gPowr5JKOGglwnqsk7y90GzlWTk%3D&expires=8h&chkv=0&chkbd=0&chkpc=&dp-logid=7392467252152627330&dp-callid=0&size=c710_u400&quality=100) 9 | a. 设定新建问题相似度阈值sim_new,若相似度大于sim_new,不创建新问题;反之创建新问题,并要求设定问题类型。 10 | 11 | b. 设定匹配旧问题答案相似度阈值sim_old,若相似度大于sim_old,将匹配到的问题答案关联到新问题上;否则不关联答案。 12 | 13 | c. 给出答案。若答案为模糊答案或者默认答案,要求新增1或n个答案,关联答案到问题;若答案为匹配答案,要求打分,可以新增1或n个答案,关联答案到问题。 14 | 15 | d. 存储问答库 16 | 17 | 4. 语料库添加方式优化,支持自动id编号,自动对应(进行中) -------------------------------------------------------------------------------- /WordSegment/__pycache__/utils.cpython-35.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/litterzhang/chatbox/3686f41c9dff623bc51f9d660d8d406ea587f124/WordSegment/__pycache__/utils.cpython-35.pyc -------------------------------------------------------------------------------- /WordSegment/dict/dict_test.txt: -------------------------------------------------------------------------------- 1 | 计算语言学 2 | 课程 3 | 意思 -------------------------------------------------------------------------------- /WordSegment/segs/__pycache__/bmseg.cpython-35.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/litterzhang/chatbox/3686f41c9dff623bc51f9d660d8d406ea587f124/WordSegment/segs/__pycache__/bmseg.cpython-35.pyc -------------------------------------------------------------------------------- /WordSegment/segs/bmseg.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | '双向最大匹配算法' 4 | 5 | __author__='litterzhang' 6 | 7 | import os 8 | import re 9 | 10 | import sys 11 | sys.path.append(os.path.join(os.path.dirname(__file__), os.path.pardir)) 12 | 13 | from utils import load_dict 14 | from functools import reduce 15 | 16 | # 分词标准流程 17 | def seg(sen_str, dict_load=None, word_max=5): 18 | # 加载词典 19 | if not dict_load: 20 | dict_path = os.path.join(os.path.dirname(__file__), '../dict/dict_small.txt') 21 | dict_load = load_dict(dict_path) 22 | 23 | # 处理标点符号,根据标点符号,将句子分割为多个子句 24 | punc = ' ~!@#$%^&*()_+-=[]{}|\\\'\";:?/.>,<~!@#¥%……&()|【】、‘“”’:;?。》《,' 25 | r = re.compile(r'[\s{}]+'.format(re.escape(punc))) 26 | sen_sub_strs = r.split(sen_str) 27 | 28 | # 词袋 29 | words = list() 30 | sen_proc_len = 0 31 | 32 | # 对每个子句分词 33 | for sen_sub_str in sen_sub_strs: 34 | words_mm = mmseg(sen_sub_str, dict_load=dict_load, word_max=word_max) 35 | words_rmm = rmmseg(sen_sub_str, dict_load=dict_load, word_max=word_max) 36 | 37 | if len(words_mm)>len(words_rmm): 38 | words.extend(words_rmm[::-1]) 39 | elif len(words_rmm)>len(words_mm): 40 | words.extend(words_mm) 41 | else: 42 | dis_mm = len(list(filter(lambda x: x[2]=='wz', words_mm))) 43 | dis_rmm = len(list(filter(lambda x: x[2]=='wz', words_rmm))) 44 | 45 | if dis_mm > dis_rmm: 46 | words.extend(words_rmm[::-1]) 47 | elif dis_rmm > dis_mm: 48 | words.extend(words_mm) 49 | else: 50 | cnt_mm = reduce(lambda x, y: len(y[2])**2+x, words_mm, 0) 51 | cnt_rmm = reduce(lambda x, y: len(y[2])**2+x, words_rmm, 0) 52 | 53 | if cnt_mm > cnt_rmm: 54 | words.extend(words_mm) 55 | else: 56 | words.extend(words_rmm[::-1]) 57 | 58 | # 将标点加入分词结果 59 | sen_proc_len += len(sen_sub_str) 60 | while sen_proc_len,<~!@#¥%……&()|【】、‘“”’:;?。》《,' 24 | r = re.compile(r'[\s{}]+'.format(re.escape(punc))) 25 | sen_sub_strs = r.split(sen_str) 26 | 27 | # 词袋 28 | words = list() 29 | sen_proc_len = 0 30 | 31 | print(sen_sub_strs) 32 | # 对每个子句分词 33 | for sen_sub_str in sen_sub_strs: 34 | words.extend(mmseg(sen_sub_str, dict_load=dict_load, word_max=word_max)) 35 | # 将标点加入分词结果 36 | sen_proc_len += len(sen_sub_str) 37 | while sen_proc_len,<~!@#¥%……&()|【】、‘“”’:;?。》《,' 24 | r = re.compile(r'[\s{}]+'.format(re.escape(punc))) 25 | sen_sub_strs = r.split(sen_str) 26 | 27 | # 词袋 28 | words = list() 29 | sen_proc_len = 0 30 | 31 | # 反转句子 32 | sen_str = sen_str[::-1] 33 | # 对每个子句分词 34 | for sen_sub_str in sen_sub_strs[::-1]: 35 | words.extend(rmmseg(sen_sub_str, dict_load=dict_load, word_max=word_max)) 36 | # 将标点加入分词结果 37 | sen_proc_len += len(sen_sub_str) 38 | while sen_proc_len 2: 27 | try: 28 | dict_load[word_inf[0]] = (int(word_inf[1]), word_inf[2]) 29 | except: 30 | dict_load[word_inf[0]] = (0, word_inf[1]) 31 | else: 32 | pass 33 | return dict_load 34 | 35 | # hash表结构定义 36 | class hash_dict: 37 | def __init__(self, dict_len=1000000): 38 | # 1000为最小长度 39 | dict_len = 1000 if dict_len < 1000 else dict_len 40 | self.dict_len = dict_len 41 | self.hash_list = [None for i in range(dict_len)] 42 | 43 | # 增加值 44 | def add(self, key, value): 45 | # 获取key的hash值 46 | hash_key = hash(key) & 0x7FFFFFFF 47 | hash_key_list = hash_key%self.dict_len 48 | 49 | if not self.hash_list[hash_key_list]: 50 | self.hash_list[hash_key_list] = (hash_key, key, value, None) 51 | else: 52 | tmp = self.hash_list[hash_key_list] 53 | self.hash_list[hash_key_list] = (hash_key, key, value, tmp) 54 | 55 | # 查询值 56 | def get(self, key): 57 | # 获取key的hash值 58 | hash_key = hash(key) & 0x7FFFFFFF 59 | hash_key_list = hash_key%self.dict_len 60 | 61 | tmp = self.hash_list[hash_key_list] 62 | while tmp: 63 | if tmp[0] == hash_key: 64 | return tmp[2] 65 | tmp = tmp[3] 66 | return None 67 | 68 | # 删除值 69 | def remove(self, key): 70 | # 获取key的hash值 71 | hash_key = hash(key) & 0x7FFFFFFF 72 | hash_key_list = hash_key%self.dict_len 73 | 74 | tmp = self.hash_list[hash_key_list] 75 | new_head = None 76 | new_now = None 77 | while tmp: 78 | if tmp[0] != hash_key: 79 | if not new_head: 80 | 81 | new_head = tmp 82 | new_now = new_head 83 | else: 84 | new_now[3] = tmp 85 | new_now = new_now[3] 86 | tmp = tmp[3] 87 | if new_now: 88 | new_now[3] = None 89 | 90 | self.hash_list[hash_key_list] = new_head 91 | 92 | # 加载字典 93 | # 返回hash表 94 | def load_dict_hash(fp, encoding='utf-8'): 95 | # 使用hash表存储词典信息 96 | dict_load = hash_dict() 97 | 98 | # 打开文件 99 | with open(fp, 'r', encoding=encoding) as fr: 100 | for line in fr: 101 | word_inf = line.strip().split() 102 | word_inf_len = len(word_inf) 103 | 104 | if word_inf_len is 1: 105 | dict_load.add(word_inf[0], (0, 'wz')) 106 | elif word_inf_len is 2: 107 | try: 108 | dict_load.add(word_inf[0], (int(word_inf[1]), 'wz')) 109 | except: 110 | dict_load.add(word_inf[0], (0, word_inf[1])) 111 | elif word_inf_len > 2: 112 | try: 113 | dict_load.add(word_inf[0], (int(word_inf[1]), word_inf[2])) 114 | except: 115 | dict_load.add(word_inf[0], (0, word_inf[1])) 116 | else: 117 | pass 118 | return dict_load 119 | 120 | # 测试 121 | if __name__=='__main__': 122 | import time 123 | s = time.time() 124 | d = load_dict_hash('./dict/dict_small.txt') 125 | with open('./dict/dict_small.txt', 'r', encoding='utf-8') as fr: 126 | for line in fr: 127 | d.get(line.strip().split()[0]) 128 | e = time.time() 129 | print(e-s) 130 | 131 | s = time.time() 132 | d = load_dict('./dict/dict_small.txt') 133 | with open('./dict/dict_small.txt', 'r', encoding='utf-8') as fr: 134 | for line in fr: 135 | d.get(line.strip().split()[0]) 136 | e = time.time() 137 | print(e-s) 138 | 139 | -------------------------------------------------------------------------------- /__pycache__/ChatUtils.cpython-35.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/litterzhang/chatbox/3686f41c9dff623bc51f9d660d8d406ea587f124/__pycache__/ChatUtils.cpython-35.pyc -------------------------------------------------------------------------------- /__pycache__/chatdb.cpython-35.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/litterzhang/chatbox/3686f41c9dff623bc51f9d660d8d406ea587f124/__pycache__/chatdb.cpython-35.pyc -------------------------------------------------------------------------------- /__pycache__/chatjsonctl.cpython-35.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/litterzhang/chatbox/3686f41c9dff623bc51f9d660d8d406ea587f124/__pycache__/chatjsonctl.cpython-35.pyc -------------------------------------------------------------------------------- /__pycache__/chatjsondb.cpython-35.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/litterzhang/chatbox/3686f41c9dff623bc51f9d660d8d406ea587f124/__pycache__/chatjsondb.cpython-35.pyc -------------------------------------------------------------------------------- /__pycache__/utils.cpython-35.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/litterzhang/chatbox/3686f41c9dff623bc51f9d660d8d406ea587f124/__pycache__/utils.cpython-35.pyc -------------------------------------------------------------------------------- /chatdb.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | 'Chat数据库' 4 | 5 | __author__='litterzhang' 6 | 7 | import os 8 | import copy 9 | 10 | from model.answer import Answer 11 | from model.question import Question 12 | from model.ans2que import Ans2Que 13 | 14 | from WordSegment.segs import bmseg 15 | 16 | import ChatUtils 17 | 18 | answers = list() 19 | questions = list() 20 | ans2ques = list() 21 | ids = list([0, 0]) 22 | 23 | def init_db(key): 24 | global answers, questions, ans2ques, ids 25 | 26 | ANSWER = os.path.join(os.path.dirname(__file__), 'data/answer_%s.json' % key) 27 | QUESTION = os.path.join(os.path.dirname(__file__), 'data/question_%s.json' % key) 28 | ANS2QUE = os.path.join(os.path.dirname(__file__), 'data/ans2que_%s.json' % key) 29 | IDS = os.path.join(os.path.dirname(__file__), 'data/ids_%s' % key) 30 | 31 | if os.path.exists(ANSWER): 32 | answers = Answer.load(ANSWER) 33 | if os.path.exists(QUESTION): 34 | questions = Question.load(QUESTION) 35 | if os.path.exists(ANS2QUE): 36 | ans2ques = Ans2Que.load(ANS2QUE) 37 | if os.path.exists(IDS): 38 | with open(IDS, 'r', encoding='utf-8') as fr: 39 | ids = [int(x) for x in fr.readline().strip().split()] 40 | 41 | print('\n----------Debug---------\n') 42 | for question in questions: 43 | print('question : %s ' % question.toString()) 44 | for answer in answers: 45 | print('answer : %s ' % answer.toString()) 46 | for ans2que in ans2ques: 47 | print('ans2que : %s ' % ans2que.toString()) 48 | print('\n----------Debug---------\n') 49 | 50 | def save_db(key): 51 | global answers, questions, ans2ques, ids 52 | 53 | ANSWER = os.path.join(os.path.dirname(__file__), 'data/answer_%s.json' % key) 54 | QUESTION = os.path.join(os.path.dirname(__file__), 'data/question_%s.json' % key) 55 | ANS2QUE = os.path.join(os.path.dirname(__file__), 'data/ans2que_%s.json' % key) 56 | IDS = os.path.join(os.path.dirname(__file__), 'data/ids_%s' % key) 57 | 58 | # print('\n----------Debug---------\n') 59 | # for question in questions: 60 | # print('question : %s ' % question.toString()) 61 | # for answer in answers: 62 | # print('answer : %s ' % answer.toString()) 63 | # for ans2que in ans2ques: 64 | # print('ans2que : %s ' % ans2que.toString()) 65 | # print('\n----------Debug---------\n') 66 | 67 | Answer.dump(answers, ANSWER) 68 | Question.dump(questions, QUESTION) 69 | Ans2Que.dump(ans2ques, ANS2QUE) 70 | 71 | with open(IDS, 'w', encoding='utf-8') as fw: 72 | fw.write('%s %s' % (str(ids[0]), str(ids[1]))) 73 | 74 | def match_question(que_str): 75 | global answers, questions, ans2ques, ids 76 | 77 | # print('\n----------Debug---------\n') 78 | # for question in questions: 79 | # print('question : %s ' % question.toString()) 80 | # for answer in answers: 81 | # print('answer : %s ' % answer.toString()) 82 | # for ans2que in ans2ques: 83 | # print('ans2que : %s ' % ans2que.toString()) 84 | # print('\n----------Debug---------\n') 85 | 86 | sims = list() 87 | 88 | que_words = [list(x) for x in bmseg.seg(que_str)] 89 | que_words = list(filter(lambda x: x[2]!='bd', que_words)) 90 | 91 | for que in questions: 92 | sims.append(ChatUtils.sim_calc(que_words, que.words)) 93 | 94 | if not sims: 95 | return None, 0 96 | 97 | sim_max = max(sims) 98 | que_mat = questions[sims.index(sim_max)] 99 | 100 | return que_mat, sim_max 101 | 102 | def get_ans_by_que(que): 103 | global answers, questions, ans2ques, ids 104 | 105 | ans2que = Ans2Que.get_ans_by_que(ans2ques, que.id) 106 | anss = list() 107 | if ans2que: 108 | for ans_id in ans2que.ans_ids: 109 | ans = Answer.get_ans_by_id(answers, ans_id['id']) 110 | if ans: 111 | anss.append({'ans' : ans, 'score' : ans_id['score']}) 112 | return anss 113 | 114 | def get_answer(que_str): 115 | global answers, questions, ans2ques, ids 116 | 117 | que, sim = match_question(que_str) 118 | if not que: 119 | return None, 0, list() 120 | anss = get_ans_by_que(que) 121 | 122 | # print('相似度: %s\n' % sim) 123 | return que, sim, anss 124 | 125 | def que_new_id(): 126 | global answers, questions, ans2ques, ids 127 | 128 | ids[0] += 1 129 | return ids[0] 130 | 131 | def ans_new_id(): 132 | global answers, questions, ans2ques, ids 133 | 134 | ids[1] += 1 135 | return ids[1] 136 | 137 | def que_new(que_str, que_type=2): 138 | global answers, questions, ans2ques, ids 139 | 140 | que_id = que_new_id() 141 | que = Question(que_id, que_type, que_str, bmseg.seg(que_str)) 142 | 143 | questions.append(que) 144 | 145 | # print('\n----------Debug---------\n') 146 | # for question in questions: 147 | # print('question : %s ' % question.toString()) 148 | # for answer in answers: 149 | # print('answer : %s ' % answer.toString()) 150 | # for ans2que in ans2ques: 151 | # print('ans2que : %s ' % ans2que.toString()) 152 | # print('\n----------Debug---------\n') 153 | 154 | return que 155 | 156 | def ans_new(ans_str, ans_type=2, ans_seed=-1, ans_deg=0): 157 | global answers, questions, ans2ques, ids 158 | 159 | ans_id = ans_new_id() 160 | ans = Answer(ans_id, ans_type, ans_seed, ans_deg, ans_str, bmseg.seg(ans_str)) 161 | 162 | answers.append(ans) 163 | return ans 164 | 165 | def ans_new_and_match_que(que_id, ans_str, ans_type=2, ans_seed=-1, ans_deg=0, score=10): 166 | global answers, questions, ans2ques, ids 167 | 168 | ans = ans_new(ans_str, ans_type, ans_seed, ans_deg) 169 | 170 | match = False 171 | for ans2que in ans2ques: 172 | if ans2que.que_id==que_id: 173 | ans2que.ans_ids.append({'id' : ans.id, 'score' : score}) 174 | match = True 175 | break 176 | if not match: 177 | ans2ques.append(Ans2Que(que_id, [{'id' : ans.id, 'score' : score}, ])) 178 | 179 | # print('\n----------Debug---------\n') 180 | # for question in questions: 181 | # print('question : %s ' % question.toString()) 182 | # for answer in answers: 183 | # print('answer : %s ' % answer.toString()) 184 | # for ans2que in ans2ques: 185 | # print('ans2que : %s ' % ans2que.toString()) 186 | # print('\n----------Debug---------\n') 187 | 188 | def match_old_anss(que_new_id, que_old_id): 189 | global answers, questions, ans2ques, ids 190 | 191 | ans2que = Ans2Que.get_ans_by_que(ans2ques, que_old_id) 192 | 193 | if ans2que: 194 | ans2que_new = Ans2Que(que_new_id, copy.deepcopy(ans2que.ans_ids)) 195 | ans2ques.append(ans2que_new) 196 | 197 | # print('\n----------Debug---------\n') 198 | # for question in questions: 199 | # print('question : %s ' % question.toString()) 200 | # for answer in answers: 201 | # print('answer : %s ' % answer.toString()) 202 | # for ans2que in ans2ques: 203 | # print('ans2que : %s ' % ans2que.toString()) 204 | # print('\n----------Debug---------\n') 205 | 206 | def change_score(que_id, ans_id, score): 207 | global answers, questions, ans2ques, ids 208 | 209 | if score!=0: 210 | for ans2que in ans2ques: 211 | if ans2que.que_id==que_id: 212 | print(ans2que.toString()) 213 | for ans_score in ans2que.ans_ids: 214 | if ans_score['id']==ans_id: 215 | ans_score['score'] += score 216 | break 217 | break 218 | 219 | # print('\n----------Debug---------\n') 220 | # for question in questions: 221 | # print('question : %s ' % question.toString()) 222 | # for answer in answers: 223 | # print('answer : %s ' % answer.toString()) 224 | # for ans2que in ans2ques: 225 | # print('ans2que : %s ' % ans2que.toString()) 226 | # print('\n----------Debug---------\n') 227 | 228 | if __name__=='__main__': 229 | que, sim = match_question('吃了吗??') 230 | anss = get_ans_by_que(que) -------------------------------------------------------------------------------- /chatjsonctl.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | '用于控制对话的进行' 4 | 5 | __author__='litterzhang' 6 | 7 | import os 8 | import datetime 9 | import json 10 | 11 | import chatjsondb 12 | import ChatUtils 13 | 14 | class Chat: 15 | # 初始化对话 16 | def __init__(self, _name, _sim_new=0.7, _sim_old=0.2): 17 | 18 | self.name = _name 19 | self.sim_new = _sim_new 20 | self.sim_old = _sim_old 21 | 22 | chatjsondb.init_db(self.name) 23 | 24 | self.coms = list() 25 | 26 | # 结束对话 27 | def __del__(self): 28 | COMS = os.path.join(os.path.dirname(__file__), 'coms') 29 | with open(os.path.join(COMS, '%s_%s' % (self.name, datetime.datetime.now().strftime("%Y%m%d %H%M%S"))), 'w', encoding='utf-8') as fw: 30 | coms_str = json.dumps(self.coms, ensure_ascii=False) 31 | fw.write(coms_str) 32 | 33 | # 创建新的问题 34 | def create_question(que_str, que_type=2): 35 | res = chatjsondb.create_question(que_str, que_type=que_type) 36 | if res.success: 37 | que = res.content.get('que', None) 38 | return que 39 | else: 40 | return None 41 | 42 | # 匹配问题 43 | def match_question(que_str): 44 | res = chatjsondb.get_answers(que_str) 45 | 46 | que = None 47 | sim = -1 48 | anss = list() 49 | if res.success: 50 | que = res.content.get('que', None) 51 | sim = res.content.get('sim', -1) 52 | anss = res.content.get('anss', list()) 53 | 54 | return que, sim, anss 55 | 56 | # 对话添加 57 | def coms_add_que(self, que_str, que, sim): 58 | self.coms.append({'que_str' : que_str, 'que' : que, 'que_sim' : sim}) 59 | 60 | def coms_add_ans(self, ans, score): 61 | self.coms[-1]['ans'] = ans 62 | self.coms[-1]['score'] = score 63 | 64 | # 进行问题控制 65 | def chat_ctl_question(self, que_str, que, sim, anss, que_type=2): 66 | que_new = Chat.create_question(que_str, que_type) 67 | 68 | if que and sim > self.sim_old: 69 | chatjsondb.match_old_anss(que_new['id'], que['id']) 70 | else: 71 | anss = list() 72 | que = que_new 73 | sim = 1 74 | return que, sim, anss 75 | 76 | # 进行回答控制 77 | def chat_ctl_answer(self, que, sim, anss): 78 | ans = ChatUtils.default_ans_json() 79 | score = 0 80 | 81 | if sim < 0.2: 82 | ans = ChatUtils.blur_ans_json() 83 | else: 84 | # 查找之前相同的问题 85 | times = 0 86 | last_ans = None 87 | for com in self.coms: 88 | if com['que_sim']>=0.2 and que['id']==com['que']['id']: 89 | last_ans = com.get('ans', None) 90 | if last_ans: 91 | times += 1 92 | 93 | # 匹配固定的回答 94 | if que['type']==0: 95 | ans_seed = -1 96 | ans_type = -1 97 | if last_ans: 98 | ans_seed = last_ans['seed'] 99 | ans_type = last_ans['type'] 100 | ans, score = ChatUtils.search_ans_json(anss, times=times, ans_seed=ans_seed, ans_type=ans_type) 101 | elif que['type']==1: 102 | ans, score = ChatUtils.search_ans_json(anss, times=times) 103 | else: 104 | ans, score = ChatUtils.search_ans_json(anss, times=times) 105 | return ans, score 106 | 107 | # 创建新的答案 108 | def create_answer(ans_str, ans_type=2, ans_seed=-1, ans_deg=0): 109 | res = chatjsondb.create_answer(ans_str, ans_type, ans_seed, ans_deg) 110 | ans_id = -1 111 | if res.success: 112 | ans_id = res.content.get('id', -1) 113 | return ans_id 114 | 115 | # 为问题创建答案 116 | def add_answer(que_id, ans_str, ans_type=2, ans_seed=-1, ans_deg=0, score=10): 117 | res = chatjsondb.add_ans_for_que(que_id, ans_str, ans_type, ans_seed, ans_deg, score) 118 | return res.success 119 | 120 | # 更改答案打分 121 | def change_score(que_id, ans_id, score=0): 122 | chatjsondb.update_ans2que(que_id, ans_id, score) 123 | 124 | # 输入int值 125 | def input_int(input_tip='', default=0): 126 | res = default 127 | try: 128 | res = int(input(input_tip)) 129 | except: 130 | pass 131 | return res 132 | 133 | # 输入float值 134 | def input_float(input_tip='', default=0.0): 135 | res = default 136 | try: 137 | res = float(input(input_tip)) 138 | except: 139 | pass 140 | return res 141 | 142 | # 添加答案 143 | def create_anss(que_id): 144 | while True: 145 | print('添加答案,按回车退出\n') 146 | ans_str = input('新增答案内容 : ') 147 | if not ans_str: 148 | break 149 | ans_type = input_int(input_tip='答案类型 : ', default=2) 150 | ans_seed = input_int(input_tip='答案中心 : ', default=-1) 151 | ans_deg = input_int(input_tip='答案语气 : ', default=0) 152 | ans_score = input_int(input_tip='答案打分 : ', default=10) 153 | 154 | Chat.add_answer(que_id, ans_str, ans_type, ans_seed, ans_deg, ans_score) 155 | 156 | # 训练模式 157 | def chat_ex(): 158 | # 这里开始对话,初始化对话问答库 159 | man_name = input('What\'s your name ? ') 160 | 161 | # 这里输入新建问题相似度阈值,及匹配旧问题相似度阈值 162 | sim_new = input_float('新问题阈值sim_new ? ', default=0.7) 163 | sim_old = input_float('旧问题阈值sim_old ? ', default=0.2) 164 | 165 | # 加载问答库 166 | chat = Chat(man_name, sim_new, sim_old) 167 | 168 | print('----------开始问答----------\n') 169 | 170 | # 开始问答 171 | while True: 172 | que_str = input('--------------------\nMr. %s: ' % man_name) 173 | 174 | if que_str=='end': 175 | break 176 | 177 | # 进行问题匹配 178 | que, sim, anss = Chat.match_question(que_str) 179 | 180 | if not que or sim < sim_new: 181 | que_new_type = input_int(input_tip='\n这是一个新问题, 输入问题类型: ', default=2) 182 | que, sim, anss = chat.chat_ctl_question(que_str, que, sim, anss, que_new_type) 183 | 184 | chat.coms_add_que(que_str, que, sim) 185 | 186 | #这里进行答案匹配 187 | ans, score = chat.chat_ctl_answer(que, sim, anss) 188 | chat.coms_add_ans(ans, score) 189 | 190 | print('Mr. Bot: %s\n' % ans['content']) 191 | print('Answer type : %s\nAnswer seed : %s\nAnswer deg : %s\nAnswer score : %s\n' % (ans['type'], ans['seed'], ans['deg'], score)) 192 | 193 | if ans['id']<=0: 194 | create_anss(que['id']) 195 | else: 196 | ans_score = input_int(input_tip='给答案打分 : ', default=0) 197 | Chat.change_score(que['id'], ans['id'], ans_score) 198 | 199 | create_anss(que['id']) 200 | 201 | # 对话模式 202 | def chat(): 203 | # 这里开始对话,初始化对话问答库 204 | man_name = input('What\'s your name ? ') 205 | 206 | # 加载问答库 207 | chat = Chat(man_name) 208 | 209 | print('----------开始问答----------\n') 210 | 211 | # 开始问答 212 | while True: 213 | que_str = input('--------------------\nMr. %s: ' % man_name) 214 | 215 | if que_str=='end': 216 | break 217 | # 进行问题匹配 218 | que, sim, anss = Chat.match_question(que_str) 219 | #这里进行答案匹配 220 | ans, score = chat.chat_ctl_answer(que, sim, anss) 221 | 222 | print('Mr. Bot: %s\n' % ans['content']) 223 | 224 | 225 | if __name__=='__main__': 226 | chat_ex() 227 | -------------------------------------------------------------------------------- /chatjsondb.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | 'Chat数据库' 4 | 5 | __author__='litterzhang' 6 | 7 | import os 8 | import functools 9 | 10 | from tinydb import TinyDB, Query 11 | 12 | import ChatUtils 13 | from WordSegment.segs import bmseg 14 | 15 | answer_db = None 16 | question_db = None 17 | ans2que_db = None 18 | 19 | # 返回结果类封装 20 | class Result: 21 | def __init__(self, success=True, message=None, content=dict()): 22 | self.success = success 23 | self.message = message 24 | self.content = content 25 | 26 | def __str__(self): 27 | return str({'success' : self.success, 'message' : self.message, 'content' : self.content}) 28 | 29 | __repr__ = __str__ 30 | 31 | 32 | # 检查数据库是否初始化 33 | def check_db(func): 34 | global answer_db, question_db, ans2que_db 35 | 36 | @functools.wraps(func) 37 | def wrapper(*args, **kw): 38 | if answer_db==None or question_db==None or ans2que_db==None: 39 | return Result(success=False, message='数据库未初始化!') 40 | return func(*args, **kw) 41 | return wrapper 42 | 43 | # 使用key数据化数据库 44 | def init_db(key): 45 | global answer_db, question_db, ans2que_db 46 | 47 | ANSWER = os.path.join(os.path.dirname(__file__), 'data/answer_%s.json' % key) 48 | QUESTION = os.path.join(os.path.dirname(__file__), 'data/question_%s.json' % key) 49 | ANS2QUE = os.path.join(os.path.dirname(__file__), 'data/ans2que_%s.json' % key) 50 | 51 | answer_db = TinyDB(ANSWER) 52 | question_db = TinyDB(QUESTION) 53 | ans2que_db = TinyDB(ANS2QUE) 54 | 55 | # 匹配问题 56 | @check_db 57 | def match_question(que_str): 58 | global answer_db, question_db, ans2que_db 59 | 60 | sim_max = -1 61 | que_res = None 62 | 63 | que_words = [list(x) for x in bmseg.seg(que_str)] 64 | que_words = list(filter(lambda x: x[2]!='bd', que_words)) 65 | 66 | for que in question_db.all(): 67 | sim = ChatUtils.sim_calc(que_words, que['words']) 68 | if sim > sim_max: 69 | sim_max = sim 70 | que_res = que 71 | 72 | if que_res: 73 | que_res['id'] = que_res.eid 74 | return Result(content=dict({'que' : que_res, 'sim' : sim_max})) 75 | 76 | # 新建问题 77 | @check_db 78 | def create_question(que_str, que_type=2): 79 | global answer_db, question_db, ans2que_db 80 | que_id = question_db.insert({'type' : que_type, 'content' : que_str, 'words' : bmseg.seg(que_str)}) 81 | 82 | return Result(success=True, content=dict({'que' : {'id' : que_id, 'type' : que_type, 'content' : que_str, 'words' : bmseg.seg(que_str)}})) 83 | 84 | # 新建答案 85 | @check_db 86 | def create_answer(ans_str, ans_type=2, ans_seed=-1, ans_deg=0): 87 | global answer_db, question_db, ans2que_db 88 | ans_id = answer_db.insert({'type' : ans_type, 'seed' : ans_seed, 'deg' : ans_deg, 'content' : ans_str, 'words' : bmseg.seg(ans_str)}) 89 | 90 | return Result(success=True, content=dict({'id' : ans_id})) 91 | 92 | # 更新问题-答案 93 | @check_db 94 | def create_ans2que(que_id, ans_id, score=10): 95 | global answer_db, question_db, ans2que_db 96 | 97 | X = Query() 98 | ans2que_db.remove((X.que_id==que_id) & (X.ans_id==ans_id)) 99 | ans2que_id = ans2que_db.insert({'que_id' : que_id, 'ans_id' : ans_id, 'score' : score}) 100 | return Result() 101 | 102 | # 更新问题-答案 103 | @check_db 104 | def update_ans2que(que_id, ans_id, score=0): 105 | global answer_db, question_db, ans2que_db 106 | 107 | X = Query() 108 | ans2que_old = ans2que_db.get((X.que_id==que_id) & (X.ans_id==ans_id)) 109 | if ans2que_old: 110 | ans2que_db.update({'score' : ans2que_old['score']+score}, (X.que_id==que_id) & (X.ans_id==ans_id)) 111 | else: 112 | ans2que_db.insert({'que_id' : que_id, 'ans_id' : ans_id, 'score' : 10+score}) 113 | 114 | # 为问题添加答案 115 | @check_db 116 | def add_ans_for_que(que_id, ans_str, ans_type=2, ans_seed=-1, ans_deg=0, score=10): 117 | global answer_db, question_db, ans2que_db 118 | 119 | res = create_answer(ans_str, ans_type, ans_seed, ans_deg) 120 | if res.success: 121 | ans_id = res.content.get('id', -1) 122 | if ans_id == -1: 123 | return Result(success=False, message='新建答案失败') 124 | create_ans2que(que_id, ans_id, score) 125 | return Result() 126 | else: 127 | return Result(success=False, message='新建答案失败') 128 | 129 | # 根据问题查找答案 130 | @check_db 131 | def get_ans2que_by_que(que_id): 132 | global answer_db, question_db, ans2que_db 133 | 134 | X = Query() 135 | ans2ques = ans2que_db.search(X.que_id==que_id) 136 | return Result(content=dict({'ans2ques' : ans2ques})) 137 | 138 | # 为问题匹配旧答案 139 | @check_db 140 | def match_old_anss(que_new_id, que_old_id): 141 | global answer_db, question_db, ans2que_db 142 | 143 | res = get_ans2que_by_que(que_old_id) 144 | 145 | if res.success: 146 | ans2ques = res.content.get('ans2ques', None) 147 | if ans2ques: 148 | for ans2que in ans2ques: 149 | ans2que_db.insert({'que_id' : que_new_id, 'ans_id' : ans2que['ans_id'], 'score' : ans2que['score']}) 150 | return Result() 151 | 152 | # 根据问题查找答案 153 | def get_answers_by_que(que_id): 154 | global answer_db, question_db, ans2que_db 155 | 156 | answers = list() 157 | 158 | X = Query() 159 | ans2ques = ans2que_db.search(X.que_id==que_id) 160 | for ans2que in ans2ques: 161 | ans_id = ans2que['ans_id'] 162 | ans_score = ans2que['score'] 163 | 164 | ans = answer_db.get(eid=ans_id) 165 | 166 | ans['id'] = ans_id 167 | answers.append({'ans' : ans, 'score' : ans_score}) 168 | return Result(content=dict({'answers' : answers})) 169 | 170 | # 根据问题匹配答案 171 | def get_answers(que_str): 172 | global answer_db, question_db, ans2que_db 173 | 174 | res = match_question(que_str) 175 | if res.success: 176 | que = res.content.get('que', None) 177 | sim = res.content.get('sim', -1) 178 | 179 | if not que: 180 | return Result(success=False, message='未能匹配到问题!') 181 | res_anss = get_answers_by_que(que.eid) 182 | anss = list() 183 | if res_anss.success: 184 | anss = res_anss.content.get('answers', list()) 185 | 186 | que['id'] = que.eid 187 | return Result(content=dict({'que' : que, 'sim' : sim, 'anss' : anss})) 188 | else: 189 | return Result(success=False, message='未能匹配到问题!') -------------------------------------------------------------------------------- /chatsession.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | '用于控制对话的进行' 4 | 5 | __author__='litterzhang' 6 | 7 | import chatdb 8 | import random 9 | import ChatUtils 10 | 11 | # 获取最佳答案 12 | def best_ans(que_str, que, sim, anss, coms): 13 | 14 | ans = ChatUtils.default_ans() 15 | score = 0 16 | 17 | if sim < 0.2: 18 | ans = ChatUtils.blur_ans() 19 | else: 20 | # 查找之前相同的问题 21 | times = 0 22 | last_ans = None 23 | for com in coms: 24 | if com['que_sim']>=0.2 and que.id==com['que'].id: 25 | times += 1 26 | last_ans = com['ans'] 27 | 28 | # 匹配固定的回答 29 | if que.type==0: 30 | ans_seed = -1 31 | ans_type = -1 32 | if last_ans: 33 | ans_seed = last_ans.seed 34 | ans_type = last_ans.type 35 | ans, score = ChatUtils.search_ans(anss, times=times, ans_seed=ans_seed, ans_type=ans_type) 36 | elif que.type==1: 37 | ans, score = ChatUtils.search_ans(anss, times=times) 38 | else: 39 | ans, score = ChatUtils.search_ans(anss, times=times) 40 | 41 | # 记录本次回答 42 | coms.append({ 43 | 'que_str' : que_str, 44 | 'que' : que, 45 | 'que_sim' : sim, 46 | 'ans' : ans, 47 | 'ans_score' : score 48 | }) 49 | 50 | return ans, score 51 | 52 | # 输入int值 53 | def input_int(input_tip='', default=0): 54 | res = default 55 | try: 56 | res = int(input(input_tip)) 57 | except: 58 | pass 59 | return res 60 | 61 | # 输入float值 62 | def input_float(input_tip='', default=0.0): 63 | res = default 64 | try: 65 | res = float(input(input_tip)) 66 | except: 67 | pass 68 | return res 69 | 70 | # 新增1或n个答案 71 | def create_anss(que_id): 72 | while True: 73 | print('添加答案,按回车退出\n') 74 | ans_str = input('新增答案内容 : ') 75 | if not ans_str: 76 | break 77 | ans_type = input_int(input_tip='答案类型 : ', default=2) 78 | ans_seed = input_int(input_tip='答案中心 : ', default=-1) 79 | ans_deg = input_int(input_tip='答案语气 : ', default=0) 80 | ans_score = input_int(input_tip='答案打分 : ', default=10) 81 | 82 | chatdb.ans_new_and_match_que(que_id, ans_str, ans_type, ans_seed, ans_deg, ans_score) 83 | 84 | # 聊天从这里开始————训练模式 85 | def chat(): 86 | # 记录对话的进行 87 | coms = list() 88 | 89 | # 这里开始对话,初始化对话问答库 90 | man_name = input('What\'s your name? ') 91 | 92 | # 这里输入新建问题相似度阈值,及匹配旧问题相似度阈值 93 | sim_new = input_float('新问题阈值sim_new ? ', default=0.7) 94 | sim_old = input_float('旧问题阈值sim_old ? ', default=0.2) 95 | 96 | # 加载问答库 97 | chatdb.init_db(man_name) 98 | 99 | print('----------开始问答----------\n') 100 | 101 | # 开始问答 102 | while True: 103 | que_str = input('--------------------\nMr. %s: ' % man_name) 104 | 105 | if que_str=='end': 106 | chatdb.save_db(man_name) 107 | break 108 | 109 | # 进行问题匹配 110 | que, sim, anss = chatdb.get_answer(que_str) 111 | 112 | # 创建新问题 113 | if sim < sim_new: 114 | # 输入新问题类型 115 | que_new_type = input_int(input_tip='\n这是一个新问题, 输入问题类型: ', default=2) 116 | que_new = chatdb.que_new(que_str, que_new_type) 117 | 118 | # 匹配旧问题答案 119 | if sim > sim_old: 120 | chatdb.match_old_anss(que_new.id, que.id) 121 | else: 122 | anss = list() 123 | que = que_new 124 | sim = 1.0 125 | 126 | #这里进行答案匹配 127 | ans, score = best_ans(que_str, que, sim, anss, coms) 128 | print('Mr. Bot: %s\n' % ans.content) 129 | print('Answer type : %s\nAnswer seed : %s\nAnswer deg : %s\nAnswer score : %s\n' % (ans.type, ans.seed, ans.deg, score)) 130 | 131 | # 默认答案,要求新增1或n个答案 132 | if ans.id <= 0: 133 | create_anss(que.id) 134 | else: 135 | # 打分 136 | ans_score = input_int(input_tip='给答案打分 : ', default=0) 137 | chatdb.change_score(que.id, ans.id, ans_score) 138 | 139 | create_anss(que.id) 140 | 141 | print('--------------------\n') 142 | 143 | if __name__=='__main__': 144 | chat() -------------------------------------------------------------------------------- /coms/he_20161205 100616: -------------------------------------------------------------------------------- 1 | [{"ans": {"id": -1, "seed": -1, "words": [], "content": "欢迎!小伙子们在火炉旁挤挤,留个位子出来~", "type": -1, "deg": -1}, "score": 0, "que_sim": 1, "que": {"id": 1, "content": "你好", "type": 2, "words": [["你好", 725, "l"]]}, "que_str": "你好"}, {"ans": {"id": -1, "seed": -1, "words": [], "content": "欢迎!小伙子们在火炉旁挤挤,留个位子出来~", "type": -1, "deg": -1}, "score": 0, "que_sim": 1, "que": {"id": 2, "content": "今天天气不错", "type": 0, "words": [["今天", 15960, "t"], ["天气", 2657, "n"], ["不错", 5322, "a"]]}, "que_str": "今天天气不错"}, {"ans": {"id": -1, "seed": -1, "words": [], "content": "欢迎!小伙子们在火炉旁挤挤,留个位子出来~", "type": -1, "deg": -1}, "score": 0, "que_sim": 1, "que": {"id": 3, "content": "吃了吗", "type": 0, "words": [["吃", 36799, "v"], ["了", 883634, "ul"], ["吗", 21245, "y"]]}, "que_str": "吃了吗"}] -------------------------------------------------------------------------------- /coms/he_20161205 100754: -------------------------------------------------------------------------------- 1 | [{"ans": {"seed": -1, "id": 1, "words": [["你好", 725, "l"]], "content": "你好", "type": 2, "deg": 0}, "score": 10, "que_sim": 1.0, "que": {"words": [["你好", 725, "l"]], "content": "你好", "id": 1, "type": 2}, "que_str": "你好"}, {"ans": {"seed": -1, "id": 2, "words": [["你好", 725, "l"], ["呀", 9580, "y"]], "content": "你好呀", "type": 2, "deg": 1}, "score": 10, "que_sim": 1.0, "que": {"words": [["你好", 725, "l"]], "content": "你好", "id": 1, "type": 2}, "que_str": "你好"}, {"ans": {"seed": -1, "id": 7, "words": [["是", 796991, "v"], ["的", 3188252, "uj"], ["呀", 9580, "y"]], "content": "是的呀", "type": 1, "deg": 0}, "score": 10, "que_sim": 1.0, "que": {"words": [["今天", 15960, "t"], ["天气", 2657, "n"], ["不错", 5322, "a"]], "content": "今天天气不错", "id": 2, "type": 0}, "que_str": "今天天气不错"}, {"ans": {"seed": -1, "id": 8, "words": [["天气", 2657, "n"], ["很", 69103, "zg"], ["好", 92543, "a"], ["呢", 28623, "y"]], "content": "天气很好呢", "type": 1, "deg": 0}, "score": 10, "que_sim": 1.0, "que": {"words": [["今天", 15960, "t"], ["天气", 2657, "n"], ["不错", 5322, "a"]], "content": "今天天气不错", "id": 2, "type": 0}, "que_str": "今天天气不错"}, {"ans": {"seed": -1, "id": 7, "words": [["是", 796991, "v"], ["的", 3188252, "uj"], ["呀", 9580, "y"]], "content": "是的呀", "type": 1, "deg": 0}, "score": 10, "que_sim": 1.0, "que": {"words": [["今天", 15960, "t"], ["天气", 2657, "n"], ["不错", 5322, "a"]], "content": "今天天气不错", "id": 2, "type": 0}, "que_str": "今天天气不错"}, {"ans": {"seed": -1, "id": 10, "words": [["下雨", 481, "v"], ["呢", 28623, "y"], [",", "0", "bd"], ["你", 234587, "r"], ["喜欢", 9783, "v"], ["下雨天", 27, "n"], ["吗", 21245, "y"]], "content": "下雨呢,你喜欢下雨天吗", "type": 1, "deg": 0}, "score": 10, "que_sim": 1.0, "que": {"words": [["今天", 15960, "t"], ["天气", 2657, "n"], ["不错", 5322, "a"]], "content": "今天天气不错", "id": 2, "type": 0}, "que_str": "今天天气不错"}, {"ans": {"seed": -1, "id": 11, "words": [["天气", 2657, "n"], ["不好", 5027, "d"], ["呀", 9580, "y"], [" ", "0", "bd"], ["污染", 2692, "vn"], ["这么", 18886, "r"], ["严重", 10445, "a"]], "content": "天气不好呀 污染这么严重", "type": 1, "deg": 0}, "score": 10, "que_sim": 1.0, "que": {"words": [["今天", 15960, "t"], ["天气", 2657, "n"], ["不错", 5322, "a"]], "content": "今天天气不错", "id": 2, "type": 0}, "que_str": "今天天气不错"}] -------------------------------------------------------------------------------- /coms/he_20161205 101011: -------------------------------------------------------------------------------- 1 | [{"ans": {"seed": -1, "id": 11, "words": [["天气", 2657, "n"], ["不好", 5027, "d"], ["呀", 9580, "y"], [" ", "0", "bd"], ["污染", 2692, "vn"], ["这么", 18886, "r"], ["严重", 10445, "a"]], "content": "天气不好呀 污染这么严重", "type": 1, "deg": 0}, "score": 10, "que_sim": 1.0, "que": {"words": [["今天", 15960, "t"], ["天气", 2657, "n"], ["不错", 5322, "a"]], "content": "今天天气不错", "id": 2, "type": 0}, "que_str": "今天天气不错"}, {"ans": {"seed": -1, "id": 11, "words": [["天气", 2657, "n"], ["不好", 5027, "d"], ["呀", 9580, "y"], [" ", "0", "bd"], ["污染", 2692, "vn"], ["这么", 18886, "r"], ["严重", 10445, "a"]], "content": "天气不好呀 污染这么严重", "type": 1, "deg": 0}, "score": 10, "que_sim": 1.0, "que": {"words": [["今天", 15960, "t"], ["天气", 2657, "n"], ["不错", 5322, "a"]], "content": "今天天气不错", "id": 2, "type": 0}, "que_str": "今天天气不错"}, {"ans": {"seed": -1, "id": 9, "words": [["是", 796991, "v"], ["个", 125538, "q"], ["出行", 414, "v"], ["的", 3188252, "uj"], ["好", 92543, "a"], ["天气", 2657, "n"], ["噢", 814, "e"]], "content": "是个出行的好天气噢", "type": 1, "deg": 0}, "score": 10, "que_sim": 1.0, "que": {"words": [["今天", 15960, "t"], ["天气", 2657, "n"], ["不错", 5322, "a"]], "content": "今天天气不错", "id": 2, "type": 0}, "que_str": "今天天气不错"}] -------------------------------------------------------------------------------- /coms/li_20161130 202248: -------------------------------------------------------------------------------- 1 | [{"que_sim": 1, "que_str": "你好", "que": {"content": "你好", "words": [["你好", 725, "l"]], "id": 1, "type": 2}, "score": 0, "ans": {"words": [], "seed": -1, "deg": -1, "type": -1, "content": "欢迎!小伙子们在火炉旁挤挤,留个位子出来~", "id": -1}}, {"que_sim": 1, "que_str": "吃了吗", "que": {"content": "吃了吗", "words": [["吃", 36799, "v"], ["了", 883634, "ul"], ["吗", 21245, "y"]], "id": 2, "type": 2}, "score": 0, "ans": {"words": [], "seed": -1, "deg": -1, "type": -1, "content": "欢迎!小伙子们在火炉旁挤挤,留个位子出来~", "id": -1}}, {"que_sim": 1.0, "que_str": "吃了吗", "que": {"id": 2, "content": "吃了吗", "type": 2, "words": [["吃", 36799, "v"], ["了", 883634, "ul"], ["吗", 21245, "y"]]}, "score": 10, "ans": {"words": [["吃", 36799, "v"], ["过", 97817, "ug"], ["了", 883634, "ul"]], "seed": -1, "deg": 0, "id": 3, "content": "吃过了", "type": 0}}, {"que_sim": 1.0, "que_str": "吃了吗", "que": {"id": 2, "content": "吃了吗", "type": 2, "words": [["吃", 36799, "v"], ["了", 883634, "ul"], ["吗", 21245, "y"]]}, "score": 10, "ans": {"words": [["吃", 36799, "v"], ["过", 97817, "ug"], ["了", 883634, "ul"]], "seed": -1, "deg": 0, "id": 3, "content": "吃过了", "type": 0}}] -------------------------------------------------------------------------------- /coms/wang_20161205 101447: -------------------------------------------------------------------------------- 1 | [{"ans": {"id": -1, "seed": -1, "words": [], "content": "欢迎!小伙子们在火炉旁挤挤,留个位子出来~", "type": -1, "deg": -1}, "score": 0, "que_sim": 1, "que": {"id": 1, "content": "你好", "type": 2, "words": [["你好", 725, "l"]]}, "que_str": "你好"}, {"ans": {"seed": -1, "id": 2, "words": [["你好", 725, "l"], ["呀", 9580, "y"]], "content": "你好呀", "type": 2, "deg": 1}, "score": 10, "que_sim": 1.0, "que": {"words": [["你好", 725, "l"]], "content": "你好", "id": 1, "type": 2}, "que_str": "你好"}, {"ans": {"seed": -1, "id": 3, "words": [["雷", 1951, "n"], ["吼", 1077, "v"], ["雷", 1951, "n"], ["吼", 1077, "v"]], "content": "雷吼雷吼", "type": 2, "deg": 2}, "score": 10, "que_sim": 1.0, "que": {"words": [["你好", 725, "l"]], "content": "你好", "id": 1, "type": 2}, "que_str": "你好"}, {"ans": {"seed": -1, "id": 5, "words": [["你好", 725, "l"], ["?", "0", "bd"]], "content": "你好?", "type": 2, "deg": 3}, "score": 10, "que_sim": 1.0, "que": {"words": [["你好", 725, "l"]], "content": "你好", "id": 1, "type": 2}, "que_str": "你好"}, {"ans": {"id": -1, "seed": -1, "words": [], "content": "欢迎!小伙子们在火炉旁挤挤,留个位子出来~", "type": -1, "deg": -1}, "score": 0, "que_sim": 1, "que": {"id": 2, "content": "今天天气不错", "type": 0, "words": [["今天", 15960, "t"], ["天气", 2657, "n"], ["不错", 5322, "a"]]}, "que_str": "今天天气不错"}] -------------------------------------------------------------------------------- /coms/wang_20161205 110120: -------------------------------------------------------------------------------- 1 | [{"ans": {"seed": -1, "id": 1, "words": [["你好", 725, "l"]], "content": "你好", "type": 2, "deg": 0}, "score": 10, "que_sim": 1.0, "que": {"words": [["你好", 725, "l"]], "content": "你好", "id": 1, "type": 2}, "que_str": "你好"}, {"ans": {"seed": -1, "id": 2, "words": [["你好", 725, "l"], ["呀", 9580, "y"]], "content": "你好呀", "type": 2, "deg": 1}, "score": 10, "que_sim": 1.0, "que": {"words": [["你好", 725, "l"]], "content": "你好", "id": 1, "type": 2}, "que_str": "你好"}, {"ans": {"seed": -1, "id": 3, "words": [["雷", 1951, "n"], ["吼", 1077, "v"], ["雷", 1951, "n"], ["吼", 1077, "v"]], "content": "雷吼雷吼", "type": 2, "deg": 2}, "score": 10, "que_sim": 1.0, "que": {"words": [["你好", 725, "l"]], "content": "你好", "id": 1, "type": 2}, "que_str": "你好"}, {"ans": {"seed": -1, "id": 4, "words": [["你好", 725, "l"], [",", "0", "bd"], ["我", 328841, "r"], ["也好", 2084, "y"], ["!", "0", "bd"]], "content": "你好,我也好!", "type": 2, "deg": 3}, "score": 10, "que_sim": 1.0, "que": {"words": [["你好", 725, "l"]], "content": "你好", "id": 1, "type": 2}, "que_str": "你好"}, {"ans": {"seed": -1, "id": 6, "words": [["不好", 5027, "d"], ["了", 883634, "ul"], ["!", "0", "bd"]], "content": "不好了!", "type": 2, "deg": 4}, "score": 10, "que_sim": 1.0, "que": {"words": [["你好", 725, "l"]], "content": "你好", "id": 1, "type": 2}, "que_str": "你好"}, {"ans": {"seed": -1, "id": 6, "words": [["不好", 5027, "d"], ["了", 883634, "ul"], ["!", "0", "bd"]], "content": "不好了!", "type": 2, "deg": 4}, "score": 10, "que_sim": 1.0, "que": {"words": [["你好", 725, "l"]], "content": "你好", "id": 1, "type": 2}, "que_str": "你好"}, {"ans": {"seed": -1, "id": 10, "words": [["天气", 2657, "n"], ["不好", 5027, "d"], ["呀", 9580, "y"]], "content": "天气不好呀", "type": 1, "deg": 0}, "score": 10, "que_sim": 1.0, "que": {"words": [["今天", 15960, "t"], ["天气", 2657, "n"], ["不错", 5322, "a"]], "content": "今天天气不错", "id": 2, "type": 0}, "que_str": "今天天气不错"}, {"ans": {"seed": -1, "id": 11, "words": [["下雨天", 27, "n"], [",", "0", "bd"], ["你", 234587, "r"], ["喜欢", 9783, "v"], ["下雨", 481, "v"], ["吗", 21245, "y"]], "content": "下雨天,你喜欢下雨吗", "type": 1, "deg": 1}, "score": 10, "que_sim": 1.0, "que": {"words": [["今天", 15960, "t"], ["天气", 2657, "n"], ["不错", 5322, "a"]], "content": "今天天气不错", "id": 2, "type": 0}, "que_str": "今天天气不错"}, {"ans": {"seed": -1, "id": 12, "words": [["污染", 2692, "vn"], ["这么", 18886, "r"], ["严重", 10445, "a"]], "content": "污染这么严重", "type": 1, "deg": 2}, "score": 10, "que_sim": 1.0, "que": {"words": [["今天", 15960, "t"], ["天气", 2657, "n"], ["不错", 5322, "a"]], "content": "今天天气不错", "id": 2, "type": 0}, "que_str": "今天天气不错"}] -------------------------------------------------------------------------------- /coms/wang_20161205 110653: -------------------------------------------------------------------------------- 1 | [] -------------------------------------------------------------------------------- /coms/zhang_20161130 171327: -------------------------------------------------------------------------------- 1 | [] -------------------------------------------------------------------------------- /coms/zhang_20161130 171804: -------------------------------------------------------------------------------- 1 | [{"score": 11, "ans": {"id": 1, "words": [["你好", 725, "l"]], "seed": -1, "deg": 0, "type": 2, "content": "你好"}, "que": {"content": "你好", "type": 2, "words": [["你好", 725, "l"]], "id": 1}, "que_str": "你好", "que_sim": 1.0}] -------------------------------------------------------------------------------- /coms/zhang_20161130 172203: -------------------------------------------------------------------------------- 1 | [{"que_str": "你好", "que_sim": 1.0, "que": {"type": 2, "id": 1, "content": "你好", "words": [["你好", 725, "l"]]}, "ans": {"id": 1, "words": [["你好", 725, "l"]], "deg": 0, "type": 2, "content": "你好", "seed": -1}, "score": 11}, {"que_str": "你好", "que_sim": 1.0, "que": {"type": 2, "id": 1, "content": "你好", "words": [["你好", 725, "l"]]}, "ans": {"id": 2, "words": [["你好", 725, "l"], ["呀", 9580, "y"]], "deg": 1, "type": 2, "content": "你好呀", "seed": -1}, "score": 10}, {"que_str": "你好", "que_sim": 1.0, "que": {"type": 2, "id": 1, "content": "你好", "words": [["你好", 725, "l"]]}, "ans": {"id": 5, "words": [["你好", 725, "l"], [",", "0", "bd"], ["我", 328841, "r"], ["也好", 2084, "y"], ["!", "0", "bd"]], "deg": 2, "type": 2, "content": "你好,我也好!", "seed": -1}, "score": 10}, {"que_str": "你好", "que_sim": 1.0, "que": {"type": 2, "id": 1, "content": "你好", "words": [["你好", 725, "l"]]}, "ans": {"id": 6, "words": [["很", 69103, "zg"], ["高兴", 5387, "b"], ["见到", 7522, "v"], ["你", 234587, "r"], [",", "0", "bd"], ["小伙子", 949, "n"]], "deg": 3, "type": 2, "content": "很高兴见到你,小伙子", "seed": -1}, "score": 10}, {"que_str": "你好", "que_sim": 1.0, "que": {"type": 2, "id": 1, "content": "你好", "words": [["你好", 725, "l"]]}, "ans": {"id": 4, "words": [["哈哈哈", 221, "o"], [",", "0", "bd"], ["大家", 19177, "n"], ["好", 92543, "a"], ["才", 55415, "d"], ["是", 796991, "v"], ["真的", 6277, "d"], ["好", 92543, "a"]], "deg": 4, "type": 2, "content": "哈哈哈,大家好才是真的好", "seed": -1}, "score": 10}] -------------------------------------------------------------------------------- /coms/zhang_20161130 202041: -------------------------------------------------------------------------------- 1 | [] -------------------------------------------------------------------------------- /coms/zhang_20161201 135449: -------------------------------------------------------------------------------- 1 | [{"que": {"type": 2, "content": "你好", "words": [["你好", 725, "l"]], "id": 1}, "ans": {"seed": -1, "content": "你好", "deg": 0, "words": [["你好", 725, "l"]], "id": 1, "type": 2}, "que_str": "你好", "que_sim": 1.0, "score": 11}, {"que": {"id": 2, "type": 2, "words": [["吃", 36799, "v"], ["了", 883634, "ul"], ["吗", 21245, "y"]], "content": "吃了吗"}, "ans": {"id": -1, "content": "欢迎!小伙子们在火炉旁挤挤,留个位子出来~", "type": -1, "words": [], "deg": -1, "seed": -1}, "que_str": "吃了吗", "que_sim": 1, "score": 0}] -------------------------------------------------------------------------------- /coms/zhang_20161201 135556: -------------------------------------------------------------------------------- 1 | [] -------------------------------------------------------------------------------- /coms/zhang_20161201 135718: -------------------------------------------------------------------------------- 1 | [] -------------------------------------------------------------------------------- /coms/zhang_20161201 140525: -------------------------------------------------------------------------------- 1 | [] -------------------------------------------------------------------------------- /coms/zhang_20161205 100042: -------------------------------------------------------------------------------- 1 | [{"ans": {"seed": -1, "id": 3, "words": [["雷", 1951, "n"], ["吼", 1077, "v"], ["雷", 1951, "n"], ["吼", 1077, "v"]], "content": "雷吼雷吼", "type": 2, "deg": 0}, "score": 11, "que_sim": 1.0, "que": {"words": [["你好", 725, "l"]], "content": "你好", "id": 1, "type": 2}, "que_str": "你好"}] -------------------------------------------------------------------------------- /data/ReadMe.md: -------------------------------------------------------------------------------- 1 | # 问题定义 2 | id : 标识问题 3 | type : 0 , 1 , 2。 0表示会话确定问题,在一次会话中,答案唯一;1表示会话发散问题,在一次会话中,答案可以有多种;2表示未知问题 4 | content : 问题内容 5 | words : 问题分词 6 | 7 | # 答案定义 8 | id : 标识答案 9 | type : 0 , 1 , 2。 0表示正向回答,1表示负向回答,2表示中立回答。 10 | seed : 标识回答的中心。 11 | deg : 标识回答的情绪程度 12 | content : 回答内容 13 | words : 回答关键词 14 | 15 | # 问题——答案定义 16 | que_id : 问题id 17 | ans_ids : [答案id] 18 | -------------------------------------------------------------------------------- /data/ans2que: -------------------------------------------------------------------------------- 1 | 1 l 1 2 3 4 5 6 7 8 2 | 2 l 9 10 11 12 13 3 | 2 e 14 10 -------------------------------------------------------------------------------- /data/ans2que.json: -------------------------------------------------------------------------------- 1 | [{"que_id": "1", "ans_ids": [{"id": "1", "score": 10}, {"id": "2", "score": 10}, {"id": "3", "score": 10}, {"id": "4", "score": 10}, {"id": "5", "score": 10}, {"id": "6", "score": 10}, {"id": "7", "score": 10}, {"id": "8", "score": 10}]}, {"que_id": "2", "ans_ids": [{"id": "9", "score": 10}, {"id": "10", "score": 10}, {"id": "11", "score": 10}, {"id": "12", "score": 10}, {"id": "13", "score": 10}, {"id": "14", "score": 10}]}] -------------------------------------------------------------------------------- /data/ans2que_he.json: -------------------------------------------------------------------------------- 1 | {"_default": {"1": {"que_id": 1, "ans_id": 1, "score": 10}, "2": {"que_id": 1, "ans_id": 2, "score": 10}, "3": {"que_id": 1, "ans_id": 3, "score": 10}, "4": {"que_id": 1, "ans_id": 4, "score": 10}, "5": {"que_id": 1, "ans_id": 5, "score": 10}, "6": {"que_id": 1, "ans_id": 6, "score": 10}, "7": {"que_id": 2, "ans_id": 7, "score": 10}, "8": {"que_id": 2, "ans_id": 8, "score": 10}, "9": {"que_id": 2, "ans_id": 9, "score": 10}, "10": {"que_id": 2, "ans_id": 10, "score": 10}, "11": {"que_id": 2, "ans_id": 11, "score": 10}, "12": {"que_id": 3, "ans_id": 12, "score": 10}, "13": {"que_id": 3, "ans_id": 13, "score": 10}, "14": {"que_id": 3, "ans_id": 14, "score": 10}, "15": {"que_id": 3, "ans_id": 15, "score": 10}, "16": {"que_id": 3, "ans_id": 16, "score": 10}, "17": {"que_id": 3, "ans_id": 17, "score": 10}, "18": {"que_id": 3, "ans_id": 18, "score": 10}}} -------------------------------------------------------------------------------- /data/ans2que_li.json: -------------------------------------------------------------------------------- 1 | {"_default": {"1": {"que_id": 1, "score": 10, "ans_id": 1}, "2": {"que_id": 2, "score": 10, "ans_id": 2}, "3": {"que_id": 2, "score": 10, "ans_id": 3}}} -------------------------------------------------------------------------------- /data/ans2que_wang.json: -------------------------------------------------------------------------------- 1 | {"_default": {"1": {"que_id": 1, "ans_id": 1, "score": 10}, "2": {"que_id": 1, "ans_id": 2, "score": 10}, "3": {"que_id": 1, "ans_id": 3, "score": 10}, "4": {"que_id": 1, "ans_id": 4, "score": 10}, "5": {"que_id": 1, "ans_id": 5, "score": 10}, "6": {"que_id": 1, "ans_id": 6, "score": -1}, "7": {"que_id": 2, "ans_id": 7, "score": 10}, "8": {"que_id": 2, "ans_id": 8, "score": 10}, "9": {"que_id": 2, "ans_id": 9, "score": 10}, "10": {"que_id": 2, "ans_id": 10, "score": 10}, "11": {"que_id": 2, "ans_id": 11, "score": 10}, "12": {"que_id": 2, "ans_id": 12, "score": 10}, "13": {"que_id": 1, "ans_id": 13, "score": 10}, "14": {"que_id": 3, "ans_id": 14, "score": 10}, "15": {"que_id": 3, "ans_id": 15, "score": 10}, "16": {"que_id": 3, "ans_id": 16, "score": 10}, "17": {"que_id": 3, "ans_id": 17, "score": 10}}} -------------------------------------------------------------------------------- /data/ans2que_xuman.json: -------------------------------------------------------------------------------- 1 | {"_default": {"1": {"ans_id": 1, "que_id": 1, "score": 10}, "2": {"ans_id": 2, "que_id": 2, "score": 10}, "3": {"ans_id": 1, "que_id": 3, "score": -12}, "4": {"ans_id": 3, "que_id": 3, "score": 10}, "5": {"ans_id": 4, "que_id": 3, "score": 10}}} -------------------------------------------------------------------------------- /data/ans2que_zhang.json: -------------------------------------------------------------------------------- 1 | {"_default": {"1": {"score": 11, "ans_id": 1, "que_id": 1}, "2": {"score": 10, "ans_id": 2, "que_id": 1}, "3": {"score": 11, "ans_id": 3, "que_id": 1}, "4": {"score": 10, "ans_id": 4, "que_id": 1}, "5": {"score": 10, "ans_id": 5, "que_id": 1}, "6": {"score": 10, "ans_id": 6, "que_id": 1}, "7": {"score": 10, "ans_id": 7, "que_id": 1}, "8": {"score": 10, "ans_id": 8, "que_id": 3}, "9": {"score": 10, "ans_id": 9, "que_id": 3}, "10": {"score": 10, "ans_id": 10, "que_id": 3}, "11": {"score": 10, "ans_id": 11, "que_id": 2}}} -------------------------------------------------------------------------------- /data/answer: -------------------------------------------------------------------------------- 1 | 1 0 0 0 吃过了 2 | 2 1 1 0 还没吃呢 3 | 3 0 0 1 吃过了,吃了蛋炒饭 4 | 4 1 1 1 没吃啊 5 | 5 0 0 2 吃过了啊,吃了蛋炒饭啊 6 | 6 1 1 2 我说我没吃啊!你没听到吗 7 | 7 0 0 3 懒得搭理你 8 | 8 1 1 3 懒得搭理你 9 | 9 0 0 0 你好 10 | 10 0 0 1 你好呀 11 | 11 0 0 2 雷吼雷吼 12 | 12 1 1 0 你也好哈哈 13 | 13 1 1 1 很高兴认识你 14 | 14 1 1 2 nice to meet you~ 15 | -------------------------------------------------------------------------------- /data/answer_he.json: -------------------------------------------------------------------------------- 1 | {"_default": {"1": {"seed": -1, "content": "\u4f60\u597d", "type": 2, "words": [["\u4f60\u597d", 725, "l"]], "deg": 0}, "2": {"seed": -1, "content": "\u4f60\u597d\u5440", "type": 2, "words": [["\u4f60\u597d", 725, "l"], ["\u5440", 9580, "y"]], "deg": 1}, "3": {"seed": -1, "content": "\u4f60\u597d\uff01\u5f88\u9ad8\u5174\u89c1\u5230\u4f60", "type": 2, "words": [["\u4f60\u597d", 725, "l"], ["\uff01", "0", "bd"], ["\u5f88", 69103, "zg"], ["\u9ad8\u5174", 5387, "b"], ["\u89c1\u5230", 7522, "v"], ["\u4f60", 234587, "r"]], "deg": 0}, "4": {"seed": -1, "content": "\u4f60\u597d\uff1f", "type": 2, "words": [["\u4f60\u597d", 725, "l"], ["\uff1f", "0", "bd"]], "deg": 2}, "5": {"seed": -1, "content": "\u4e0d\u597d\u4e86\uff01", "type": 2, "words": [["\u4e0d\u597d", 5027, "d"], ["\u4e86", 883634, "ul"], ["\uff01", "0", "bd"]], "deg": 3}, "6": {"seed": -1, "content": "\u6709\u4e8b\u5417\uff1f", "type": 2, "words": [["\u6709\u4e8b", 458, "r"], ["\u5417", 21245, "y"], ["\uff1f", "0", "bd"]], "deg": 4}, "7": {"seed": -1, "content": "\u662f\u7684\u5440", "type": 1, "words": [["\u662f", 796991, "v"], ["\u7684", 3188252, "uj"], ["\u5440", 9580, "y"]], "deg": 0}, "8": {"seed": -1, "content": "\u5929\u6c14\u5f88\u597d\u5462", "type": 1, "words": [["\u5929\u6c14", 2657, "n"], ["\u5f88", 69103, "zg"], ["\u597d", 92543, "a"], ["\u5462", 28623, "y"]], "deg": 0}, "9": {"seed": -1, "content": "\u662f\u4e2a\u51fa\u884c\u7684\u597d\u5929\u6c14\u5662", "type": 1, "words": [["\u662f", 796991, "v"], ["\u4e2a", 125538, "q"], ["\u51fa\u884c", 414, "v"], ["\u7684", 3188252, "uj"], ["\u597d", 92543, "a"], ["\u5929\u6c14", 2657, "n"], ["\u5662", 814, "e"]], "deg": 0}, "10": {"seed": -1, "content": "\u4e0b\u96e8\u5462\uff0c\u4f60\u559c\u6b22\u4e0b\u96e8\u5929\u5417", "type": 1, "words": [["\u4e0b\u96e8", 481, "v"], ["\u5462", 28623, "y"], ["\uff0c", "0", "bd"], ["\u4f60", 234587, "r"], ["\u559c\u6b22", 9783, "v"], ["\u4e0b\u96e8\u5929", 27, "n"], ["\u5417", 21245, "y"]], "deg": 0}, "11": {"seed": -1, "content": "\u5929\u6c14\u4e0d\u597d\u5440 \u6c61\u67d3\u8fd9\u4e48\u4e25\u91cd", "type": 1, "words": [["\u5929\u6c14", 2657, "n"], ["\u4e0d\u597d", 5027, "d"], ["\u5440", 9580, "y"], [" ", "0", "bd"], ["\u6c61\u67d3", 2692, "vn"], ["\u8fd9\u4e48", 18886, "r"], ["\u4e25\u91cd", 10445, "a"]], "deg": 0}, "12": {"seed": -1, "content": "\u5403\u8fc7\u4e86", "type": 0, "words": [["\u5403", 36799, "v"], ["\u8fc7", 97817, "ug"], ["\u4e86", 883634, "ul"]], "deg": 0}, "13": {"seed": -1, "content": "\u5403\u8fc7\u4e86\uff0c\u5403\u4e86\u571f\u8c46", "type": 1, "words": [["\u5403", 36799, "v"], ["\u8fc7", 97817, "ug"], ["\u4e86", 883634, "ul"], ["\uff0c", "0", "bd"], ["\u5403", 36799, "v"], ["\u4e86", 883634, "ul"], ["\u571f\u8c46", 493, "n"]], "deg": 0}, "14": {"seed": -1, "content": "\u6211\u5403\u8fc7\u4e86\u5440\uff01\u5403\u4e86\u571f\u8c46", "type": 0, "words": [["\u6211", 328841, "r"], ["\u5403", 36799, "v"], ["\u8fc7", 97817, "ug"], ["\u4e86", 883634, "ul"], ["\u5440", 9580, "y"], ["\uff01", "0", "bd"], ["\u5403", 36799, "v"], ["\u4e86", 883634, "ul"], ["\u571f\u8c46", 493, "n"]], "deg": 1}, "15": {"seed": -1, "content": "\u771f\u7684\u5403\u8fc7\u4e86\uff01\uff01\u571f\u8c46\u997c\uff01", "type": 0, "words": [["\u771f\u7684", 6277, "d"], ["\u5403", 36799, "v"], ["\u8fc7", 97817, "ug"], ["\u4e86", 883634, "ul"], ["\uff01", "0", "bd"], ["\uff01", "0", "bd"], ["\u571f", 8560, "zg"], ["\u8c46\u997c", 10, "n"], ["\uff01", "0", "bd"]], "deg": 2}, "16": {"seed": -1, "content": "\u6ca1\u5403\u5462", "type": 1, "words": [["\u6ca1", 52407, "v"], ["\u5403", 36799, "v"], ["\u5462", 28623, "y"]], "deg": 0}, "17": {"seed": -1, "content": "\u8fd8\u6ca1\u6709\u5403\u5440", "type": 1, "words": [["\u8fd8", 157058, "d"], ["\u6ca1\u6709", 87597, "v"], ["\u5403", 36799, "v"], ["\u5440", 9580, "y"]], "deg": 2}, "18": {"seed": -1, "content": "\u6211\u8fd8\u6ca1\u5403\u54ce", "type": 1, "words": [["\u6211", 328841, "r"], ["\u8fd8", 157058, "d"], ["\u6ca1", 52407, "v"], ["\u5403", 36799, "v"], ["\u54ce", 1282, "e"]], "deg": 3}}} -------------------------------------------------------------------------------- /data/answer_li.json: -------------------------------------------------------------------------------- 1 | {"_default": {"1": {"content": "\u4f60\u597d", "words": [["\u4f60\u597d", 725, "l"]], "type": 2, "deg": 0, "seed": -1}, "2": {"content": "\u8fd8\u6ca1\u5403", "words": [["\u8fd8", 157058, "d"], ["\u6ca1", 52407, "v"], ["\u5403", 36799, "v"]], "seed": -1, "deg": 0, "type": 1}, "3": {"content": "\u5403\u8fc7\u4e86", "words": [["\u5403", 36799, "v"], ["\u8fc7", 97817, "ug"], ["\u4e86", 883634, "ul"]], "type": 0, "deg": 0, "seed": -1}}} -------------------------------------------------------------------------------- /data/answer_wang.json: -------------------------------------------------------------------------------- 1 | {"_default": {"1": {"seed": -1, "content": "\u4f60\u597d", "type": 2, "words": [["\u4f60\u597d", 725, "l"]], "deg": 0}, "2": {"seed": -1, "content": "\u4f60\u597d\u5440", "type": 2, "words": [["\u4f60\u597d", 725, "l"], ["\u5440", 9580, "y"]], "deg": 1}, "3": {"seed": -1, "content": "\u96f7\u543c\u96f7\u543c", "type": 2, "words": [["\u96f7", 1951, "n"], ["\u543c", 1077, "v"], ["\u96f7", 1951, "n"], ["\u543c", 1077, "v"]], "deg": 2}, "4": {"seed": -1, "content": "\u4f60\u597d\uff0c\u6211\u4e5f\u597d\uff01", "type": 2, "words": [["\u4f60\u597d", 725, "l"], ["\uff0c", "0", "bd"], ["\u6211", 328841, "r"], ["\u4e5f\u597d", 2084, "y"], ["\uff01", "0", "bd"]], "deg": 3}, "5": {"seed": -1, "content": "\u4f60\u597d\uff1f", "type": 2, "words": [["\u4f60\u597d", 725, "l"], ["\uff1f", "0", "bd"]], "deg": 3}, "6": {"seed": -1, "content": "\u4e0d\u597d\u4e86\uff01", "type": 2, "words": [["\u4e0d\u597d", 5027, "d"], ["\u4e86", 883634, "ul"], ["\uff01", "0", "bd"]], "deg": 4}, "7": {"seed": -1, "content": "\u55ef \u5929\u6c14\u4e0d\u9519", "type": 0, "words": [["\u55ef", 2213, "e"], [" ", "0", "bd"], ["\u5929\u6c14", 2657, "n"], ["\u4e0d\u9519", 5322, "a"]], "deg": 0}, "8": {"seed": -1, "content": "\u5929\u6c14\u5f88\u597d\u5462", "type": 0, "words": [["\u5929\u6c14", 2657, "n"], ["\u5f88", 69103, "zg"], ["\u597d", 92543, "a"], ["\u5462", 28623, "y"]], "deg": 1}, "9": {"seed": -1, "content": "\u662f\u4e2a\u51fa\u884c\u7684\u597d\u5929\u6c14\u5662", "type": 0, "words": [["\u662f", 796991, "v"], ["\u4e2a", 125538, "q"], ["\u51fa\u884c", 414, "v"], ["\u7684", 3188252, "uj"], ["\u597d", 92543, "a"], ["\u5929\u6c14", 2657, "n"], ["\u5662", 814, "e"]], "deg": 2}, "10": {"seed": -1, "content": "\u5929\u6c14\u4e0d\u597d\u5440", "type": 1, "words": [["\u5929\u6c14", 2657, "n"], ["\u4e0d\u597d", 5027, "d"], ["\u5440", 9580, "y"]], "deg": 0}, "11": {"seed": -1, "content": "\u4e0b\u96e8\u5929\uff0c\u4f60\u559c\u6b22\u4e0b\u96e8\u5417", "type": 1, "words": [["\u4e0b\u96e8\u5929", 27, "n"], ["\uff0c", "0", "bd"], ["\u4f60", 234587, "r"], ["\u559c\u6b22", 9783, "v"], ["\u4e0b\u96e8", 481, "v"], ["\u5417", 21245, "y"]], "deg": 1}, "12": {"seed": -1, "content": "\u6c61\u67d3\u8fd9\u4e48\u4e25\u91cd", "type": 1, "words": [["\u6c61\u67d3", 2692, "vn"], ["\u8fd9\u4e48", 18886, "r"], ["\u4e25\u91cd", 10445, "a"]], "deg": 2}, "13": {"seed": -1, "content": "\u600e\u4e48\u603b\u662f\u95ee", "type": 2, "words": [["\u600e\u4e48", 27339, "r"], ["\u603b\u662f", 6089, "c"], ["\u95ee", 34296, "n"]], "deg": 5}, "14": {"seed": -1, "content": "\u5403\u8fc7\u4e86", "type": 0, "words": [["\u5403", 36799, "v"], ["\u8fc7", 97817, "ug"], ["\u4e86", 883634, "ul"]], "deg": 0}, "15": {"seed": -1, "content": "\u5403\u8fc7\u4e86\uff0c\u5403\u4e86\u571f\u8c46", "type": 0, "words": [["\u5403", 36799, "v"], ["\u8fc7", 97817, "ug"], ["\u4e86", 883634, "ul"], ["\uff0c", "0", "bd"], ["\u5403", 36799, "v"], ["\u4e86", 883634, "ul"], ["\u571f\u8c46", 493, "n"]], "deg": 1}, "16": {"seed": -1, "content": "\u8fd8\u6ca1\u5403", "type": 1, "words": [["\u8fd8", 157058, "d"], ["\u6ca1", 52407, "v"], ["\u5403", 36799, "v"]], "deg": 0}, "17": {"seed": -1, "content": "\u6211\u8fd8\u6ca1\u5403\u5462", "type": 1, "words": [["\u6211", 328841, "r"], ["\u8fd8", 157058, "d"], ["\u6ca1", 52407, "v"], ["\u5403", 36799, "v"], ["\u5462", 28623, "y"]], "deg": 1}}} -------------------------------------------------------------------------------- /data/answer_xuman.json: -------------------------------------------------------------------------------- 1 | {"_default": {"1": {"deg": 0, "content": "\u4f60\u597d\u5440", "type": 2, "seed": -1, "words": [["\u4f60\u597d", 725, "l"], ["\u5440", 9580, "y"]]}, "2": {"deg": 0, "content": "\u55ef\u55ef", "type": 2, "seed": -1, "words": [["\u55ef", 2213, "e"], ["\u55ef", 2213, "e"]]}, "3": {"deg": 0, "content": "\u8fd8\u4e0d\u9519", "type": 2, "seed": -1, "words": [["\u8fd8", 157058, "d"], ["\u4e0d\u9519", 5322, "a"]]}, "4": {"deg": 0, "content": "\u4f60\u597d\u5417", "type": 2, "seed": -1, "words": [["\u4f60\u597d", 725, "l"], ["\u5417", 21245, "y"]]}}} -------------------------------------------------------------------------------- /data/answer_zhang.json: -------------------------------------------------------------------------------- 1 | {"_default": {"1": {"seed": -1, "words": [["\u4f60\u597d", 725, "l"]], "content": "\u4f60\u597d", "deg": 0, "type": 2}, "2": {"seed": -1, "words": [["\u4f60\u597d", 725, "l"], ["\u5440", 9580, "y"]], "content": "\u4f60\u597d\u5440", "deg": 1, "type": 2}, "3": {"seed": -1, "words": [["\u96f7", 1951, "n"], ["\u543c", 1077, "v"], ["\u96f7", 1951, "n"], ["\u543c", 1077, "v"]], "content": "\u96f7\u543c\u96f7\u543c", "deg": 0, "type": 2}, "4": {"seed": -1, "words": [["\u54c8\u54c8\u54c8", 221, "o"], ["\uff0c", "0", "bd"], ["\u5927\u5bb6", 19177, "n"], ["\u597d", 92543, "a"], ["\u624d", 55415, "d"], ["\u662f", 796991, "v"], ["\u771f\u7684", 6277, "d"], ["\u597d", 92543, "a"]], "content": "\u54c8\u54c8\u54c8\uff0c\u5927\u5bb6\u597d\u624d\u662f\u771f\u7684\u597d", "deg": 4, "type": 2}, "5": {"seed": -1, "words": [["\u4f60\u597d", 725, "l"], ["\uff0c", "0", "bd"], ["\u6211", 328841, "r"], ["\u4e5f\u597d", 2084, "y"], ["\uff01", "0", "bd"]], "content": "\u4f60\u597d\uff0c\u6211\u4e5f\u597d\uff01", "deg": 2, "type": 2}, "6": {"seed": -1, "words": [["\u5f88", 69103, "zg"], ["\u9ad8\u5174", 5387, "b"], ["\u89c1\u5230", 7522, "v"], ["\u4f60", 234587, "r"], ["\uff0c", "0", "bd"], ["\u5c0f\u4f19\u5b50", 949, "n"]], "content": "\u5f88\u9ad8\u5174\u89c1\u5230\u4f60\uff0c\u5c0f\u4f19\u5b50", "deg": 3, "type": 2}, "7": {"seed": -1, "words": [["\u5f88", 69103, "zg"], ["\u9ad8\u5174", 5387, "b"], ["\u89c1\u5230", 7522, "v"], ["\u4f60", 234587, "r"]], "content": "\u5f88\u9ad8\u5174\u89c1\u5230\u4f60", "deg": 0, "type": 2}, "8": {"seed": -1, "words": [["\u662f", 796991, "v"], ["\u7684", 3188252, "uj"], ["\u5440", 9580, "y"]], "content": "\u662f\u7684\u5440", "deg": 0, "type": 2}, "9": {"seed": -1, "words": [["\u7a7a\u6c14", 3732, "n"], ["\u4e5f", 307851, "d"], ["\u4e0d\u9519", 5322, "a"]], "content": "\u7a7a\u6c14\u4e5f\u4e0d\u9519", "deg": 0, "type": 2}, "10": {"seed": -1, "words": [["\u8fd9\u513f", 3784, "r"], ["\u7684", 3188252, "uj"], ["\u6c14\u5019", 6832, "n"], ["\u771f", 19988, "d"], ["\u597d", 92543, "a"]], "content": "\u8fd9\u513f\u7684\u6c14\u5019\u771f\u597d", "deg": 0, "type": 2}, "11": {"seed": -1, "words": [["\u5403", 36799, "v"], ["\u8fc7", 97817, "ug"], ["\u4e86", 883634, "ul"], ["\uff01", "0", "bd"]], "content": "\u5403\u8fc7\u4e86\uff01", "type": 2, "deg": 0}}} -------------------------------------------------------------------------------- /data/data_helper.py: -------------------------------------------------------------------------------- 1 | #-*- coding:utf8 -*- 2 | 3 | '处理问题、回答、问题-回答' 4 | 5 | __author__='litterzhang' 6 | 7 | import os 8 | import json 9 | 10 | import sys 11 | sys.path.append(os.path.join(os.path.dirname(__file__), os.path.pardir)) 12 | 13 | from WordSegment.segs import bmseg 14 | 15 | ANSWER = os.path.join(os.path.dirname(__file__), 'answer.json') 16 | QUESTION = os.path.join(os.path.dirname(__file__), 'question.json') 17 | ANS2OQUE = os.path.join(os.path.dirname(__file__), 'ans2que.json') 18 | 19 | def ParseAnswer(fp): 20 | answers = list() 21 | if os.path.exists(ANSWER): 22 | with open(ANSWER, 'r', encoding='utf-8') as fr: 23 | answers = json.load(fr) 24 | 25 | with open(fp, 'r', encoding='utf-8') as fr: 26 | for line in fr: 27 | line_s = line.strip().split() 28 | 29 | ans = { 30 | 'id' : line_s[0], 31 | 'type' : line_s[1], 32 | 'seed' : line_s[2], 33 | 'deg' : line_s[3], 34 | 'content' : ' '.join(line_s[4:]), 35 | 'words' : bmseg.seg(' '.join(line_s[4:])) 36 | } 37 | 38 | index = -1 39 | for i in range(0, len(answers)): 40 | if ans['content'] == answers[i]['content'] and ans['id'] == answers[i]['id']: 41 | index = i 42 | break 43 | if index != -1: 44 | answers[index] = ans 45 | else: 46 | answers.append(ans) 47 | if answers: 48 | with open(ANSWER, 'w', encoding='utf-8') as fw: 49 | fw.write(json.dumps(answers, ensure_ascii=False)) 50 | 51 | def ParseQuestion(fp): 52 | questions = list() 53 | if os.path.exists(QUESTION): 54 | with open(QUESTION, 'r', encoding='utf-8') as fr: 55 | questions = json.load(fr) 56 | 57 | with open(fp, 'r', encoding='utf-8') as fr: 58 | for line in fr: 59 | line_s = line.strip().split() 60 | que = { 61 | 'id' : line_s[0], 62 | 'type' : line_s[1], 63 | 'content' : ' '.join(line_s[2:]), 64 | 'words' : bmseg.seg(' '.join(line_s[2:])) 65 | } 66 | 67 | index = -1 68 | for i in range(0, len(questions)): 69 | if que['content'] == questions[i]['content'] and que['id'] == questions[i]['id']: 70 | index = i 71 | break 72 | if index != -1: 73 | questions[index] = que 74 | else: 75 | questions.append(que) 76 | 77 | if questions: 78 | with open(QUESTION, 'w', encoding='utf-8') as fw: 79 | fw.write(json.dumps(questions, ensure_ascii=False)) 80 | 81 | def ParseAns2Que(fp): 82 | ans2ques = list() 83 | if os.path.exists(ANS2OQUE): 84 | with open(ANS2OQUE, 'r', encoding='utf-8') as fr: 85 | ans2ques = json.load(fr) 86 | 87 | with open(fp, 'r', encoding='utf-8') as fr: 88 | for line in fr: 89 | line_s = line.strip().split() 90 | if line_s[1]=='l': 91 | ans2que = { 92 | 'que_id' : line_s[0], 93 | 'ans_ids' : [{'id' : x, 'score' : 10} for x in line_s[2:]], 94 | } 95 | elif line_s[1]=='e': 96 | ans2que = { 97 | 'que_id' : line_s[0], 98 | 'ans_ids' : [{'id' : line_s[2], 'score' : int(line_s[3])}], 99 | } 100 | else: 101 | pass 102 | 103 | index = -1 104 | for i in range(0, len(ans2ques)): 105 | if ans2que['que_id'] == ans2ques[i]['que_id']: 106 | index = i 107 | break 108 | if index != -1: 109 | for ans in ans2que['ans_ids']: 110 | in_anss = False 111 | for _ans in ans2ques[index]['ans_ids']: 112 | if _ans['id'] == ans['id']: 113 | in_anss = True 114 | break 115 | if not in_anss: 116 | ans2ques[index]['ans_ids'].append(ans) 117 | else: 118 | ans2ques.append(ans2que) 119 | if ans2ques: 120 | with open(ANS2OQUE, 'w', encoding='utf-8') as fw: 121 | fw.write(json.dumps(ans2ques, ensure_ascii=False)) 122 | 123 | if __name__=='__main__': 124 | ParseAnswer(os.path.join(os.path.dirname(__file__), 'answer')) 125 | ParseQuestion(os.path.join(os.path.dirname(__file__), 'question')) 126 | ParseAns2Que(os.path.join(os.path.dirname(__file__), 'ans2que')) 127 | 128 | -------------------------------------------------------------------------------- /data/ids_zhang: -------------------------------------------------------------------------------- 1 | 15 16 -------------------------------------------------------------------------------- /data/question: -------------------------------------------------------------------------------- 1 | 1 0 吃了吗 2 | 2 1 你好 -------------------------------------------------------------------------------- /data/question.json: -------------------------------------------------------------------------------- 1 | [{"id": "1", "words": [["吃", 36799, "v"], ["了", 883634, "ul"], ["吗", 21245, "y"]], "type": "0", "content": "吃了吗"}, {"id": "2", "words": [["你好", 725, "l"]], "type": "1", "content": "你好"}] -------------------------------------------------------------------------------- /data/question_he.json: -------------------------------------------------------------------------------- 1 | {"_default": {"1": {"words": [["\u4f60\u597d", 725, "l"]], "content": "\u4f60\u597d", "type": 2}, "2": {"words": [["\u4eca\u5929", 15960, "t"], ["\u5929\u6c14", 2657, "n"], ["\u4e0d\u9519", 5322, "a"]], "content": "\u4eca\u5929\u5929\u6c14\u4e0d\u9519", "type": 0}, "3": {"words": [["\u5403", 36799, "v"], ["\u4e86", 883634, "ul"], ["\u5417", 21245, "y"]], "content": "\u5403\u4e86\u5417", "type": 0}}} -------------------------------------------------------------------------------- /data/question_li.json: -------------------------------------------------------------------------------- 1 | {"_default": {"1": {"content": "\u4f60\u597d", "type": 2, "words": [["\u4f60\u597d", 725, "l"]]}, "2": {"content": "\u5403\u4e86\u5417", "type": 0, "words": [["\u5403", 36799, "v"], ["\u4e86", 883634, "ul"], ["\u5417", 21245, "y"]]}}} -------------------------------------------------------------------------------- /data/question_wang.json: -------------------------------------------------------------------------------- 1 | {"_default": {"1": {"words": [["\u4f60\u597d", 725, "l"]], "content": "\u4f60\u597d", "type": 2}, "2": {"words": [["\u4eca\u5929", 15960, "t"], ["\u5929\u6c14", 2657, "n"], ["\u4e0d\u9519", 5322, "a"]], "content": "\u4eca\u5929\u5929\u6c14\u4e0d\u9519", "type": 0}, "3": {"words": [["\u5403", 36799, "v"], ["\u4e86", 883634, "ul"], ["\u5417", 21245, "y"]], "content": "\u5403\u4e86\u5417", "type": 0}}} -------------------------------------------------------------------------------- /data/question_xuman.json: -------------------------------------------------------------------------------- 1 | {"_default": {"1": {"words": [["\u4f60\u597d", 725, "l"]], "content": "\u4f60\u597d", "type": 2}, "2": {"words": [["\u5f88", 69103, "zg"], ["\u9ad8\u5174", 5387, "b"], ["\u8ba4\u8bc6", 8901, "v"], ["\u4f60", 234587, "r"]], "content": "\u5f88\u9ad8\u5174\u8ba4\u8bc6\u4f60", "type": 2}, "3": {"words": [["\u4f60\u597d", 725, "l"], ["\u5417", 21245, "y"]], "content": "\u4f60\u597d\u5417", "type": 2}}} -------------------------------------------------------------------------------- /data/question_zhang.json: -------------------------------------------------------------------------------- 1 | {"_default": {"1": {"words": [["\u4f60\u597d", 725, "l"]], "type": 2, "content": "\u4f60\u597d"}, "2": {"words": [["\u5403", 36799, "v"], ["\u4e86", 883634, "ul"], ["\u5417", 21245, "y"]], "type": 2, "content": "\u5403\u4e86\u5417"}, "3": {"words": [["\u4eca\u5929", 15960, "t"], ["\u5929\u6c14", 2657, "n"], ["\u4e0d\u9519", 5322, "a"]], "type": 2, "content": "\u4eca\u5929\u5929\u6c14\u4e0d\u9519"}}} -------------------------------------------------------------------------------- /model/__pycache__/ans2que.cpython-35.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/litterzhang/chatbox/3686f41c9dff623bc51f9d660d8d406ea587f124/model/__pycache__/ans2que.cpython-35.pyc -------------------------------------------------------------------------------- /model/__pycache__/answer.cpython-35.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/litterzhang/chatbox/3686f41c9dff623bc51f9d660d8d406ea587f124/model/__pycache__/answer.cpython-35.pyc -------------------------------------------------------------------------------- /model/__pycache__/question.cpython-35.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/litterzhang/chatbox/3686f41c9dff623bc51f9d660d8d406ea587f124/model/__pycache__/question.cpython-35.pyc -------------------------------------------------------------------------------- /model/ans2que.py: -------------------------------------------------------------------------------- 1 | #-*- coding:utf8 -*- 2 | 3 | '问题-答案' 4 | 5 | __author__='litterzhang' 6 | 7 | import json 8 | 9 | # 问题与答案之间的对应关系 10 | # que_id : 问题id 11 | # ans_ids : 答案ids 12 | class Ans2Que(object): 13 | def __init__(self, _que_id, _ans_ids): 14 | self.que_id = _que_id 15 | self.ans_ids = _ans_ids 16 | 17 | def ansque2dict(ans2que): 18 | return { 19 | 'que_id' : ans2que.que_id, 20 | 'ans_ids' : ans2que.ans_ids 21 | } 22 | 23 | def dict2ansque(dic): 24 | return Ans2Que(dic['que_id'], dic['ans_ids']) 25 | 26 | def load(fp): 27 | ans2ques = list() 28 | with open(fp, 'r', encoding='utf-8') as fr: 29 | ans2ques_json = json.load(fr) 30 | for ans2que_json in ans2ques_json: 31 | ans2ques.append(Ans2Que.dict2ansque(ans2que_json)) 32 | return ans2ques 33 | 34 | def dump(ans2ques, fp): 35 | with open(fp, 'w', encoding='utf-8') as fw: 36 | ans2ques_json = json.dumps(ans2ques, ensure_ascii=False, default=Ans2Que.ansque2dict) 37 | fw.write(ans2ques_json) 38 | 39 | def get_ans_by_que(ans2ques, que_id): 40 | for ans2que in ans2ques: 41 | if ans2que.que_id == que_id: 42 | return ans2que 43 | return None 44 | 45 | def toString(self): 46 | return { 47 | 'que_id' : self.que_id, 48 | 'ans_ids' : self.ans_ids 49 | } -------------------------------------------------------------------------------- /model/answer.py: -------------------------------------------------------------------------------- 1 | #-*- coding:utf8 -*- 2 | 3 | '问题模型' 4 | 5 | __author__='litterzhang' 6 | 7 | import json 8 | 9 | # 答案定义 10 | # id : 标识答案 11 | # type : 0 , 1 , 2。 0表示正向回答,1表示负向回答,2表示中立回答。 12 | # seed : 标识回答的中心。 13 | # deg : 标识回答的情绪程度 14 | # content : 回答内容 15 | # words : 回答关键词 16 | class Answer(object): 17 | def __init__(self, _id, _type, _seed, _deg, _content, _words=[]): 18 | self.id = _id 19 | self.type = _type 20 | self.seed = _seed 21 | self.deg = _deg 22 | self.content = _content 23 | self.words = _words 24 | 25 | def answer2dict(answer): 26 | return { 27 | 'id' : answer.id, 28 | 'type' : answer.type, 29 | 'seed' : answer.seed, 30 | 'deg' : answer.deg, 31 | 'content' : answer.content, 32 | 'words' : answer.words 33 | } 34 | 35 | def toString(self): 36 | return { 37 | 'id' : self.id, 38 | 'type' : self.type, 39 | 'seed' : self.seed, 40 | 'deg' : self.deg, 41 | 'content' : self.content, 42 | 'words' : self.words 43 | } 44 | 45 | def dict2answer(dic): 46 | return Answer(dic['id'], int(dic['type']), int(dic['seed']), int(dic['deg']), dic['content'], _words=dic['words']) 47 | 48 | def load(fp): 49 | answers = list() 50 | with open(fp, 'r', encoding='utf-8') as fr: 51 | answers = json.load(fr, object_hook=Answer.dict2answer) 52 | return answers 53 | 54 | def dump(answers, fp): 55 | with open(fp, 'w', encoding='utf-8') as fw: 56 | answers_json = json.dumps(answers, ensure_ascii=False, default=Answer.answer2dict) 57 | fw.write(answers_json) 58 | 59 | def get_ans_by_id(answers, _id): 60 | for answer in answers: 61 | if answer.id == _id: 62 | return answer 63 | return None -------------------------------------------------------------------------------- /model/question.py: -------------------------------------------------------------------------------- 1 | #-*- coding:utf8 -*- 2 | 3 | '回答模型' 4 | 5 | __author__='litterzhang' 6 | 7 | import json 8 | 9 | # 问题定义 10 | # id : 标识问题 11 | # type : 0 , 1 , 2。 0表示会话确定问题,在一次会话中,答案唯一;1表示会话发散问题,在一次会话中,答案可以有多种;2表示未知问题 12 | # content : 问题内容 13 | # words : 问题分词 14 | class Question(object): 15 | def __init__(self, _id, _type, _content, _words=[]): 16 | self.id = _id 17 | self.type = _type 18 | self.content = _content 19 | self.words = _words 20 | 21 | def question2dict(question): 22 | return { 23 | 'id' : question.id, 24 | 'type' : question.type, 25 | 'content' : question.content, 26 | 'words' : question.words 27 | } 28 | 29 | def dict2questiuon(dic): 30 | return Question(dic['id'], int(dic['type']), dic['content'], _words=dic['words']) 31 | 32 | def load(fp): 33 | questions = list() 34 | with open(fp, 'r', encoding='utf-8') as fr: 35 | questions = json.load(fr, object_hook=Question.dict2questiuon) 36 | return questions 37 | 38 | def dump(questions, fp): 39 | with open(fp, 'w', encoding='utf-8') as fw: 40 | questions_json = json.dumps(questions, ensure_ascii=False, default=Question.question2dict) 41 | fw.write(questions_json) 42 | 43 | def toString(self): 44 | return { 45 | 'id' : self.id, 46 | 'type' : self.type, 47 | 'content' : self.content, 48 | 'words' : self.words 49 | } -------------------------------------------------------------------------------- /web/__pycache__/settings.cpython-35.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/litterzhang/chatbox/3686f41c9dff623bc51f9d660d8d406ea587f124/web/__pycache__/settings.cpython-35.pyc -------------------------------------------------------------------------------- /web/app.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | 'web入口' 4 | 5 | __author__='litterzhang' 6 | 7 | import tornado.ioloop 8 | import tornado.web 9 | 10 | from settings import * 11 | 12 | import os 13 | import sys 14 | sys.path.append(os.path.join(os.path.dirname(__file__), os.path.pardir)) 15 | from chatjsonctl import Chat 16 | 17 | import functools 18 | 19 | chats = dict() 20 | 21 | class BaseHandler(tornado.web.RequestHandler): 22 | @property 23 | def name(self): 24 | name_cookie = self.get_secure_cookie('name') 25 | name = None 26 | if name_cookie: 27 | name = bytes.decode(self.get_secure_cookie('name')) 28 | return name 29 | 30 | @property 31 | def chat(self): 32 | global chats 33 | 34 | chat = chats.get(self.name, None) 35 | if chat: 36 | chat = chat['chat'] 37 | return chat 38 | 39 | def check_login(func): 40 | @functools.wraps(func) 41 | def wrapper(self): 42 | if not self.name or not self.chat: 43 | self.redirect('/login') 44 | return 45 | return func(self) 46 | return wrapper 47 | 48 | def check_not_login(func): 49 | @functools.wraps(func) 50 | def wrapper(self): 51 | if self.name: 52 | self.redirect('/') 53 | return 54 | return func(self) 55 | return wrapper 56 | 57 | 58 | def tofloat(float_str, default=0): 59 | res = default 60 | try: 61 | res = float(float_str) 62 | except: 63 | pass 64 | return res 65 | 66 | def toint(int_str, default=0): 67 | res = default 68 | try: 69 | res = int(int_str) 70 | except: 71 | pass 72 | return res 73 | 74 | class MainHandler(BaseHandler): 75 | @check_login 76 | def get(self): 77 | global chats 78 | 79 | self.render('que_ask.html', chat=self.chat) 80 | 81 | class LoginHandler(BaseHandler): 82 | @check_not_login 83 | def get(self): 84 | self.render('login.html') 85 | 86 | @check_not_login 87 | def post(self): 88 | global chats 89 | 90 | if self.get_argument('name'): 91 | self.set_secure_cookie('name', self.get_argument('name')) 92 | 93 | name = self.get_argument('name') 94 | sim_new = tofloat(self.get_argument('sim_new'), default=sim_new_defalut) 95 | sim_old = tofloat(self.get_argument('sim_old'), default=sim_old_defalut) 96 | chats[name] = {'name' : name, 'chat' : Chat(name, sim_new, sim_old)} 97 | 98 | self.redirect('/') 99 | else: 100 | self.redirect('/login') 101 | 102 | class LogoutHandler(BaseHandler): 103 | @check_login 104 | def get(self): 105 | global chats 106 | 107 | del chats[self.name]['chat'] 108 | del chats[self.name] 109 | 110 | self.set_secure_cookie('name', '') 111 | 112 | self.redirect('/login') 113 | 114 | class QuestionAskHandler(BaseHandler): 115 | @check_login 116 | def post(self): 117 | if self.get_argument('que_content'): 118 | que, sim, anss = Chat.match_question(self.get_argument('que_content')) 119 | if not que or sim < self.chat.sim_new: 120 | self.render('que_add.html', chat=self.chat, que_content=self.get_argument('que_content')) 121 | else: 122 | self.chat.coms_add_que(self.get_argument('que_content'), que, sim) 123 | ans, score = self.chat.chat_ctl_answer(que, sim, anss) 124 | self.chat.coms_add_ans(ans, score) 125 | 126 | if ans['id'] > 0: 127 | self.render('ans_score.html', chat=self.chat, que_id=que['id'], ans=ans, score=score) 128 | else: 129 | self.render('ans_add.html', chat=self.chat, que_id=que['id']) 130 | else: 131 | self.redirect('/') 132 | 133 | class QuestionAddHandler(BaseHandler): 134 | @check_login 135 | def post(self): 136 | if self.get_argument('que_content'): 137 | que_type = toint(self.get_argument('que_type'), default=2) 138 | 139 | que, sim, anss = Chat.match_question(self.get_argument('que_content')) 140 | que, sim, anss = self.chat.chat_ctl_question(self.get_argument('que_content'), que, sim, anss, que_type) 141 | self.chat.coms_add_que(self.get_argument('que_content'), que, sim) 142 | 143 | ans, score = self.chat.chat_ctl_answer(que, sim, anss) 144 | self.chat.coms_add_ans(ans, score) 145 | 146 | if ans['id'] > 0: 147 | self.render('ans_score.html', chat=self.chat, que_id=que['id'], ans=ans, score=score) 148 | else: 149 | self.render('ans_add.html', chat=self.chat, que_id=que['id']) 150 | else: 151 | self.redirect('/') 152 | 153 | class AnswerAddHandler(BaseHandler): 154 | @check_login 155 | def post(self): 156 | if self.get_argument('que_id') and self.get_argument('ans_content'): 157 | que_id = toint(self.get_argument('que_id')) 158 | ans_content = self.get_argument('ans_content') 159 | ans_type = toint(self.get_argument('ans_type'), default=2) 160 | # ans_seed = toint(self.get_argument('ans_seed'), default=-1) 161 | ans_seed = -1 162 | ans_deg = toint(self.get_argument('ans_deg'), default=0) 163 | ans_score = toint(self.get_argument('ans_score'), default=10) 164 | 165 | Chat.add_answer(que_id, ans_content, ans_type, ans_seed, ans_deg, ans_score) 166 | 167 | self.render('ans_add.html', chat=self.chat, que_id=que_id) 168 | else: 169 | self.redirect('/') 170 | 171 | class AnswerScoreHandler(BaseHandler): 172 | @check_login 173 | def post(self): 174 | if self.get_argument('que_id') and self.get_argument('ans_id'): 175 | que_id = toint(self.get_argument('que_id')) 176 | ans_id = toint(self.get_argument('ans_id')) 177 | ans_score = toint(self.get_argument('ans_score'), default=10) 178 | 179 | Chat.change_score(que_id, ans_id, ans_score) 180 | 181 | self.render('ans_add.html', chat=self.chat, que_id=que_id) 182 | 183 | if __name__=='__main__': 184 | application = tornado.web.Application([ 185 | (r'/', MainHandler), 186 | (r'/login', LoginHandler), 187 | (r'/logout', LogoutHandler), 188 | (r'/que_ask', QuestionAskHandler), 189 | (r'/que_add', QuestionAddHandler), 190 | (r'/ans_add', AnswerAddHandler), 191 | (r'/ans_score', AnswerScoreHandler) 192 | ], **app_settings) 193 | 194 | application.listen(3000) 195 | tornado.ioloop.IOLoop.current().start() -------------------------------------------------------------------------------- /web/settings.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | 'web 配置' 4 | 5 | __author__='litterzhang' 6 | 7 | import os 8 | 9 | app_settings = { 10 | 'cookie_secret' : 'litterzhang', 11 | 'login_url' : '/login', 12 | 'xsrf_cookies' : False, 13 | 'template_path' : os.path.join(os.path.dirname(__file__), 'templates'), 14 | 'static_path' : os.path.join(os.path.dirname(__file__), 'static') 15 | } 16 | 17 | sim_new_defalut = 0.7 18 | sim_old_defalut = 0.2 -------------------------------------------------------------------------------- /web/static/chat.css: -------------------------------------------------------------------------------- 1 | body { 2 | background-color: #fff; 3 | } 4 | 5 | .container { 6 | width: 800px; 7 | margin-right: auto; 8 | margin-left: auto; 9 | padding-top: 20px; 10 | } 11 | 12 | .dashboards { 13 | float: left; 14 | padding-right: 10px; 15 | padding-left: 10px; 16 | width: 33.333333%; 17 | } 18 | 19 | .chatbox { 20 | float: left; 21 | padding-right: 10px; 22 | padding-left: 10px; 23 | width: 66.666667%; 24 | } 25 | 26 | .board { 27 | position: relative; 28 | margin-bottom: 30px; 29 | border-radius: 3px; 30 | margin-bottom: 20px; 31 | text-align: center; 32 | } 33 | 34 | .board>h3 { 35 | display: block; 36 | padding: 9px 10px 10px; 37 | margin: 0; 38 | font-size: 14px; 39 | line-height: 17px; 40 | background-color: #f5f5f5; 41 | border: 1px solid #d8d8d8; 42 | border-bottom: 0; 43 | border-radius: 3px 3px 0 0; 44 | } 45 | 46 | .board-inner { 47 | padding: 10px; 48 | color: #666; 49 | background: #fff; 50 | border: 1px solid #d8d8d8; 51 | border-bottom-right-radius: 3px; 52 | border-bottom-left-radius: 3px; 53 | padding: 0; 54 | border-top: 0; 55 | } 56 | 57 | .board-inner ul { 58 | list-style: none; 59 | padding-left: 0; 60 | margin-top: 0; 61 | margin-bottom: 0; 62 | } 63 | 64 | .board-inner ul>li { 65 | position: relative; 66 | display: block; 67 | padding: 6px 30px 6px 30px; 68 | font-size: 14px; 69 | border-top: 1px solid #e5e5e5; 70 | } 71 | 72 | .board-inner ul>li.logout { 73 | background-color: #6cc644; 74 | background-image: -webkit-linear-gradient(#91dd70, #55ae2e); 75 | background-image: linear-gradient(#91dd70, #55ae2e); 76 | text-shadow: 0 -1px 0 rgba(0,0,0,0.15); 77 | border-bottom-left-radius: 3px; 78 | border-bottom-right-radius: 3px; 79 | -webkit-appearance: none; 80 | -moz-appearance: none; 81 | appearance: none; 82 | } 83 | 84 | .board-inner ul>li.logout>a { 85 | color: #fff; 86 | position: relative; 87 | display: inline-block; 88 | font-size: 14px; 89 | font-weight: 600; 90 | line-height: 20px; 91 | white-space: nowrap; 92 | vertical-align: middle; 93 | cursor: pointer; 94 | -webkit-user-select: none; 95 | -moz-user-select: none; 96 | -ms-user-select: none; 97 | user-select: none; 98 | } 99 | 100 | .board-inner ul>li.logout>input { 101 | color: #fff; 102 | position: relative; 103 | display: inline-block; 104 | font-size: 14px; 105 | font-weight: 600; 106 | line-height: 20px; 107 | white-space: nowrap; 108 | vertical-align: middle; 109 | cursor: pointer; 110 | -webkit-user-select: none; 111 | -moz-user-select: none; 112 | -ms-user-select: none; 113 | user-select: none; 114 | border: 0; 115 | background: none; 116 | } 117 | 118 | .chatbox-msgbox { 119 | display: block; 120 | padding: 20px; 121 | margin: 0; 122 | font-size: 14px; 123 | line-height: 17px; 124 | background-color: #eee; 125 | border: 1px solid #d8d8d8; 126 | border-bottom: 0; 127 | border-radius: 3px 3px 0 0; 128 | height: 360px; 129 | overflow: overlay; 130 | } 131 | 132 | .que_input { 133 | width: 80%; 134 | border-right: 0; 135 | border-radius: 0 0 0 3px; 136 | float: left; 137 | } 138 | 139 | .que_submit { 140 | width: 20%; 141 | float: right; 142 | border-radius: 0 0 3px 0; 143 | } 144 | 145 | .chatbox-tips { 146 | display: block; 147 | padding: 5px 20px; 148 | margin: 0; 149 | font-size: 14px; 150 | background-color: #eee; 151 | border: 1px solid #d8d8d8; 152 | border-bottom: 0; 153 | line-height: 20px; 154 | overflow: overlay; 155 | color: #f50000; 156 | text-align: center; 157 | } 158 | 159 | .chatbox-msgbox>ul { 160 | list-style: none; 161 | padding-left: 0; 162 | margin-top: 0; 163 | margin-bottom: 0; 164 | } 165 | 166 | .chatbox-msgbox>ul>li.chat_left>span { 167 | padding: 5px 10px; 168 | background-color: #fff; 169 | border: 1px solid #d8d8d8; 170 | border-radius: 3px; 171 | line-height: 30px; 172 | } 173 | 174 | .chatbox-msgbox>ul>li.chat_right { 175 | text-align: right; 176 | } 177 | 178 | .chatbox-msgbox>ul>li.chat_right>span { 179 | padding: 5px 10px; 180 | background-color: #5fa9d6; 181 | border: 1px solid #439bcf; 182 | border-radius: 3px; 183 | line-height: 30px; 184 | color: #fff; 185 | } -------------------------------------------------------------------------------- /web/static/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/litterzhang/chatbox/3686f41c9dff623bc51f9d660d8d406ea587f124/web/static/favicon.ico -------------------------------------------------------------------------------- /web/static/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | background-color: #f9f9f9; 3 | font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; 4 | font-size: 14px; 5 | line-height: 1.5; 6 | color: #333; 7 | margin: 0; 8 | word-wrap: break-word; 9 | } 10 | 11 | * { 12 | box-sizing: border-box; 13 | } 14 | 15 | form { 16 | display: block; 17 | margin-top: 0; 18 | } 19 | 20 | div { 21 | display: block; 22 | } 23 | 24 | h1 { 25 | display: block; 26 | font-size: 2em; 27 | -webkit-margin-before: 0.67em; 28 | -webkit-margin-after: 0.67em; 29 | -webkit-margin-start: 0px; 30 | -webkit-margin-end: 0px; 31 | font-weight: bold; 32 | margin-top: 0; 33 | margin-bottom: 0; 34 | margin: 0.67em 0; 35 | } 36 | 37 | h3 { 38 | display: block; 39 | -webkit-margin-before: 1em; 40 | -webkit-margin-after: 1em; 41 | -webkit-margin-start: 0px; 42 | -webkit-margin-end: 0px; 43 | font-size: 20px; 44 | font-weight: 600; 45 | } 46 | 47 | label { 48 | cursor: default; 49 | font-weight: 600; 50 | } 51 | 52 | input, textarea { 53 | -webkit-font-feature-settings: "liga" 0; 54 | font-feature-settings: "liga" 0; 55 | } 56 | 57 | input, select, textarea, button { 58 | font-family: inherit; 59 | font-size: inherit; 60 | line-height: inherit; 61 | } 62 | 63 | button, input { 64 | overflow: visible; 65 | } 66 | 67 | button, input, select, textarea { 68 | font: inherit; 69 | margin: 0; 70 | } 71 | 72 | ul, menu, dir { 73 | display: block; 74 | list-style-type: disc; 75 | -webkit-margin-before: 1em; 76 | -webkit-margin-after: 1em; 77 | -webkit-margin-start: 0px; 78 | -webkit-margin-end: 0px; 79 | -webkit-padding-start: 40px; 80 | } 81 | 82 | li { 83 | display: list-item; 84 | text-align: -webkit-match-parent; 85 | } 86 | 87 | a { 88 | color: #4078c0; 89 | text-decoration: none; 90 | } 91 | 92 | .header { 93 | padding-top: 10px; 94 | padding-bottom: 10px; 95 | background-color: #f5f5f5; 96 | border-bottom: 1px solid #e5e5e5; 97 | background-color: transparent; 98 | border-bottom: 0; 99 | } 100 | 101 | .input-block { 102 | display: block; 103 | width: 100%; 104 | } 105 | 106 | .form-control, .form-select { 107 | min-height: 34px; 108 | padding: 6px 8px; 109 | font-size: 14px; 110 | line-height: 20px; 111 | color: #333; 112 | vertical-align: middle; 113 | background-color: #fff; 114 | background-repeat: no-repeat; 115 | background-position: right 8px center; 116 | border: 1px solid #ddd; 117 | border-radius: 3px; 118 | outline: none; 119 | box-shadow: inset 0 1px 2px rgba(0,0,0,0.075); 120 | } 121 | 122 | .btn { 123 | position: relative; 124 | display: inline-block; 125 | padding: 6px 12px; 126 | font-size: 14px; 127 | font-weight: 600; 128 | line-height: 20px; 129 | color: #333; 130 | white-space: nowrap; 131 | vertical-align: middle; 132 | cursor: pointer; 133 | -webkit-user-select: none; 134 | -moz-user-select: none; 135 | -ms-user-select: none; 136 | user-select: none; 137 | background-color: #eee; 138 | background-image: -webkit-linear-gradient(#fcfcfc, #eee); 139 | background-image: linear-gradient(#fcfcfc, #eee); 140 | border: 1px solid #d5d5d5; 141 | border-radius: 3px; 142 | -webkit-appearance: none; 143 | -moz-appearance: none; 144 | appearance: none; 145 | } 146 | 147 | .btn-primary { 148 | color: #fff; 149 | text-shadow: 0 -1px 0 rgba(0,0,0,0.15); 150 | background-color: #6cc644; 151 | background-image: -webkit-linear-gradient(#91dd70, #55ae2e); 152 | background-image: linear-gradient(#91dd70, #55ae2e); 153 | border: 1px solid #5aad35; 154 | } 155 | 156 | .btn-block { 157 | display: block; 158 | width: 100%; 159 | text-align: center; 160 | } -------------------------------------------------------------------------------- /web/static/login.css: -------------------------------------------------------------------------------- 1 | .auth-form { 2 | width: 340px; 3 | margin: 0 auto; 4 | padding-right: 16px !important; 5 | padding-left: 16px !important; 6 | } 7 | 8 | .auth-form-header { 9 | margin-bottom: 15px; 10 | color: #333; 11 | text-align: center; 12 | text-shadow: none; 13 | background-color: transparent; 14 | border: 0; 15 | } 16 | 17 | .auth-form-header h1 { 18 | font-size: 24px; 19 | font-weight: 300; 20 | letter-spacing: -0.5px; 21 | } 22 | 23 | .auth-form-body { 24 | padding: 20px; 25 | font-size: 14px; 26 | background-color: #fff; 27 | border: 1px solid #d8dee2; 28 | border-top: 1px solid #d8dee2; 29 | border-radius: 5px; 30 | margin-top: 16px !important; 31 | } 32 | 33 | .auth-form label { 34 | display: block; 35 | margin-bottom: 7px; 36 | font-weight: normal; 37 | } 38 | 39 | .auth-form-body .input-block { 40 | margin-top: 5px; 41 | margin-bottom: 15px; 42 | } 43 | 44 | .auth-form .btn { 45 | margin-top: 20px; 46 | } -------------------------------------------------------------------------------- /web/static/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/litterzhang/chatbox/3686f41c9dff623bc51f9d660d8d406ea587f124/web/static/logo.png -------------------------------------------------------------------------------- /web/templates/ans_add.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {{ _("ChatBox") }} 6 | 7 | 8 | 9 | 10 | 11 |
12 |
13 |
14 |
15 |
16 |
17 |
    18 | {% for com in chat.coms %} 19 |
  • {{ escape(com['que_str']) }}
  • 20 |
  • {{ escape(com['ans']['content']) }}
  • 21 | {% end %} 22 |
23 |
24 | 25 |
26 |
27 | 28 | 29 | 30 |
31 |
32 |
33 | 34 |
35 |
36 |

Chatter Message

37 |
38 |
    39 |
  • Name : {{ chat.name }}
  • 40 |
  • Sim New : {{ chat.sim_new }}
  • 41 |
  • Sim Old : {{ chat.sim_old }}
  • 42 |
  • {{ _('结束训练') }}
  • 43 |
44 |
45 |
46 | 47 |
48 |

Add Answer

49 |
50 |
51 | 52 |
    53 |
  • 54 |
  • 55 |
  • 56 |
  • 57 |
  • 58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 | 66 | -------------------------------------------------------------------------------- /web/templates/ans_score.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {{ _("ChatBox") }} 6 | 7 | 8 | 9 | 10 | 11 |
12 |
13 |
14 |
15 |
16 |
17 |
    18 | {% for com in chat.coms %} 19 |
  • {{ escape(com['que_str']) }}
  • 20 |
  • {{ escape(com['ans']['content']) }}
  • 21 | {% end %} 22 |
23 |
24 |

Please Score This Answer !

25 |
26 |
27 | 28 | 29 | 30 | 31 | 32 |
33 |
34 |
35 | 36 |
37 |
38 |

Chatter Message

39 |
40 |
    41 |
  • Name : {{ chat.name }}
  • 42 |
  • Sim New : {{ chat.sim_new }}
  • 43 |
  • Sim Old : {{ chat.sim_old }}
  • 44 |
  • {{ _('结束训练') }}
  • 45 |
46 |
47 |
48 | 49 |
50 |

Answer Message

51 |
52 |
    53 |
  • {{ _("Answer Type : ") }} {{ ans['type'] }}
  • 54 |
  • {{ _("Answer Seed : ") }} {{ ans['seed'] }}
  • 55 |
  • {{ _("Answer Degree : ") }} {{ ans['deg'] }}
  • 56 |
  • {{ _("Answer Socre : ") }} {{ score }}
  • 57 |
58 |
59 |
60 |
61 |
62 |
63 | 64 | -------------------------------------------------------------------------------- /web/templates/login.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {{ _("ChatBox") }} 6 | 7 | 8 | 9 | 10 | 11 |
12 |
13 |
14 |
15 | 16 |
17 |
18 |

Sign in to ChatBox

19 |
20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 |
34 | 35 |
36 |
37 |
38 | 39 | -------------------------------------------------------------------------------- /web/templates/que_add.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {{ _("ChatBox") }} 6 | 7 | 8 | 9 | 10 | 11 |
12 |
13 |
14 |
15 |
16 |
17 |
    18 | {% for com in chat.coms %} 19 |
  • {{ escape(com['que_str']) }}
  • 20 |
  • {{ escape(com['ans']['content']) }}
  • 21 | {% end %} 22 |
23 |
24 |

This is a New Question! Please Set Question Type !

25 |
26 |
27 | 28 | 29 | 30 | 31 | 32 |
33 |
34 |
35 | 36 |
37 |
38 |

Chatter Message

39 |
40 |
    41 |
  • Name : {{ chat.name }}
  • 42 |
  • Sim New : {{ chat.sim_new }}
  • 43 |
  • Sim Old : {{ chat.sim_old }}
  • 44 |
  • {{ _('结束训练') }}
  • 45 |
46 |
47 |
48 |
49 |
50 |
51 | 52 | -------------------------------------------------------------------------------- /web/templates/que_ask.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {{ _("ChatBox") }} 6 | 7 | 8 | 9 | 10 | 11 |
12 |
13 |
14 |
15 |
16 |
17 |
    18 | {% for com in chat.coms %} 19 |
  • {{ escape(com['que_str']) }}
  • 20 |
  • {{ escape(com['ans']['content']) }}
  • 21 | {% end %} 22 |
23 |
24 | 25 |
26 |
27 | 28 | 29 | 30 |
31 |
32 |
33 | 34 |
35 |
36 |

Chatter Message

37 |
38 |
    39 |
  • Name : {{ chat.name }}
  • 40 |
  • Sim New : {{ chat.sim_new }}
  • 41 |
  • Sim Old : {{ chat.sim_old }}
  • 42 |
  • {{ _('结束训练') }}
  • 43 |
44 |
45 |
46 |
47 |
48 |
49 | 50 | --------------------------------------------------------------------------------