ChatterBot 1.2.4__py3-none-any.whl → 1.2.6__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- chatterbot/__init__.py +1 -1
- chatterbot/chatterbot.py +3 -3
- chatterbot/comparisons.py +5 -9
- chatterbot/conversation.py +1 -2
- chatterbot/ext/django_chatterbot/abstract_models.py +16 -8
- chatterbot/ext/django_chatterbot/apps.py +7 -0
- chatterbot/ext/django_chatterbot/migrations/0020_alter_statement_conversation_and_more.py +53 -0
- chatterbot/ext/django_chatterbot/settings.py +2 -3
- chatterbot/logic/logic_adapter.py +14 -9
- chatterbot/preprocessors.py +4 -3
- chatterbot/response_selection.py +4 -6
- chatterbot/storage/django_storage.py +4 -1
- chatterbot/storage/sql_storage.py +1 -1
- chatterbot/tagging.py +5 -4
- chatterbot/trainers.py +82 -55
- chatterbot/utils.py +1 -3
- {chatterbot-1.2.4.dist-info → chatterbot-1.2.6.dist-info}/METADATA +4 -3
- {chatterbot-1.2.4.dist-info → chatterbot-1.2.6.dist-info}/RECORD +21 -20
- {chatterbot-1.2.4.dist-info → chatterbot-1.2.6.dist-info}/WHEEL +0 -0
- {chatterbot-1.2.4.dist-info → chatterbot-1.2.6.dist-info}/licenses/LICENSE +0 -0
- {chatterbot-1.2.4.dist-info → chatterbot-1.2.6.dist-info}/top_level.txt +0 -0
chatterbot/__init__.py
CHANGED
chatterbot/chatterbot.py
CHANGED
@@ -3,6 +3,7 @@ from chatterbot.storage import StorageAdapter
|
|
3
3
|
from chatterbot.logic import LogicAdapter
|
4
4
|
from chatterbot.search import TextSearch, IndexedTextSearch
|
5
5
|
from chatterbot.tagging import PosLemmaTagger
|
6
|
+
from chatterbot.conversation import Statement
|
6
7
|
from chatterbot import languages
|
7
8
|
from chatterbot import utils
|
8
9
|
import spacy
|
@@ -114,13 +115,12 @@ class ChatBot(object):
|
|
114
115
|
# Allow the bot to save input it receives so that it can learn
|
115
116
|
self.read_only = kwargs.get('read_only', False)
|
116
117
|
|
117
|
-
def get_response(self, statement=None, **kwargs):
|
118
|
+
def get_response(self, statement=None, **kwargs) -> Statement:
|
118
119
|
"""
|
119
120
|
Return the bot's response based on the input.
|
120
121
|
|
121
122
|
:param statement: An statement object or string.
|
122
123
|
:returns: A response to the input.
|
123
|
-
:rtype: Statement
|
124
124
|
|
125
125
|
:param additional_response_selection_parameters: Parameters to pass to the
|
126
126
|
chat bot's logic adapters to control response selection.
|
@@ -314,7 +314,7 @@ class ChatBot(object):
|
|
314
314
|
# Save the response statement
|
315
315
|
return self.storage.create(**statement.serialize())
|
316
316
|
|
317
|
-
def get_latest_response(self, conversation):
|
317
|
+
def get_latest_response(self, conversation: str):
|
318
318
|
"""
|
319
319
|
Returns the latest response in a conversation if it exists.
|
320
320
|
Returns None if a matching conversation cannot be found.
|
chatterbot/comparisons.py
CHANGED
@@ -19,19 +19,17 @@ class Comparator:
|
|
19
19
|
def __call__(self, statement_a, statement_b):
|
20
20
|
return self.compare(statement_a, statement_b)
|
21
21
|
|
22
|
-
def compare_text(self, text_a, text_b):
|
22
|
+
def compare_text(self, text_a: str, text_b: str) -> float:
|
23
23
|
"""
|
24
24
|
Implemented in subclasses: compare text_a to text_b.
|
25
25
|
|
26
26
|
:return: The percent of similarity between the statements based on the implemented algorithm.
|
27
|
-
:rtype: float
|
28
27
|
"""
|
29
28
|
return 0
|
30
29
|
|
31
|
-
def compare(self, statement_a, statement_b):
|
30
|
+
def compare(self, statement_a, statement_b) -> float:
|
32
31
|
"""
|
33
32
|
:return: The percent of similarity between the statements based on the implemented algorithm.
|
34
|
-
:rtype: float
|
35
33
|
"""
|
36
34
|
return self.compare_text(statement_a.text, statement_b.text)
|
37
35
|
|
@@ -46,12 +44,11 @@ class LevenshteinDistance(Comparator):
|
|
46
44
|
based on the Levenshtein distance algorithm.
|
47
45
|
"""
|
48
46
|
|
49
|
-
def compare_text(self, text_a, text_b):
|
47
|
+
def compare_text(self, text_a: str, text_b: str) -> float:
|
50
48
|
"""
|
51
49
|
Compare the two pieces of text.
|
52
50
|
|
53
51
|
:return: The percent of similarity between the text of the statements.
|
54
|
-
:rtype: float
|
55
52
|
"""
|
56
53
|
|
57
54
|
# Return 0 if either statement has a None text value
|
@@ -105,12 +102,11 @@ class SpacySimilarity(Comparator):
|
|
105
102
|
# Disable the Named Entity Recognition (NER) component because it is not necessary
|
106
103
|
self.nlp = spacy.load(model, exclude=['ner'])
|
107
104
|
|
108
|
-
def compare_text(self, text_a, text_b):
|
105
|
+
def compare_text(self, text_a: str, text_b: str) -> float:
|
109
106
|
"""
|
110
107
|
Compare the similarity of two strings.
|
111
108
|
|
112
109
|
:return: The percent of similarity between the closest synset distance.
|
113
|
-
:rtype: float
|
114
110
|
"""
|
115
111
|
|
116
112
|
# Return 0 if either statement has a None text value
|
@@ -157,7 +153,7 @@ class JaccardSimilarity(Comparator):
|
|
157
153
|
# Disable the Named Entity Recognition (NER) component because it is not necessary
|
158
154
|
self.nlp = spacy.load(model, exclude=['ner'])
|
159
155
|
|
160
|
-
def compare_text(self, text_a, text_b):
|
156
|
+
def compare_text(self, text_a: str, text_b: str) -> float:
|
161
157
|
"""
|
162
158
|
Return the calculated similarity of two
|
163
159
|
statements based on the Jaccard index.
|
chatterbot/conversation.py
CHANGED
@@ -32,7 +32,8 @@ class AbstractBaseTag(models.Model):
|
|
32
32
|
|
33
33
|
name = models.SlugField(
|
34
34
|
max_length=constants.TAG_NAME_MAX_LENGTH,
|
35
|
-
unique=True
|
35
|
+
unique=True,
|
36
|
+
help_text='The unique name of the tag.'
|
36
37
|
)
|
37
38
|
|
38
39
|
class Meta:
|
@@ -49,16 +50,19 @@ class AbstractBaseStatement(models.Model, StatementMixin):
|
|
49
50
|
"""
|
50
51
|
|
51
52
|
text = models.CharField(
|
52
|
-
max_length=constants.STATEMENT_TEXT_MAX_LENGTH
|
53
|
+
max_length=constants.STATEMENT_TEXT_MAX_LENGTH,
|
54
|
+
help_text='The text of the statement.'
|
53
55
|
)
|
54
56
|
|
55
57
|
search_text = models.CharField(
|
56
58
|
max_length=constants.STATEMENT_TEXT_MAX_LENGTH,
|
57
|
-
blank=True
|
59
|
+
blank=True,
|
60
|
+
help_text='A modified version of the statement text optimized for searching.'
|
58
61
|
)
|
59
62
|
|
60
63
|
conversation = models.CharField(
|
61
|
-
max_length=constants.CONVERSATION_LABEL_MAX_LENGTH
|
64
|
+
max_length=constants.CONVERSATION_LABEL_MAX_LENGTH,
|
65
|
+
help_text='A label used to link this statement to a conversation.'
|
62
66
|
)
|
63
67
|
|
64
68
|
created_at = models.DateTimeField(
|
@@ -68,21 +72,25 @@ class AbstractBaseStatement(models.Model, StatementMixin):
|
|
68
72
|
|
69
73
|
in_response_to = models.CharField(
|
70
74
|
max_length=constants.STATEMENT_TEXT_MAX_LENGTH,
|
71
|
-
null=True
|
75
|
+
null=True,
|
76
|
+
help_text='The text of the statement that this statement is in response to.'
|
72
77
|
)
|
73
78
|
|
74
79
|
search_in_response_to = models.CharField(
|
75
80
|
max_length=constants.STATEMENT_TEXT_MAX_LENGTH,
|
76
|
-
blank=True
|
81
|
+
blank=True,
|
82
|
+
help_text='A modified version of the in_response_to text optimized for searching.'
|
77
83
|
)
|
78
84
|
|
79
85
|
persona = models.CharField(
|
80
|
-
max_length=constants.PERSONA_MAX_LENGTH
|
86
|
+
max_length=constants.PERSONA_MAX_LENGTH,
|
87
|
+
help_text='A label used to link this statement to a persona.'
|
81
88
|
)
|
82
89
|
|
83
90
|
tags = models.ManyToManyField(
|
84
91
|
TAG_MODEL,
|
85
|
-
related_name='statements'
|
92
|
+
related_name='statements',
|
93
|
+
help_text='The tags that are associated with this statement.'
|
86
94
|
)
|
87
95
|
|
88
96
|
# This is the confidence with which the chat bot believes
|
@@ -6,3 +6,10 @@ class DjangoChatterBotConfig(AppConfig):
|
|
6
6
|
name = 'chatterbot.ext.django_chatterbot'
|
7
7
|
label = 'django_chatterbot'
|
8
8
|
verbose_name = 'Django ChatterBot'
|
9
|
+
|
10
|
+
def ready(self):
|
11
|
+
from chatterbot.ext.django_chatterbot import settings as defaults
|
12
|
+
from django.conf import settings
|
13
|
+
|
14
|
+
settings.CHATTERBOT = getattr(settings, 'CHATTERBOT', {})
|
15
|
+
settings.CHATTERBOT.update(defaults.CHATTERBOT_DEFAULTS)
|
@@ -0,0 +1,53 @@
|
|
1
|
+
# Generated by Django 4.1 on 2025-03-29 23:27
|
2
|
+
|
3
|
+
from django.db import migrations, models
|
4
|
+
|
5
|
+
|
6
|
+
class Migration(migrations.Migration):
|
7
|
+
|
8
|
+
dependencies = [
|
9
|
+
('django_chatterbot', '0019_alter_statement_id_alter_tag_id_and_more'),
|
10
|
+
]
|
11
|
+
|
12
|
+
operations = [
|
13
|
+
migrations.AlterField(
|
14
|
+
model_name='statement',
|
15
|
+
name='conversation',
|
16
|
+
field=models.CharField(help_text='A label used to link this statement to a conversation.', max_length=32),
|
17
|
+
),
|
18
|
+
migrations.AlterField(
|
19
|
+
model_name='statement',
|
20
|
+
name='in_response_to',
|
21
|
+
field=models.CharField(help_text='The text of the statement that this statement is in response to.', max_length=255, null=True),
|
22
|
+
),
|
23
|
+
migrations.AlterField(
|
24
|
+
model_name='statement',
|
25
|
+
name='persona',
|
26
|
+
field=models.CharField(help_text='A label used to link this statement to a persona.', max_length=50),
|
27
|
+
),
|
28
|
+
migrations.AlterField(
|
29
|
+
model_name='statement',
|
30
|
+
name='search_in_response_to',
|
31
|
+
field=models.CharField(blank=True, help_text='A modified version of the in_response_to text optimized for searching.', max_length=255),
|
32
|
+
),
|
33
|
+
migrations.AlterField(
|
34
|
+
model_name='statement',
|
35
|
+
name='search_text',
|
36
|
+
field=models.CharField(blank=True, help_text='A modified version of the statement text optimized for searching.', max_length=255),
|
37
|
+
),
|
38
|
+
migrations.AlterField(
|
39
|
+
model_name='statement',
|
40
|
+
name='tags',
|
41
|
+
field=models.ManyToManyField(help_text='The tags that are associated with this statement.', related_name='statements', to='django_chatterbot.tag'),
|
42
|
+
),
|
43
|
+
migrations.AlterField(
|
44
|
+
model_name='statement',
|
45
|
+
name='text',
|
46
|
+
field=models.CharField(help_text='The text of the statement.', max_length=255),
|
47
|
+
),
|
48
|
+
migrations.AlterField(
|
49
|
+
model_name='tag',
|
50
|
+
name='name',
|
51
|
+
field=models.SlugField(help_text='The unique name of the tag.', unique=True),
|
52
|
+
),
|
53
|
+
]
|
@@ -5,7 +5,7 @@ from django.conf import settings
|
|
5
5
|
from chatterbot import constants
|
6
6
|
|
7
7
|
|
8
|
-
|
8
|
+
CHATTERBOT = getattr(settings, 'CHATTERBOT', {})
|
9
9
|
|
10
10
|
CHATTERBOT_DEFAULTS = {
|
11
11
|
'name': 'ChatterBot',
|
@@ -13,5 +13,4 @@ CHATTERBOT_DEFAULTS = {
|
|
13
13
|
'django_app_name': constants.DEFAULT_DJANGO_APP_NAME
|
14
14
|
}
|
15
15
|
|
16
|
-
CHATTERBOT
|
17
|
-
CHATTERBOT.update(CHATTERBOT_SETTINGS)
|
16
|
+
CHATTERBOT.update(CHATTERBOT_DEFAULTS)
|
@@ -4,6 +4,7 @@ from chatterbot.adapters import Adapter
|
|
4
4
|
from chatterbot.storage import StorageAdapter
|
5
5
|
from chatterbot.search import IndexedTextSearch
|
6
6
|
from chatterbot.conversation import Statement
|
7
|
+
from chatterbot import utils
|
7
8
|
|
8
9
|
|
9
10
|
class LogicAdapter(Adapter):
|
@@ -28,7 +29,7 @@ class LogicAdapter(Adapter):
|
|
28
29
|
:type response_selection_method: collections.abc.Callable
|
29
30
|
|
30
31
|
:param default_response:
|
31
|
-
The default response returned by this logic
|
32
|
+
The default response returned by this logic adapter
|
32
33
|
if there is no other possible response to return.
|
33
34
|
:type default_response: str or list or tuple
|
34
35
|
"""
|
@@ -50,6 +51,14 @@ class LogicAdapter(Adapter):
|
|
50
51
|
'maximum_similarity_threshold', 0.95
|
51
52
|
)
|
52
53
|
|
54
|
+
if response_selection_method := kwargs.get('response_selection_method'):
|
55
|
+
if isinstance(response_selection_method, str):
|
56
|
+
# If an import path is provided, import the method
|
57
|
+
response_selection_method = utils.import_module(
|
58
|
+
response_selection_method
|
59
|
+
)
|
60
|
+
kwargs['response_selection_method'] = response_selection_method
|
61
|
+
|
53
62
|
# By default, select the first available response
|
54
63
|
self.select_response = kwargs.get(
|
55
64
|
'response_selection_method',
|
@@ -68,18 +77,16 @@ class LogicAdapter(Adapter):
|
|
68
77
|
Statement(text=default) for default in default_responses
|
69
78
|
]
|
70
79
|
|
71
|
-
def can_process(self, statement):
|
80
|
+
def can_process(self, statement) -> bool:
|
72
81
|
"""
|
73
82
|
A preliminary check that is called to determine if a
|
74
83
|
logic adapter can process a given statement. By default,
|
75
84
|
this method returns true but it can be overridden in
|
76
85
|
child classes as needed.
|
77
|
-
|
78
|
-
:rtype: bool
|
79
86
|
"""
|
80
87
|
return True
|
81
88
|
|
82
|
-
def process(self, statement, additional_response_selection_parameters=None):
|
89
|
+
def process(self, statement, additional_response_selection_parameters=None) -> Statement:
|
83
90
|
"""
|
84
91
|
Override this method and implement your logic for selecting a response to an input statement.
|
85
92
|
|
@@ -97,12 +104,10 @@ class LogicAdapter(Adapter):
|
|
97
104
|
:param additional_response_selection_parameters: Parameters to be used when
|
98
105
|
filtering results to choose a response from.
|
99
106
|
:type additional_response_selection_parameters: dict
|
100
|
-
|
101
|
-
:rtype: Statement
|
102
107
|
"""
|
103
108
|
raise self.AdapterMethodNotImplementedError()
|
104
109
|
|
105
|
-
def get_default_response(self, input_statement):
|
110
|
+
def get_default_response(self, input_statement: Statement) -> Statement:
|
106
111
|
"""
|
107
112
|
This method is called when a logic adapter is unable to generate any
|
108
113
|
other meaningful response.
|
@@ -125,7 +130,7 @@ class LogicAdapter(Adapter):
|
|
125
130
|
return response
|
126
131
|
|
127
132
|
@property
|
128
|
-
def class_name(self):
|
133
|
+
def class_name(self) -> str:
|
129
134
|
"""
|
130
135
|
Return the name of the current logic adapter class.
|
131
136
|
This is typically used for logging and debugging.
|
chatterbot/preprocessors.py
CHANGED
@@ -1,12 +1,13 @@
|
|
1
1
|
"""
|
2
2
|
Statement pre-processors.
|
3
3
|
"""
|
4
|
+
from chatterbot.conversation import Statement
|
4
5
|
from unicodedata import normalize
|
5
6
|
from re import sub as re_sub
|
6
7
|
from html import unescape
|
7
8
|
|
8
9
|
|
9
|
-
def clean_whitespace(statement):
|
10
|
+
def clean_whitespace(statement: Statement) -> Statement:
|
10
11
|
"""
|
11
12
|
Remove any consecutive whitespace characters from the statement text.
|
12
13
|
"""
|
@@ -24,7 +25,7 @@ def clean_whitespace(statement):
|
|
24
25
|
return statement
|
25
26
|
|
26
27
|
|
27
|
-
def unescape_html(statement):
|
28
|
+
def unescape_html(statement: Statement) -> Statement:
|
28
29
|
"""
|
29
30
|
Convert escaped html characters into unescaped html characters.
|
30
31
|
For example: "<b>" becomes "<b>".
|
@@ -34,7 +35,7 @@ def unescape_html(statement):
|
|
34
35
|
return statement
|
35
36
|
|
36
37
|
|
37
|
-
def convert_to_ascii(statement):
|
38
|
+
def convert_to_ascii(statement: Statement) -> Statement:
|
38
39
|
"""
|
39
40
|
Converts unicode characters to ASCII character equivalents.
|
40
41
|
For example: "på fédéral" becomes "pa federal".
|
chatterbot/response_selection.py
CHANGED
@@ -2,10 +2,11 @@
|
|
2
2
|
Response selection methods determines which response should be used in
|
3
3
|
the event that multiple responses are generated within a logic adapter.
|
4
4
|
"""
|
5
|
+
from chatterbot.conversation import Statement
|
5
6
|
import logging
|
6
7
|
|
7
8
|
|
8
|
-
def get_most_frequent_response(input_statement, response_list, storage=None):
|
9
|
+
def get_most_frequent_response(input_statement, response_list, storage=None) -> Statement:
|
9
10
|
"""
|
10
11
|
:param input_statement: A statement, that closely matches an input to the chat bot.
|
11
12
|
:type input_statement: Statement
|
@@ -18,7 +19,6 @@ def get_most_frequent_response(input_statement, response_list, storage=None):
|
|
18
19
|
:type storage: StorageAdapter
|
19
20
|
|
20
21
|
:return: The response statement with the greatest number of occurrences.
|
21
|
-
:rtype: Statement
|
22
22
|
"""
|
23
23
|
matching_response = None
|
24
24
|
occurrence_count = -1
|
@@ -41,7 +41,7 @@ def get_most_frequent_response(input_statement, response_list, storage=None):
|
|
41
41
|
return matching_response
|
42
42
|
|
43
43
|
|
44
|
-
def get_first_response(input_statement, response_list, storage=None):
|
44
|
+
def get_first_response(input_statement, response_list, storage=None) -> Statement:
|
45
45
|
"""
|
46
46
|
:param input_statement: A statement, that closely matches an input to the chat bot.
|
47
47
|
:type input_statement: Statement
|
@@ -54,7 +54,6 @@ def get_first_response(input_statement, response_list, storage=None):
|
|
54
54
|
:type storage: StorageAdapter
|
55
55
|
|
56
56
|
:return: Return the first statement in the response list.
|
57
|
-
:rtype: Statement
|
58
57
|
"""
|
59
58
|
logger = logging.getLogger(__name__)
|
60
59
|
logger.info('Selecting first response from list of {} options.'.format(
|
@@ -63,7 +62,7 @@ def get_first_response(input_statement, response_list, storage=None):
|
|
63
62
|
return response_list[0]
|
64
63
|
|
65
64
|
|
66
|
-
def get_random_response(input_statement, response_list, storage=None):
|
65
|
+
def get_random_response(input_statement, response_list, storage=None) -> Statement:
|
67
66
|
"""
|
68
67
|
:param input_statement: A statement, that closely matches an input to the chat bot.
|
69
68
|
:type input_statement: Statement
|
@@ -76,7 +75,6 @@ def get_random_response(input_statement, response_list, storage=None):
|
|
76
75
|
:type storage: StorageAdapter
|
77
76
|
|
78
77
|
:return: Choose a random response from the selection.
|
79
|
-
:rtype: Statement
|
80
78
|
"""
|
81
79
|
from random import choice
|
82
80
|
logger = logging.getLogger(__name__)
|
@@ -110,6 +110,9 @@ class DjangoStorageAdapter(StorageAdapter):
|
|
110
110
|
|
111
111
|
tags = kwargs.pop('tags', [])
|
112
112
|
|
113
|
+
if 'search_in_response_to' in kwargs and kwargs['search_in_response_to'] is None:
|
114
|
+
kwargs['search_in_response_to'] = ''
|
115
|
+
|
113
116
|
statement = Statement(**kwargs)
|
114
117
|
|
115
118
|
statement.save()
|
@@ -169,7 +172,7 @@ class DjangoStorageAdapter(StorageAdapter):
|
|
169
172
|
search_text=statement.search_text,
|
170
173
|
conversation=statement.conversation,
|
171
174
|
in_response_to=statement.in_response_to,
|
172
|
-
search_in_response_to=statement.search_in_response_to,
|
175
|
+
search_in_response_to=statement.search_in_response_to or '',
|
173
176
|
created_at=statement.created_at
|
174
177
|
)
|
175
178
|
|
@@ -44,7 +44,7 @@ class SQLStorageAdapter(StorageAdapter):
|
|
44
44
|
dbapi_connection.execute('PRAGMA journal_mode=WAL')
|
45
45
|
dbapi_connection.execute('PRAGMA synchronous=NORMAL')
|
46
46
|
|
47
|
-
if not inspect(self.engine).has_table(
|
47
|
+
if not inspect(self.engine).has_table('statement'):
|
48
48
|
self.create_database()
|
49
49
|
|
50
50
|
# Check if the expected index exists on the text field of the statement table
|
chatterbot/tagging.py
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
from typing import List, Union, Tuple
|
1
2
|
from chatterbot import languages
|
2
3
|
from chatterbot.utils import get_model_for_language
|
3
4
|
import spacy
|
@@ -20,7 +21,7 @@ class LowercaseTagger(object):
|
|
20
21
|
'chatterbot_lowercase_indexer', name='chatterbot_lowercase_indexer', last=True
|
21
22
|
)
|
22
23
|
|
23
|
-
def get_text_index_string(self, text):
|
24
|
+
def get_text_index_string(self, text: Union[str, List[str]]):
|
24
25
|
if isinstance(text, list):
|
25
26
|
documents = self.nlp.pipe(text)
|
26
27
|
return [document._.search_index for document in documents]
|
@@ -28,7 +29,7 @@ class LowercaseTagger(object):
|
|
28
29
|
document = self.nlp(text)
|
29
30
|
return document._.search_index
|
30
31
|
|
31
|
-
def as_nlp_pipeline(self, texts):
|
32
|
+
def as_nlp_pipeline(self, texts: Union[List[str], Tuple[str, dict]]):
|
32
33
|
|
33
34
|
process_as_tuples = texts and isinstance(texts[0], tuple)
|
34
35
|
|
@@ -52,7 +53,7 @@ class PosLemmaTagger(object):
|
|
52
53
|
'chatterbot_bigram_indexer', name='chatterbot_bigram_indexer', last=True
|
53
54
|
)
|
54
55
|
|
55
|
-
def get_text_index_string(self, text):
|
56
|
+
def get_text_index_string(self, text: Union[str, List[str]]):
|
56
57
|
"""
|
57
58
|
Return a string of text containing part-of-speech, lemma pairs.
|
58
59
|
"""
|
@@ -63,7 +64,7 @@ class PosLemmaTagger(object):
|
|
63
64
|
document = self.nlp(text)
|
64
65
|
return document._.search_index
|
65
66
|
|
66
|
-
def as_nlp_pipeline(self, texts):
|
67
|
+
def as_nlp_pipeline(self, texts: Union[List[str], Tuple[str, dict]]):
|
67
68
|
"""
|
68
69
|
Accepts a single string or a list of strings, or a list of tuples
|
69
70
|
where the first element is the text and the second element is a
|
chatterbot/trainers.py
CHANGED
@@ -1,12 +1,13 @@
|
|
1
1
|
import os
|
2
|
-
import sys
|
3
2
|
import csv
|
4
3
|
import time
|
5
4
|
import glob
|
6
5
|
import json
|
7
6
|
import tarfile
|
7
|
+
from typing import List, Union
|
8
8
|
from tqdm import tqdm
|
9
9
|
from dateutil import parser as date_parser
|
10
|
+
from chatterbot.chatterbot import ChatBot
|
10
11
|
from chatterbot.conversation import Statement
|
11
12
|
|
12
13
|
|
@@ -20,7 +21,7 @@ class Trainer(object):
|
|
20
21
|
the environment variable if it is set.
|
21
22
|
"""
|
22
23
|
|
23
|
-
def __init__(self, chatbot, **kwargs):
|
24
|
+
def __init__(self, chatbot: ChatBot, **kwargs):
|
24
25
|
self.chatbot = chatbot
|
25
26
|
|
26
27
|
environment_default = bool(int(os.environ.get('CHATTERBOT_SHOW_TRAINING_PROGRESS', True)))
|
@@ -30,7 +31,7 @@ class Trainer(object):
|
|
30
31
|
environment_default
|
31
32
|
)
|
32
33
|
|
33
|
-
def get_preprocessed_statement(self, input_statement):
|
34
|
+
def get_preprocessed_statement(self, input_statement: Statement) -> Statement:
|
34
35
|
"""
|
35
36
|
Preprocess the input statement.
|
36
37
|
"""
|
@@ -58,7 +59,7 @@ class Trainer(object):
|
|
58
59
|
)
|
59
60
|
super().__init__(message or default)
|
60
61
|
|
61
|
-
def _generate_export_data(self):
|
62
|
+
def _generate_export_data(self) -> list:
|
62
63
|
result = []
|
63
64
|
for statement in self.chatbot.storage.filter():
|
64
65
|
if statement.in_response_to:
|
@@ -82,7 +83,7 @@ class ListTrainer(Trainer):
|
|
82
83
|
where the list represents a conversation.
|
83
84
|
"""
|
84
85
|
|
85
|
-
def train(self, conversation:
|
86
|
+
def train(self, conversation: List[str]):
|
86
87
|
"""
|
87
88
|
Train the chat bot based on the provided list of
|
88
89
|
statements that represents a single conversation.
|
@@ -95,7 +96,6 @@ class ListTrainer(Trainer):
|
|
95
96
|
# Run the pipeline in bulk to improve performance
|
96
97
|
documents = self.chatbot.tagger.as_nlp_pipeline(conversation)
|
97
98
|
|
98
|
-
# for text in enumerate(conversation):
|
99
99
|
for document in tqdm(documents, desc='List Trainer', disable=self.disable_progress):
|
100
100
|
statement_search_text = document._.search_index
|
101
101
|
|
@@ -123,7 +123,7 @@ class ChatterBotCorpusTrainer(Trainer):
|
|
123
123
|
ChatterBot dialog corpus.
|
124
124
|
"""
|
125
125
|
|
126
|
-
def train(self, *corpus_paths):
|
126
|
+
def train(self, *corpus_paths: Union[str, List[str]]):
|
127
127
|
from chatterbot.corpus import load_corpus, list_corpus_files
|
128
128
|
|
129
129
|
data_file_paths = []
|
@@ -178,7 +178,17 @@ class GenericFileTrainer(Trainer):
|
|
178
178
|
or directory of those file types.
|
179
179
|
"""
|
180
180
|
|
181
|
-
|
181
|
+
# NOTE: If the value is an integer, this be the
|
182
|
+
# column index instead of the key or header
|
183
|
+
DEFAULT_STATEMENT_TO_HEADER_MAPPING = {
|
184
|
+
'text': 'text',
|
185
|
+
'conversation': 'conversation',
|
186
|
+
'created_at': 'created_at',
|
187
|
+
'persona': 'persona',
|
188
|
+
'tags': 'tags'
|
189
|
+
}
|
190
|
+
|
191
|
+
def __init__(self, chatbot: ChatBot, **kwargs):
|
182
192
|
"""
|
183
193
|
data_path: str The path to the data file or directory.
|
184
194
|
field_map: dict A dictionary containing the column name to header mapping.
|
@@ -187,22 +197,12 @@ class GenericFileTrainer(Trainer):
|
|
187
197
|
|
188
198
|
self.file_extension = None
|
189
199
|
|
190
|
-
# NOTE: If the key is an integer, this be the
|
191
|
-
# column index instead of the key or header
|
192
|
-
DEFAULT_STATEMENT_TO_HEADER_MAPPING = {
|
193
|
-
'text': 'text',
|
194
|
-
'conversation': 'conversation',
|
195
|
-
'created_at': 'created_at',
|
196
|
-
'persona': 'persona',
|
197
|
-
'tags': 'tags'
|
198
|
-
}
|
199
|
-
|
200
200
|
self.field_map = kwargs.get(
|
201
201
|
'field_map',
|
202
|
-
DEFAULT_STATEMENT_TO_HEADER_MAPPING
|
202
|
+
self.DEFAULT_STATEMENT_TO_HEADER_MAPPING
|
203
203
|
)
|
204
204
|
|
205
|
-
def _get_file_list(self, data_path, limit):
|
205
|
+
def _get_file_list(self, data_path: str, limit: Union[int, None]):
|
206
206
|
"""
|
207
207
|
Get a list of files to read from the data set.
|
208
208
|
"""
|
@@ -210,7 +210,7 @@ class GenericFileTrainer(Trainer):
|
|
210
210
|
if self.file_extension is None:
|
211
211
|
raise self.TrainerInitializationException(
|
212
212
|
'The file_extension attribute must be set before calling train().'
|
213
|
-
)
|
213
|
+
)
|
214
214
|
|
215
215
|
# List all csv or json files in the specified directory
|
216
216
|
if os.path.isdir(data_path):
|
@@ -226,7 +226,7 @@ class GenericFileTrainer(Trainer):
|
|
226
226
|
|
227
227
|
yield file_path
|
228
228
|
else:
|
229
|
-
|
229
|
+
yield data_path
|
230
230
|
|
231
231
|
def train(self, data_path: str, limit=None):
|
232
232
|
"""
|
@@ -254,7 +254,9 @@ class GenericFileTrainer(Trainer):
|
|
254
254
|
|
255
255
|
statements_to_create = []
|
256
256
|
|
257
|
-
|
257
|
+
file_abspath = os.path.abspath(data_file)
|
258
|
+
|
259
|
+
with open(file_abspath, 'r', encoding='utf-8') as file:
|
258
260
|
|
259
261
|
if self.file_extension == 'json':
|
260
262
|
data = json.load(file)
|
@@ -281,18 +283,39 @@ class GenericFileTrainer(Trainer):
|
|
281
283
|
|
282
284
|
text_row = self.field_map['text']
|
283
285
|
|
284
|
-
|
286
|
+
try:
|
287
|
+
documents = self.chatbot.tagger.as_nlp_pipeline([
|
288
|
+
(
|
289
|
+
row[text_row],
|
290
|
+
{
|
291
|
+
# Include any defined metadata columns
|
292
|
+
key: row[value]
|
293
|
+
for key, value in self.field_map.items()
|
294
|
+
if key != text_row
|
295
|
+
}
|
296
|
+
) for row in data if len(row) > 0
|
297
|
+
])
|
298
|
+
except KeyError as e:
|
299
|
+
raise KeyError(
|
300
|
+
f'{e}. Please check the field_map parameter used to initialize '
|
301
|
+
f'the training class and remove this value if it is not needed. '
|
302
|
+
f'Current mapping: {self.field_map}'
|
303
|
+
)
|
304
|
+
|
305
|
+
response_to_search_index_mapping = {}
|
306
|
+
|
307
|
+
if 'in_response_to' in self.field_map.keys():
|
308
|
+
# Generate the search_in_response_to value for the in_response_to fields
|
309
|
+
response_documents = self.chatbot.tagger.as_nlp_pipeline([
|
285
310
|
(
|
286
|
-
row[
|
287
|
-
|
288
|
-
# Include any defined metadata columns
|
289
|
-
key: row[value]
|
290
|
-
for key, value in self.field_map.items()
|
291
|
-
if key != text_row
|
292
|
-
}
|
293
|
-
) for row in data if len(row) > 0
|
311
|
+
row[self.field_map['in_response_to']]
|
312
|
+
) for row in data if len(row) > 0 and row[self.field_map['in_response_to']] is not None
|
294
313
|
])
|
295
314
|
|
315
|
+
# (Process the response values the same way as the text values)
|
316
|
+
for document in response_documents:
|
317
|
+
response_to_search_index_mapping[document.text] = document._.search_index
|
318
|
+
|
296
319
|
for document, context in documents:
|
297
320
|
statement = Statement(
|
298
321
|
text=document.text,
|
@@ -305,14 +328,19 @@ class GenericFileTrainer(Trainer):
|
|
305
328
|
statement.created_at = date_parser.parse(context['created_at'])
|
306
329
|
|
307
330
|
statement.search_text = document._.search_index
|
308
|
-
statement.search_in_response_to = previous_statement_search_text
|
309
331
|
|
310
332
|
# Use the in_response_to attribute for the previous statement if
|
311
333
|
# one is defined, otherwise use the last statement which was created
|
312
334
|
if 'in_response_to' in self.field_map.keys():
|
313
335
|
statement.in_response_to = context.get(self.field_map['in_response_to'], None)
|
336
|
+
statement.search_in_response_to = response_to_search_index_mapping.get(
|
337
|
+
context.get(self.field_map['in_response_to'], None), ''
|
338
|
+
)
|
314
339
|
else:
|
340
|
+
# List-type data such as CSVs with no response specified can use
|
341
|
+
# the previous statement as the in_response_to value
|
315
342
|
statement.in_response_to = previous_statement_text
|
343
|
+
statement.search_in_response_to = previous_statement_search_text
|
316
344
|
|
317
345
|
for preprocessor in self.chatbot.preprocessors:
|
318
346
|
statement = preprocessor(statement)
|
@@ -336,7 +364,6 @@ class GenericFileTrainer(Trainer):
|
|
336
364
|
)
|
337
365
|
)
|
338
366
|
|
339
|
-
|
340
367
|
class CsvFileTrainer(GenericFileTrainer):
|
341
368
|
"""
|
342
369
|
.. note::
|
@@ -349,11 +376,11 @@ class CsvFileTrainer(GenericFileTrainer):
|
|
349
376
|
parameter is set to 'tsv'.
|
350
377
|
|
351
378
|
:param str file_extension: The file extension to look for when searching for files (defaults to 'csv').
|
352
|
-
:param
|
379
|
+
:param dict field_map: A dictionary containing the database column name to header mapping.
|
353
380
|
Values can be either the header name (str) or the column index (int).
|
354
381
|
"""
|
355
382
|
|
356
|
-
def __init__(self, chatbot, **kwargs):
|
383
|
+
def __init__(self, chatbot: ChatBot, **kwargs):
|
357
384
|
super().__init__(chatbot, **kwargs)
|
358
385
|
|
359
386
|
self.file_extension = kwargs.get('file_extension', 'csv')
|
@@ -367,26 +394,26 @@ class JsonFileTrainer(GenericFileTrainer):
|
|
367
394
|
Allow chatbots to be trained with data from a JSON file or
|
368
395
|
directory of JSON files.
|
369
396
|
|
370
|
-
:param
|
397
|
+
:param dict field_map: A dictionary containing the database column name to header mapping.
|
371
398
|
"""
|
372
399
|
|
373
|
-
|
400
|
+
DEFAULT_STATEMENT_TO_KEY_MAPPING = {
|
401
|
+
'text': 'text',
|
402
|
+
'conversation': 'conversation',
|
403
|
+
'created_at': 'created_at',
|
404
|
+
'in_response_to': 'in_response_to',
|
405
|
+
'persona': 'persona',
|
406
|
+
'tags': 'tags'
|
407
|
+
}
|
408
|
+
|
409
|
+
def __init__(self, chatbot: ChatBot, **kwargs):
|
374
410
|
super().__init__(chatbot, **kwargs)
|
375
411
|
|
376
412
|
self.file_extension = 'json'
|
377
413
|
|
378
|
-
DEFAULT_STATEMENT_TO_KEY_MAPPING = {
|
379
|
-
'text': 'text',
|
380
|
-
'conversation': 'conversation',
|
381
|
-
'created_at': 'created_at',
|
382
|
-
'in_response_to': 'in_response_to',
|
383
|
-
'persona': 'persona',
|
384
|
-
'tags': 'tags'
|
385
|
-
}
|
386
|
-
|
387
414
|
self.field_map = kwargs.get(
|
388
415
|
'field_map',
|
389
|
-
DEFAULT_STATEMENT_TO_KEY_MAPPING
|
416
|
+
self.DEFAULT_STATEMENT_TO_KEY_MAPPING
|
390
417
|
)
|
391
418
|
|
392
419
|
|
@@ -403,7 +430,7 @@ class UbuntuCorpusTrainer(CsvFileTrainer):
|
|
403
430
|
:param str ubuntu_corpus_data_directory: The directory where the Ubuntu corpus data is already located, or where it should be downloaded and extracted.
|
404
431
|
"""
|
405
432
|
|
406
|
-
def __init__(self, chatbot, **kwargs):
|
433
|
+
def __init__(self, chatbot: ChatBot, **kwargs):
|
407
434
|
super().__init__(chatbot, **kwargs)
|
408
435
|
home_directory = os.path.expanduser('~')
|
409
436
|
|
@@ -425,7 +452,7 @@ class UbuntuCorpusTrainer(CsvFileTrainer):
|
|
425
452
|
'persona': 1,
|
426
453
|
}
|
427
454
|
|
428
|
-
def is_downloaded(self, file_path):
|
455
|
+
def is_downloaded(self, file_path: str):
|
429
456
|
"""
|
430
457
|
Check if the data file is already downloaded.
|
431
458
|
"""
|
@@ -435,7 +462,7 @@ class UbuntuCorpusTrainer(CsvFileTrainer):
|
|
435
462
|
|
436
463
|
return False
|
437
464
|
|
438
|
-
def is_extracted(self, file_path):
|
465
|
+
def is_extracted(self, file_path: str):
|
439
466
|
"""
|
440
467
|
Check if the data file is already extracted.
|
441
468
|
"""
|
@@ -445,7 +472,7 @@ class UbuntuCorpusTrainer(CsvFileTrainer):
|
|
445
472
|
return True
|
446
473
|
return False
|
447
474
|
|
448
|
-
def download(self, url, show_status=True):
|
475
|
+
def download(self, url: str, show_status=True):
|
449
476
|
"""
|
450
477
|
Download a file from the given url.
|
451
478
|
Show a progress indicator for the download status.
|
@@ -484,7 +511,7 @@ class UbuntuCorpusTrainer(CsvFileTrainer):
|
|
484
511
|
print('Download location: %s' % file_path)
|
485
512
|
return file_path
|
486
513
|
|
487
|
-
def extract(self, file_path):
|
514
|
+
def extract(self, file_path: str):
|
488
515
|
"""
|
489
516
|
Extract a tar file at the specified file path.
|
490
517
|
"""
|
@@ -524,7 +551,7 @@ class UbuntuCorpusTrainer(CsvFileTrainer):
|
|
524
551
|
|
525
552
|
return True
|
526
553
|
|
527
|
-
def _get_file_list(self, data_path, limit):
|
554
|
+
def _get_file_list(self, data_path: str, limit: Union[int, None]):
|
528
555
|
"""
|
529
556
|
Get a list of files to read from the data set.
|
530
557
|
"""
|
@@ -555,7 +582,7 @@ class UbuntuCorpusTrainer(CsvFileTrainer):
|
|
555
582
|
|
556
583
|
yield file_path
|
557
584
|
|
558
|
-
def train(self, data_download_url, limit=None):
|
585
|
+
def train(self, data_download_url: str, limit: Union[int, None] = None):
|
559
586
|
"""
|
560
587
|
:param str data_download_url: The URL to download the Ubuntu dialog corpus from.
|
561
588
|
:param int limit: The maximum number of files to train from.
|
chatterbot/utils.py
CHANGED
@@ -3,7 +3,6 @@ ChatterBot utility functions
|
|
3
3
|
"""
|
4
4
|
import importlib
|
5
5
|
import time
|
6
|
-
import sys
|
7
6
|
|
8
7
|
|
9
8
|
def import_module(dotted_path):
|
@@ -71,7 +70,7 @@ def validate_adapter_class(validate_class, adapter_class):
|
|
71
70
|
)
|
72
71
|
|
73
72
|
|
74
|
-
def get_response_time(chatbot, statement='Hello'):
|
73
|
+
def get_response_time(chatbot, statement='Hello') -> float:
|
75
74
|
"""
|
76
75
|
Returns the amount of time taken for a given
|
77
76
|
chat bot to return a response.
|
@@ -80,7 +79,6 @@ def get_response_time(chatbot, statement='Hello'):
|
|
80
79
|
:type chatbot: ChatBot
|
81
80
|
|
82
81
|
:returns: The response time in seconds.
|
83
|
-
:rtype: float
|
84
82
|
"""
|
85
83
|
start_time = time.time()
|
86
84
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: ChatterBot
|
3
|
-
Version: 1.2.
|
3
|
+
Version: 1.2.6
|
4
4
|
Summary: ChatterBot is a machine learning, conversational dialog engine
|
5
5
|
Author: Gunther Cox
|
6
6
|
License-Expression: BSD-3-Clause
|
@@ -66,10 +66,11 @@ known conversations. The language independent design of ChatterBot allows it
|
|
66
66
|
to be trained to speak any language.
|
67
67
|
|
68
68
|
[](https://pypi.python.org/pypi/chatterbot/)
|
69
|
-
[](https://www.python.org/downloads/release/python-360/)
|
70
70
|
[](https://coveralls.io/r/gunthercox/ChatterBot)
|
71
|
-
[](https://bsky.app/profile/chatterbot.us)
|
72
72
|
[](https://gitter.im/chatterbot/Lobby?utm_source=badge&utm_medium=badge&utm_content=badge)
|
73
|
+
<!-- [](https://codeclimate.com/github/gunthercox/ChatterBot) -->
|
73
74
|
|
74
75
|
An example of typical input would be something like this:
|
75
76
|
|
@@ -1,31 +1,31 @@
|
|
1
|
-
chatterbot/__init__.py,sha256=
|
1
|
+
chatterbot/__init__.py,sha256=wHoKxLsCOplHJ02JmxRCg5cRL-Z-blQblhJKdE95Pck,158
|
2
2
|
chatterbot/__main__.py,sha256=zvH4uxtGlGrP-ht_LkhX29duzjm3hRH800SDCq4YOwg,637
|
3
3
|
chatterbot/adapters.py,sha256=LJ_KqLpHKPdYAFpMGK63RVH4weV5X0Zh5uGyan6qdVU,878
|
4
|
-
chatterbot/chatterbot.py,sha256=
|
5
|
-
chatterbot/comparisons.py,sha256=
|
4
|
+
chatterbot/chatterbot.py,sha256=nqxdeTBWdA_LDIEWTMf2gphvpNfd0c9htNwrxa_7pzo,12543
|
5
|
+
chatterbot/comparisons.py,sha256=kYYR5DUipdzr7ok08m8s6r9LBez4GBQICaSmLZcmoiM,6184
|
6
6
|
chatterbot/components.py,sha256=ld3Xam8olBClvE5QqcFYggE7Q7tODCFek7BO7lhfyeU,1782
|
7
7
|
chatterbot/constants.py,sha256=c_KPQKc82CHX6H3maeyTYqWatx6j-N-8HJhmejoVi60,1875
|
8
|
-
chatterbot/conversation.py,sha256
|
8
|
+
chatterbot/conversation.py,sha256=-JshXr4Uvsl8NVeEgm1am2e4UStBN1BXfMQHYkQFvco,3162
|
9
9
|
chatterbot/corpus.py,sha256=n1sFU0KF-oRdj7g3nXft7uHOVilwbj_mVZnaeIHgC54,2409
|
10
10
|
chatterbot/exceptions.py,sha256=gqAlckDna6SB53kyqutmCtCqWxia40WBdUOnGVQ2Kbk,163
|
11
11
|
chatterbot/filters.py,sha256=vDSDJz2FM10xT6ybs7qJiqy4X5I4gTEfwEnjBGUxZ9g,847
|
12
12
|
chatterbot/languages.py,sha256=XSenfc5FxHk_JWG5gGHsZvjvrPBbCaVCm_OU-BeER_M,32784
|
13
13
|
chatterbot/parsing.py,sha256=vS-w70cMkjq4YEpDOv_pXWhAI6Zj06WYDAcMDhYDj0M,23174
|
14
|
-
chatterbot/preprocessors.py,sha256=
|
15
|
-
chatterbot/response_selection.py,sha256=
|
14
|
+
chatterbot/preprocessors.py,sha256=kqsgnejSj6Z1rr9U2TGHKOp-MMaFWBdNT41EwyhQFls,1389
|
15
|
+
chatterbot/response_selection.py,sha256=JpUVuBYrgxhHkDMRHXyWvhluSLxQED5mAhE1-VvJSmg,2970
|
16
16
|
chatterbot/search.py,sha256=FTwwON2eKPWqoc5uoKh4AUmuXDCqyfMcMcXB4wijpxg,4910
|
17
|
-
chatterbot/tagging.py,sha256=
|
18
|
-
chatterbot/trainers.py,sha256=
|
19
|
-
chatterbot/utils.py,sha256=
|
17
|
+
chatterbot/tagging.py,sha256=si0PQ3CY5EbiZ0-PIslbBtExZaQZ3NYrLUGoourweKo,2585
|
18
|
+
chatterbot/trainers.py,sha256=CZezNX68Byg9gg2z-PUZbTc5pqzTzbhgSmqHx7P6Ivg,20973
|
19
|
+
chatterbot/utils.py,sha256=ubPiBapvUvdFVhrDjxqq5IGekUh9qMUJs_dQ605xLAI,2924
|
20
20
|
chatterbot/vectorstores.py,sha256=-S1NB8PrZzoFIu95n2W7N4UaXuCUpyDUXIGYFebjv08,2056
|
21
21
|
chatterbot/ext/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
22
22
|
chatterbot/ext/django_chatterbot/__init__.py,sha256=iWzmBzpAsYwkwi1faxAPFY9L1bbL97RgVXK2uqULIMc,92
|
23
|
-
chatterbot/ext/django_chatterbot/abstract_models.py,sha256=
|
23
|
+
chatterbot/ext/django_chatterbot/abstract_models.py,sha256=skMqOqxIL_xOyfU8ZabtDqzUKTz0YtqGkaylB3TC1JA,3883
|
24
24
|
chatterbot/ext/django_chatterbot/admin.py,sha256=jyCJGLRcRoeaoYWZFv-TCivcDUNTE4Li7pmYE8_hYCM,266
|
25
|
-
chatterbot/ext/django_chatterbot/apps.py,sha256=
|
25
|
+
chatterbot/ext/django_chatterbot/apps.py,sha256=YSqF77pD9Pl2-BP6KeQZRr22XhL8gInpHVkVTLtZsUU,464
|
26
26
|
chatterbot/ext/django_chatterbot/model_admin.py,sha256=aJVE6u1fquMrvFTm_0aclK6FSAcUtfZcj-RPnXmm6iM,353
|
27
27
|
chatterbot/ext/django_chatterbot/models.py,sha256=GqIXvDxSRKaeFgAVh71t9MRS6qEAIOUQ8a42I4wBxYs,360
|
28
|
-
chatterbot/ext/django_chatterbot/settings.py,sha256=
|
28
|
+
chatterbot/ext/django_chatterbot/settings.py,sha256=CBPnTLCIrznPm_YHd0-ss8E_gzRrydujBX37gI0G0gA,381
|
29
29
|
chatterbot/ext/django_chatterbot/migrations/0001_initial.py,sha256=mZQYculJOOVyo9QdSlnbT3Bp_B5_e7y81aEyRQjfRgQ,1266
|
30
30
|
chatterbot/ext/django_chatterbot/migrations/0002_statement_extra_data.py,sha256=hbMubk-eBsseP8QZ5pxt13jrxP5e5RJyEFOqxxk5Tzk,441
|
31
31
|
chatterbot/ext/django_chatterbot/migrations/0003_change_occurrence_default.py,sha256=maDz1Y9F5oTeCFotQdk7Tf-hpkjWVUqiDVXP4nQJTNg,408
|
@@ -45,24 +45,25 @@ chatterbot/ext/django_chatterbot/migrations/0016_statement_stemmed_text.py,sha25
|
|
45
45
|
chatterbot/ext/django_chatterbot/migrations/0017_tags_unique.py,sha256=3RGCsV9fAFAYjuyHbGVUXFdzvT3fj9FAKoNZmyfaR9M,692
|
46
46
|
chatterbot/ext/django_chatterbot/migrations/0018_text_max_length.py,sha256=508TxWE8xGff1jKExxxBj9Ulu9Exz6rWDHnNxFli2xU,876
|
47
47
|
chatterbot/ext/django_chatterbot/migrations/0019_alter_statement_id_alter_tag_id_and_more.py,sha256=rsVxwDFMQ-cU1KMhjDq9Wcl_6gTPKc_dc3p-gv_R7v8,999
|
48
|
+
chatterbot/ext/django_chatterbot/migrations/0020_alter_statement_conversation_and_more.py,sha256=PpcIvl6sO9jNBxW4UgvFMv_j0eNmUBHire5qo7u-XAg,2133
|
48
49
|
chatterbot/ext/django_chatterbot/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
49
50
|
chatterbot/ext/sqlalchemy_app/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
50
51
|
chatterbot/ext/sqlalchemy_app/models.py,sha256=ZQ-R_5rA-f1agaqYGUQhuuO7zx__BvTDUvJo5R7ZrDY,2492
|
51
52
|
chatterbot/logic/__init__.py,sha256=28-5swBCPfSVMl8xB5C8frOKZ2oj28rQfenbd9E4r-4,531
|
52
53
|
chatterbot/logic/best_match.py,sha256=8TNW0uZ_Uq-XPfaZUMUZDVH6KzDT65j59xblxQBv-dQ,4820
|
53
|
-
chatterbot/logic/logic_adapter.py,sha256=
|
54
|
+
chatterbot/logic/logic_adapter.py,sha256=zcYrzyywZ0kT3GsjcMRr69abvswurlNYOPLsUpIwaB8,5144
|
54
55
|
chatterbot/logic/mathematical_evaluation.py,sha256=GPDKUwNFajERof2R-MkPGi2jJRP-rKAGm_f0V9JHDHE,2282
|
55
56
|
chatterbot/logic/specific_response.py,sha256=akWHkfe0AjzlCUvjs_PbKFNkX4SZhu_tzY45xCRXoo0,2236
|
56
57
|
chatterbot/logic/time_adapter.py,sha256=1PT6tWtGauZLRH02-Xlh2LublDpu_3hnCqHBqNGM9yg,2256
|
57
58
|
chatterbot/logic/unit_conversion.py,sha256=-ENMLqZqtZx0riUi0guda2oJECST0M7pZG4cSIv3ieM,5898
|
58
59
|
chatterbot/storage/__init__.py,sha256=ADw0WQe0YKr1UIDQLaxwf0mHDnuKW_CSzgz11K4TM-4,465
|
59
|
-
chatterbot/storage/django_storage.py,sha256=
|
60
|
+
chatterbot/storage/django_storage.py,sha256=BpuVEO4rPOiPu7f7KW1Zyar2LqEXy6I4HgPYhyGP0kE,6305
|
60
61
|
chatterbot/storage/mongodb.py,sha256=Ozvdvcjb3LGZxcvbSQGzwP9VloYQbmsa2FaKunFpMyU,7934
|
61
62
|
chatterbot/storage/redis.py,sha256=FKROrzZ-7WXZ8ZoK0dKmTDdS45TxL04XOSeu0p3Jrak,12675
|
62
|
-
chatterbot/storage/sql_storage.py,sha256=
|
63
|
+
chatterbot/storage/sql_storage.py,sha256=wESsp0OKuXjYmAZ7dl-ztX7lt4xEpjD0WCBQXK22__4,13063
|
63
64
|
chatterbot/storage/storage_adapter.py,sha256=fvyb-qNiB0HMJ0siVMCWUIY--6d-C47N1_kKZVFZAv4,6110
|
64
|
-
chatterbot-1.2.
|
65
|
-
chatterbot-1.2.
|
66
|
-
chatterbot-1.2.
|
67
|
-
chatterbot-1.2.
|
68
|
-
chatterbot-1.2.
|
65
|
+
chatterbot-1.2.6.dist-info/licenses/LICENSE,sha256=5b04U8mi0wp5gJMYlKi49EalnD9Q2nwY_6UEI_Avgu4,1476
|
66
|
+
chatterbot-1.2.6.dist-info/METADATA,sha256=lOBXOb2GEaOguy3_Rwqo_TEP77GeunbhiI9BGqB1zfc,7175
|
67
|
+
chatterbot-1.2.6.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
|
68
|
+
chatterbot-1.2.6.dist-info/top_level.txt,sha256=W2TzAbAJ-eBXTIKZZhVlkrh87msJNmBQpyhkrHqjSrE,11
|
69
|
+
chatterbot-1.2.6.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|