ChatterBot 1.2.12__tar.gz → 1.2.13__tar.gz
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-1.2.12 → chatterbot-1.2.13}/ChatterBot.egg-info/PKG-INFO +7 -7
- {chatterbot-1.2.12 → chatterbot-1.2.13}/ChatterBot.egg-info/SOURCES.txt +2 -1
- {chatterbot-1.2.12 → chatterbot-1.2.13}/ChatterBot.egg-info/requires.txt +3 -3
- {chatterbot-1.2.12 → chatterbot-1.2.13}/PKG-INFO +7 -7
- {chatterbot-1.2.12 → chatterbot-1.2.13}/README.md +1 -1
- {chatterbot-1.2.12 → chatterbot-1.2.13}/chatterbot/__init__.py +1 -1
- {chatterbot-1.2.12 → chatterbot-1.2.13}/chatterbot/chatterbot.py +37 -16
- {chatterbot-1.2.12 → chatterbot-1.2.13}/chatterbot/conversation.py +1 -1
- {chatterbot-1.2.12 → chatterbot-1.2.13}/chatterbot/logic/__init__.py +8 -0
- chatterbot-1.2.13/chatterbot/logic/best_match.py +150 -0
- chatterbot-1.2.13/chatterbot/logic/llm_adapters.py +887 -0
- {chatterbot-1.2.12 → chatterbot-1.2.13}/chatterbot/logic/mathematical_evaluation.py +52 -1
- chatterbot-1.2.13/chatterbot/logic/mcp_tools.py +209 -0
- {chatterbot-1.2.12 → chatterbot-1.2.13}/chatterbot/logic/time_adapter.py +26 -1
- {chatterbot-1.2.12 → chatterbot-1.2.13}/chatterbot/logic/unit_conversion.py +49 -1
- {chatterbot-1.2.12 → chatterbot-1.2.13}/chatterbot/parsing.py +4 -1
- {chatterbot-1.2.12 → chatterbot-1.2.13}/chatterbot/search.py +23 -2
- {chatterbot-1.2.12 → chatterbot-1.2.13}/chatterbot/storage/redis.py +159 -60
- {chatterbot-1.2.12 → chatterbot-1.2.13}/chatterbot/trainers.py +39 -7
- {chatterbot-1.2.12 → chatterbot-1.2.13}/pyproject.toml +5 -5
- {chatterbot-1.2.12 → chatterbot-1.2.13}/setup.cfg +1 -1
- {chatterbot-1.2.12 → chatterbot-1.2.13}/tests/test_chatbot.py +15 -11
- chatterbot-1.2.13/tests/test_conversations.py +117 -0
- chatterbot-1.2.12/chatterbot/llm.py +0 -145
- chatterbot-1.2.12/chatterbot/logic/best_match.py +0 -123
- chatterbot-1.2.12/tests/test_conversations.py +0 -12
- {chatterbot-1.2.12 → chatterbot-1.2.13}/ChatterBot.egg-info/dependency_links.txt +0 -0
- {chatterbot-1.2.12 → chatterbot-1.2.13}/ChatterBot.egg-info/top_level.txt +0 -0
- {chatterbot-1.2.12 → chatterbot-1.2.13}/LICENSE +0 -0
- {chatterbot-1.2.12 → chatterbot-1.2.13}/chatterbot/__main__.py +0 -0
- {chatterbot-1.2.12 → chatterbot-1.2.13}/chatterbot/adapters.py +0 -0
- {chatterbot-1.2.12 → chatterbot-1.2.13}/chatterbot/comparisons.py +0 -0
- {chatterbot-1.2.12 → chatterbot-1.2.13}/chatterbot/components.py +0 -0
- {chatterbot-1.2.12 → chatterbot-1.2.13}/chatterbot/constants.py +0 -0
- {chatterbot-1.2.12 → chatterbot-1.2.13}/chatterbot/corpus.py +0 -0
- {chatterbot-1.2.12 → chatterbot-1.2.13}/chatterbot/exceptions.py +0 -0
- {chatterbot-1.2.12 → chatterbot-1.2.13}/chatterbot/ext/__init__.py +0 -0
- {chatterbot-1.2.12 → chatterbot-1.2.13}/chatterbot/ext/django_chatterbot/__init__.py +0 -0
- {chatterbot-1.2.12 → chatterbot-1.2.13}/chatterbot/ext/django_chatterbot/abstract_models.py +0 -0
- {chatterbot-1.2.12 → chatterbot-1.2.13}/chatterbot/ext/django_chatterbot/admin.py +0 -0
- {chatterbot-1.2.12 → chatterbot-1.2.13}/chatterbot/ext/django_chatterbot/apps.py +0 -0
- {chatterbot-1.2.12 → chatterbot-1.2.13}/chatterbot/ext/django_chatterbot/migrations/0001_initial.py +0 -0
- {chatterbot-1.2.12 → chatterbot-1.2.13}/chatterbot/ext/django_chatterbot/migrations/0002_statement_extra_data.py +0 -0
- {chatterbot-1.2.12 → chatterbot-1.2.13}/chatterbot/ext/django_chatterbot/migrations/0003_change_occurrence_default.py +0 -0
- {chatterbot-1.2.12 → chatterbot-1.2.13}/chatterbot/ext/django_chatterbot/migrations/0004_rename_in_response_to.py +0 -0
- {chatterbot-1.2.12 → chatterbot-1.2.13}/chatterbot/ext/django_chatterbot/migrations/0005_statement_created_at.py +0 -0
- {chatterbot-1.2.12 → chatterbot-1.2.13}/chatterbot/ext/django_chatterbot/migrations/0006_create_conversation.py +0 -0
- {chatterbot-1.2.12 → chatterbot-1.2.13}/chatterbot/ext/django_chatterbot/migrations/0007_response_created_at.py +0 -0
- {chatterbot-1.2.12 → chatterbot-1.2.13}/chatterbot/ext/django_chatterbot/migrations/0008_update_conversations.py +0 -0
- {chatterbot-1.2.12 → chatterbot-1.2.13}/chatterbot/ext/django_chatterbot/migrations/0009_tags.py +0 -0
- {chatterbot-1.2.12 → chatterbot-1.2.13}/chatterbot/ext/django_chatterbot/migrations/0010_statement_text.py +0 -0
- {chatterbot-1.2.12 → chatterbot-1.2.13}/chatterbot/ext/django_chatterbot/migrations/0011_blank_extra_data.py +0 -0
- {chatterbot-1.2.12 → chatterbot-1.2.13}/chatterbot/ext/django_chatterbot/migrations/0012_statement_created_at.py +0 -0
- {chatterbot-1.2.12 → chatterbot-1.2.13}/chatterbot/ext/django_chatterbot/migrations/0013_change_conversations.py +0 -0
- {chatterbot-1.2.12 → chatterbot-1.2.13}/chatterbot/ext/django_chatterbot/migrations/0014_remove_statement_extra_data.py +0 -0
- {chatterbot-1.2.12 → chatterbot-1.2.13}/chatterbot/ext/django_chatterbot/migrations/0015_statement_persona.py +0 -0
- {chatterbot-1.2.12 → chatterbot-1.2.13}/chatterbot/ext/django_chatterbot/migrations/0016_statement_stemmed_text.py +0 -0
- {chatterbot-1.2.12 → chatterbot-1.2.13}/chatterbot/ext/django_chatterbot/migrations/0017_tags_unique.py +0 -0
- {chatterbot-1.2.12 → chatterbot-1.2.13}/chatterbot/ext/django_chatterbot/migrations/0018_text_max_length.py +0 -0
- {chatterbot-1.2.12 → chatterbot-1.2.13}/chatterbot/ext/django_chatterbot/migrations/0019_alter_statement_id_alter_tag_id_and_more.py +0 -0
- {chatterbot-1.2.12 → chatterbot-1.2.13}/chatterbot/ext/django_chatterbot/migrations/0020_alter_statement_conversation_and_more.py +0 -0
- {chatterbot-1.2.12 → chatterbot-1.2.13}/chatterbot/ext/django_chatterbot/migrations/0021_increase_text_max_length_to_1100.py +0 -0
- {chatterbot-1.2.12 → chatterbot-1.2.13}/chatterbot/ext/django_chatterbot/migrations/__init__.py +0 -0
- {chatterbot-1.2.12 → chatterbot-1.2.13}/chatterbot/ext/django_chatterbot/model_admin.py +0 -0
- {chatterbot-1.2.12 → chatterbot-1.2.13}/chatterbot/ext/django_chatterbot/models.py +0 -0
- {chatterbot-1.2.12 → chatterbot-1.2.13}/chatterbot/ext/django_chatterbot/settings.py +0 -0
- {chatterbot-1.2.12 → chatterbot-1.2.13}/chatterbot/ext/sqlalchemy_app/__init__.py +0 -0
- {chatterbot-1.2.12 → chatterbot-1.2.13}/chatterbot/ext/sqlalchemy_app/models.py +0 -0
- {chatterbot-1.2.12 → chatterbot-1.2.13}/chatterbot/filters.py +0 -0
- {chatterbot-1.2.12 → chatterbot-1.2.13}/chatterbot/languages.py +0 -0
- {chatterbot-1.2.12 → chatterbot-1.2.13}/chatterbot/logic/logic_adapter.py +0 -0
- {chatterbot-1.2.12 → chatterbot-1.2.13}/chatterbot/logic/specific_response.py +0 -0
- {chatterbot-1.2.12 → chatterbot-1.2.13}/chatterbot/preprocessors.py +0 -0
- {chatterbot-1.2.12 → chatterbot-1.2.13}/chatterbot/response_selection.py +0 -0
- {chatterbot-1.2.12 → chatterbot-1.2.13}/chatterbot/storage/__init__.py +0 -0
- {chatterbot-1.2.12 → chatterbot-1.2.13}/chatterbot/storage/django_storage.py +0 -0
- {chatterbot-1.2.12 → chatterbot-1.2.13}/chatterbot/storage/mongodb.py +0 -0
- {chatterbot-1.2.12 → chatterbot-1.2.13}/chatterbot/storage/sql_storage.py +0 -0
- {chatterbot-1.2.12 → chatterbot-1.2.13}/chatterbot/storage/storage_adapter.py +0 -0
- {chatterbot-1.2.12 → chatterbot-1.2.13}/chatterbot/tagging.py +0 -0
- {chatterbot-1.2.12 → chatterbot-1.2.13}/chatterbot/utils.py +0 -0
- {chatterbot-1.2.12 → chatterbot-1.2.13}/chatterbot/vectorstores.py +0 -0
- {chatterbot-1.2.12 → chatterbot-1.2.13}/tests/test_adapter_validation.py +0 -0
- {chatterbot-1.2.12 → chatterbot-1.2.13}/tests/test_benchmarks.py +0 -0
- {chatterbot-1.2.12 → chatterbot-1.2.13}/tests/test_cli.py +0 -0
- {chatterbot-1.2.12 → chatterbot-1.2.13}/tests/test_comparisons.py +0 -0
- {chatterbot-1.2.12 → chatterbot-1.2.13}/tests/test_corpus.py +0 -0
- {chatterbot-1.2.12 → chatterbot-1.2.13}/tests/test_examples.py +0 -0
- {chatterbot-1.2.12 → chatterbot-1.2.13}/tests/test_filters.py +0 -0
- {chatterbot-1.2.12 → chatterbot-1.2.13}/tests/test_initialization.py +0 -0
- {chatterbot-1.2.12 → chatterbot-1.2.13}/tests/test_languages.py +0 -0
- {chatterbot-1.2.12 → chatterbot-1.2.13}/tests/test_parsing.py +0 -0
- {chatterbot-1.2.12 → chatterbot-1.2.13}/tests/test_preprocessors.py +0 -0
- {chatterbot-1.2.12 → chatterbot-1.2.13}/tests/test_response_selection.py +0 -0
- {chatterbot-1.2.12 → chatterbot-1.2.13}/tests/test_search.py +0 -0
- {chatterbot-1.2.12 → chatterbot-1.2.13}/tests/test_tagging.py +0 -0
- {chatterbot-1.2.12 → chatterbot-1.2.13}/tests/test_turing.py +0 -0
- {chatterbot-1.2.12 → chatterbot-1.2.13}/tests/test_utils.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ChatterBot
|
|
3
|
-
Version: 1.2.
|
|
3
|
+
Version: 1.2.13
|
|
4
4
|
Summary: ChatterBot is a machine learning, conversational dialog engine
|
|
5
5
|
Author: Gunther Cox
|
|
6
6
|
License-Expression: BSD-3-Clause
|
|
@@ -26,9 +26,9 @@ Classifier: Topic :: Text Processing :: Indexing
|
|
|
26
26
|
Classifier: Topic :: Text Processing :: Linguistic
|
|
27
27
|
Classifier: Programming Language :: Python
|
|
28
28
|
Classifier: Programming Language :: Python :: 3
|
|
29
|
-
Classifier: Programming Language :: Python :: 3.
|
|
29
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
30
30
|
Classifier: Programming Language :: Python :: 3 :: Only
|
|
31
|
-
Requires-Python: <3.
|
|
31
|
+
Requires-Python: <3.15,>=3.10
|
|
32
32
|
Description-Content-Type: text/markdown
|
|
33
33
|
License-File: LICENSE
|
|
34
34
|
Requires-Dist: mathparse<0.3,>=0.2
|
|
@@ -42,7 +42,7 @@ Requires-Dist: coverage; extra == "test"
|
|
|
42
42
|
Requires-Dist: sphinx<9.2,>=5.3; extra == "test"
|
|
43
43
|
Requires-Dist: sphinx-sitemap>=2.6.0; extra == "test"
|
|
44
44
|
Requires-Dist: huggingface_hub; extra == "test"
|
|
45
|
-
Requires-Dist: django<6.0
|
|
45
|
+
Requires-Dist: django<6.0,>=4.1; extra == "test"
|
|
46
46
|
Provides-Extra: dev
|
|
47
47
|
Requires-Dist: pint>=0.8.1; extra == "dev"
|
|
48
48
|
Requires-Dist: pyyaml<7.0,>=6.0; extra == "dev"
|
|
@@ -50,10 +50,10 @@ Requires-Dist: chatterbot-corpus<1.3.0,>=1.2.2; extra == "dev"
|
|
|
50
50
|
Requires-Dist: ollama<1.0,>=0.6.0; extra == "dev"
|
|
51
51
|
Requires-Dist: openai; extra == "dev"
|
|
52
52
|
Provides-Extra: redis
|
|
53
|
-
Requires-Dist: redis[hiredis]<7.
|
|
53
|
+
Requires-Dist: redis[hiredis]<7.3,>=7.0; extra == "redis"
|
|
54
54
|
Requires-Dist: langchain-redis<0.3.0; extra == "redis"
|
|
55
55
|
Requires-Dist: langchain-huggingface<1.3.0,>=0.1.2; extra == "redis"
|
|
56
|
-
Requires-Dist: accelerate<1.
|
|
56
|
+
Requires-Dist: accelerate<1.14,>=1.6.0; extra == "redis"
|
|
57
57
|
Requires-Dist: sentence-transformers<5.3.0,>=4.0.2; extra == "redis"
|
|
58
58
|
Provides-Extra: mongodb
|
|
59
59
|
Requires-Dist: pymongo<4.17,>=4.11; extra == "mongodb"
|
|
@@ -163,7 +163,7 @@ https://docs.chatterbot.us/contributing/
|
|
|
163
163
|
ChatterBot is sponsored by:
|
|
164
164
|
|
|
165
165
|
<p>
|
|
166
|
-
<a href="https://www.
|
|
166
|
+
<a href="https://www.testmuai.com/?utm_source=chatterbot&utm_medium=sponsor" target="_blank">
|
|
167
167
|
<img src="docs/_static/testmu-ai-white-logo.png" style="vertical-align: middle;" width="250" height="80" />
|
|
168
168
|
</a>
|
|
169
169
|
</p>
|
|
@@ -19,7 +19,6 @@ chatterbot/corpus.py
|
|
|
19
19
|
chatterbot/exceptions.py
|
|
20
20
|
chatterbot/filters.py
|
|
21
21
|
chatterbot/languages.py
|
|
22
|
-
chatterbot/llm.py
|
|
23
22
|
chatterbot/parsing.py
|
|
24
23
|
chatterbot/preprocessors.py
|
|
25
24
|
chatterbot/response_selection.py
|
|
@@ -62,8 +61,10 @@ chatterbot/ext/sqlalchemy_app/__init__.py
|
|
|
62
61
|
chatterbot/ext/sqlalchemy_app/models.py
|
|
63
62
|
chatterbot/logic/__init__.py
|
|
64
63
|
chatterbot/logic/best_match.py
|
|
64
|
+
chatterbot/logic/llm_adapters.py
|
|
65
65
|
chatterbot/logic/logic_adapter.py
|
|
66
66
|
chatterbot/logic/mathematical_evaluation.py
|
|
67
|
+
chatterbot/logic/mcp_tools.py
|
|
67
68
|
chatterbot/logic/specific_response.py
|
|
68
69
|
chatterbot/logic/time_adapter.py
|
|
69
70
|
chatterbot/logic/unit_conversion.py
|
|
@@ -15,10 +15,10 @@ openai
|
|
|
15
15
|
pymongo<4.17,>=4.11
|
|
16
16
|
|
|
17
17
|
[redis]
|
|
18
|
-
redis[hiredis]<7.
|
|
18
|
+
redis[hiredis]<7.3,>=7.0
|
|
19
19
|
langchain-redis<0.3.0
|
|
20
20
|
langchain-huggingface<1.3.0,>=0.1.2
|
|
21
|
-
accelerate<1.
|
|
21
|
+
accelerate<1.14,>=1.6.0
|
|
22
22
|
sentence-transformers<5.3.0,>=4.0.2
|
|
23
23
|
|
|
24
24
|
[test]
|
|
@@ -27,4 +27,4 @@ coverage
|
|
|
27
27
|
sphinx<9.2,>=5.3
|
|
28
28
|
sphinx-sitemap>=2.6.0
|
|
29
29
|
huggingface_hub
|
|
30
|
-
django<6.0
|
|
30
|
+
django<6.0,>=4.1
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ChatterBot
|
|
3
|
-
Version: 1.2.
|
|
3
|
+
Version: 1.2.13
|
|
4
4
|
Summary: ChatterBot is a machine learning, conversational dialog engine
|
|
5
5
|
Author: Gunther Cox
|
|
6
6
|
License-Expression: BSD-3-Clause
|
|
@@ -26,9 +26,9 @@ Classifier: Topic :: Text Processing :: Indexing
|
|
|
26
26
|
Classifier: Topic :: Text Processing :: Linguistic
|
|
27
27
|
Classifier: Programming Language :: Python
|
|
28
28
|
Classifier: Programming Language :: Python :: 3
|
|
29
|
-
Classifier: Programming Language :: Python :: 3.
|
|
29
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
30
30
|
Classifier: Programming Language :: Python :: 3 :: Only
|
|
31
|
-
Requires-Python: <3.
|
|
31
|
+
Requires-Python: <3.15,>=3.10
|
|
32
32
|
Description-Content-Type: text/markdown
|
|
33
33
|
License-File: LICENSE
|
|
34
34
|
Requires-Dist: mathparse<0.3,>=0.2
|
|
@@ -42,7 +42,7 @@ Requires-Dist: coverage; extra == "test"
|
|
|
42
42
|
Requires-Dist: sphinx<9.2,>=5.3; extra == "test"
|
|
43
43
|
Requires-Dist: sphinx-sitemap>=2.6.0; extra == "test"
|
|
44
44
|
Requires-Dist: huggingface_hub; extra == "test"
|
|
45
|
-
Requires-Dist: django<6.0
|
|
45
|
+
Requires-Dist: django<6.0,>=4.1; extra == "test"
|
|
46
46
|
Provides-Extra: dev
|
|
47
47
|
Requires-Dist: pint>=0.8.1; extra == "dev"
|
|
48
48
|
Requires-Dist: pyyaml<7.0,>=6.0; extra == "dev"
|
|
@@ -50,10 +50,10 @@ Requires-Dist: chatterbot-corpus<1.3.0,>=1.2.2; extra == "dev"
|
|
|
50
50
|
Requires-Dist: ollama<1.0,>=0.6.0; extra == "dev"
|
|
51
51
|
Requires-Dist: openai; extra == "dev"
|
|
52
52
|
Provides-Extra: redis
|
|
53
|
-
Requires-Dist: redis[hiredis]<7.
|
|
53
|
+
Requires-Dist: redis[hiredis]<7.3,>=7.0; extra == "redis"
|
|
54
54
|
Requires-Dist: langchain-redis<0.3.0; extra == "redis"
|
|
55
55
|
Requires-Dist: langchain-huggingface<1.3.0,>=0.1.2; extra == "redis"
|
|
56
|
-
Requires-Dist: accelerate<1.
|
|
56
|
+
Requires-Dist: accelerate<1.14,>=1.6.0; extra == "redis"
|
|
57
57
|
Requires-Dist: sentence-transformers<5.3.0,>=4.0.2; extra == "redis"
|
|
58
58
|
Provides-Extra: mongodb
|
|
59
59
|
Requires-Dist: pymongo<4.17,>=4.11; extra == "mongodb"
|
|
@@ -163,7 +163,7 @@ https://docs.chatterbot.us/contributing/
|
|
|
163
163
|
ChatterBot is sponsored by:
|
|
164
164
|
|
|
165
165
|
<p>
|
|
166
|
-
<a href="https://www.
|
|
166
|
+
<a href="https://www.testmuai.com/?utm_source=chatterbot&utm_medium=sponsor" target="_blank">
|
|
167
167
|
<img src="docs/_static/testmu-ai-white-logo.png" style="vertical-align: middle;" width="250" height="80" />
|
|
168
168
|
</a>
|
|
169
169
|
</p>
|
|
@@ -102,7 +102,7 @@ https://docs.chatterbot.us/contributing/
|
|
|
102
102
|
ChatterBot is sponsored by:
|
|
103
103
|
|
|
104
104
|
<p>
|
|
105
|
-
<a href="https://www.
|
|
105
|
+
<a href="https://www.testmuai.com/?utm_source=chatterbot&utm_medium=sponsor" target="_blank">
|
|
106
106
|
<img src="docs/_static/testmu-ai-white-logo.png" style="vertical-align: middle;" width="250" height="80" />
|
|
107
107
|
</a>
|
|
108
108
|
</p>
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import logging
|
|
2
|
+
import uuid
|
|
2
3
|
from typing import Union
|
|
3
4
|
from chatterbot.storage import StorageAdapter
|
|
4
5
|
from chatterbot.logic import LogicAdapter
|
|
@@ -56,6 +57,14 @@ class ChatBot(object):
|
|
|
56
57
|
|
|
57
58
|
self.stream = stream
|
|
58
59
|
|
|
60
|
+
# Generate a default conversation ID for this ChatBot instance.
|
|
61
|
+
# This is used as a fallback when callers don't provide an explicit
|
|
62
|
+
# conversation ID, ensuring that conversation history is tracked
|
|
63
|
+
# within a session. Conversation IDs are necessary for cases such as
|
|
64
|
+
# the LLM-based logic adapters which require it to retrieve previous
|
|
65
|
+
# messages.
|
|
66
|
+
self.default_conversation = uuid.uuid4().hex
|
|
67
|
+
|
|
59
68
|
self.logger = kwargs.get('logger', logging.getLogger(__name__))
|
|
60
69
|
|
|
61
70
|
storage_adapter = kwargs.get('storage_adapter', 'chatterbot.storage.SQLStorageAdapter')
|
|
@@ -147,11 +156,6 @@ class ChatBot(object):
|
|
|
147
156
|
# NOTE: 'xx' is the language code for a multi-language model
|
|
148
157
|
self.nlp = spacy.blank(self.tagger.language.ISO_639_1)
|
|
149
158
|
|
|
150
|
-
self.model = None
|
|
151
|
-
if model := kwargs.get('model'):
|
|
152
|
-
import_path = model.pop('client')
|
|
153
|
-
self.model = utils.initialize_class(import_path, self, **model)
|
|
154
|
-
|
|
155
159
|
# Allow the bot to save input it receives so that it can learn
|
|
156
160
|
self.read_only = kwargs.get('read_only', False)
|
|
157
161
|
|
|
@@ -199,6 +203,13 @@ class ChatBot(object):
|
|
|
199
203
|
|
|
200
204
|
input_statement.add_tags(*tags)
|
|
201
205
|
|
|
206
|
+
# If no conversation ID was provided, use the default session ID
|
|
207
|
+
# so that conversation history is tracked across calls. Callers
|
|
208
|
+
# can override this by passing an explicit conversation kwarg or
|
|
209
|
+
# setting it on the Statement object.
|
|
210
|
+
if not input_statement.conversation:
|
|
211
|
+
input_statement.conversation = self.default_conversation
|
|
212
|
+
|
|
202
213
|
# Preprocess the input statement
|
|
203
214
|
for preprocessor in self.preprocessors:
|
|
204
215
|
input_statement = preprocessor(input_statement)
|
|
@@ -269,12 +280,6 @@ class ChatBot(object):
|
|
|
269
280
|
result = None
|
|
270
281
|
max_confidence = -1
|
|
271
282
|
|
|
272
|
-
# If a model is provided, use it to process the input statement
|
|
273
|
-
# instead of the logic adapters
|
|
274
|
-
if self.model:
|
|
275
|
-
model_response = self.model.process(input_statement)
|
|
276
|
-
return model_response
|
|
277
|
-
|
|
278
283
|
for adapter in self.logic_adapters:
|
|
279
284
|
if adapter.can_process(input_statement):
|
|
280
285
|
|
|
@@ -349,24 +354,40 @@ class ChatBot(object):
|
|
|
349
354
|
|
|
350
355
|
if not previous_statement:
|
|
351
356
|
previous_statement = self.get_latest_response(statement.conversation)
|
|
352
|
-
if previous_statement:
|
|
353
|
-
previous_statement = previous_statement.text
|
|
354
357
|
|
|
355
358
|
previous_statement_text = previous_statement
|
|
356
359
|
|
|
357
|
-
if
|
|
360
|
+
if isinstance(previous_statement, Statement):
|
|
358
361
|
statement.in_response_to = previous_statement.text
|
|
362
|
+
previous_statement_text = previous_statement.text
|
|
363
|
+
|
|
364
|
+
# Set search_in_response_to from the previous statement's search_text
|
|
365
|
+
if previous_statement.search_text:
|
|
366
|
+
statement.search_in_response_to = previous_statement.search_text
|
|
367
|
+
elif previous_statement.text:
|
|
368
|
+
statement.search_in_response_to = self.tagger.get_text_index_string(
|
|
369
|
+
previous_statement.text
|
|
370
|
+
)
|
|
359
371
|
elif isinstance(previous_statement, str):
|
|
360
372
|
statement.in_response_to = previous_statement
|
|
373
|
+
statement.search_in_response_to = self.tagger.get_text_index_string(
|
|
374
|
+
previous_statement
|
|
375
|
+
)
|
|
361
376
|
|
|
362
377
|
self.logger.info('Adding "{}" as a response to "{}"'.format(
|
|
363
|
-
|
|
364
|
-
|
|
378
|
+
statement.text,
|
|
379
|
+
previous_statement_text
|
|
365
380
|
))
|
|
366
381
|
|
|
367
382
|
if not statement.persona:
|
|
368
383
|
statement.persona = 'bot:' + self.name
|
|
369
384
|
|
|
385
|
+
# Ensure search_text is set for the statement being saved
|
|
386
|
+
if not statement.search_text and statement.text:
|
|
387
|
+
statement.search_text = self.tagger.get_text_index_string(
|
|
388
|
+
statement.text
|
|
389
|
+
)
|
|
390
|
+
|
|
370
391
|
# Save the response statement
|
|
371
392
|
return self.storage.create(**statement.serialize())
|
|
372
393
|
|
|
@@ -101,7 +101,7 @@ class Statement(StatementMixin):
|
|
|
101
101
|
# This is the confidence with which the chat bot believes
|
|
102
102
|
# this is an accurate response. This value is set when the
|
|
103
103
|
# statement is returned by the chat bot.
|
|
104
|
-
self.confidence = 0
|
|
104
|
+
self.confidence = kwargs.get('confidence', 0)
|
|
105
105
|
|
|
106
106
|
self.storage = None
|
|
107
107
|
|
|
@@ -4,6 +4,11 @@ from chatterbot.logic.mathematical_evaluation import MathematicalEvaluation
|
|
|
4
4
|
from chatterbot.logic.specific_response import SpecificResponseAdapter
|
|
5
5
|
from chatterbot.logic.time_adapter import TimeLogicAdapter
|
|
6
6
|
from chatterbot.logic.unit_conversion import UnitConversion
|
|
7
|
+
from chatterbot.logic.llm_adapters import (
|
|
8
|
+
LLMLogicAdapter,
|
|
9
|
+
OllamaLogicAdapter,
|
|
10
|
+
OpenAILogicAdapter,
|
|
11
|
+
)
|
|
7
12
|
|
|
8
13
|
|
|
9
14
|
__all__ = (
|
|
@@ -13,4 +18,7 @@ __all__ = (
|
|
|
13
18
|
'SpecificResponseAdapter',
|
|
14
19
|
'TimeLogicAdapter',
|
|
15
20
|
'UnitConversion',
|
|
21
|
+
'LLMLogicAdapter',
|
|
22
|
+
'OllamaLogicAdapter',
|
|
23
|
+
'OpenAILogicAdapter',
|
|
16
24
|
)
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
from chatterbot.logic import LogicAdapter
|
|
2
|
+
from chatterbot.conversation import Statement
|
|
3
|
+
from chatterbot import filters
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class BestMatch(LogicAdapter):
|
|
7
|
+
"""
|
|
8
|
+
A logic adapter that returns a response based on known responses to
|
|
9
|
+
the closest matches to the input statement.
|
|
10
|
+
|
|
11
|
+
:param excluded_words:
|
|
12
|
+
The excluded_words parameter allows a list of words to be set that will
|
|
13
|
+
prevent the logic adapter from returning statements that have text
|
|
14
|
+
containing any of those words. This can be useful for preventing your
|
|
15
|
+
chat bot from saying swears when it is being demonstrated in front of
|
|
16
|
+
an audience.
|
|
17
|
+
Defaults to None
|
|
18
|
+
:type excluded_words: list
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
def __init__(self, chatbot, **kwargs):
|
|
22
|
+
super().__init__(chatbot, **kwargs)
|
|
23
|
+
|
|
24
|
+
self.excluded_words = kwargs.get('excluded_words')
|
|
25
|
+
|
|
26
|
+
def process(self, input_statement: Statement, additional_response_selection_parameters=None) -> Statement:
|
|
27
|
+
|
|
28
|
+
# Get all statements that have a response text similar to the input statement
|
|
29
|
+
search_results = self.search_algorithm.search(input_statement)
|
|
30
|
+
|
|
31
|
+
# Use the input statement as the closest match if no other results are found
|
|
32
|
+
input_statement.confidence = 0 # Use 0 confidence when no other results are found
|
|
33
|
+
closest_match = input_statement
|
|
34
|
+
|
|
35
|
+
# Search for the closest match to the input statement
|
|
36
|
+
for result in search_results:
|
|
37
|
+
closest_match = result
|
|
38
|
+
|
|
39
|
+
# Stop searching if a match that is close enough is found
|
|
40
|
+
if result.confidence >= self.maximum_similarity_threshold:
|
|
41
|
+
break
|
|
42
|
+
|
|
43
|
+
self.chatbot.logger.info('Selecting "{}" as a response to "{}" with a confidence of {}'.format(
|
|
44
|
+
closest_match.text, input_statement.text, closest_match.confidence
|
|
45
|
+
))
|
|
46
|
+
|
|
47
|
+
# Semantic vector search vs indexed text search have different architectures:
|
|
48
|
+
#
|
|
49
|
+
# For SQL with indexed text search:
|
|
50
|
+
# - Phase 1 finds a match based on string similarity (Levenshtein distance)
|
|
51
|
+
# - Phase 2 finds variations of that match to get diverse responses
|
|
52
|
+
# - This makes sense because you might have multiple instances of similar statements
|
|
53
|
+
# learned from different conversations that provide different response options
|
|
54
|
+
#
|
|
55
|
+
# For Redis with semantic vectors:
|
|
56
|
+
# - Phase 1 finds semantically similar responses using vector embeddings
|
|
57
|
+
# - The semantic similarity already captures the "closeness" we want
|
|
58
|
+
# - Phase 2 would be redundant - we already have the best semantic match
|
|
59
|
+
# - The vector search inherently considers the entire semantic space, not just
|
|
60
|
+
# exact string matches, so additional variation searching is unnecessary
|
|
61
|
+
#
|
|
62
|
+
# NOTE: This difference of functionality may need to be modified in the future
|
|
63
|
+
# if the redis adapter is determined to benefit from a Phase 2 style response
|
|
64
|
+
# selection. The main symptom that would drive such a change would be low
|
|
65
|
+
# quality or repetitive responses when using semantic vector search.
|
|
66
|
+
#
|
|
67
|
+
# Therefore, semantic vector search returns the Phase 1 result directly.
|
|
68
|
+
if self.search_algorithm.name == 'semantic_vector_search' and closest_match.confidence > 0:
|
|
69
|
+
response = closest_match
|
|
70
|
+
self.chatbot.logger.info('Using semantic search result directly: "{}"'.format(response.text))
|
|
71
|
+
else:
|
|
72
|
+
# For other search algorithms (indexed_text_search, text_search),
|
|
73
|
+
# we need to find responses to the closest match
|
|
74
|
+
recent_repeated_responses = filters.get_recent_repeated_responses(
|
|
75
|
+
self.chatbot,
|
|
76
|
+
input_statement.conversation
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
for index, recent_repeated_response in enumerate(recent_repeated_responses):
|
|
80
|
+
self.chatbot.logger.info('{}. Excluding recent repeated response of "{}"'.format(
|
|
81
|
+
index, recent_repeated_response
|
|
82
|
+
))
|
|
83
|
+
|
|
84
|
+
response_selection_parameters = {
|
|
85
|
+
'search_text': closest_match.search_text,
|
|
86
|
+
'persona_not_startswith': 'bot:',
|
|
87
|
+
'exclude_text': recent_repeated_responses,
|
|
88
|
+
'exclude_text_words': self.excluded_words
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
alternate_response_selection_parameters = {
|
|
92
|
+
'search_in_response_to': input_statement.search_text or self.chatbot.tagger.get_text_index_string(
|
|
93
|
+
input_statement.text
|
|
94
|
+
),
|
|
95
|
+
'persona_not_startswith': 'bot:',
|
|
96
|
+
'exclude_text': recent_repeated_responses,
|
|
97
|
+
'exclude_text_words': self.excluded_words
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
if additional_response_selection_parameters:
|
|
101
|
+
response_selection_parameters.update(
|
|
102
|
+
additional_response_selection_parameters
|
|
103
|
+
)
|
|
104
|
+
alternate_response_selection_parameters.update(
|
|
105
|
+
additional_response_selection_parameters
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
# Get all statements with text similar to the closest match
|
|
109
|
+
response_list = list(self.chatbot.storage.filter(**response_selection_parameters))
|
|
110
|
+
|
|
111
|
+
if response_list:
|
|
112
|
+
response = self.select_response(
|
|
113
|
+
input_statement,
|
|
114
|
+
response_list,
|
|
115
|
+
self.chatbot.storage
|
|
116
|
+
)
|
|
117
|
+
|
|
118
|
+
response.confidence = closest_match.confidence
|
|
119
|
+
self.chatbot.logger.info('Selecting "{}" from {} optimal responses.'.format(
|
|
120
|
+
response.text,
|
|
121
|
+
len(response_list)
|
|
122
|
+
))
|
|
123
|
+
else:
|
|
124
|
+
'''
|
|
125
|
+
The case where there was no responses returned for the selected match
|
|
126
|
+
but a value exists for the statement the match is in response to.
|
|
127
|
+
'''
|
|
128
|
+
self.chatbot.logger.info('No responses found. Generating alternate response list.')
|
|
129
|
+
|
|
130
|
+
alternate_response_list = list(self.chatbot.storage.filter(
|
|
131
|
+
**alternate_response_selection_parameters
|
|
132
|
+
))
|
|
133
|
+
|
|
134
|
+
if alternate_response_list:
|
|
135
|
+
response = self.select_response(
|
|
136
|
+
input_statement,
|
|
137
|
+
alternate_response_list,
|
|
138
|
+
self.chatbot.storage
|
|
139
|
+
)
|
|
140
|
+
|
|
141
|
+
response.confidence = closest_match.confidence
|
|
142
|
+
self.chatbot.logger.info('Selected alternative response "{}" from {} options'.format(
|
|
143
|
+
response.text,
|
|
144
|
+
len(alternate_response_list)
|
|
145
|
+
))
|
|
146
|
+
else:
|
|
147
|
+
response = self.get_default_response(input_statement)
|
|
148
|
+
self.chatbot.logger.info('Using "%s" as a default response.', response.text)
|
|
149
|
+
|
|
150
|
+
return response
|