Added basic entity support

pull/1/head
TechieDamien 2021-11-12 11:59:33 +00:00
parent 4d2a4dacdd
commit 98a4f5349d
1 changed files with 61 additions and 3 deletions

View File

@ -3,15 +3,73 @@ from opsdroid.matchers import match_rasanlu, match_parse
import random
class Respond(Skill):
# Constructor gets configs for the skill and applies the decorator
# to match using rasa.
def __init__(self, opsdroid, config):
super().__init__(opsdroid, config)
self.intent = self.config.get("intent")
self._get_configs()
self.respond = match_rasanlu(self.intent)(self.respond)
# This utility function will grab the relevent config variables
# for this skill to function.
def _get_configs(self):
# The intent to match.
self.intent = self.config.get("intent")
# Possible responses given a match.
self.response_options = self.config.get("response_options")
# A bool to check if we want to use entities in our response.
self.use_entities = self.config.get("use_entities", False)
# Fallback responses if we do not get the required entities
# from Rasa.
self.fallback_response_options = self.config.get("fallback_response_options",
["Sorry, Rasa did not extract sufficient entities to fulfil your request"])
# Extract the entities from the rasanlu response
def _get_entities(self, message):
# This includes data such as the extractor used, which we
# don't need.
raw_entities = message.rasanlu["entities"]
entities = {}
for entity in raw_entities:
entity_type = entity["entity"]
unique_entity_type = self._get_unique_key(entity_type, entities)
entity_value = entity["value"]
entities[unique_entity_type] = entity_value
return entities
# Appends the smallest integer to the name of the key in order to
# create a new key that is not already in the dictionary.
def _get_unique_key(self, base_key, dictionary):
counter = 0
while True:
unique_key_attempt = base_key + str(counter)
if unique_key_attempt in dictionary:
counter += 1
continue
return unique_key_attempt
# Takes the response and attempts to replace all entities in it
# with the extracted entities. Failing that, we will fall back to a
# fallback response.
def _substitute_entities(self, response, entities):
try:
response = response.format(**entities)
except KeyError as e:
chosen_fallback = random.choice(self.fallback_response_options)
return chosen_fallback
return response
# This line is to add properties to respond on declaration
# as doing this in __init__ would cause an exception to be
# raised. If you don't believe me, remove it!
@match_parse("hgftgyhjknbvhgftyuihjkvhgftyuijkbjhgtyyuijhkjghfdtrytyihujkbvncgfxdtrytuyiuhkbjvbhcfdytryuhjkbvhcfdyrtuyiuhkbhj")
async def respond(self, message):
response_options = self.config.get("response_options")
await message.respond(random.choice(response_options))
chosen_response = random.choice(self.response_options)
if self.use_entities:
entities = self._get_entities(message)
chosen_response = self._substitute_entities(chosen_response, entities)
await message.respond(random.choice(self.response_options))