Skip to content

Commit

Permalink
Updated for raspberry pi and fixed some other issues
Browse files Browse the repository at this point in the history
- updated spaCy requirements
- included install script for raspi
- made changes to spaCy loading save memory
- by default, have best_match adapter allow repeated responses, with option to disable
  • Loading branch information
gitCommitWiL committed Mar 26, 2020
1 parent 0c4e388 commit 4f2275e
Show file tree
Hide file tree
Showing 11 changed files with 74 additions and 22 deletions.
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,12 @@ This package can be installed from [PyPi](https://pypi.python.org/pypi/ChatterBo
pip install chatterbot
```

For Raspberry Pi users: download or clone the repo and then run the install script:

```
./install.sh
```

## Basic Usage

```
Expand Down
15 changes: 11 additions & 4 deletions chatterbot/chatterbot.py
Original file line number Diff line number Diff line change
Expand Up @@ -127,10 +127,11 @@ def get_response(self, statement=None, **kwargs):
setattr(response, response_key, response_value)

if not self.read_only:
self.learn_response(input_statement)
# want to learn that response is valid for input statement
self.learn_response(response, input_statement)

# Save the response generated for the input
self.storage.create(**response.serialize())
# also save the input statement
self.storage.create(**input_statement.serialize())

return response

Expand Down Expand Up @@ -211,6 +212,8 @@ def learn_response(self, statement, previous_statement=None):
"""
Learn that the statement provided is a valid response.
"""
if not statement.search_text:
statement.search_text = self.storage.tagger.get_text_index_string(statement.text)
if not previous_statement:
previous_statement = statement.in_response_to

Expand All @@ -223,15 +226,19 @@ def learn_response(self, statement, previous_statement=None):

if not isinstance(previous_statement, (str, type(None), )):
statement.in_response_to = previous_statement.text
if not statement.search_in_response_to:
statement.search_in_response_to = previous_statement.search_text
elif isinstance(previous_statement, str):
statement.in_response_to = previous_statement
if not statement.search_in_response_to:
statement.search_in_response_to = self.storage.tagger.get_text_index_string(previous_statement)

self.logger.info('Adding "{}" as a response to "{}"'.format(
statement.text,
previous_statement_text
))

# Save the input statement
# Save the response
return self.storage.create(**statement.serialize())

def get_latest_response(self, conversation):
Expand Down
5 changes: 2 additions & 3 deletions chatterbot/comparisons.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
designed to compare one statement to another.
"""
from difflib import SequenceMatcher

from chatterbot import singleton_classes

class Comparator:

Expand Down Expand Up @@ -63,9 +63,8 @@ class SpacySimilarity(Comparator):

def __init__(self, language):
super().__init__(language)
import spacy

self.nlp = spacy.load(self.language.ISO_639_1)
self.nlp = singleton_classes.singleSpacy.getInstance(language)

def compare(self, statement_a, statement_b):
"""
Expand Down
21 changes: 13 additions & 8 deletions chatterbot/logic/best_match.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ def __init__(self, chatbot, **kwargs):
super().__init__(chatbot, **kwargs)

self.excluded_words = kwargs.get('excluded_words')
self.exclude_recent_repeated = kwargs.get('exclude_recent_repeated')

def process(self, input_statement, additional_response_selection_parameters=None):
search_results = self.search_algorithm.search(input_statement)
Expand All @@ -40,15 +41,19 @@ def process(self, input_statement, additional_response_selection_parameters=None
closest_match.text, input_statement.text, closest_match.confidence
))

recent_repeated_responses = filters.get_recent_repeated_responses(
self.chatbot,
input_statement.conversation
)
recent_repeated_responses = None

for index, recent_repeated_response in enumerate(recent_repeated_responses):
self.chatbot.logger.info('{}. Excluding recent repeated response of "{}"'.format(
index, recent_repeated_response
))
# remove recently repeated only if user specifies
if self.exclude_recent_repeated:
recent_repeated_responses = filters.get_recent_repeated_responses(
self.chatbot,
input_statement.conversation
)

for index, recent_repeated_response in enumerate(recent_repeated_responses):
self.chatbot.logger.info('{}. Excluding recent repeated response of "{}"'.format(
index, recent_repeated_response
))

response_selection_parameters = {
'search_in_response_to': closest_match.search_text,
Expand Down
16 changes: 16 additions & 0 deletions chatterbot/singleton_classes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
from chatterbot import languages
import spacy

# loading spacy more than once slows down everything and makes it consume a lot of extra memory
# so having a single instance will save memory
class singleSpacy:
_instance = None
@staticmethod
def getInstance(language=None):
if singleSpacy._instance is None:
singleSpacy(language)
return singleSpacy._instance

def __init__(self, language=None):
language = language or languages.ENG
singleSpacy._instance = spacy.load(language.ISO_639_1.lower())
2 changes: 2 additions & 0 deletions chatterbot/storage/mongodb.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,8 @@ def filter(self, **kwargs):
or_regex = '|'.join([
'{}'.format(re.escape(word)) for word in search_text_contains.split(' ')
])
# try matching whole words rather than part; for example 'hi' shouldn't match 'white'
or_regex = '\\b' + or_regex + '\\b'
kwargs['search_text'] = re.compile(or_regex)

mongo_ordering = []
Expand Down
5 changes: 2 additions & 3 deletions chatterbot/tagging.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import string
from chatterbot import languages

from chatterbot import singleton_classes

class LowercaseTagger(object):
"""
Expand All @@ -17,13 +17,12 @@ def get_text_index_string(self, text):
class PosLemmaTagger(object):

def __init__(self, language=None):
import spacy

self.language = language or languages.ENG

self.punctuation_table = str.maketrans(dict.fromkeys(string.punctuation))

self.nlp = spacy.load(self.language.ISO_639_1.lower())
self.nlp = singleton_classes.singleSpacy.getInstance(language)

def get_text_index_string(self, text):
"""
Expand Down
19 changes: 19 additions & 0 deletions install.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#!/bin/bash

# may need to install/ update Cython
# python3 -m pip install -U Cython

if
# for arm architecure, need to set BLIS to generic for install to work
lscpu| head -n 1 | grep -q 'aarch\|arm'; then
echo "Setting BLIS_ARCH to generic"
export BLIS_ARCH='generic'
fi
echo "Installing Chatterbot"
python3 -m pip install .

# change 'en' to any other language if desired; by default the small model is downloaded
# but this can be changed; for example: change 'en' to 'en_core_web_lg' for the large model
# then will need to create corresponding shortcut link; for example: python3 -m spacy link --force en_core_web_lg en
echo "Downloading and linking spaCy en model"
python3 -m spacy download en
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@ nltk>=3.2,<4.0
pint>=0.8.1
python-dateutil>=2.7,<2.8
pyyaml>=5.1,<5.2
spacy>=2.1,<2.2
spacy>=2.2,<2.3
sqlalchemy>=1.3,<1.4
pytz
2 changes: 1 addition & 1 deletion setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ max_line_length = 175
exclude = .eggs, .git, .tox, build,

[chatterbot]
version = 1.1.0
version = 1.1.1
author = Gunther Cox
email = [email protected]
url = https://github.com/gunthercox/ChatterBot
3 changes: 1 addition & 2 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@
else:
REQUIREMENTS.append(requirement)


setup(
name='ChatterBot',
version=VERSION,
Expand Down Expand Up @@ -71,7 +70,7 @@
dependency_links=DEPENDENCIES,
python_requires='>=3.4, <4',
license='BSD',
zip_safe=True,
zip_safe=False,
platforms=['any'],
keywords=['ChatterBot', 'chatbot', 'chat', 'bot'],
classifiers=[
Expand Down

0 comments on commit 4f2275e

Please sign in to comment.