diff --git a/chatterbot/adapters/storage/jsondatabase.py b/chatterbot/adapters/storage/jsondatabase.py index 8a8ae0282..1a1e64388 100644 --- a/chatterbot/adapters/storage/jsondatabase.py +++ b/chatterbot/adapters/storage/jsondatabase.py @@ -54,12 +54,19 @@ def _all_kwargs_match_values(self, kwarguments, values): if "__" in kwarg: kwarg_parts = kwarg.split("__") - if kwarg_parts[1] == "contains": + key = kwarg_parts[0] + identifier = kwarg_parts[1] + + if identifier == "contains": text_values = [] - for val in values[kwarg_parts[0]]: + for val in values[key]: text_values.append(val[0]) - if (kwarguments[kwarg] not in text_values) and (kwarguments[kwarg] not in values[kwarg_parts[0]]): + if (kwarguments[kwarg] not in text_values) and (kwarguments[kwarg] not in values[key]): + return False + + if identifier == "not": + if (key in values) and (kwarguments[kwarg] == values[key]): return False if kwarg in values: diff --git a/chatterbot/chatterbot.py b/chatterbot/chatterbot.py index 847775dda..5e45a891d 100644 --- a/chatterbot/chatterbot.py +++ b/chatterbot/chatterbot.py @@ -90,6 +90,22 @@ def get_response(self, input_text): all_statements = self.storage.filter() + ''' + Filter out all statements that are not in response to another statement. + A statement must exist which lists the closest matching statement in the + in_response_to field. Otherwise, the logic adapter may find a closest + matching statement that does not have a known response. + ''' + for statement in all_statements: + response_exists = False + for s in all_statements: + if statement in s.in_response_to: + response_exists = True + break # Exit for loop since one exists + + if not response_exists: + all_statements.remove(statement) + # Select the closest match to the input statement closest_match = self.logic.get( input_statement, diff --git a/tests/storage_adapter_tests/test_jsondb_adapter.py b/tests/storage_adapter_tests/test_jsondb_adapter.py index 78503a4b8..ddc8e492d 100644 --- a/tests/storage_adapter_tests/test_jsondb_adapter.py +++ b/tests/storage_adapter_tests/test_jsondb_adapter.py @@ -288,6 +288,58 @@ def test_filter_returns_statement_with_multiple_responses(self): self.assertEqual(len(response.in_response_to), 2) + def test_not_filter_no_responses(self): + statement = Statement( + "You are welcome.", + in_response_to=[] + ) + self.adapter.update(statement) + response = self.adapter.filter( + in_response_to__not=[] + ) + + self.assertEqual( + len(response), + 0, + "A response was found when none should have been returned." + ) + + def test_not_filter_multiple_responses(self): + statements = [ + Statement( + "You are welcome.", + in_response_to=[] + ), + Statement( + "I like ducks.", + in_response_to=[] + ), + Statement( + "Hello.", + in_response_to=[Response("Hi.")] + ), + Statement( + "Hi.", + in_response_to=[Response("Hello.")] + ), + Statement( + "Hey!", + in_response_to=[Response("Hello.")] + ) + ] + + for statement in statements: + self.adapter.update(statement) + + response = self.adapter.filter( + in_response_to__not=[] + ) + + self.assertEqual(len(response), 3) + self.assertIn("Hello.", response) + self.assertIn("Hi.", response) + self.assertIn("Hey!", response) + class ReadOnlyJsonDatabaseAdapterTestCase(BaseJsonDatabaseAdapterTestCase): diff --git a/tests/test_chatbot_output.py b/tests/test_chatbot_output.py index c75146310..05dfd6b0f 100644 --- a/tests/test_chatbot_output.py +++ b/tests/test_chatbot_output.py @@ -170,12 +170,12 @@ def test_second_response_format(self): response = self.chatbot.get_response("Hi") # response = "Hello" second_response = self.chatbot.get_response("How are you?") - statement_object = self.chatbot.storage.find(second_response) + statement = self.chatbot.storage.find(second_response) self.assertEqual(second_response, self.test_statement.text) - #TODO: self.assertEqual(statement_object.get_response_count(), 2) - self.assertEqual(len(statement_object.in_response_to), 1) - self.assertIn("Hi", statement_object.in_response_to) + #TODO: self.assertEqual(statement.get_response_count(), 2) + self.assertEqual(len(statement.in_response_to), 1) + self.assertIn("Hi", statement.in_response_to) class ChatterBotStorageIntegrationTests(UntrainedChatBotTestCase): diff --git a/tests/training_tests/test_training.py b/tests/training_tests/test_training.py index 2269426bc..f1effeb17 100644 --- a/tests/training_tests/test_training.py +++ b/tests/training_tests/test_training.py @@ -108,3 +108,24 @@ def test_training_with_unicode_characters(self): self.assertEqual(response, conversation[2]) + def test_similar_sentence_gets_same_response_multiple_times(self): + """ + Tests if the bot returns the same response for the same question (which + is similar to the one present in the training set) when asked repeatedly. + """ + training = [ + 'how do you login to gmail?', + 'Goto gmail.com, enter your login information and hit enter!' + ] + + similar_question = 'how do I login to gmail?' + + self.chatbot.train(training) + + response_to_trained_set = self.chatbot.get_response('how do you login to gmail?') + response_to_similar_question_1 = self.chatbot.get_response(similar_question) + response_to_similar_question_2 = self.chatbot.get_response(similar_question) + + self.assertEqual(response_to_trained_set, response_to_similar_question_1) + self.assertEqual(response_to_similar_question_1, response_to_similar_question_2) +