Source code for alex.components.hub.nlg

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import multiprocessing
import time

from alex.components.nlg.common import nlg_factory, get_nlg_type

from alex.components.hub.messages import Command, DMDA, TTSText
from alex.components.dm.exceptions import DMException

from alex.utils.procname import set_proc_name


[docs]class NLG(multiprocessing.Process): """The NLG component receives a dialogue act generated by the dialogue manager and then it converts the act into the text. This component is a wrapper around multiple NLG components which handles multiprocessing communication. """ def __init__(self, cfg, commands, dialogue_act_in, text_out, close_event): multiprocessing.Process.__init__(self) self.cfg = cfg self.commands = commands self.dialogue_act_in = dialogue_act_in self.text_out = text_out self.close_event = close_event nlg_type = get_nlg_type(cfg) self.nlg = nlg_factory(nlg_type, cfg)
[docs] def process_da(self, da): if da != "silence()": text = self.nlg.generate(da) if self.cfg['NLG']['debug']: s = [] s.append("NLG Output") s.append("-"*60) s.append(text) s.append("") s = '\n'.join(s) self.cfg['Logging']['system_logger'].debug(s) self.cfg['Logging']['session_logger'].text("system", text) self.commands.send(Command('nlg_text_generated()', 'NLG', 'HUB')) self.text_out.send(TTSText(text)) else: # the input dialogue is silence. Therefore, do not generate eny output. if self.cfg['NLG']['debug']: s = [] s.append("NLG Output") s.append("-"*60) s.append("DM sent 'silence()' therefore generating nothing") s.append("") s = '\n'.join(s) self.cfg['Logging']['system_logger'].debug(s) self.cfg['Logging']['session_logger'].text("system", "_silence_") self.commands.send(Command('nlg_text_generated()', 'NLG', 'HUB'))
[docs] def process_pending_commands(self): """Process all pending commands. Available commands: stop() - stop processing and exit the process flush() - flush input buffers. Now it only flushes the input connection. Return True if the process should terminate. """ while self.commands.poll(): command = self.commands.recv() if self.cfg['NLG']['debug']: self.cfg['Logging']['system_logger'].debug(command) if isinstance(command, Command): if command.parsed['__name__'] == 'stop': return True if command.parsed['__name__'] == 'flush': # discard all data in in input buffers while self.dialogue_act_in.poll(): data_in = self.dialogue_act_in.recv() # the NLG component does not have to be flushed #self.nlg.flush() self.commands.send(Command("flushed()", 'NLG', 'HUB')) return False elif isinstance(command, DMDA): self.process_da(command.da) return False
[docs] def read_dialogue_act_write_text(self): if self.dialogue_act_in.poll(): data_da = self.dialogue_act_in.recv() if isinstance(data_da, DMDA): self.process_da(data_da.da) elif isinstance(data_da, Command): self.cfg['Logging']['system_logger'].info(data_da) else: raise DMException('Unsupported input.')
[docs] def run(self): try: set_proc_name("Alex_NLG") self.cfg['Logging']['session_logger'].cancel_join_thread() while 1: # Check the close event. if self.close_event.is_set(): print 'Received close event in: %s' % multiprocessing.current_process().name return time.sleep(self.cfg['Hub']['main_loop_sleep_time']) s = (time.time(), time.clock()) # process all pending commands if self.process_pending_commands(): return # process the incoming DM dialogue acts self.read_dialogue_act_write_text() d = (time.time() - s[0], time.clock() - s[1]) if d[0] > 0.200: print "EXEC Time inner loop: NLG t = {t:0.4f} c = {c:0.4f}\n".format(t=d[0], c=d[1]) except KeyboardInterrupt: print 'KeyboardInterrupt exception in: %s' % multiprocessing.current_process().name self.close_event.set() return except: self.cfg['Logging']['system_logger'].exception('Uncaught exception in NLG process.') self.close_event.set() raise print 'Exiting: %s. Setting close event' % multiprocessing.current_process().name self.close_event.set()