mycroft-core/mycroft/skills/intent_service.py

99 lines
3.6 KiB
Python

# Copyright 2016 Mycroft AI, Inc.
#
# This file is part of Mycroft Core.
#
# Mycroft Core is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Mycroft Core is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Mycroft Core. If not, see <http://www.gnu.org/licenses/>.
from adapt.engine import IntentDeterminationEngine
from mycroft.messagebus.message import Message
from mycroft.skills.core import open_intent_envelope
from mycroft.util.log import getLogger
from mycroft.util.parse import normalize
__author__ = 'seanfitz'
logger = getLogger(__name__)
class IntentService(object):
def __init__(self, emitter):
self.engine = IntentDeterminationEngine()
self.emitter = emitter
self.emitter.on('register_vocab', self.handle_register_vocab)
self.emitter.on('register_intent', self.handle_register_intent)
self.emitter.on('recognizer_loop:utterance', self.handle_utterance)
self.emitter.on('detach_intent', self.handle_detach_intent)
self.emitter.on('detach_skill', self.handle_detach_skill)
def handle_utterance(self, message):
# Get language of the utterance
lang = message.data.get('lang', None)
if not lang:
lang = "en-us"
utterances = message.data.get('utterances', '')
best_intent = None
for utterance in utterances:
try:
# normalize() changes "it's a boy" to "it is boy", etc.
best_intent = next(self.engine.determine_intent(
normalize(utterance, lang), 100))
# TODO - Should Adapt handle this?
best_intent['utterance'] = utterance
except StopIteration, e:
logger.exception(e)
continue
if best_intent and best_intent.get('confidence', 0.0) > 0.0:
reply = message.reply(
best_intent.get('intent_type'), best_intent)
self.emitter.emit(reply)
else:
self.emitter.emit(Message("intent_failure", {
"utterance": utterances[0],
"lang": lang
}))
def handle_register_vocab(self, message):
start_concept = message.data.get('start')
end_concept = message.data.get('end')
regex_str = message.data.get('regex')
alias_of = message.data.get('alias_of')
if regex_str:
self.engine.register_regex_entity(regex_str)
else:
self.engine.register_entity(
start_concept, end_concept, alias_of=alias_of)
def handle_register_intent(self, message):
intent = open_intent_envelope(message)
self.engine.register_intent_parser(intent)
def handle_detach_intent(self, message):
intent_name = message.data.get('intent_name')
new_parsers = [
p for p in self.engine.intent_parsers if p.name != intent_name]
self.engine.intent_parsers = new_parsers
def handle_detach_skill(self, message):
skill_name = message.data.get('skill_name')
new_parsers = [
p for p in self.engine.intent_parsers if
not p.name.startswith(skill_name)]
self.engine.intent_parsers = new_parsers