class AIMLCharacter(Character): def __init__(self, id, name, level=99): super(AIMLCharacter, self).__init__(id, name, level) self.kernel = Kernel() self.aiml_files = [] self.kernel.verbose(True) self.current_topic = '' self.counter = 0 self.N = 10 # How many times of reponse on the same topic self.languages = ['en'] self.max_chat_tries = 5 self.trace_pattern = re.compile( r'.*/(?P<fname>.*), (?P<tloc>\(.*\)), (?P<pname>.*), (?P<ploc>\(.*\))' ) self.response_limit = 512 self.type = TYPE_AIML def load_aiml_files(self, kernel, aiml_files): errors = [] for f in aiml_files: if '*' not in f and not os.path.isfile(f): self.logger.warn("{} is not found".format(f)) errors.extend(kernel.learn(f)) self.logger.info("Load {}".format(f)) if f not in self.aiml_files: self.aiml_files.append(f) return errors def set_property_file(self, propname): try: with open(propname) as f: for line in f: parts = line.split('=') key = parts[0].strip() value = parts[1].strip() self.kernel.setBotPredicate(key, value) self.properties[key] = value self.logger.info("Set properties file {}".format(propname)) except Exception: self.logger.error("Couldn't open {}".format(propname)) def set_properties(self, props): super(AIMLCharacter, self).set_properties(props) for key, value in self.properties.iteritems(): self.kernel.setBotPredicate(key, value) def check_reset_topic(self, session): """If it's on the same topic for N round, then reset the topic""" topic = self.kernel.getPredicate('topic', session).strip() if not topic: self.reset_topic(session) return if topic == self.current_topic: self.counter += 1 self.logger.info('Topic is continued {} {}'.format( topic, self.counter)) else: self.counter = 0 self.logger.info('Topic is changed from "{}" to "{}", ' 'reset counter'.format(self.current_topic, topic)) self.current_topic = topic if self.counter >= self.N: self.counter = 0 self.reset_topic(session) def reset_topic(self, session): self.current_topic = '' self.kernel.setPredicate('topic', '', session) self.logger.info("Topic is reset") def respond(self, question, lang, session, query, request_id=None): ret = {} ret['text'] = '' ret['botid'] = self.id ret['botname'] = self.name ret['repeat'] = '' sid = session.sid answer, res = '', '' if lang not in self.languages: return ret elif re.search(r'\[.*\]', question): return ret chat_tries = 0 answer = self.kernel.respond(question, sid, query) answer, res = shorten(answer, self.response_limit) if self.non_repeat: while chat_tries < self.max_chat_tries: if answer and session.check(question, answer): break answer = self.kernel.respond(question, sid, query) answer, res = shorten(answer, self.response_limit) chat_tries += 1 if answer: if not session.check(question, answer): ret['repeat'] = answer answer = '' self.logger.warn("Repeat answer") if res: self.kernel.setPredicate('continue', res, sid) self.logger.info("Set predicate continue={}".format(res)) ret['text'] = answer ret['emotion'] = self.kernel.getPredicate('emotion', sid) ret['performance'] = self.kernel.getPredicate('performance', sid) traces = self.kernel.getTraceDocs() if traces: self.logger.debug("Trace: {}".format(traces)) patterns = [] for trace in traces: match_obj = self.trace_pattern.match(trace) if match_obj: patterns.append(match_obj.group('pname')) ret['pattern'] = patterns if patterns: first = patterns[0] if '*' in first or '_' in first: pattern_len = len(first.strip().split()) if '*' not in first: ret['ok_match'] = True if pattern_len > 3 and pattern_len > 0.9 * len( question.strip().split()): ret['ok_match'] = True else: ret['exact_match'] = True traces = replace_aiml_abs_path(traces) ret['trace'] = '\n'.join(traces) return ret def refresh(self, session): sid = session.sid self.kernel._deleteSession(sid) self.logger.info("Character is refreshed") def get_context(self, session): sid = session.sid return self.kernel.getSessionData(sid) def set_context(self, session, context): assert isinstance(context, dict) sid = session.sid for k, v in context.iteritems(): if k.startswith('_'): continue self.kernel.setPredicate(k, v, sid) self.logger.info("Set predicate {}={}".format(k, v)) if k in ['firstname', 'fullname']: self.kernel.setPredicate('name', v, sid) def remove_context(self, session, key): sid = session.sid if key in self.get_context(session).keys(): del self.kernel._sessions[sid][key] self.logger.info("Removed context {}".format(key)) return True else: self.logger.debug("No such context {}".format(key)) return False def get_templates(self): templates = [] root = self.kernel._brain._root self.kernel._brain.get_templates(root, templates) return templates def print_duplicated_patterns(self): patterns = defaultdict(list) for t in self.get_templates(): key = (t[1]['pattern'].lower(), t[1]['that'].lower(), t[1]['topic'].lower()) patterns[key].append(t[1]) for pattern in patterns: if len(patterns[pattern]) > 1: self.logger.error("Duplicated patterns {}\n{}\n".format( len(patterns[pattern]), pformat(patterns[pattern]))) def said(self, session, text): sid = session.sid outputHistory = self.kernel.getPredicate(self.kernel._outputHistory, sid) if isinstance(outputHistory, list): outputHistory.append(text) self.logger.info("Add '{}' to output history".format(text))
class AIMLCharacter(Character): def __init__(self, id, name, level=99): super(AIMLCharacter, self).__init__(id, name, level) self.kernel = Kernel() self.aiml_files = [] self.kernel.verbose(True) self.current_topic = '' self.counter = 0 self.N = 10 # How many times of reponse on the same topic self.languages = ['en'] def load_aiml_files(self, kernel, aiml_files): for f in aiml_files: if '*' not in f and not os.path.isfile(f): logger.warn("[{}] {} is not found".format(self.id, f)) errors = kernel.learn(f) if errors: raise Exception("Load {} error\n{}".format( os.path.basename(f), errors[0][1])) logger.info("[{}] Load {}".format(self.id, f)) if f not in self.aiml_files: self.aiml_files.append(f) def set_property_file(self, propname): try: with open(propname) as f: for line in f: parts = line.split('=') key = parts[0].strip() value = parts[1].strip() self.kernel.setBotPredicate(key, value) self.properties[key] = value logger.info("[{}] Set properties file {}".format(self.id, propname)) except Exception: logger.error("Couldn't open {}".format(propname)) def set_properties(self, props): super(AIMLCharacter, self).set_properties(props) for key, value in self.properties.iteritems(): self.kernel.setBotPredicate(key, value) def check_reset_topic(self, session): """If it's on the same topic for N round, then reset the topic""" topic = self.kernel.getPredicate('topic', session).strip() if not topic: self.reset_topic(session) return if topic == self.current_topic: self.counter += 1 logger.info('[{}] Topic is continued {} {}'.format( self.id, topic, self.counter)) else: self.counter = 0 logger.info('[{}] Topic is changed from "{}" to "{}", '\ 'reset counter'.format(self.id, self.current_topic, topic)) self.current_topic = topic if self.counter >= self.N: self.counter = 0 self.reset_topic(session) def reset_topic(self, session): self.current_topic = '' self.kernel.setPredicate('topic', '', session) logger.info("[{}] Topic is reset".format(self.id)) def respond(self, question, lang, session): ret = {} if lang not in self.languages: ret['text'] = '' else: ret['text'] = self.kernel.respond(question, session) ret['emotion'] = self.kernel.getPredicate('emotion', session) ret['botid'] = self.id ret['botname'] = self.name trace = self.kernel.getTraceDocs() if trace: logger.info("Trace: {}".format(trace)) ret['trace'] = trace return ret def refresh(self, sid): self.kernel._deleteSession(sid) logger.info("Character {} is refreshed".format(self.id)) def get_context(self, sid): return self.kernel.getSessionData(sid) def set_context(self, sid, context): assert isinstance(context, dict) for k, v in context.iteritems(): if k.startswith('_'): continue self.kernel.setPredicate(k, v, sid) logger.info("[{}] Set predicate {}={}".format(self.id, k, v))
class AIMLCharacter(Character): def __init__(self, id, name, level=99): super(AIMLCharacter, self).__init__(id, name, level) self.kernel = Kernel() self.aiml_files = [] self.kernel.verbose(True) self.current_topic = '' self.counter = 0 self.N = 10 # How many times of reponse on the same topic self.languages = ['en'] self.max_chat_tries = 5 self.trace_pattern = re.compile( r'.*/(?P<fname>.*), (?P<tloc>\(.*\)), (?P<pname>.*), (?P<ploc>\(.*\))') self.response_limit = 512 self.type = TYPE_AIML def load_aiml_files(self, kernel, aiml_files): errors = [] for f in aiml_files: if '*' not in f and not os.path.isfile(f): self.logger.warn("{} is not found".format(f)) errors.extend(kernel.learn(f)) self.logger.info("Load {}".format(f)) if f not in self.aiml_files: self.aiml_files.append(f) return errors def set_property_file(self, propname): try: with open(propname) as f: for line in f: parts = line.split('=') key = parts[0].strip() value = parts[1].strip() self.kernel.setBotPredicate(key, value) self.properties[key] = value self.logger.info("Set properties file {}".format(propname)) except Exception: self.logger.error("Couldn't open {}".format(propname)) def set_properties(self, props): super(AIMLCharacter, self).set_properties(props) for key, value in self.properties.iteritems(): self.kernel.setBotPredicate(key, value) def check_reset_topic(self, session): """If it's on the same topic for N round, then reset the topic""" topic = self.kernel.getPredicate('topic', session).strip() if not topic: self.reset_topic(session) return if topic == self.current_topic: self.counter += 1 self.logger.info('Topic is continued {} {}'.format( topic, self.counter)) else: self.counter = 0 self.logger.info('Topic is changed from "{}" to "{}", ' 'reset counter'.format(self.current_topic, topic)) self.current_topic = topic if self.counter >= self.N: self.counter = 0 self.reset_topic(session) def reset_topic(self, session): self.current_topic = '' self.kernel.setPredicate('topic', '', session) self.logger.info("Topic is reset") def respond(self, question, lang, session, query): ret = {} ret['text'] = '' ret['botid'] = self.id ret['botname'] = self.name ret['repeat'] = '' sid = session.sid answer, res = '', '' if lang not in self.languages: return ret elif re.search(r'\[.*\]', question): return ret chat_tries = 0 answer = self.kernel.respond(question, sid, query) answer, res = shorten(answer, self.response_limit) if self.non_repeat: while chat_tries < self.max_chat_tries: if answer and session.check(question, answer): break answer = self.kernel.respond(question, sid, query) answer, res = shorten(answer, self.response_limit) chat_tries += 1 if answer: if not session.check(question, answer): ret['repeat'] = answer answer = '' self.logger.warn("Repeat answer") if res: self.kernel.setPredicate('continue', res, sid) self.logger.info("Set predicate continue={}".format(res)) ret['text'] = answer ret['emotion'] = self.kernel.getPredicate('emotion', sid) ret['performance'] = self.kernel.getPredicate('performance', sid) traces = self.kernel.getTraceDocs() if traces: self.logger.debug("Trace: {}".format(traces)) patterns = [] for trace in traces: match_obj = self.trace_pattern.match(trace) if match_obj: patterns.append(match_obj.group('pname')) ret['pattern'] = patterns if patterns: first = patterns[0] if '*' in first or '_' in first: pattern_len = len(first.strip().split()) if '*' not in first: ret['ok_match'] = True if pattern_len>3 and pattern_len>0.9*len(question.strip().split()): ret['ok_match'] = True else: ret['exact_match'] = True traces = replace_aiml_abs_path(traces) ret['trace'] = '\n'.join(traces) return ret def refresh(self, session): sid = session.sid self.kernel._deleteSession(sid) self.logger.info("Character is refreshed") def get_context(self, session): sid = session.sid return self.kernel.getSessionData(sid) def set_context(self, session, context): assert isinstance(context, dict) sid = session.sid for k, v in context.iteritems(): if k.startswith('_'): continue self.kernel.setPredicate(k, v, sid) self.logger.info("Set predicate {}={}".format(k, v)) if k in ['firstname', 'fullname']: self.kernel.setPredicate('name', v, sid) def remove_context(self, session, key): sid = session.sid if key in self.get_context(session).keys(): del self.kernel._sessions[sid][key] self.logger.info("Removed context {}".format(key)) return True else: self.logger.debug("No such context {}".format(key)) return False def get_templates(self): templates = [] root = self.kernel._brain._root self.kernel._brain.get_templates(root, templates) return templates def print_duplicated_patterns(self): patterns = defaultdict(list) for t in self.get_templates(): key = (t[1]['pattern'].lower(), t[1]['that'].lower(), t[1]['topic'].lower()) patterns[key].append(t[1]) for pattern in patterns: if len(patterns[pattern]) > 1: self.logger.error("Duplicated patterns {}\n{}\n".format( len(patterns[pattern]), pformat(patterns[pattern]))) def said(self, session, text): sid = session.sid outputHistory = self.kernel.getPredicate(self.kernel._outputHistory, sid) if isinstance(outputHistory, list): outputHistory.append(text) self.logger.info("Add '{}' to output history".format(text))
class AIMLCharacter(Character): def __init__(self, id, name, level=99): super(AIMLCharacter, self).__init__(id, name, level) self.kernel = Kernel() self.aiml_files = [] self.kernel.verbose(True) self.current_topic = '' self.counter = 0 self.N = 10 # How many times of reponse on the same topic self.languages = ['en'] def load_aiml_files(self, kernel, aiml_files): errors = [] for f in aiml_files: if '*' not in f and not os.path.isfile(f): logger.warn("[{}] {} is not found".format(self.id, f)) errors.extend(kernel.learn(f)) logger.info("[{}] Load {}".format(self.id, f)) if f not in self.aiml_files: self.aiml_files.append(f) return errors def set_property_file(self, propname): try: with open(propname) as f: for line in f: parts = line.split('=') key = parts[0].strip() value = parts[1].strip() self.kernel.setBotPredicate(key, value) self.properties[key] = value logger.info("[{}] Set properties file {}".format(self.id, propname)) except Exception: logger.error("Couldn't open {}".format(propname)) def set_properties(self, props): super(AIMLCharacter, self).set_properties(props) for key, value in self.properties.iteritems(): self.kernel.setBotPredicate(key, value) def check_reset_topic(self, session): """If it's on the same topic for N round, then reset the topic""" topic = self.kernel.getPredicate('topic', session).strip() if not topic: self.reset_topic(session) return if topic == self.current_topic: self.counter += 1 logger.info('[{}] Topic is continued {} {}'.format( self.id, topic, self.counter)) else: self.counter = 0 logger.info('[{}] Topic is changed from "{}" to "{}", '\ 'reset counter'.format(self.id, self.current_topic, topic)) self.current_topic = topic if self.counter >= self.N: self.counter = 0 self.reset_topic(session) def reset_topic(self, session): self.current_topic = '' self.kernel.setPredicate('topic', '', session) logger.info("[{}] Topic is reset".format(self.id)) def respond(self, question, lang, session): ret = {} if lang not in self.languages: ret['text'] = '' else: ret['text'] = self.kernel.respond(question, session) ret['emotion'] = self.kernel.getPredicate('emotion', session) ret['botid'] = self.id ret['botname'] = self.name trace = self.kernel.getTraceDocs() if trace: logger.info("Trace: {}".format(trace)) ret['trace'] = trace return ret def refresh(self, sid): self.kernel._deleteSession(sid) logger.info("Character {} is refreshed".format(self.id)) def get_context(self, sid): return self.kernel.getSessionData(sid) def set_context(self, sid, context): assert isinstance(context, dict) for k, v in context.iteritems(): if k.startswith('_'): continue self.kernel.setPredicate(k, v, sid) logger.info("[{}] Set predicate {}={}".format(self.id, k, v))