Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove registered keywords on skill shutdown #2877

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
71 changes: 60 additions & 11 deletions mycroft/skills/intent_services/adapt_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
# limitations under the License.
#
"""An intent parsing service using the Adapt parser."""
from threading import Lock
import time

from adapt.context import ContextManagerFrame
Expand All @@ -23,6 +24,21 @@
from .base import IntentMatch


def _entity_skill_id(skill_id):
"""Helper converting a skill id to the format used in entities.

Arguments:
skill_id (str): skill identifier

Returns:
(str) skill id on the format used by skill entities
"""
skill_id = skill_id[:-1]
skill_id = skill_id.replace('.', '_')
skill_id = skill_id.replace('-', '_')
return skill_id


class AdaptIntent(IntentBuilder):
"""Wrapper for IntentBuilder setting a blank name.

Expand Down Expand Up @@ -161,6 +177,7 @@ def __init__(self, config):
self.context_timeout = self.config.get('timeout', 2)
self.context_greedy = self.config.get('greedy', False)
self.context_manager = ContextManager(self.context_timeout)
self.lock = Lock()

def update_context(self, intent):
"""Updates context with keyword from the intent.
Expand Down Expand Up @@ -227,31 +244,63 @@ def take_best(intent, utt):

def register_vocab(self, start_concept, end_concept, alias_of, regex_str):
"""Register vocabulary."""
if regex_str:
self.engine.register_regex_entity(regex_str)
else:
self.engine.register_entity(
start_concept, end_concept, alias_of=alias_of)
with self.lock:
if regex_str:
self.engine.register_regex_entity(regex_str)
else:
self.engine.register_entity(
start_concept, end_concept, alias_of=alias_of)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is beyond the scope of this PR but I just went down a small rabbit hole of what start vs end concepts were and I think that these need to be renamed to better match it's usage eg Adapt now seems to use entity_value, entity_type.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a terrific idea. it's always been a bit (to say the least) un-intuitive names

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i always need to double check what these mean, i approve the renaming 👍


def register_intent(self, intent):
"""Register new intent with adapt engine.

Arguments:
intent (IntentParser): IntentParser to register
"""
self.engine.register_intent_parser(intent)
with self.lock:
self.engine.register_intent_parser(intent)

def detach_skill(self, skill_id):
"""Remove all intents for skill.

Arguments:
skill_id (str): skill to process
"""
new_parsers = [
p for p in self.engine.intent_parsers if
not p.name.startswith(skill_id)
]
self.engine.intent_parsers = new_parsers
with self.lock:
skill_parsers = [
p.name for p in self.engine.intent_parsers if
p.name.startswith(skill_id)
]
self.engine.drop_intent_parser(skill_parsers)
self._detach_skill_keywords(skill_id)
self._detach_skill_regexes(skill_id)

def _detach_skill_keywords(self, skill_id):
"""Detach all keywords registered with a particular skill.

Arguments:
skill_id (str): skill identifier
"""
skill_id = _entity_skill_id(skill_id)

def match_skill_entities(data):
return data and data[1].startswith(skill_id)

self.engine.drop_entity(match_func=match_skill_entities)

def _detach_skill_regexes(self, skill_id):
"""Detach all regexes registered with a particular skill.

Arguments:
skill_id (str): skill identifier
"""
skill_id = _entity_skill_id(skill_id)

def match_skill_regexes(regexp):
return any([r.startswith(skill_id)
for r in regexp.groupindex.keys()])

self.engine.drop_regex_entity(match_func=match_skill_regexes)

def detach_intent(self, intent_name):
"""Detatch a single intent
Expand Down
2 changes: 1 addition & 1 deletion requirements/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ lingua-franca==0.4.1
msm==0.8.9
msk==0.3.16
mycroft-messagebus-client==0.9.1
adapt-parser==0.3.7
adapt-parser==0.4.1
padatious==0.4.8
fann2==1.0.7
padaos==0.1.9
Expand Down