# Path: chatbot/globals.py
# DEFAULT_FULL_CONFIG = {
#     "model": "DynamicBot",
#     "dataset": "Cornell",
#     "model_params": {
#         "base_cell": "GRUCell",
#         "ckpt_dir": "out",  # Directory to store training checkpoints.
#         "decode": False,
#         "batch_size": 256,
#         "dropout_prob": 0.2,  # Drop rate applied at encoder/decoders output.
#         "decoder.class": "BasicDecoder",
#         "encoder.class": "BasicEncoder",
#         "embed_size": 128,
#         "learning_rate": 0.002,
#         "l1_reg": 1.0e-6,  # L1 regularization applied to word embeddings.
#         "lr_decay": 0.98,
#         "max_gradient": 5.0,
#         "max_steps": int(1e6),  # Max number of training iterations.
#         "num_layers": 1,  # Num layers for each of encoder, decoder.
#         "num_samples": 512,  # IF sampled_loss is true, default sample size.
#         "optimizer": "Adam",  # Options are those in OPTIMIZERS above.
#         "reset_model": True,
#         "sampled_loss": False,  # Whether to do sampled softmax.
#         "state_size": 512,
#         "steps_per_ckpt": 200,
#         "temperature": 0.0,  # Response temp for chat sessions. (default argmax)
#     },
#     "dataset_params": {
#         "data_dir": None,  # Require user to specify.
#         "vocab_size": 40000,
#         "max_seq_len": 10,  # Maximum length of sentence used to train bot.
#         "optimize_params": True  # Reduce vocab size if exceeds num unique words
#     },
# }


import os
import re
import sys
import yaml
import copy
import pandas as pd
import logging
import tensorflow as tf
from collections import Counter, namedtuple
from tensorflow.python.platform import gfile
from subprocess import Popen, PIPE
from chatbot.globals import DEFAULT_FULL_CONFIG
                  config_path=None,
                  return_config=True,
                  **kwargs):
    """Update contents of a config file, overwriting any that 
    match those in kwargs.
   
    Args:
        config: (dict) subset of DEFAULT_FULL_CONFIG.
        config_path: (str) location of a yaml config file.
        return_config: (bool) whether or not to return the config dictionary.
        kwargs: key-value pairs to update in the config dictionary and/or file.
         
    At least one of {config, config_path} must be not None. If both are not
    None, then we update the config dictionary with the kwargs, and then set
    the file at config_path to match updated dictionary contents. 
    
    In other words, if config is not None, we do won't consider the contents 
    of config_path when doing the updates.
    """

    if config is None and config_path is None:
        raise ValueError("Configuration info not given to update_config.")

    if config is None:
        # Grab the current config file contents into a dictionary.
        config = get_yaml_config(config_path)
        logging.info("Updating config values %r for %s",
                     list(kwargs.keys()), config_path)

    # Update its values with those in kwargs.

# Path: chatbot/globals.py
# DEFAULT_FULL_CONFIG = {
#     "model": "DynamicBot",
#     "dataset": "Cornell",
#     "model_params": {
#         "base_cell": "GRUCell",
#         "ckpt_dir": "out",  # Directory to store training checkpoints.
#         "decode": False,
#         "batch_size": 256,
#         "dropout_prob": 0.2,  # Drop rate applied at encoder/decoders output.
#         "decoder.class": "BasicDecoder",
#         "encoder.class": "BasicEncoder",
#         "embed_size": 128,
#         "learning_rate": 0.002,
#         "l1_reg": 1.0e-6,  # L1 regularization applied to word embeddings.
#         "lr_decay": 0.98,
#         "max_gradient": 5.0,
#         "max_steps": int(1e6),  # Max number of training iterations.
#         "num_layers": 1,  # Num layers for each of encoder, decoder.
#         "num_samples": 512,  # IF sampled_loss is true, default sample size.
#         "optimizer": "Adam",  # Options are those in OPTIMIZERS above.
#         "reset_model": True,
#         "sampled_loss": False,  # Whether to do sampled softmax.
#         "state_size": 512,
#         "steps_per_ckpt": 200,
#         "temperature": 0.0,  # Response temp for chat sessions. (default argmax)
#     },
#     "dataset_params": {
#         "data_dir": None,  # Require user to specify.
#         "vocab_size": 40000,
#         "max_seq_len": 10,  # Maximum length of sentence used to train bot.
#         "optimize_params": True  # Reduce vocab size if exceeds num unique words
#     },
# }


# Path: utils/io_utils.py
import os
import re
import sys
import yaml
import copy
import pandas as pd
import logging
import tensorflow as tf
from collections import Counter, namedtuple
from tensorflow.python.platform import gfile
from subprocess import Popen, PIPE
from chatbot.globals import DEFAULT_FULL_CONFIG

                  config_path=None,
                  return_config=True,
                  **kwargs):
    """Update contents of a config file, overwriting any that 
    match those in kwargs.
   
    Args:
        config: (dict) subset of DEFAULT_FULL_CONFIG.
        config_path: (str) location of a yaml config file.
        return_config: (bool) whether or not to return the config dictionary.
        kwargs: key-value pairs to update in the config dictionary and/or file.
         
    At least one of {config, config_path} must be not None. If both are not
    None, then we update the config dictionary with the kwargs, and then set
    the file at config_path to match updated dictionary contents. 
    
    In other words, if config is not None, we do won't consider the contents 
    of config_path when doing the updates.
    """

    if config is None and config_path is None:
        raise ValueError("Configuration info not given to update_config.")

    if config is None:
        # Grab the current config file contents into a dictionary.
        config = get_yaml_config(config_path)
        logging.info("Updating config values %r for %s",
                     list(kwargs.keys()), config_path)

    # Update its values with those in kwargs.

    for top_level_key in DEFAULT_FULL_CONFIG: