def start_chat(userentry): try: input_statement = Statement(text=userentry, conversation='training', persona='user:Amira') input_statement.add_tags('Amira') response = Bot.get_response(input_statement) except IOError: return str(IOError) return response.text
class StatementIntegrationTestCase(TestCase): """ Test case to make sure that the Django Statement model and ChatterBot Statement object have a common interface. """ def setUp(self): super(StatementIntegrationTestCase, self).setUp() from datetime import datetime from pytz import UTC now = datetime(2020, 2, 15, 3, 14, 10, 0, UTC) self.object = StatementObject(text='_', created_at=now) self.model = StatementModel(text='_', created_at=now) # Simulate both statements being saved self.model.save() self.object.id = self.model.id def test_text(self): self.assertTrue(hasattr(self.object, 'text')) self.assertTrue(hasattr(self.model, 'text')) def test_in_response_to(self): self.assertTrue(hasattr(self.object, 'in_response_to')) self.assertTrue(hasattr(self.model, 'in_response_to')) def test_conversation(self): self.assertTrue(hasattr(self.object, 'conversation')) self.assertTrue(hasattr(self.model, 'conversation')) def test_tags(self): self.assertTrue(hasattr(self.object, 'tags')) self.assertTrue(hasattr(self.model, 'tags')) def test__str__(self): self.assertTrue(hasattr(self.object, '__str__')) self.assertTrue(hasattr(self.model, '__str__')) self.assertEqual(str(self.object), str(self.model)) def test_add_tags(self): self.object.add_tags('a', 'b') self.model.add_tags('a', 'b') self.assertIn('a', self.object.get_tags()) self.assertIn('a', self.model.get_tags()) def test_serialize(self): object_data = self.object.serialize() model_data = self.model.serialize() self.assertEqual(object_data, model_data)
class StatementIntegrationTestCase(TestCase): """ Test case to make sure that the Django Statement model and ChatterBot Statement object have a common interface. """ def setUp(self): super().setUp() from datetime import datetime from pytz import UTC now = datetime(2020, 2, 15, 3, 14, 10, 0, UTC) self.object = StatementObject(text='_', created_at=now) self.model = StatementModel(text='_', created_at=now) # Simulate both statements being saved self.model.save() self.object.id = self.model.id def test_text(self): self.assertTrue(hasattr(self.object, 'text')) self.assertTrue(hasattr(self.model, 'text')) def test_in_response_to(self): self.assertTrue(hasattr(self.object, 'in_response_to')) self.assertTrue(hasattr(self.model, 'in_response_to')) def test_conversation(self): self.assertTrue(hasattr(self.object, 'conversation')) self.assertTrue(hasattr(self.model, 'conversation')) def test_tags(self): self.assertTrue(hasattr(self.object, 'tags')) self.assertTrue(hasattr(self.model, 'tags')) def test__str__(self): self.assertTrue(hasattr(self.object, '__str__')) self.assertTrue(hasattr(self.model, '__str__')) self.assertEqual(str(self.object), str(self.model)) def test_add_tags(self): self.object.add_tags('a', 'b') self.model.add_tags('a', 'b') self.assertIn('a', self.object.get_tags()) self.assertIn('a', self.model.get_tags()) def test_serialize(self): object_data = self.object.serialize() model_data = self.model.serialize() self.assertEqual(object_data, model_data)
def test_can_process_tags(testbot): """It should not process when the adapter is disabled in the request.""" responses.add( responses.GET, "https://api.wolframalpha.com/v2/validatequery", body=validate_result_success, status=200, ) wa = wolframalpha.WolframAlpha(testbot, wolfram_alpha_app_id="abcd") statement = Statement("hello") statement.add_tags("disable_wolfram") assert not wa.can_process(statement)
def train(self, *corpus_paths): from 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.stemmer.stem(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({ 'text': statement.text, 'in_response_to': statement.in_response_to, 'conversation': statement.conversation, 'tags': statement.tags }) self.chatbot.storage.create_many(statements_to_create)
def train(self, *corpus_paths): from 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.stemmer.get_bigram_pair_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) self.chatbot.storage.create_many(statements_to_create)
def train(self, *corpus_paths): # Allow a list of corpora to be passed instead of arguments if len(corpus_paths) == 1: if isinstance(corpus_paths[0], list): corpus_paths = corpus_paths[0] # Train the chat bot with each statement and response pair for corpus_path in corpus_paths: corpora = self.corpus.load_corpus(corpus_path) corpus_files = self.corpus.list_corpus_files(corpus_path) for corpus_count, corpus in enumerate(corpora): for conversation_count, conversation in enumerate(corpus): if self.show_training_progress: utils.print_progress_bar( str(os.path.basename(corpus_files[corpus_count])) + ' Training', conversation_count + 1, len(corpus)) previous_statement_text = None for text in conversation: _statement = Statement( text=text, in_response_to=previous_statement_text, conversation='training') _statement.add_tags(*corpus.categories) statement = self.get_preprocessed_statement(_statement) previous_statement_text = statement.text self.chatbot.storage.create( text=statement.text, in_response_to=statement.in_response_to, conversation=statement.conversation, tags=statement.tags)
def process_input(self, statement): """ Process input from the HipChat room. """ new_message = False conversation = self.chatbot.storage.filter( conversation=statement.conversation, order_by=['id'] ) response_statement = conversation[-1] if conversation else None if response_statement: tags = response_statement.get_tags() last_message_id = None for tag in tags: if tag.startswith('hipchat_message_id:'): last_message_id = tag.split('hipchat_message_id:')[-1] break if last_message_id: self.recent_message_ids.add(last_message_id) while not new_message: data = self.get_most_recent_message(self.hipchat_room) if data and data['id'] not in self.recent_message_ids: self.recent_message_ids.add(data['id']) new_message = True else: pass sleep(3.5) text = data['message'] statement = Statement(text) statement.add_tags('hipchat_message_id' + data['id']) return statement
def train(self, *corpus_paths): from 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, conversations 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_statements_texts = [None] previous_statements_search_texts = [''] for conversation in conversations: if isinstance(conversation, str): conversation = [conversation] statements_texts = [] statements_search_texts = [] for previous_statement_text, previous_statement_search_text in zip( previous_statements_texts, previous_statements_search_texts): for text in conversation: statement_search_text = self.chatbot.storage.tagger.get_bigram_pair_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) statements_texts.append(statement.text) statements_search_texts.append( statement_search_text) statements_to_create.append(statement) previous_statements_texts = statements_texts previous_statements_search_texts = statements_search_texts if statements_to_create: self.chatbot.storage.create_many(statements_to_create)
class ChatterBotResponseTestCase(ChatBotTestCase): def setUp(self): super(ChatterBotResponseTestCase, self).setUp() self.test_statement = Statement('Hello', in_response_to='Hi') def test_empty_database(self): """ If there is no statements in the database, then the user's input is the only thing that can be returned. """ response = self.chatbot.get_response('How are you?') self.assertEqual('How are you?', response) def test_statement_saved_empty_database(self): """ Test that when database is empty, the first statement is saved and returned as a response. """ statement_text = 'Wow!' response = self.chatbot.get_response(statement_text) results = self.chatbot.storage.filter(text=statement_text) self.assertIsLength(results, 1) self.assertEqual(response, statement_text) def test_statement_added_to_conversation(self): """ An input statement should be added to the recent response list. """ statement = Statement(text='Wow!', conversation='test') response = self.chatbot.get_response(statement) self.assertEqual(statement.text, response) self.assertEqual(response.conversation, 'test') def test_response_known(self): self.chatbot.storage.update(self.test_statement) response = self.chatbot.get_response('Hi') self.assertEqual(response, self.test_statement.text) def test_response_format(self): self.chatbot.storage.update(self.test_statement) response = self.chatbot.get_response('Hi') results = self.chatbot.storage.filter(text=response.text) self.assertEqual(response, self.test_statement.text) self.assertIsLength(results, 1) self.assertEqual(results[0].in_response_to, 'Hi') def test_second_response_format(self): self.chatbot.storage.update(self.test_statement) response = self.chatbot.get_response('Hi') self.assertEqual(response.text, 'Hello') second_response = self.chatbot.get_response('How are you?') results = self.chatbot.storage.filter(text=second_response.text) # Make sure that the second response was saved to the database self.assertIsLength(self.chatbot.storage.filter(text='How are you?'), 1) self.assertEqual(second_response, self.test_statement.text) self.assertIsLength(results, 1) self.assertEqual(results[0].in_response_to, 'Hi') def test_get_response_unicode(self): """ Test the case that a unicode string is passed in. """ response = self.chatbot.get_response(u'سلام') self.assertGreater(len(response.text), 0) def test_get_response_emoji(self): """ Test the case that the input string contains an emoji. """ response = self.chatbot.get_response(u'💩 ') self.assertGreater(len(response.text), 0) def test_get_response_non_whitespace(self): """ Test the case that a non-whitespace C1 control string is passed in. """ response = self.chatbot.get_response(u'') self.assertGreater(len(response.text), 0) def test_get_response_two_byte_characters(self): """ Test the case that a string containing two-byte characters is passed in. """ response = self.chatbot.get_response(u'田中さんにあげて下さい') self.assertGreater(len(response.text), 0) def test_get_response_corrupted_text(self): """ Test the case that a string contains "corrupted" text. """ response = self.chatbot.get_response( u'Ṱ̺̺̕h̼͓̲̦̳̘̲e͇̣̰̦̬͎ ̢̼̻̱̘h͚͎͙̜̣̲ͅi̦̲̣̰̤v̻͍e̺̭̳̪̰-m̢iͅn̖̺̞̲̯̰d̵̼̟͙̩̼̘̳.̨̹͈̣' ) self.assertGreater(len(response.text), 0) def test_response_with_tags_added(self): """ If an input statement has tags added to it, that data should saved with the input statement. """ self.test_statement.add_tags('test') self.chatbot.get_response(self.test_statement) results = self.chatbot.storage.filter(text=self.test_statement.text) self.assertIsLength(results, 1) self.assertIn('test', results[0].get_tags()) def test_generate_response(self): statement = Statement( 'Many insects adopt a tripedal gait for rapid yet stable walking.') response = self.chatbot.generate_response(statement) self.assertEqual(response, statement) self.assertEqual(response.confidence, 1) def test_learn_response(self): previous_response = Statement('Define Hemoglobin.') statement = Statement( 'Hemoglobin is an oxygen-transport metalloprotein.') self.chatbot.learn_response(statement, previous_response) results = self.chatbot.storage.filter(text=statement.text) self.assertIsLength(results, 1) def test_get_response_does_not_add_new_statement(self): """ Test that a new statement is not learned if `read_only` is set to True. """ self.chatbot.read_only = True self.chatbot.get_response('Hi!') results = self.chatbot.storage.filter(text='Hi!') self.assertIsLength(results, 0) def test_get_latest_response_from_zero_responses(self): response = self.chatbot.get_latest_response('invalid') self.assertIsNone(response) def test_get_latest_response_from_one_responses(self): self.chatbot.storage.create(text='A', conversation='test') self.chatbot.storage.create(text='B', conversation='test', in_response_to='A') response = self.chatbot.get_latest_response('test') self.assertEqual(response.text, 'A') def test_get_latest_response_from_two_responses(self): self.chatbot.storage.create(text='A', conversation='test') self.chatbot.storage.create(text='B', conversation='test', in_response_to='A') self.chatbot.storage.create(text='C', conversation='test', in_response_to='B') response = self.chatbot.get_latest_response('test') self.assertEqual(response.text, 'B') def test_get_latest_response_from_three_responses(self): self.chatbot.storage.create(text='A', conversation='test') self.chatbot.storage.create(text='B', conversation='test', in_response_to='A') self.chatbot.storage.create(text='C', conversation='test', in_response_to='B') self.chatbot.storage.create(text='D', conversation='test', in_response_to='C') response = self.chatbot.get_latest_response('test') self.assertEqual(response.text, 'C')
def get_response(self, statement=None, **kwargs): """ Return the bot's response based on the input. :param statement: An statement object or string. :returns: A response to the input. :rtype: Statement :param additional_response_selection_parameters: Parameters to pass to the chat bot's logic adapters to control response selection. :type additional_response_selection_parameters: dict :param persist_values_to_response: Values that should be saved to the response that the chat bot generates. :type persist_values_to_response: dict """ Statement = self.storage.get_object('statement') additional_response_selection_parameters = kwargs.pop( 'additional_response_selection_parameters', {}) persist_values_to_response = kwargs.pop('persist_values_to_response', {}) if isinstance(statement, str): kwargs['text'] = statement if isinstance(statement, dict): kwargs.update(statement) if statement is None and 'text' not in kwargs: raise self.ChatBotException( 'Either a statement object or a "text" keyword ' 'argument is required. Neither was provided.') if hasattr(statement, 'serialize'): kwargs.update(**statement.serialize()) tags = kwargs.pop('tags', []) text = kwargs.pop('text') input_statement = Statement(text=text, **kwargs) input_statement.add_tags(*tags) # Preprocess the input statement for preprocessor in self.preprocessors: input_statement = preprocessor(input_statement) # Make sure the input statement has its search text saved if not input_statement.search_text: input_statement.search_text = self.storage.tagger.get_bigram_pair_string( input_statement.text) if not input_statement.search_in_response_to and input_statement.in_response_to: input_statement.search_in_response_to = self.storage.tagger.get_bigram_pair_string( input_statement.in_response_to) response = self.generate_response( input_statement, additional_response_selection_parameters) # Update any response data that needs to be changed if persist_values_to_response: for response_key in persist_values_to_response: response_value = persist_values_to_response[response_key] if response_key == 'tags': input_statement.add_tags(*response_value) response.add_tags(*response_value) else: setattr(input_statement, response_key, response_value) setattr(response, response_key, response_value) if not self.read_only: self.learn_response(input_statement) # Save the response generated for the input self.storage.create(**response.serialize()) return response
def train(self, *corpus_paths): from 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: suggestion_tags = [] if text.strip('.?!/;:\'\"') in constants.AFFIRMATIVES: text = 'AFF' elif text.strip('.?!/;:\'\"') in constants.NEGATIVES: text = 'NEG' elif text[0] is '^': (suggestion, text) = text.split(maxsplit=1) suggestion = suggestion[1:] if not suggestion.find('/'): suggestion_tags.append(suggestion) else: for suggestion in suggestion.split('/'): suggestion_tags.append(suggestion) statement_search_text = self.chatbot.storage.tagger.get_bigram_pair_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') # YesNoLogicAdapter deals with responses to AFF/NEG via statement tags. # No need for statements in_response_to = AFF/NEG In fact, it was causing # erroneous responses if statement.in_response_to in ['AFF', 'NEG']: statement.in_response_to = None statement.search_in_response_to = None statement.add_tags(*categories) if suggestion_tags: for suggestion in suggestion_tags: statement.add_tags('SUGGESTION:' + suggestion) if previous_statement_text: if previous_statement_text == 'AFF': statements_to_create[-2].add_tags('AFF:' + statement.text) elif previous_statement_text == 'NEG': statements_to_create[-2].add_tags('NEG:' + statement.text) statement = self.get_preprocessed_statement(statement) previous_statement_text = statement.text previous_statement_search_text = statement_search_text statements_to_create.append(statement) # Using update() because create_many() makes duplicate statements. AFF/NEG tag data was lost on some. for stmnts in statements_to_create: self.chatbot.storage.update(stmnts)
class ChatterBotResponseTestCase(ChatBotTestCase): def setUp(self): super(ChatterBotResponseTestCase, self).setUp() self.test_statement = Statement(text='Hello', in_response_to='Hi') def test_empty_database(self): """ If there is no statements in the database, then the user's input is the only thing that can be returned. """ response = self.chatbot.get_response('How are you?') self.assertEqual('How are you?', response) def test_statement_saved_empty_database(self): """ Test that when database is empty, the first statement is saved and returned as a response. """ statement_text = 'Wow!' response = self.chatbot.get_response(statement_text) results = self.chatbot.storage.filter(text=statement_text) self.assertIsLength(results, 1) self.assertEqual(response, statement_text) def test_statement_added_to_conversation(self): """ An input statement should be added to the recent response list. """ statement = Statement(text='Wow!', conversation='test') response = self.chatbot.get_response(statement) self.assertEqual(statement.text, response) self.assertEqual(response.conversation, 'test') def test_response_known(self): self.chatbot.storage.update(self.test_statement) response = self.chatbot.get_response('Hi') self.assertEqual(response, self.test_statement.text) def test_response_format(self): self.chatbot.storage.update(self.test_statement) response = self.chatbot.get_response('Hi') results = self.chatbot.storage.filter(text=response.text) self.assertEqual(response, self.test_statement.text) self.assertIsLength(results, 1) self.assertEqual(results[0].in_response_to, 'Hi') def test_second_response_format(self): self.chatbot.storage.update(self.test_statement) response = self.chatbot.get_response('Hi') self.assertEqual(response.text, 'Hello') second_response = self.chatbot.get_response('How are you?') results = self.chatbot.storage.filter(text=second_response.text) # Make sure that the second response was saved to the database self.assertIsLength(self.chatbot.storage.filter(text='How are you?'), 1) self.assertEqual(second_response, self.test_statement.text) self.assertIsLength(results, 1) self.assertEqual(results[0].in_response_to, 'Hi') def test_get_response_unicode(self): """ Test the case that a unicode string is passed in. """ response = self.chatbot.get_response(u'سلام') self.assertGreater(len(response.text), 0) def test_get_response_emoji(self): """ Test the case that the input string contains an emoji. """ response = self.chatbot.get_response(u'💩 ') self.assertGreater(len(response.text), 0) def test_get_response_non_whitespace(self): """ Test the case that a non-whitespace C1 control string is passed in. """ response = self.chatbot.get_response(u'') self.assertGreater(len(response.text), 0) def test_get_response_two_byte_characters(self): """ Test the case that a string containing two-byte characters is passed in. """ response = self.chatbot.get_response(u'田中さんにあげて下さい') self.assertGreater(len(response.text), 0) def test_get_response_corrupted_text(self): """ Test the case that a string contains "corrupted" text. """ response = self.chatbot.get_response(u'Ṱ̺̺̕h̼͓̲̦̳̘̲e͇̣̰̦̬͎ ̢̼̻̱̘h͚͎͙̜̣̲ͅi̦̲̣̰̤v̻͍e̺̭̳̪̰-m̢iͅn̖̺̞̲̯̰d̵̼̟͙̩̼̘̳.̨̹͈̣') self.assertGreater(len(response.text), 0) def test_response_with_tags_added(self): """ If an input statement has tags added to it, that data should saved with the input statement. """ self.test_statement.add_tags('test') self.chatbot.get_response( self.test_statement ) results = self.chatbot.storage.filter(text=self.test_statement.text) self.assertIsLength(results, 1) self.assertIn('test', results[0].get_tags()) def test_get_response_with_text_and_kwargs(self): self.chatbot.get_response('Hello', conversation='greetings') results = self.chatbot.storage.filter(text='Hello') self.assertIsLength(results, 1) self.assertEqual(results[0].conversation, 'greetings') def test_get_response_missing_text(self): with self.assertRaises(self.chatbot.ChatBotException): self.chatbot.get_response() def test_get_response_missing_text_with_conversation(self): with self.assertRaises(self.chatbot.ChatBotException): self.chatbot.get_response(conversation='test') def test_generate_response(self): statement = Statement(text='Many insects adopt a tripedal gait for rapid yet stable walking.') response = self.chatbot.generate_response(statement) self.assertEqual(response, statement) self.assertEqual(response.confidence, 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 = self.chatbot.storage.filter(text=statement.text) self.assertIsLength(results, 1) def test_get_response_does_not_add_new_statement(self): """ Test that a new statement is not learned if `read_only` is set to True. """ self.chatbot.read_only = True self.chatbot.get_response('Hi!') results = self.chatbot.storage.filter(text='Hi!') self.assertIsLength(results, 0) def test_get_latest_response_from_zero_responses(self): response = self.chatbot.get_latest_response('invalid') self.assertIsNone(response) def test_get_latest_response_from_one_responses(self): self.chatbot.storage.create(text='A', conversation='test') self.chatbot.storage.create(text='B', conversation='test', in_response_to='A') response = self.chatbot.get_latest_response('test') self.assertEqual(response.text, 'A') def test_get_latest_response_from_two_responses(self): self.chatbot.storage.create(text='A', conversation='test') self.chatbot.storage.create(text='B', conversation='test', in_response_to='A') self.chatbot.storage.create(text='C', conversation='test', in_response_to='B') response = self.chatbot.get_latest_response('test') self.assertEqual(response.text, 'B') def test_get_latest_response_from_three_responses(self): self.chatbot.storage.create(text='A', conversation='test') self.chatbot.storage.create(text='B', conversation='test', in_response_to='A') self.chatbot.storage.create(text='C', conversation='test', in_response_to='B') self.chatbot.storage.create(text='D', conversation='test', in_response_to='C') response = self.chatbot.get_latest_response('test') self.assertEqual(response.text, 'C')