def main(): reset_sigint_handler() # Create PID file, prevent multiple instances of this service mycroft.lock.Lock('skills') config = Configuration.get() # Set the active lang to match the configured one set_active_lang(config.get('lang', 'en-us')) # Connect this process to the Mycroft message bus bus = _start_message_bus_client() _register_intent_services(bus) event_scheduler = EventScheduler(bus) skill_manager = _initialize_skill_manager(bus) _wait_for_internet_connection() if skill_manager is None: skill_manager = _initialize_skill_manager(bus) device_primer = DevicePrimer(bus, config) device_primer.prepare_device() skill_manager.start() wait_for_exit_signal() shutdown(skill_manager, event_scheduler)
def main(ready_hook=on_ready, error_hook=on_error, stopping_hook=on_stopping, watchdog=None): reset_sigint_handler() # Create PID file, prevent multiple instances of this service mycroft.lock.Lock('skills') config = Configuration.get() # Set the active lang to match the configured one set_active_lang(config.get('lang', 'en-us')) # Connect this process to the Mycroft message bus bus = _start_message_bus_client() _register_intent_services(bus) event_scheduler = EventScheduler(bus) skill_manager = _initialize_skill_manager(bus, watchdog) _wait_for_internet_connection() if skill_manager is None: skill_manager = _initialize_skill_manager(bus, watchdog) device_primer = DevicePrimer(bus, config) device_primer.prepare_device() skill_manager.start() while not skill_manager.is_alive(): time.sleep(0.1) ready_hook() # Report ready status wait_for_exit_signal() stopping_hook() # Report shutdown started shutdown(skill_manager, event_scheduler)
def listener(): rospy.init_node('mycroft_skills') rospy.loginfo(rospy.get_caller_id() + " started") rospy.Subscriber("mycroft/utterance", String, handle_utterance) rospy.Subscriber("mycroft/remove_skill", String, handle_remove_skill) s = rospy.Service('mycroft/register_skill', MycroftService, handle_register_skill) global bus reset_sigint_handler() # Create PID file, prevent multiple instancesof this service mycroft.lock.Lock('skills') # Connect this Skill management process to the Mycroft Messagebus bus = WebsocketClient() Configuration.init(bus) config = Configuration.get() # Set the active lang to match the configured one set_active_lang(config.get('lang', 'en-us')) bus.on('skill.manager.initialised', initialise_response_server) bus.on('message', create_echo_function('SKILLS')) # Startup will be called after the connection with the Messagebus is done bus.once('open', _starting_up) bus.on('skill.converse.request', check_working) create_daemon(bus.run_forever) wait_for_exit_signal() shutdown() rospy.spin()
def handle_utterance(self, message): """ Main entrypoint for handling user utterances with Mycroft skills Monitor the messagebus for 'recognizer_loop:utterance', typically generated by a spoken interaction but potentially also from a CLI or other method of injecting a 'user utterance' into the system. Utterances then work through this sequence to be handled: 1) Active skills attempt to handle using converse() 2) Adapt intent handlers 3) Padatious intent handlers 4) Other fallbacks Args: message (Message): The messagebus data """ try: # Get language of the utterance lang = message.data.get('lang', "en-us") set_active_lang(lang) utterances = message.data.get('utterances', '') stopwatch = Stopwatch() with stopwatch: # Give active skills an opportunity to handle the utterance converse = self._converse(utterances, lang) if not converse: # No conversation, use intent system to handle utterance intent = self._adapt_intent_match(utterances, lang) padatious_intent = PadatiousService.instance.calc_intent( utterances[0]) if converse: # Report that converse handled the intent and return ident = message.context['ident'] if message.context else None report_timing(ident, 'intent_service', stopwatch, {'intent_type': 'converse'}) return elif intent and not (padatious_intent and padatious_intent.conf >= 0.95): # Send the message to the Adapt intent's handler unless # Padatious is REALLY sure it was directed at it instead. reply = message.reply(intent.get('intent_type'), intent) else: # Allow fallback system to handle utterance # NOTE: Padatious intents are handled this way, too reply = message.reply('intent_failure', { 'utterance': utterances[0], 'lang': lang }) self.bus.emit(reply) self.send_metrics(intent, message.context, stopwatch) except Exception as e: LOG.exception(e)
def main(alive_hook=on_alive, started_hook=on_started, ready_hook=on_ready, error_hook=on_error, stopping_hook=on_stopping, watchdog=None): reset_sigint_handler() # Create PID file, prevent multiple instances of this service mycroft.lock.Lock('skills') config = Configuration.get() # Set the active lang to match the configured one set_active_lang(config.get('lang', 'en-us')) # Connect this process to the Mycroft message bus bus = start_message_bus_client("SKILLS") _register_intent_services(bus) event_scheduler = EventScheduler(bus) callbacks = StatusCallbackMap(on_started=started_hook, on_alive=alive_hook, on_ready=ready_hook, on_error=error_hook, on_stopping=stopping_hook) status = ProcessStatus('skills', bus, callbacks) SkillApi.connect_bus(bus) skill_manager = _initialize_skill_manager(bus, watchdog) status.set_started() _wait_for_internet_connection() if skill_manager is None: skill_manager = _initialize_skill_manager(bus, watchdog) device_primer = DevicePrimer(bus, config) device_primer.prepare_device() skill_manager.start() while not skill_manager.is_alive(): time.sleep(0.1) status.set_alive() while not skill_manager.is_all_loaded(): time.sleep(0.1) status.set_ready() wait_for_exit_signal() status.set_stopping() shutdown(skill_manager, event_scheduler)
def main(): global bus reset_sigint_handler() # Create PID file, prevent multiple instancesof this service mycroft.lock.Lock('skills') # Connect this Skill management process to the Mycroft Messagebus bus = WebsocketClient() Configuration.init(bus) config = Configuration.get() # Set the active lang to match the configured one set_active_lang(config.get('lang', 'en-us')) bus.on('message', create_echo_function('SKILLS')) # Startup will be called after the connection with the Messagebus is done bus.once('open', _starting_up) create_daemon(bus.run_forever) wait_for_exit_signal() shutdown()
def tearDown(self): set_active_lang(self.old_lang)
def handle_utterance(self, message): """Main entrypoint for handling user utterances with Mycroft skills Monitor the messagebus for 'recognizer_loop:utterance', typically generated by a spoken interaction but potentially also from a CLI or other method of injecting a 'user utterance' into the system. Utterances then work through this sequence to be handled: 1) Active skills attempt to handle using converse() 2) Padatious high match intents (conf > 0.95) 3) Adapt intent handlers 5) High Priority Fallbacks 6) Padatious near match intents (conf > 0.8) 7) General Fallbacks 8) Padatious loose match intents (conf > 0.5) 9) Catch all fallbacks including Unknown intent handler If all these fail the complete_intent_failure message will be sent and a generic info of the failure will be spoken. Arguments: message (Message): The messagebus data """ try: lang = _get_message_lang(message) set_active_lang(lang) utterances = message.data.get('utterances', []) combined = _normalize_all_utterances(utterances) stopwatch = Stopwatch() # List of functions to use to match the utterance with intent. # These are listed in priority order. match_funcs = [ self._converse, 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 ] match = None with stopwatch: # Loop through the matching functions until a match is found. for match_func in match_funcs: match = match_func(combined, lang, message) if match: break if match: if match.skill_id: self.add_active_skill(match.skill_id) # If the service didn't report back the skill_id it # takes on the responsibility of making the skill "active" # Launch skill if not handled by the match function if match.intent_type: reply = message.reply(match.intent_type, match.intent_data) self.bus.emit(reply) else: # Nothing was able to handle the intent # Ask politely for forgiveness for failing in this vital task self.send_complete_intent_failure(message) self.send_metrics(match, message.context, stopwatch) except Exception as err: LOG.exception(err)
def reset_converse(self, message): """Let skills know there was a problem with speech recognition""" lang = _get_message_lang(message) set_active_lang(lang) for skill in copy(self.active_skills): self.do_converse(None, skill[0], lang, message)
def handle_utterance(self, message): """ Main entrypoint for handling user utterances with Mycroft skills Monitor the messagebus for 'recognizer_loop:utterance', typically generated by a spoken interaction but potentially also from a CLI or other method of injecting a 'user utterance' into the system. Utterances then work through this sequence to be handled: 1) Active skills attempt to handle using converse() 2) Padatious high match intents (conf > 0.95) 3) Adapt intent handlers 5) Fallbacks: - Padatious near match intents (conf > 0.8) - General fallbacks - Padatious loose match intents (conf > 0.5) - Unknown intent handler Args: message (Message): The messagebus data """ try: # Get language of the utterance lang = message.data.get('lang', "en-us") set_active_lang(lang) utterances = message.data.get('utterances', []) # normalize() changes "it's a boy" to "it is a boy", etc. norm_utterances = [ normalize(u.lower(), remove_articles=False) for u in utterances ] # Build list with raw utterance(s) first, then optionally a # normalized version following. combined = utterances + list( set(norm_utterances) - set(utterances)) LOG.debug("Utterances: {}".format(combined)) stopwatch = Stopwatch() intent = None padatious_intent = None with stopwatch: # Give active skills an opportunity to handle the utterance converse = self._converse(combined, lang, message) if not converse: # No conversation, use intent system to handle utterance intent = self._adapt_intent_match(utterances, norm_utterances, lang) for utt in combined: _intent = PadatiousService.instance.calc_intent(utt) if _intent: best = padatious_intent.conf if padatious_intent \ else 0.0 if best < _intent.conf: padatious_intent = _intent LOG.debug("Padatious intent: {}".format(padatious_intent)) LOG.debug(" Adapt intent: {}".format(intent)) if converse: # Report that converse handled the intent and return LOG.debug("Handled in converse()") ident = None if message.context and 'ident' in message.context: ident = message.context['ident'] report_timing(ident, 'intent_service', stopwatch, {'intent_type': 'converse'}) return elif (intent and intent.get('confidence', 0.0) > 0.0 and not (padatious_intent and padatious_intent.conf >= 0.95)): # Send the message to the Adapt intent's handler unless # Padatious is REALLY sure it was directed at it instead. self.update_context(intent) # update active skills skill_id = intent['intent_type'].split(":")[0] self.add_active_skill(skill_id) # Adapt doesn't handle context injection for one_of keywords # correctly. Workaround this issue if possible. try: intent = workaround_one_of_context(intent) except LookupError: LOG.error('Error during workaround_one_of_context') reply = message.reply(intent.get('intent_type'), intent) else: # Allow fallback system to handle utterance # NOTE: A matched padatious_intent is handled this way, too # TODO: Need to redefine intent_failure when STT can return # multiple hypothesis -- i.e. len(utterances) > 1 reply = message.reply( 'intent_failure', { 'utterance': utterances[0], 'norm_utt': norm_utterances[0], 'lang': lang }) self.bus.emit(reply) self.send_metrics(intent, message.context, stopwatch) except Exception as e: LOG.exception(e)
def reset_converse(self, message): """Let skills know there was a problem with speech recognition""" lang = message.data.get('lang', "en-us") set_active_lang(lang) for skill in self.active_skills: self.do_converse(None, skill[0], lang)
def setUp(self): self.old_lang = get_active_lang() set_active_lang("de-de")
def handle_utterance(self, message): """ Main entrypoint for handling user utterances with Mycroft skills Monitor the messagebus for 'recognizer_loop:utterance', typically generated by a spoken interaction but potentially also from a CLI or other method of injecting a 'user utterance' into the system. Utterances then work through this sequence to be handled: 1) Active skills attempt to handle using converse() 2) Padatious high match intents (conf > 0.95) 3) Adapt intent handlers 5) Fallbacks: - Padatious near match intents (conf > 0.8) - General fallbacks - Padatious loose match intents (conf > 0.5) - Unknown intent handler Args: message (Message): The messagebus data """ try: # Get language of the utterance lang = message.data.get('lang', "en-us") set_active_lang(lang) utterances = message.data.get('utterances', []) # normalize() changes "it's a boy" to "it is a boy", etc. norm_utterances = [normalize(u.lower(), remove_articles=False) for u in utterances] # Build list with raw utterance(s) first, then optionally a # normalized version following. combined = utterances + list(set(norm_utterances) - set(utterances)) LOG.debug("Utterances: {}".format(combined)) stopwatch = Stopwatch() intent = None padatious_intent = None with stopwatch: # Give active skills an opportunity to handle the utterance converse = self._converse(combined, lang) if not converse: # No conversation, use intent system to handle utterance intent = self._adapt_intent_match(utterances, norm_utterances, lang) for utt in combined: _intent = PadatiousService.instance.calc_intent(utt) if _intent: best = padatious_intent.conf if padatious_intent\ else 0.0 if best < _intent.conf: padatious_intent = _intent LOG.debug("Padatious intent: {}".format(padatious_intent)) LOG.debug(" Adapt intent: {}".format(intent)) if converse: # Report that converse handled the intent and return LOG.debug("Handled in converse()") ident = message.context['ident'] if message.context else None report_timing(ident, 'intent_service', stopwatch, {'intent_type': 'converse'}) return elif (intent and intent.get('confidence', 0.0) > 0.0 and not (padatious_intent and padatious_intent.conf >= 0.95)): # Send the message to the Adapt intent's handler unless # Padatious is REALLY sure it was directed at it instead. self.update_context(intent) # update active skills skill_id = intent['intent_type'].split(":")[0] self.add_active_skill(skill_id) # Adapt doesn't handle context injection for one_of keywords # correctly. Workaround this issue if possible. try: intent = workaround_one_of_context(intent) except LookupError: LOG.error('Error during workaround_one_of_context') reply = message.reply(intent.get('intent_type'), intent) else: # Allow fallback system to handle utterance # NOTE: A matched padatious_intent is handled this way, too # TODO: Need to redefine intent_failure when STT can return # multiple hypothesis -- i.e. len(utterances) > 1 reply = message.reply('intent_failure', {'utterance': utterances[0], 'norm_utt': norm_utterances[0], 'lang': lang}) self.bus.emit(reply) self.send_metrics(intent, message.context, stopwatch) except Exception as e: LOG.exception(e)