def handle_matches(self, match): """ Returns a response statement from a matched input statement. :param match: It is a valid matched pattern from the input statement :type: `_sre.SRE_Match` """ response = Statement(text='') from_parsed = match.group("from") target_parsed = match.group("target") n_statement = match.group("number") if n_statement == 'a' or n_statement == 'an': n_statement = '1.0' n = mathparse.parse(n_statement, self.language.ISO_639.upper()) from_parsed, target_parsed = self.get_valid_units( from_parsed, target_parsed) if from_parsed is None or target_parsed is None: response.confidence = 0.0 else: from_value = self.unit_registry.Quantity(float(n), from_parsed) target_value = from_value.to(target_parsed) response.confidence = 1.0 response.text = str(target_value.magnitude) return response
def process(self, statement, additional_response_selection_parameters=None): """ Takes a statement string. Returns the equation from the statement with the mathematical terms solved. """ from mathparse import mathparse input_text = statement.text # Use the result cached by the process method if it exists if input_text in self.cache: cached_result = self.cache[input_text] self.cache = {} return cached_result # Getting the mathematical terms within the input statement expression = mathparse.extract_expression( input_text, language=self.language.ISO_639.upper()) response = Statement(text=expression) try: response.text += ' = ' + str( mathparse.parse(expression, language=self.language.ISO_639.upper())) # The confidence is 1 if the expression could be evaluated response.confidence = 1 except mathparse.PostfixTokenEvaluationException: response.confidence = 0 return response
def test_true(self): # Test that text capitalization is ignored. text = '你好' statement = Statement(text=text, search_text=self.tagger.get_text_index_string(text)) other_text = '你好' other_statement = Statement(text=other_text, search_text=self.tagger.get_text_index_string(other_text)) value = self.compare(statement, other_statement) self.assertEqual(value, 1)
def test_learn_response(self): previous_response = Statement(text='Define Hemoglobin.') statement = Statement( text='Hemoglobin is an oxygen-transport metalloprotein.') self.chatbot.learn_response(statement, previous_response) results = list(self.chatbot.storage.filter(text=statement.text)) self.assertIsLength(results, 1)
def process(self, statement, additional_response_selection_parameters=None): rules_list = self.chatbot.storage.filter_rules() # 提取所有规则对话 response = Statement(text='',confidence=0) for rule in rules_list: if statement.text == rule.text: response = Statement(text=rule.in_response_to) response.confidence=10 break return response
def test_low_confidence_options_list(self): """ Test the case that a high confidence response is not known. """ self.adapter.default_responses = [Statement(text='没有')] statement = Statement(text='那里有土豆么') match = self.adapter.process(statement) self.assertEqual(match.confidence, 0) self.assertEqual(match.text, '没有')
def test_true(self): # Test sentences with different stopwords. statement = Statement(text='今天天气怎么样') other_statement = Statement(text='今天天气怎么样啊') value = self.compare(statement, other_statement) self.assertAlmostEqual(value, 0.9, places=1) # Test that text capitalization is ignored. statement = Statement(text='你好') other_statement = Statement(text='你好') value = self.compare(statement, other_statement) self.assertAlmostEqual(value, 1, places=1)
def process(self, statement, additional_response_selection_parameters=None): now = datetime.now() time_features = self.time_question_features(statement.text.lower()) confidence = self.classifier.classify(time_features) response = Statement(text='The current time is ' + now.strftime('%I:%M %p')) response.confidence = confidence return response
def test_filter_text_with_equal_results(self): statement1 = Statement(text="Testing...", in_response_to=None) statement2 = Statement(text="Testing one, two, three.", in_response_to=None) self.adapter.update_text(statement1) self.adapter.update_text(statement2) res = list(self.adapter.filter_text(in_response_to=None)) self.assertEqual(len(res), 2) res_text = [result.text for result in res] self.assertEqual(len(res_text), 2) self.assertIn(statement1.text, res_text) self.assertIn(statement2.text, res_text)
def create(self, **kwargs): """ Creates a new statement matching the keyword arguments specified. Returns the created statement. """ Statement = self.get_model('statement') if 'tags' in kwargs: kwargs['tags'] = list(set(kwargs['tags'])) if 'search_text' not in kwargs: kwargs['search_text'] = self.tagger.get_text_index_string( kwargs['text']) if 'search_in_response_to' not in kwargs: if kwargs.get('in_response_to'): kwargs[ 'search_in_response_to'] = self.tagger.get_text_index_string( kwargs['in_response_to']) inserted = self.statements.insert_one(kwargs) kwargs['id'] = inserted.inserted_id return Statement(**kwargs)
def __init__(self, chatbot, **kwargs): super().__init__(chatbot, **kwargs) from app.chatterbot.response_selection import get_first_response self.search_algorithm_name = kwargs.get( 'search_algorithm_name', IndexedTextSearch.name ) self.search_algorithm = self.chatbot.search_algorithms[ self.search_algorithm_name ] self.maximum_similarity_threshold = kwargs.get( 'maximum_similarity_threshold', 0.95 ) # By default, select the first available response self.select_response = kwargs.get( 'response_selection_method', get_first_response ) default_responses = kwargs.get('default_response', []) # Convert a single string into a list if isinstance(default_responses, str): default_responses = [ default_responses ] self.default_responses = [ Statement(text=default) for default in default_responses ]
def train(self, conversation): """ Train the chat bot based on the provided list of statements that represents a single conversation. """ previous_statement_text = None previous_statement_search_text = '' statements_to_create = [] for conversation_count, text in enumerate(conversation): if self.show_training_progress: utils.print_progress_bar('List Trainer', conversation_count + 1, len(conversation)) statement_search_text = self.chatbot.storage.tagger.get_text_index_string( text) statement = self.get_preprocessed_statement( Statement(text=text, search_text=statement_search_text, in_response_to=previous_statement_text, search_in_response_to=previous_statement_search_text, conversation='training')) previous_statement_text = statement.text previous_statement_search_text = statement_search_text statements_to_create.append(statement) self.chatbot.storage.create_many(statements_to_create)
def train(self, *corpus_paths): from app.chatterbot.corpus import load_corpus, list_corpus_files data_file_paths = [] # Get the paths to each file the bot will be trained with for corpus_path in corpus_paths: data_file_paths.extend(list_corpus_files(corpus_path)) for corpus, categories, file_path in load_corpus(*data_file_paths): statements_to_create = [] # Train the chat bot with each statement and response pair for conversation_count, conversation in enumerate(corpus): if self.show_training_progress: utils.print_progress_bar( 'Training ' + str(os.path.basename(file_path)), conversation_count + 1, len(corpus)) previous_statement_text = None previous_statement_search_text = '' for text in conversation: statement_search_text = self.chatbot.storage.tagger.get_text_index_string( text) statement = Statement( text=text, search_text=statement_search_text, in_response_to=previous_statement_text, search_in_response_to=previous_statement_search_text, conversation='training') statement.add_tags(*categories) statement = self.get_preprocessed_statement(statement) previous_statement_text = statement.text previous_statement_search_text = statement_search_text statements_to_create.append(statement) if statements_to_create: self.chatbot.storage.create_many(statements_to_create)
def test_search_text_results_after_training(self): """ ChatterBot should return close matches to an input string when filtering using the search_text parameter. """ self.chatbot.storage.create_many([ Statement('Example A for search.'), Statement('Another example.'), Statement('Example B for search.'), Statement(text='Another statement.'), ]) text = self.chatbot.storage.tagger.get_text_index_string( 'Example A for search.') results = list(self.chatbot.storage.filter(search_text=text)) self.assertEqual(len(results), 1) self.assertEqual('Example A for search.', results[0].text)
def __init__(self, chatbot, **kwargs): super().__init__(chatbot, **kwargs) from app.chatterbot.conversation import Statement self.input_text = kwargs.get('input_text') output_text = kwargs.get('output_text') self.response_statement = Statement(text=output_text)
def test_no_data(self): """ If there is no data to return, an exception should be raised. """ statement = Statement(text='你想干什么') self.assertRaises( storage_adapter_new.StorageAdapterNew.EmptyDatabaseException, self.adapter.process, statement)
def test_no_known_responses(self): """ A match can be selected which has no known responses. In this case a random response will be returned, but the confidence should be zero because it is a random choice. """ from unittest.mock import MagicMock self.chatbot.storage.update = MagicMock() self.chatbot.storage.count = MagicMock(return_value=1) self.chatbot.storage.get_random = MagicMock(return_value=Statement( text='罗马')) match = self.adapter.process(Statement(text='巴拉巴拉')) self.assertEqual(match.confidence, 0) self.assertEqual(match.text, '罗马')
def __init__(self, chatbot, **kwargs): super().__init__(chatbot, **kwargs) from app.chatterbot.conversation import Statement self.text = kwargs.get('const_response', '看不懂唉') self.confidence = kwargs.get('const_confidence', 0.0) self.response_statement = Statement(text=self.text)
def test_get_response_additional_response_selection_parameters(self): self.chatbot.storage.create_many([ Statement('A', conversation='test_1'), Statement('B', conversation='test_1', in_response_to='A'), Statement('A', conversation='test_2'), Statement('C', conversation='test_2', in_response_to='A'), ]) statement = Statement(text='A', conversation='test_3') response = self.chatbot.get_response( statement, additional_response_selection_parameters={ 'conversation': 'test_2' }) self.assertEqual(response.text, 'C') self.assertEqual(response.conversation, 'test_3')
def test_true(self): """ Test the case that an exact match is given. """ statement = Statement(text='你想干什么') match = self.adapter.process(statement) self.assertEqual(match.confidence, 0.1) self.assertEqual(match, self.adapter.response_statement)
def test_update_text_modifies_existed_statement(self): self.adapter.create_text(text='How are you?') res = list(self.adapter.filter_text(text='How are you?')) self.assertEqual(len(res), 1) self.assertEqual(res[0].in_response_to, None) statement = Statement(text='How are you?', in_response_to='I am fine.') self.adapter.update_text(statement) res = list(self.adapter.filter_text(text='How are you?')) self.assertEqual(len(res), 1) self.assertEqual(res[0].in_response_to, statement.in_response_to)
def test_not_exact_match(self): """ Test the case that an exact match is not given. """ self.chatbot.storage.create_rule(text='你喜欢音乐么', in_response_to='喜欢') statement = Statement(text='你要干什么') match = self.adapter.process(statement) self.assertEqual(match.confidence, 0) self.assertEqual(match.text, '')
def mongo_to_object(self, statement_data): """ Return Statement object when given data returned from Mongo DB. """ Statement = self.get_model('statement') statement_data['id'] = statement_data['_id'] return Statement(**statement_data)
def test_match_with_no_response(self): """ A response to the input should be returned if a response is known. """ self.chatbot.storage.create(text='去吃披萨', in_response_to='你想干什么') statement = Statement(text='你想干什么') response = self.adapter.process(statement) self.assertEqual(response.text, '去吃披萨') self.assertEqual(response.confidence, 0)
def test_no_choices(self): """ The input should be returned as the closest match if there are no other results to return. """ self.chatbot.storage.create(text='罗马') statement = Statement(text='你的问题是什么') response = self.adapter.process(statement) self.assertEqual(response.text, '罗马') self.assertEqual(response.confidence, 0)
def process(self, statement, additional_response_selection_parameters=None): response = Statement(text='') input_text = statement.text try: # Use the result cached by the process method if it exists if input_text in self.cache: response = self.cache[input_text] self.cache = {} return response for pattern, func in self.patterns: p = pattern.match(input_text) if p is not None: response = func(p) if response.confidence == 1.0: break except Exception: response.confidence = 0.0 finally: return response
def test_excluded_words(self): """ Test that the logic adapter cannot return a response containing any of the listed words for exclusion. """ self.chatbot.storage.create(text='我喜欢音乐') self.chatbot.storage.create(text='音乐很无聊', in_response_to='我喜欢音乐') self.chatbot.storage.create(text='音乐很有趣', in_response_to='我喜欢音乐') self.adapter.excluded_words = ['无聊'] response = self.adapter.process(Statement(text='我喜欢音乐')) self.assertEqual(response.confidence, 1) self.assertEqual(response.text, '音乐很有趣')
def train(self, file): statements_to_create = [] with open(file, encoding='utf-8') as f: for line in f: line = line.split('\t') text = line[1] in_response_to = line[0] statement_search_text = self.chatbot.storage.tagger.get_text_index_string( text) search_in_response_to = self.chatbot.storage.tagger.get_text_index_string( in_response_to) statement = self.get_preprocessed_statement( Statement(text=text, search_text=statement_search_text, in_response_to=in_response_to, search_in_response_to=search_in_response_to, conversation='training')) statements_to_create.append(statement) self.chatbot.storage.create_many(statements_to_create)
def update(): try: data = json.loads(request.get_data(as_text=True)) except ValueError: return error_jsonify(10000041) except Exception: traceback.print_exc() return error_jsonify(10000002) check_keys = ('id', 'text', 'response', 'username', 'token') if not all(k in data for k in check_keys): return error_jsonify(10000001) b, result = certify_token(data['username'], data['token'].encode('utf-8')) if not b: return result s_id = data['id'] if s_id == '': return error_jsonify(10000046) try: int(s_id) except Exception: return error_jsonify(10000001) text = data['text'] response = data['response'] if text == '' or response == '': return error_jsonify(10000045) tag_list = [] if 'tags' in data: tags = data['tags'] tag_list = tags.split('+') # 调用数据接口 code = 1 new_statement = Statement(text=text, in_response_to=response, id=s_id, tags=tag_list) db.update_text(new_statement) # 调用数据接口 result = {'code': code, 'statement': _statement2dict(new_statement)} return jsonify(result)
def test_false(self): """ Falsy values should match by zero. """ # Test first statement is empty statement = Statement(text='', search_text=self.tagger.get_text_index_string('')) other_statement = Statement(text='你好', search_text=self.tagger.get_text_index_string('你好')) value = self.compare(statement, other_statement) self.assertEqual(value, 0) # Test latter statement is empty statement = Statement(text='你好', search_text=self.tagger.get_text_index_string('你好')) other_statement = Statement(text='', search_text=self.tagger.get_text_index_string('')) value = self.compare(statement, other_statement) self.assertEqual(value, 0) # Test that an exception is not raised # if a statement is initialized with an integer value as its text attribute. statement = Statement(text=2) other_statement = Statement(text='你好') value = self.compare(statement, other_statement) self.assertEqual(value, 0)