Skip to content

Commit

Permalink
Add check for logic adapter agreement
Browse files Browse the repository at this point in the history
  • Loading branch information
gunthercox committed Oct 31, 2016
1 parent 0f55cd9 commit 213240b
Show file tree
Hide file tree
Showing 4 changed files with 113 additions and 4 deletions.
28 changes: 28 additions & 0 deletions chatterbot/adapters/logic/multi_adapter.py
@@ -1,4 +1,5 @@
from .logic_adapter import LogicAdapter
from collections import Counter


class MultiLogicAdapter(LogicAdapter):
Expand All @@ -21,12 +22,14 @@ def process(self, statement):
:param statement: The input statement to be processed.
"""
results = []
result = None
max_confidence = -1

for adapter in self.adapters:
if adapter.can_process(statement):
confidence, output = adapter.process(statement)
results.append((confidence, output, ))

self.logger.info(
u'{} selected "{}" as a response with a confidence of {}'.format(
Expand All @@ -44,8 +47,33 @@ def process(self, statement):
)
)

# If multiple adapters agree on the same statement,
# then that statement is more likely to be the correct response
if len(results) >= 3:
statements = [s[1] for s in results]
count = Counter(statements)
most_common = count.most_common()
if most_common[0][1] > 1:
result = most_common[0][0]
max_confidence = self.get_greatest_confidence(result, results)

return max_confidence, result

def get_greatest_confidence(self, statement, options):
"""
Returns the greatest confidence value for a statement that occurs
multiple times in the set of options.
:param statement: A statement object.
:param options: A tuple in the format of (confidence, statement).
"""
values = []
for option in options:
if option[1] == statement:
values.append(option[0])

return max(values)

def add_adapter(self, adapter):
"""
Appends a logic adapter to the list of logic adapters being used.
Expand Down
11 changes: 7 additions & 4 deletions chatterbot/conversation/response.py
Expand Up @@ -5,13 +5,16 @@ class Response(object):

def __init__(self, text, **kwargs):
self.text = text
self.occurrence = kwargs.get("occurrence", 1)
self.occurrence = kwargs.get('occurrence', 1)

def __str__(self):
return self.text

def __repr__(self):
return "<Response text:%s>" % (self.text)
return '<Response text:%s>' % (self.text)

def __hash__(self):
return hash(self.text)

def __eq__(self, other):
if not other:
Expand All @@ -25,7 +28,7 @@ def __eq__(self, other):
def serialize(self):
data = {}

data["text"] = self.text
data["occurrence"] = self.occurrence
data['text'] = self.text
data['occurrence'] = self.occurrence

return data
3 changes: 3 additions & 0 deletions chatterbot/conversation/statement.py
Expand Up @@ -21,6 +21,9 @@ def __str__(self):
def __repr__(self):
return '<Statement text:%s>' % (self.text)

def __hash__(self):
return hash(self.text)

def __eq__(self, other):
if not other:
return False
Expand Down
75 changes: 75 additions & 0 deletions tests/logic_adapter_tests/test_multi_adapter.py
@@ -0,0 +1,75 @@
from tests.base_case import ChatBotTestCase
from chatterbot.conversation import Statement
from chatterbot.adapters.logic import LogicAdapter
from chatterbot.adapters.logic import MultiLogicAdapter


class TestAdapterA(LogicAdapter):

def process(self, statement):
return 0.2, Statement('Good morning.')


class TestAdapterB(LogicAdapter):

def process(self, statement):
return 0.5, Statement('Good morning.')


class TestAdapterC(LogicAdapter):

def process(self, statement):
return 0.7, Statement('Good night.')


class MultiLogicAdapterTestCase(ChatBotTestCase):

def setUp(self):
super(MultiLogicAdapterTestCase, self).setUp()
self.adapter = MultiLogicAdapter()
self.adapter.set_context(self.chatbot)

def test_sub_adapter_agreement(self):
"""
In the case that multiple adapters agree on a given
statement, this statement should be returned with the
highest confidence available from these matching options.
"""
self.adapter.add_adapter(TestAdapterA())
self.adapter.add_adapter(TestAdapterB())
self.adapter.add_adapter(TestAdapterC())

confidence, statement = self.adapter.process(Statement('Howdy!'))

self.assertEqual(confidence, 0.5)
self.assertEqual(statement, 'Good morning.')

def test_get_greatest_confidence(self):
statement = 'Hello'
options = [
(0.50, 'Hello'),
(0.85, 'Hello'),
(0.42, 'Hello')
]
value = self.adapter.get_greatest_confidence(statement, options)

self.assertEqual(value, 0.85)

def test_add_adapter(self):
sub_adapter = TestAdapterA()
adapter_count_before = len(self.adapter.adapters)
self.adapter.add_adapter(sub_adapter)
adapter_count_after = len(self.adapter.adapters)

self.assertEqual(adapter_count_after, adapter_count_before + 1)

def test_set_context(self):
adapter = MultiLogicAdapter()
adapter.set_context(self.chatbot)

# Test that the multi adapter's context is set
self.assertEqual(adapter.context, self.chatbot)

# Test that all sub adapters have the context set
for sub_adapter in adapter.adapters:
self.assertEqual(sub_adapter.context, self.chatbot)

0 comments on commit 213240b

Please sign in to comment.