Skip to content
This repository was archived by the owner on Sep 8, 2024. It is now read-only.
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
8 changes: 3 additions & 5 deletions mycroft/client/speech/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,8 @@ def mute_and_speak(utterance):
lock.release()


def handle_multi_utterance_intent_failure(event):
logger.info("Failed to find intent on multiple intents.")
def handle_complete_intent_failure(event):
logger.info("Failed to find intent.")
# TODO: Localize
mute_and_speak("Sorry, I didn't catch that. Please rephrase your request.")

Expand Down Expand Up @@ -205,9 +205,7 @@ def main():
loop.on('recognizer_loop:no_internet', handle_no_internet)
ws.on('open', handle_open)
ws.on('speak', handle_speak)
ws.on(
'multi_utterance_intent_failure',
handle_multi_utterance_intent_failure)
ws.on('complete_intent_failure', handle_complete_intent_failure)
ws.on('recognizer_loop:sleep', handle_sleep)
ws.on('recognizer_loop:wake_up', handle_wake_up)
ws.on('mycroft.mic.mute', handle_mic_mute)
Expand Down
50 changes: 48 additions & 2 deletions mycroft/skills/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,11 @@
#
# You should have received a copy of the GNU General Public License
# along with Mycroft Core. If not, see <http://www.gnu.org/licenses/>.


import abc
import imp
import time

import operator
import os.path
import re
import time
Expand Down Expand Up @@ -383,3 +382,50 @@ def shutdown(self):
self.emitter.emit(
Message("detach_skill", {"skill_name": self.name + ":"}))
self.stop()


class FallbackSkill(MycroftSkill):
fallback_handlers = {}

def __init__(self, name, emitter=None):
MycroftSkill.__init__(self, name, emitter)

@classmethod
def make_intent_failure_handler(cls, ws):
"""Goes through all fallback handlers until one returns true"""

def handler(message):
for _, handler in sorted(cls.fallback_handlers.items(),
key=operator.itemgetter(0)):
try:
if handler(message):
return
except Exception as e:
logger.info('Exception in fallback: ' + str(e))
ws.emit(Message('complete_intent_failure'))
logger.warn('No fallback could handle intent.')

return handler

@classmethod
def register_fallback(cls, handler, priority):
"""
Register a function to be called as a general info fallback
Fallback should receive message and return
a boolean (True if succeeded or False if failed)

Lower priority gets run first
0 for high priority 100 for low priority
"""
while priority in cls.fallback_handlers:
priority += 1

cls.fallback_handlers[priority] = handler

@classmethod
def remove_fallback(cls, handler_to_del):
for priority, handler in cls.fallback_handlers.items():
if handler == handler_to_del:
del cls.fallback_handlers[priority]
return
logger.warn('Could not remove fallback!')
7 changes: 1 addition & 6 deletions mycroft/skills/intent_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,16 +63,11 @@ def handle_utterance(self, message):
reply = message.reply(
best_intent.get('intent_type'), best_intent)
self.emitter.emit(reply)
elif len(utterances) == 1:
else:
self.emitter.emit(Message("intent_failure", {
"utterance": utterances[0],
"lang": lang
}))
else:
self.emitter.emit(Message("multi_utterance_intent_failure", {
"utterances": utterances,
"lang": lang
}))

def handle_register_vocab(self, message):
start_concept = message.data.get('start')
Expand Down
4 changes: 3 additions & 1 deletion mycroft/skills/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
from mycroft.messagebus.client.ws import WebsocketClient
from mycroft.messagebus.message import Message
from mycroft.skills.core import load_skill, create_skill_descriptor, \
MainModule, SKILLS_DIR
MainModule, SKILLS_DIR, FallbackSkill
from mycroft.skills.intent_service import IntentService
from mycroft.util import connected
from mycroft.util.log import getLogger
Expand Down Expand Up @@ -117,6 +117,8 @@ def _load_skills():

check_connection()

ws.on('intent_failure', FallbackSkill.make_intent_failure_handler(ws))

# Create skill_manager listener and invoke the first time
ws.on('skill_manager', skills_manager)
ws.on('mycroft.internet.connected', install_default_skills)
Expand Down