Merge pull request #2418 from forslund/bugfix/missing-hotword-parts

Make sure hotword entry has phonemes and threshold
pull/2424/head
Åke 2019-12-09 20:24:58 +01:00 committed by GitHub
commit 2263fab0b6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 76 additions and 12 deletions

View File

@ -309,32 +309,52 @@ class RecognizerLoop(EventEmitter):
self.state = RecognizerLoopState() self.state = RecognizerLoopState()
def create_wake_word_recognizer(self): def create_wake_word_recognizer(self):
# Create a local recognizer to hear the wakeup word, e.g. 'Hey Mycroft' """Create a local recognizer to hear the wakeup word
LOG.info("creating wake word engine")
word = self.config.get("wake_word", "hey mycroft") For example 'Hey Mycroft'.
The method uses the hotword entry for the selected wakeword, if
one is missing it will fall back to the old phoneme and threshold in
the listener entry in the config.
If the hotword entry doesn't include phoneme and threshold values these
will be patched in using the defaults from the config listnere entry.
"""
LOG.info('Creating wake word engine')
word = self.config.get('wake_word', 'hey mycroft')
# TODO remove this, only for server settings compatibility # TODO remove this, only for server settings compatibility
phonemes = self.config.get("phonemes") phonemes = self.config.get('phonemes')
thresh = self.config.get("threshold") thresh = self.config.get('threshold')
# Since we're editing it for server backwards compatibility # Since we're editing it for server backwards compatibility
# use a copy so we don't alter the hash of the config and # use a copy so we don't alter the hash of the config and
# trigger a reload. # trigger a reload.
config = deepcopy(self.config_core.get("hotwords", {})) config = deepcopy(self.config_core.get('hotwords', {}))
if word not in config: if word not in config:
# Fallback to using config from "listener" block # Fallback to using config from "listener" block
LOG.warning('Wakeword doesn\'t have an entry falling back' LOG.warning('Wakeword doesn\'t have an entry falling back'
'to old listener config') 'to old listener config')
config[word] = {'module': 'precise'} config[word] = {'module': 'precise'}
if phonemes: if phonemes:
config[word]["phonemes"] = phonemes config[word]['phonemes'] = phonemes
if thresh: if thresh:
config[word]["threshold"] = thresh config[word]['threshold'] = thresh
if phonemes is None or thresh is None: if phonemes is None or thresh is None:
config = None config = None
return HotWordFactory.create_hotword( else:
word, config, self.lang, loop=self LOG.info('Using hotword entry for {}'.format(word))
) if 'phonemes' not in config[word]:
LOG.warning('Phonemes are missing falling back to listeners '
'configuration')
config[word]['phonemes'] = phonemes
if 'threshold' not in config[word]:
LOG.warning('Threshold is missing falling back to listeners '
'configuration')
config[word]['threshold'] = thresh
return HotWordFactory.create_hotword(word, config, self.lang,
loop=self)
def create_wakeup_recognizer(self): def create_wakeup_recognizer(self):
LOG.info("creating stand up word engine") LOG.info("creating stand up word engine")

View File

@ -51,7 +51,10 @@ class PocketSphinxRecognizerTest(unittest.TestCase):
class LocalRecognizerInitTest(unittest.TestCase): class LocalRecognizerInitTest(unittest.TestCase):
@patch.object(Configuration, 'get') @patch.object(Configuration, 'get')
def testRecognizer(self, mock_config_get): def testListenerConfig(self, mock_config_get):
"""Ensure that the fallback method collecting phonemes etc.
from the listener config works.
"""
test_config = base_config() test_config = base_config()
mock_config_get.return_value = test_config mock_config_get.return_value = test_config
@ -71,3 +74,44 @@ class LocalRecognizerInitTest(unittest.TestCase):
test_config['listener']['phonemes'] = 'ZZZZZZZZZZZZ' test_config['listener']['phonemes'] = 'ZZZZZZZZZZZZ'
rl = RecognizerLoop() rl = RecognizerLoop()
self.assertEqual(rl.wakeword_recognizer.key_phrase, "hey mycroft") self.assertEqual(rl.wakeword_recognizer.key_phrase, "hey mycroft")
@patch.object(Configuration, 'get')
def testHotwordConfig(self, mock_config_get):
"""Ensure that the fallback method collecting phonemes etc.
from the listener config works.
"""
test_config = base_config()
mock_config_get.return_value = test_config
# Set fallback values
test_config['listener']['phonemes'] = 'HH EY . V IH K T AO R IY AH'
test_config['listener']['threshold'] = 1e-90
steve_conf = {
'model': 'pocketsphinx',
'phonemes': 'S T IY V .',
'threshold': 1e-42
}
test_config['hotwords']['steve'] = steve_conf
test_config['listener']['wake_word'] = 'steve'
rl = RecognizerLoop()
self.assertEqual(rl.wakeword_recognizer.key_phrase, 'steve')
# Ensure phonemes and threshold are poulated from listener config
# if they're missing
# Set fallback values
test_config['listener']['phonemes'] = 'S T IY V .'
test_config['listener']['threshold'] = 1e-90
steve_conf = {
'model': 'pocketsphinx'
}
test_config['hotwords']['steve'] = steve_conf
test_config['listener']['wake_word'] = 'steve'
rl = RecognizerLoop()
self.assertEqual(rl.wakeword_recognizer.key_phrase, 'steve')
self.assertEqual(rl.wakeword_recognizer.phonemes, 'S T IY V .')