Merge pull request #2009 from MycroftAI/bugfix/voc-match

Fix behavior of MycroftSkills.voc_match()
pull/2017/head
Åke 2019-02-24 15:50:25 +01:00 committed by GitHub
commit faf29d1fef
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 67 additions and 21 deletions

View File

@ -26,6 +26,7 @@ from datetime import datetime, timedelta
import abc
import re
from itertools import chain
from adapt.intent import Intent, IntentBuilder
from os.path import join, abspath, dirname, basename, exists
from threading import Event, Timer
@ -41,7 +42,8 @@ from mycroft.messagebus.message import Message
from mycroft.metrics import report_metric, report_timing, Stopwatch
from mycroft.skills.settings import SkillSettings
from mycroft.skills.skill_data import (load_vocabulary, load_regex, to_alnum,
munge_regex, munge_intent_parser)
munge_regex, munge_intent_parser,
read_vocab_file)
from mycroft.util import camel_case_split, resolve_resource_file
from mycroft.util.log import LOG
@ -716,15 +718,15 @@ class MycroftSkill:
if not voc or not exists(voc):
raise FileNotFoundError(
'Could not find {}.voc file'.format(voc_filename))
with open(voc) as f:
self.voc_match_cache[cache_key] = f.read().splitlines()
# Check for match
if utt and any(i.strip() in utt
for i in self.voc_match_cache[cache_key]):
return True
return False
# load vocab and flatten into a simple list
vocab = list(chain(*read_vocab_file(voc)))
self.voc_match_cache[cache_key] = vocab
if utt:
# Check for matches against complete words
return any([re.match(r'.*\b' + i + r'\b.*', utt)
for i in self.voc_match_cache[cache_key]])
else:
return False
def report_metric(self, name, data):
""" Report a skill metric to the Mycroft servers

View File

@ -25,6 +25,28 @@ from mycroft.messagebus.message import Message
from mycroft.util.format import expand_options
def read_vocab_file(path):
""" Read voc file.
This reads a .voc file, stripping out empty lines comments and expand
parentheses. It retruns each line as a list of all expanded
alternatives.
Arguments:
path (str): path to vocab file.
Returns:
List of Lists of strings.
"""
vocab = []
with open(path, 'r', encoding='utf8') as voc_file:
for line in voc_file.readlines():
if line.startswith('#') or line.strip() == '':
continue
vocab.append(expand_options(line))
return vocab
def load_vocab_from_file(path, vocab_type, bus):
"""Load Mycroft vocabulary from file
The vocab is sent to the intent handler using the message bus
@ -36,19 +58,15 @@ def load_vocab_from_file(path, vocab_type, bus):
skill_id(str): skill id
"""
if path.endswith('.voc'):
with open(path, 'r', encoding='utf8') as voc_file:
for line in voc_file.readlines():
if line.startswith("#"):
continue
parts = expand_options(line)
entity = parts[0]
for parts in read_vocab_file(path):
entity = parts[0]
bus.emit(Message("register_vocab", {
'start': entity, 'end': vocab_type
}))
for alias in parts[1:]:
bus.emit(Message("register_vocab", {
'start': entity, 'end': vocab_type
'start': alias, 'end': vocab_type, 'alias_of': entity
}))
for alias in parts[1:]:
bus.emit(Message("register_vocab", {
'start': alias, 'end': vocab_type, 'alias_of': entity
}))
def load_regex_from_file(path, bus, skill_id):

View File

@ -0,0 +1 @@
(turn off|switch off)

View File

@ -0,0 +1,3 @@
turn off
switch off

View File

@ -484,6 +484,28 @@ class MycroftSkillTest(unittest.TestCase):
# handler
self.assertTrue('A:sched_handler1' not in [e[0] for e in s.events])
def test_voc_match(self):
s = SimpleSkill1()
s.root_dir = abspath(dirname(__file__))
self.assertTrue(s.voc_match("turn off the lights", "turn_off_test"))
self.assertTrue(s.voc_match("would you please turn off the lights",
"turn_off_test"))
self.assertFalse(s.voc_match("return office", "turn_off_test"))
self.assertTrue(s.voc_match("switch off the lights", "turn_off_test"))
self.assertFalse(s.voc_match("", "turn_off_test"))
self.assertFalse(s.voc_match("switch", "turn_off_test"))
self.assertFalse(s.voc_match("My hovercraft is full of eels",
"turn_off_test"))
self.assertTrue(s.voc_match("turn off the lights", "turn_off2_test"))
self.assertFalse(s.voc_match("return office", "turn_off2_test"))
self.assertTrue(s.voc_match("switch off the lights", "turn_off2_test"))
self.assertFalse(s.voc_match("", "turn_off_test"))
self.assertFalse(s.voc_match("switch", "turn_off_test"))
self.assertFalse(s.voc_match("My hovercraft is full of eels",
"turn_off_test"))
class _TestSkill(MycroftSkill):
def __init__(self):