Skip to content
This repository has been archived by the owner on Sep 8, 2024. It is now read-only.

fix/intent_api #2786

Merged
merged 5 commits into from
Dec 31, 2020
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
117 changes: 91 additions & 26 deletions mycroft/skills/intent_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -117,14 +117,21 @@ def add_active_skill_handler(message):

# Intents API
self.registered_vocab = []
self.bus.on('intent.service.adapt.get', self.handle_get_adapt)
self.bus.on('intent.service.intent.get', self.handle_get_intent)
self.bus.on('intent.service.skills.get', self.handle_get_skills)
self.bus.on('intent.service.active_skills.get',
self.handle_get_active_skills)
self.bus.on('intent.service.adapt.manifest.get', self.handle_manifest)
self.bus.on('intent.service.adapt.get', self.handle_get_adapt)
self.bus.on('intent.service.adapt.manifest.get',
self.handle_adapt_manifest)
self.bus.on('intent.service.adapt.vocab.manifest.get',
self.handle_vocab_manifest)
self.bus.on('intent.service.padatious.get',
self.handle_get_padatious)
self.bus.on('intent.service.padatious.manifest.get',
self.handle_padatious_manifest)
self.bus.on('intent.service.padatious.entities.manifest.get',
self.handle_entity_manifest)

@property
def registered_intents(self):
Expand Down Expand Up @@ -420,20 +427,6 @@ def handle_clear_context(self, _):
"""Clears all keywords from context """
self.adapt_service.context_manager.clear_context()

def handle_get_adapt(self, message):
"""handler getting the adapt response for an utterance.

Arguments:
message (Message): message containing utterance
"""
utterance = message.data["utterance"]
lang = message.data.get("lang", "en-us")
combined = _normalize_all_utterances([utterance])
intent = self.adapt_service.match_intent(combined, lang)
intent_data = intent.intent_data if intent else None
self.bus.emit(message.reply("intent.service.adapt.reply",
{"intent": intent_data}))

def handle_get_intent(self, message):
"""Get intent from either adapt or padatious.

Expand All @@ -443,14 +436,37 @@ def handle_get_intent(self, message):
utterance = message.data["utterance"]
lang = message.data.get("lang", "en-us")
combined = _normalize_all_utterances([utterance])
adapt_intent = self.adapt_service.match_intent(combined, lang)
# Adapt intent's handler is used unless
# Padatious is REALLY sure it was directed at it instead.
padatious_intent = self.padatious_service.match_high(combined)
intent = padatious_intent or adapt_intent
intent_data = intent.intent_data if intent else None

# List of functions to use to match the utterance with intent.
# These are listed in priority order.
# TODO once we have a mechanism for checking if a fallback will
# trigger without actually triggering it, those should be added here
match_funcs = [
self.padatious_service.match_high,
self.adapt_service.match_intent,
# self.fallback.high_prio,
self.padatious_service.match_medium,
# self.fallback.medium_prio,
self.padatious_service.match_low,
# self.fallback.low_prio
]
JarbasAl marked this conversation as resolved.
Show resolved Hide resolved
# Loop through the matching functions until a match is found.
for match_func in match_funcs:
match = match_func(combined, lang, message)
if match:
if match.intent_type:
intent_data = match.intent_data
intent_data["intent_name"] = match.intent_type
intent_data["intent_service"] = match.intent_service
intent_data["skill_id"] = match.skill_id
intent_data["handler"] = match_func.__name__
self.bus.emit(message.reply("intent.service.intent.reply",
{"intent": intent_data}))
return

# signal intent failure
self.bus.emit(message.reply("intent.service.intent.reply",
{"intent": intent_data}))
{"intent": None}))

def handle_get_skills(self, message):
"""Send registered skills to caller.
Expand All @@ -468,10 +484,23 @@ def handle_get_active_skills(self, message):
message: query message to reply to.
"""
self.bus.emit(message.reply("intent.service.active_skills.reply",
{"skills": [s[0] for s in
self.active_skills]}))
{"skills": self.active_skills}))

def handle_get_adapt(self, message):
"""handler getting the adapt response for an utterance.

def handle_manifest(self, message):
Arguments:
message (Message): message containing utterance
"""
utterance = message.data["utterance"]
lang = message.data.get("lang", "en-us")
combined = _normalize_all_utterances([utterance])
intent = self.adapt_service.match_intent(combined, lang)
intent_data = intent.intent_data if intent else None
self.bus.emit(message.reply("intent.service.adapt.reply",
{"intent": intent_data}))

def handle_adapt_manifest(self, message):
"""Send adapt intent manifest to caller.

Argument:
Expand All @@ -488,3 +517,39 @@ def handle_vocab_manifest(self, message):
"""
self.bus.emit(message.reply("intent.service.adapt.vocab.manifest",
{"vocab": self.registered_vocab}))

def handle_get_padatious(self, message):
"""messagebus handler for perfoming padatious parsing.

Arguments:
message (Message): message triggering the method
"""
utterance = message.data["utterance"]
norm = message.data.get('norm_utt', utterance)
intent = self.padatious_service.calc_intent(utterance)
if not intent and norm != utterance:
intent = self.padatious_service.calc_intent(norm)
if intent:
intent = intent.__dict__
self.bus.emit(message.reply("intent.service.padatious.reply",
{"intent": intent}))

def handle_padatious_manifest(self, message):
"""Messagebus handler returning the registered padatious intents.

Arguments:
message (Message): message triggering the method
"""
self.bus.emit(message.reply(
"intent.service.padatious.manifest",
{"intents": self.padatious_service.registered_intents}))

def handle_entity_manifest(self, message):
"""Messagebus handler returning the registered padatious entities.

Arguments:
message (Message): message triggering the method
"""
self.bus.emit(message.reply(
"intent.service.padatious.entities.manifest",
{"entities": self.padatious_service.registered_entities}))
13 changes: 9 additions & 4 deletions mycroft/skills/intent_service_interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ class IntentServiceInterface:

This class wraps the messagebus interface of the intent service allowing
for easier interaction with the service. It wraps both the Adapt and
Precise parts of the intent services.
Padatious parts of the intent services.
"""

def __init__(self, bus=None):
Expand Down Expand Up @@ -225,8 +225,11 @@ def get_skill(self, utterance, lang="en-us"):
intent = self.get_intent(utterance, lang)
if not intent:
return None
# theoretically skill_id might be missing
if intent.get("skill_id"):
return intent["skill_id"]
# retrieve skill from munged intent name
if intent.get("name"): # padatious
if intent.get("intent_name"): # padatious + adapt
return intent["name"].split(":")[0]
if intent.get("intent_type"): # adapt
return intent["intent_type"].split(":")[0]
Expand All @@ -245,7 +248,7 @@ def get_skills_manifest(self):
return None
return data["skills"]

def get_active_skills(self):
def get_active_skills(self, include_timestamps=False):
msg = Message("intent.service.active_skills.get",
context={"destination": "intent_service",
"source": "intent_api"})
Expand All @@ -256,7 +259,9 @@ def get_active_skills(self):
if not data:
LOG.error("Intent Service timed out!")
return None
return data["skills"]
if include_timestamps:
return data["skills"]
return [s[0] for s in data["skills"]]

def get_adapt_manifest(self):
msg = Message("intent.service.adapt.manifest.get",
Expand Down
40 changes: 0 additions & 40 deletions mycroft/skills/intent_services/padatious_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,11 +52,6 @@ def __init__(self, bus, config):
self.bus.on('detach_intent', self.handle_detach_intent)
self.bus.on('detach_skill', self.handle_detach_skill)
self.bus.on('mycroft.skills.initialized', self.train)
self.bus.on('intent.service.padatious.get', self.handle_get_padatious)
self.bus.on('intent.service.padatious.manifest.get',
self.handle_manifest)
self.bus.on('intent.service.padatious.entities.manifest.get',
self.handle_entity_manifest)

self.finished_training_event = Event()
self.finished_initial_train = False
Expand Down Expand Up @@ -229,41 +224,6 @@ def match_low(self, utterances, _=None, __=None):
"""
return self._match_level(utterances, 0.5)

def handle_get_padatious(self, message):
"""messagebus handler for perfoming padatious parsing.

Arguments:
message (Message): message triggering the method
"""
utterance = message.data["utterance"]
norm = message.data.get('norm_utt', utterance)
intent = self.calc_intent(utterance)
if not intent and norm != utterance:
intent = self.calc_intent(norm)
if intent:
intent = intent.__dict__
self.bus.emit(message.reply("intent.service.padatious.reply",
{"intent": intent}))

def handle_manifest(self, message):
"""Messagebus handler returning the registered padatious intents.

Arguments:
message (Message): message triggering the method
"""
self.bus.emit(message.reply("intent.service.padatious.manifest",
{"intents": self.registered_intents}))

def handle_entity_manifest(self, message):
"""Messagebus handler returning the registered padatious entities.

Arguments:
message (Message): message triggering the method
"""
self.bus.emit(
message.reply("intent.service.padatious.entities.manifest",
{"entities": self.registered_entities}))

@lru_cache(maxsize=2) # 2 catches both raw and normalized utts in cache
def calc_intent(self, utt):
"""Cached version of container calc_intent.
Expand Down
2 changes: 1 addition & 1 deletion test/unittests/skills/test_intent_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -289,7 +289,7 @@ def test_get_adapt_intent_manifest(self):
"""Make sure the manifest returns a list of Intent Parser objects."""
self.setup_simple_adapt_intent()
msg = Message('intent.service.adapt.manifest.get')
self.intent_service.handle_manifest(msg)
self.intent_service.handle_adapt_manifest(msg)
reply = get_last_message(self.intent_service.bus)
self.assertEqual(reply.data['intents'][0]['name'],
'skill:testIntent')
Expand Down