Esempio n. 1
0
#!/usr/bin/env python
# -*- coding: utf-8 -*-

from module_manager import ModuleManager
from module_list import module_list_data
if __name__ == '__main__':
    mm = ModuleManager()

    for i in module_list_data:
        mm.create_class_instance(i[0], i[1], i[2], i[3] )

    # init all instances
    mm.init_all_instance()

    # start server 
    mm.get_class_instance('nfc_server').start()
Esempio n. 2
0
    if args.test_mode:

        print('Starting evaluation: {}'.format(
            datetime.now().strftime("%m/%d/%Y %H:%M:%S")))

        model = load_model(args.model_path, args.task == 'detect')
        evaluate(args.task, model, test_examples, args.model_name, args.rerank)

        print('Terminating evaluation: {}'.format(
            datetime.now().strftime("%m/%d/%Y %H:%M:%S")))
    else:
        print('Starting training: {}'.format(
            datetime.now().strftime("%m/%d/%Y %H:%M:%S")))

        manager = ModuleManager(args.attend_code_sequence_states,
                                args.attend_code_graph_states, args.features,
                                args.posthoc, args.task, args.pickle)
        manager.initialize(train_examples)
        model = build_model(args.task, args.model_path, manager)



        # bacthes = manager.get_batches(train_examples, device=torch.device('cuda'), shuffle=True)
        #
        # print('BATCHES:')
        # for b in bacthes:
        #     print(b)
        #     break
        #
        # exit(0)
Esempio n. 3
0
    def __init__(self, **kwargs):
        ## Make sure there's a Discord token before doing anything else
        self.token = CONFIG_OPTIONS.get("discord_token")
        if (not self.token):
            raise RuntimeError("Unable to get Discord token!")

        self.version = kwargs.get(self.VERSION_KEY, self.VERSION)
        self.activation_str = kwargs.get(self.ACTIVATION_STR_KEY,
                                         self.ACTIVATION_STR)
        self.description = kwargs.get(self.DESCRIPTION_KEY, self.DESCRIPTION)
        self.invalid_command_minimum_similarity = float(
            kwargs.get(self.INVALID_COMMAND_MINIMUM_SIMILARITY, 0.66))

        self.dynamo_db = dynamo_helper.DynamoHelper()

        ## Init the bot and module manager
        self.bot = commands.Bot(command_prefix=commands.when_mentioned_or(
            self.activation_str),
                                description=self.description)
        self.module_manager = ModuleManager(self, self.bot)

        ## Apply customized HelpCommand
        self.bot.help_command = help_command.HawkingHelpCommand()

        ## Register the modules (Order of registration is important, make sure dependancies are loaded first)
        self.module_manager.register(message_parser.MessageParser, False)
        self.module_manager.register(admin.Admin, True, self, self.bot)
        self.module_manager.register(speech.Speech, True, self)
        self.module_manager.register(
            audio_player.AudioPlayer, True, self.bot,
            self.get_speech_cog().play_random_channel_timeout_message)

        ## Load any dynamic modules inside the /modules folder
        self.module_manager.discover()

        ## Give some feedback for when the bot is ready to go, and provide some help text via the 'playing' status
        @self.bot.event
        async def on_ready():
            ## todo: Activity instead of Game? Potentially remove "Playing" text below bot
            bot_status = discord.Game(type=0,
                                      name="Use {}help".format(
                                          self.activation_str))
            await self.bot.change_presence(activity=bot_status)

            logger.info("Logged in as '{}' (version: {}), (id: {})".format(
                self.bot.user.name, self.version, self.bot.user.id))

        ## Give some feedback to users when their command doesn't execute.
        @self.bot.event
        async def on_command_error(ctx, exception):
            '''Handles command errors. Attempts to find a similar command and suggests it, otherwise directs the user to the help prompt.'''

            self.dynamo_db.put(
                dynamo_helper.DynamoItem(ctx, ctx.message.content,
                                         inspect.currentframe().f_code.co_name,
                                         False, str(exception)))

            ## Attempt to find a command that's similar to the one they wanted. Otherwise just direct them to the help page
            most_similar_command = self.find_most_similar_command(
                ctx.message.content)

            if (most_similar_command[0] == ctx.invoked_with):
                logger.exception(
                    "Unable to complete command, with content: {}, for author: {}, in channel {}, in server: {}"
                    .format(ctx.message.content, ctx.message.author.name,
                            ctx.guild.name),
                    exc_info=exception)
                ## Handle issues where the command is valid, but couldn't be completed for whatever reason.
                await ctx.send(
                    "I'm sorry <@{}>, I'm afraid I can't do that.\nSomething went wrong, and I couldn't complete the command."
                    .format(ctx.message.author.id))
            else:
                logger.exception(
                    "Received invalid command: '{0}{1}', suggested: '{0}{2}', for author: {3}, in server: {4}"
                    .format(self.activation_str, ctx.invoked_with,
                            most_similar_command[0], ctx.message.author.name,
                            ctx.guild.name),
                    exc_info=exception)

                help_text_chunks = [
                    "Sorry <@{}>, **{}{}** isn't a valid command.".format(
                        ctx.message.author.id, ctx.prefix, ctx.invoked_with)
                ]

                if (most_similar_command[1] >
                        self.invalid_command_minimum_similarity):
                    help_text_chunks.append("Did you mean **{}{}**?".format(
                        self.activation_str, most_similar_command[0]))
                else:
                    help_text_chunks.append("Try the **{}help** page.".format(
                        self.activation_str))

                ## Dump output to user
                await ctx.send(" ".join(help_text_chunks))
                return
Esempio n. 4
0
class Hawking:
    ## Keys and Defaults
    ## Basically, any given class can be configured by changing the respective value for the
    ## desired key in config.json (see the Keys section at the top of each class for a list of
    ## keys). However, if you want to use Hawking as a part of something else, you may want to
    ## dynamically configure objects as necessary. Thus, you can also instantiate classes with
    ## keyworded arguments, which will then override any existing defaults, or config.json data.
    ## The existing defaults in each class are sort of like a fallback, in case the config.json is
    ## broken in some way.

    ## Keys
    VERSION_KEY = "version"
    ACTIVATION_STR_KEY = "activation_str"
    DESCRIPTION_KEY = "description"
    INVALID_COMMAND_MINIMUM_SIMILARITY = "invalid_command_minimum_similarity"

    ## Defaults
    VERSION = CONFIG_OPTIONS.get(VERSION_KEY, "Invalid version")
    ACTIVATION_STR = CONFIG_OPTIONS.get(ACTIVATION_STR_KEY, "\\")
    DESCRIPTION = CONFIG_OPTIONS.get(
        DESCRIPTION_KEY,
        "A retro TTS bot for Discord\n Visit https://github.com/naschorr/hawking"
    )

    ## Initialize the bot, and add base cogs
    def __init__(self, **kwargs):
        ## Make sure there's a Discord token before doing anything else
        self.token = CONFIG_OPTIONS.get("discord_token")
        if (not self.token):
            raise RuntimeError("Unable to get Discord token!")

        self.version = kwargs.get(self.VERSION_KEY, self.VERSION)
        self.activation_str = kwargs.get(self.ACTIVATION_STR_KEY,
                                         self.ACTIVATION_STR)
        self.description = kwargs.get(self.DESCRIPTION_KEY, self.DESCRIPTION)
        self.invalid_command_minimum_similarity = float(
            kwargs.get(self.INVALID_COMMAND_MINIMUM_SIMILARITY, 0.66))

        self.dynamo_db = dynamo_helper.DynamoHelper()

        ## Init the bot and module manager
        self.bot = commands.Bot(command_prefix=commands.when_mentioned_or(
            self.activation_str),
                                description=self.description)
        self.module_manager = ModuleManager(self, self.bot)

        ## Apply customized HelpCommand
        self.bot.help_command = help_command.HawkingHelpCommand()

        ## Register the modules (Order of registration is important, make sure dependancies are loaded first)
        self.module_manager.register(message_parser.MessageParser, False)
        self.module_manager.register(admin.Admin, True, self, self.bot)
        self.module_manager.register(speech.Speech, True, self)
        self.module_manager.register(
            audio_player.AudioPlayer, True, self.bot,
            self.get_speech_cog().play_random_channel_timeout_message)

        ## Load any dynamic modules inside the /modules folder
        self.module_manager.discover()

        ## Give some feedback for when the bot is ready to go, and provide some help text via the 'playing' status
        @self.bot.event
        async def on_ready():
            ## todo: Activity instead of Game? Potentially remove "Playing" text below bot
            bot_status = discord.Game(type=0,
                                      name="Use {}help".format(
                                          self.activation_str))
            await self.bot.change_presence(activity=bot_status)

            logger.info("Logged in as '{}' (version: {}), (id: {})".format(
                self.bot.user.name, self.version, self.bot.user.id))

        ## Give some feedback to users when their command doesn't execute.
        @self.bot.event
        async def on_command_error(ctx, exception):
            '''Handles command errors. Attempts to find a similar command and suggests it, otherwise directs the user to the help prompt.'''

            self.dynamo_db.put(
                dynamo_helper.DynamoItem(ctx, ctx.message.content,
                                         inspect.currentframe().f_code.co_name,
                                         False, str(exception)))

            ## Attempt to find a command that's similar to the one they wanted. Otherwise just direct them to the help page
            most_similar_command = self.find_most_similar_command(
                ctx.message.content)

            if (most_similar_command[0] == ctx.invoked_with):
                logger.exception(
                    "Unable to complete command, with content: {}, for author: {}, in channel {}, in server: {}"
                    .format(ctx.message.content, ctx.message.author.name,
                            ctx.guild.name),
                    exc_info=exception)
                ## Handle issues where the command is valid, but couldn't be completed for whatever reason.
                await ctx.send(
                    "I'm sorry <@{}>, I'm afraid I can't do that.\nSomething went wrong, and I couldn't complete the command."
                    .format(ctx.message.author.id))
            else:
                logger.exception(
                    "Received invalid command: '{0}{1}', suggested: '{0}{2}', for author: {3}, in server: {4}"
                    .format(self.activation_str, ctx.invoked_with,
                            most_similar_command[0], ctx.message.author.name,
                            ctx.guild.name),
                    exc_info=exception)

                help_text_chunks = [
                    "Sorry <@{}>, **{}{}** isn't a valid command.".format(
                        ctx.message.author.id, ctx.prefix, ctx.invoked_with)
                ]

                if (most_similar_command[1] >
                        self.invalid_command_minimum_similarity):
                    help_text_chunks.append("Did you mean **{}{}**?".format(
                        self.activation_str, most_similar_command[0]))
                else:
                    help_text_chunks.append("Try the **{}help** page.".format(
                        self.activation_str))

                ## Dump output to user
                await ctx.send(" ".join(help_text_chunks))
                return

    ## Methods

    ## Add an arbitary cog to the bot
    def add_cog(self, cls):
        self.bot.add_cog(cls)

    ## Returns a cog with a given name
    def get_cog(self, cls_name):
        return self.bot.get_cog(cls_name)

    ## Returns the bot's audio player cog
    def get_audio_player_cog(self):
        return self.bot.get_cog("AudioPlayer")

    ## Returns the bot's audio player cog
    def get_speech_cog(self):
        return self.bot.get_cog("Speech")

    ## Returns the bot's phrases cog
    def get_phrases_cog(self):
        return self.bot.get_cog("Phrases")

    ## Returns the bot's music cog
    def get_music_cog(self):
        return self.bot.get_cog("Music")

    ## Register an arbitrary module with hawking (easy wrapper for self.module_manager.register)
    def register_module(self, cls, is_cog, *init_args, **init_kwargs):
        self.module_manager.register(cls, is_cog, *init_args, **init_kwargs)

    ## Finds the most similar command to the supplied one
    def find_most_similar_command(self, command):
        ## Build a message string that we can compare with.
        try:
            message = command[len(self.activation_str):]
        except TypeError:
            message = command

        ## Get a list of all visible commands
        commands = [cmd.name for cmd in self.bot.commands if not cmd.hidden]

        ## Find the most similar command
        most_similar_command = (None, 0)
        for key in commands:
            distance = StringSimilarity.similarity(key, message)
            if (distance > most_similar_command[1]):
                most_similar_command = (key, distance)

        return most_similar_command

    ## Run the bot
    def run(self):
        '''Starts the bot up'''

        ## So ideally there would be some flavor of atexit.register or signal.signal command to gracefully shut the bot
        ## down upon SIGTERM or SIGINT. However that doesn't seem to be possible at the moment. Discord.py's got most of
        ## the functionality built into the base close() method that fires on SIGINT and SIGTERM, but the bot never ends
        ## up getting properly disconnected from the voice channels that it's connected to. I end up having to wait for
        ## a time out. Otherwise the bot will be in a weird state upon starting back up, and attempting to speak in one
        ## of the channels that it was previously in. Fortunately this bad state will self-recover in a minute or so,
        ## but it's still unpleasant. A temporary fix is to bump up the RestartSec= property in the service config to be
        ## long enough to allow for the bot to be forcefully disconnected

        logger.info('Starting up the bot.')
        self.bot.run(self.token)
Esempio n. 5
0
    def __init__(self, **kwargs):
        self.activation_str = kwargs.get(self.ACTIVATION_STR_KEY, self.ACTIVATION_STR)
        self.description = kwargs.get(self.DESCRIPTION_KEY, self.DESCRIPTION)
        self.token_file_path = kwargs.get(self.TOKEN_FILE_PATH_KEY, self.TOKEN_FILE_PATH)
        self.invalid_command_minimum_similarity = float(kwargs.get(self.INVALID_COMMAND_MINIMUM_SIMILARITY, 0.66))
        self.dynamo_db = dynamo_helper.DynamoHelper()
        ## Todo: pass kwargs to the their modules

        ## Init the bot and module manager
        self.bot = commands.Bot(
            command_prefix=commands.when_mentioned_or(self.activation_str),
            formatter=help_formatter.HawkingHelpFormatter(),
            description=self.description
        )
        self.module_manager = ModuleManager(self, self.bot)

        ## Register the modules (Order of registration is important, make sure dependancies are loaded first)
        self.module_manager.register(message_parser.MessageParser, False)
        self.module_manager.register(speech.Speech, True, self.bot)
        self.module_manager.register(admin.Admin, True, self, self.bot)

        ## Load any dynamic modules inside the /modules folder
        self.module_manager.discover()

        ## Give some feedback for when the bot is ready to go, and provide some help text via the 'playing' status
        @self.bot.event
        async def on_ready():
            bot_status = discord.Game(type=0, name="Use {}help".format(self.activation_str))
            await self.bot.change_presence(game=bot_status)
            print("Logged in as '{}' (version: {}), (id: {})".format(self.bot.user.name, self.VERSION, self.bot.user.id))

        ## Give some feedback to users when their command doesn't execute.
        @self.bot.event
        async def on_command_error(exception, ctx):
            # discord.py uses reflection to set the destination chat channel for whatever reason (sans command ctx)
            _internal_channel = ctx.message.channel

            utilities.debug_print(exception, debug_level=2)

            self.dynamo_db.put(dynamo_helper.DynamoItem(
                ctx, ctx.message.content, inspect.currentframe().f_code.co_name, False, str(exception)))

            ## Handy for debugging
            # import traceback
            # print('Ignoring exception in command {}:'.format(ctx.command), file=sys.stderr)
            # traceback.print_exception(type(exception), exception, exception.__traceback__, file=sys.stderr)

            ## Permissions error?
            if (isinstance(exception, CommandInvokeError) and isinstance(exception.original, TimeoutError)):
                await self.bot.say("Sorry <@{}>, I'm not able to join the voice channel right now. Discord might be having issues, or I might not have permission to join."
                    .format(ctx.message.author.id))
                return

            ## Poorly handled (for now, until I can get more concrete examples in my database) error messages for users
            if ("code =" in str(exception)):
                await self.bot.say("Sorry <@{}>, Discord is having some issues that won't let me speak right now."
                    .format(ctx.message.author.id))
                return

            ## Attempt to find a command that's similar to the one they wanted. Otherwise just direct them to the help page
            else:
                most_similar_command = self.find_most_similar_command(ctx.message.content)

                if (most_similar_command[0] == ctx.invoked_with):
                    ## Handle issues where the command is valid, but couldn't be completed for whatever reason.
                    await self.bot.say("Sorry <@{}>, I can't talk right now. Try again in a little bit.".format(ctx.message.author.id))
                else:
                    ## Otherwise, handle other issues involving invalid commands
                    help_text_chunks = [
                        "Sorry <@{}>, **{}{}** isn't a valid command.".format(ctx.message.author.id, ctx.prefix, ctx.invoked_with)
                    ]

                    ## Build the output to give to the user
                    if (most_similar_command[1] > self.invalid_command_minimum_similarity):
                        help_text_chunks.append("Did you mean **{}{}**?".format(self.activation_str, most_similar_command[0]))
                    else:
                        help_text_chunks.append("Try the **{}help** page.".format(self.activation_str))

                    await self.bot.say(" ".join(help_text_chunks))
Esempio n. 6
0
class Hawking:
    ## Keys and Defaults
    ## Basically, any given class can be configured by changing the respective value for the
    ## desired key in config.json (see the Keys section at the top of each class for a list of
    ## keys). However, if you want to use Hawking as a part of something else, you may want to
    ## dynamically configure objects as necessary. Thus, you can also instantiate classes with
    ## keyworded arguments, which will then override any existing defaults, or config.json data.
    ## The existing defaults in each class are sort of like a fallback, in case the config.json is
    ## broken in some way.

    ## Keys
    VERSION_KEY = "version"
    ACTIVATION_STR_KEY = "activation_str"
    DESCRIPTION_KEY = "description"
    TOKEN_KEY = "token"
    TOKEN_FILE_KEY = "token_file"
    TOKEN_FILE_PATH_KEY = "token_file_path"
    INVALID_COMMAND_MINIMUM_SIMILARITY = "invalid_command_minimum_similarity"

    ## Defaults
    VERSION = CONFIG_OPTIONS.get(VERSION_KEY, "Invalid version")
    ACTIVATION_STR = CONFIG_OPTIONS.get(ACTIVATION_STR_KEY, "\\")
    DESCRIPTION = CONFIG_OPTIONS.get(DESCRIPTION_KEY, "A retro TTS bot for Discord (Alpha)\n Visit https://github.com/naschorr/hawking")
    TOKEN_FILE = CONFIG_OPTIONS.get(TOKEN_FILE_KEY, "token.json")
    TOKEN_FILE_PATH = CONFIG_OPTIONS.get(TOKEN_FILE_PATH_KEY, os.sep.join([utilities.get_root_path(), TOKEN_FILE]))


    ## Initialize the bot, and add base cogs
    def __init__(self, **kwargs):
        self.activation_str = kwargs.get(self.ACTIVATION_STR_KEY, self.ACTIVATION_STR)
        self.description = kwargs.get(self.DESCRIPTION_KEY, self.DESCRIPTION)
        self.token_file_path = kwargs.get(self.TOKEN_FILE_PATH_KEY, self.TOKEN_FILE_PATH)
        self.invalid_command_minimum_similarity = float(kwargs.get(self.INVALID_COMMAND_MINIMUM_SIMILARITY, 0.66))
        self.dynamo_db = dynamo_helper.DynamoHelper()
        ## Todo: pass kwargs to the their modules

        ## Init the bot and module manager
        self.bot = commands.Bot(
            command_prefix=commands.when_mentioned_or(self.activation_str),
            formatter=help_formatter.HawkingHelpFormatter(),
            description=self.description
        )
        self.module_manager = ModuleManager(self, self.bot)

        ## Register the modules (Order of registration is important, make sure dependancies are loaded first)
        self.module_manager.register(message_parser.MessageParser, False)
        self.module_manager.register(speech.Speech, True, self.bot)
        self.module_manager.register(admin.Admin, True, self, self.bot)

        ## Load any dynamic modules inside the /modules folder
        self.module_manager.discover()

        ## Give some feedback for when the bot is ready to go, and provide some help text via the 'playing' status
        @self.bot.event
        async def on_ready():
            bot_status = discord.Game(type=0, name="Use {}help".format(self.activation_str))
            await self.bot.change_presence(game=bot_status)
            print("Logged in as '{}' (version: {}), (id: {})".format(self.bot.user.name, self.VERSION, self.bot.user.id))

        ## Give some feedback to users when their command doesn't execute.
        @self.bot.event
        async def on_command_error(exception, ctx):
            # discord.py uses reflection to set the destination chat channel for whatever reason (sans command ctx)
            _internal_channel = ctx.message.channel

            utilities.debug_print(exception, debug_level=2)

            self.dynamo_db.put(dynamo_helper.DynamoItem(
                ctx, ctx.message.content, inspect.currentframe().f_code.co_name, False, str(exception)))

            ## Handy for debugging
            # import traceback
            # print('Ignoring exception in command {}:'.format(ctx.command), file=sys.stderr)
            # traceback.print_exception(type(exception), exception, exception.__traceback__, file=sys.stderr)

            ## Permissions error?
            if (isinstance(exception, CommandInvokeError) and isinstance(exception.original, TimeoutError)):
                await self.bot.say("Sorry <@{}>, I'm not able to join the voice channel right now. Discord might be having issues, or I might not have permission to join."
                    .format(ctx.message.author.id))
                return

            ## Poorly handled (for now, until I can get more concrete examples in my database) error messages for users
            if ("code =" in str(exception)):
                await self.bot.say("Sorry <@{}>, Discord is having some issues that won't let me speak right now."
                    .format(ctx.message.author.id))
                return

            ## Attempt to find a command that's similar to the one they wanted. Otherwise just direct them to the help page
            else:
                most_similar_command = self.find_most_similar_command(ctx.message.content)

                if (most_similar_command[0] == ctx.invoked_with):
                    ## Handle issues where the command is valid, but couldn't be completed for whatever reason.
                    await self.bot.say("Sorry <@{}>, I can't talk right now. Try again in a little bit.".format(ctx.message.author.id))
                else:
                    ## Otherwise, handle other issues involving invalid commands
                    help_text_chunks = [
                        "Sorry <@{}>, **{}{}** isn't a valid command.".format(ctx.message.author.id, ctx.prefix, ctx.invoked_with)
                    ]

                    ## Build the output to give to the user
                    if (most_similar_command[1] > self.invalid_command_minimum_similarity):
                        help_text_chunks.append("Did you mean **{}{}**?".format(self.activation_str, most_similar_command[0]))
                    else:
                        help_text_chunks.append("Try the **{}help** page.".format(self.activation_str))

                    await self.bot.say(" ".join(help_text_chunks))

    ## Methods

    ## Add an arbitary cog to the bot
    def add_cog(self, cls):
        self.bot.add_cog(cls)


    ## Returns a cog with a given name
    def get_cog(self, cls_name):
        return self.bot.get_cog(cls_name)


    ## Returns the bot's speech cog
    def get_speech_cog(self):
        return self.bot.get_cog("Speech")


    ## Returns the bot's phrases cog
    def get_phrases_cog(self):
        return self.bot.get_cog("Phrases")


    ## Returns the bot's music cog
    def get_music_cog(self):
        return self.bot.get_cog("Music")


    ## Register an arbitrary module with hawking (easy wrapper for self.module_manager.register)
    def register_module(self, cls, is_cog, *init_args, **init_kwargs):
        self.module_manager.register(cls, is_cog, *init_args, **init_kwargs)


    ## Finds the most similar command to the supplied one
    def find_most_similar_command(self, command):
        ## Build a message string that we can compare with.
        try:
            message = command[len(self.activation_str):].lower()
        except TypeError:
            message = command.lower()

        ## Get a list of all visible commands 
        commands = [name for name, cmd in self.bot.commands.items() if not cmd.hidden]

        ## Find the most similar command
        most_similar_command = (None, 0)
        for key in commands:
            distance = StringSimilarity.similarity(key.lower(), message)
            if (distance > most_similar_command[1]):
                most_similar_command = (key, distance)

        return most_similar_command


    ## Run the bot
    def run(self):
        ## Keep bot going despite any misc service errors
        try:
            self.bot.run(utilities.load_json(self.token_file_path)[self.TOKEN_KEY])
        except RuntimeError as e:
            utilities.debug_print("Critical Runtime Error when running bot:", e, debug_level=0)
        except Exception as e:
            utilities.debug_print("Critical exception when running bot:", e, debug_level=0)
            time.sleep(1)
            self.run()
        raise ValueError('Please specify attention states for detection')
    if args.posthoc and (args.task != 'detect' or args.features):
        # Features and update rely on code changes
        raise ValueError('Posthoc setting not supported for given arguments')

    if args.test_mode:
        print('Starting evaluation: {}'.format(
            datetime.now().strftime("%m/%d/%Y %H:%M:%S")))

        model = load_model(args.model_path, args.task == 'detect')
        evaluate(args.task, model, test_examples, args.model_name, args.rerank)

        print('Terminating evaluation: {}'.format(
            datetime.now().strftime("%m/%d/%Y %H:%M:%S")))
    else:
        print('Starting training: {}'.format(
            datetime.now().strftime("%m/%d/%Y %H:%M:%S")))

        manager = ModuleManager(args.attend_code_sequence_states,
                                args.attend_code_graph_states, args.features,
                                args.posthoc, args.task)
        manager.initialize(train_examples)
        model = build_model(args.task, args.model_path, manager)

        print('Model path: {}'.format(args.model_path))
        sys.stdout.flush()

        train(model, train_examples, valid_examples)

        print('Terminating training: {}'.format(
            datetime.now().strftime("%m/%d/%Y %H:%M:%S")))