# Buggy code
def __init__(
    self,
    tokenizer,
    max_seq_len,
    data_dir,
    labels=None,
    metric=None,
    train_filename="train-v2.0.json",
    dev_filename="dev-v2.0.json",
    test_filename=None,
    dev_split=0,
    doc_stride=128,
    max_query_length=64,
    **kwargs,
):
    """
    :param tokenizer: Used to split a sentence (str) into tokens.
    :param max_seq_len: Samples are truncated after this many tokens.
    :type max_seq_len: int
    :param data_dir: The directory in which the train and dev files can be found. Squad has a private test file
    :type data_dir: str
    :param train_filename: The name of the file containing training data.
    :type train_filename: str
    :param dev_filename: The name of the file containing the dev data. If None and 0.0 < dev_split < 1.0 the dev set
                         will be a slice of the train set.
    :type dev_filename: str or None
    :param test_filename: None
    :type test_filename: str
    :param dev_split: The proportion of the train set that will sliced. Only works if dev_filename is set to None
    :type dev_split: float
    :param data_dir: The directory in which the train, test and perhaps dev files can be found.
    :type data_dir: str
    :param doc_stride: When the document containing the answer is too long it gets split into part, strided by doc_stride
    :type doc_stride: int
    :param max_query_length: Maximum length of the question (in number of subword tokens)
    :type max_query_length: int
    :param kwargs: placeholder for passing generic parameters
    :type kwargs: object
    """

    self.target = "classification"
    self.ph_output_type = "per_token_squad"

    self.doc_stride = doc_stride
    self.max_query_length = max_query_length

    super(SquadProcessor, self).__init__(
        tokenizer=tokenizer,
        max_seq_len=max_seq_len,
        train_filename=train_filename,
        dev_filename=dev_filename,
        test_filename=test_filename,
        dev_split=dev_split,
        data_dir=data_dir,
        tasks={},
    )

    if metric and labels:
        self.add_task("question_answering", metric, labels)
    else:
        logger.info(
            "Initialized processor without tasks. Supply `metric` and `label_list` to the constructor for "
            "using the default task or add a custom task later via processor.add_task()"
        )


# Traceback (KeyError)
10/17/2019 20:16:51 - INFO - pytorch_transformers.modeling_utils -   load
ing weights file https://s3.amazonaws.com/models.huggingface.co/bert/bert
-base-cased-pytorch_model.bin from cache at /root/.cache/torch/pytorch_tr
ansformers/35d8b9d36faaf46728a0192d82bf7d00137490cd6074e8500778afed552a67
e5.3fadbea36527ae472139fe84cddaa65454d7429f12d543d80bfc3ad70de55ac2
10/17/2019 20:16:54 - WARNING - farm.modeling.language_model -   Could no
t automatically detect from language model name what language it is.
We guess it's an *ENGLISH* model ...
If not: Init the language model by supplying the 'language' param.
Example: Bert.load('my_mysterious_model_name', language='de')
10/17/2019 20:16:58 - INFO - farm.modeling.optimization -   Number of opt
imization steps: 12220
Traceback (most recent call last):
File "run_all_experiments.py", line 36, in <module>
main()
File "run_all_experiments.py", line 33, in main
run_experiment(experiment)
File "/home/user/farm/experiment.py", line 147, in run_experiment
model = trainer.train(model)
File "/home/user/farm/train.py", line 129, in train
model.connect_heads_with_processor(self.data_silo.processor.tasks)
File "/home/user/farm/modeling/adaptive_model.py", line 233, in connect
_heads_with_processor
head.label_tensor_name = tasks[head.task_name]["label_tensor_name"]
KeyError: 'question_answering'

# Fixed code
def __init__(
    self,
    tokenizer,
    max_seq_len,
    data_dir,
    label_list=None,
    metric=None,
    train_filename="train-v2.0.json",
    dev_filename="dev-v2.0.json",
    test_filename=None,
    dev_split=0,
    doc_stride=128,
    max_query_length=64,
    **kwargs,
):
    """
    :param tokenizer: Used to split a sentence (str) into tokens.
    :param max_seq_len: Samples are truncated after this many tokens.
    :type max_seq_len: int
    :param data_dir: The directory in which the train and dev files can be found. Squad has a private test file
    :type data_dir: str
    :param label_list: list of labels to predict (strings). For most cases this should be: ["start_token", "end_token"]
    :type label_list: list
    :param metric: name of metric that shall be used for evaluation, e.g. "squad".
    :type metric: str
    :param train_filename: The name of the file containing training data.
    :type train_filename: str
    :param dev_filename: The name of the file containing the dev data. If None and 0.0 < dev_split < 1.0 the dev set
                         will be a slice of the train set.
    :type dev_filename: str or None
    :param test_filename: None
    :type test_filename: str
    :param dev_split: The proportion of the train set that will sliced. Only works if dev_filename is set to None
    :type dev_split: float
    :param doc_stride: When the document containing the answer is too long it gets split into part, strided by doc_stride
    :type doc_stride: int
    :param max_query_length: Maximum length of the question (in number of subword tokens)
    :type max_query_length: int
    :param kwargs: placeholder for passing generic parameters
    :type kwargs: object
    """

    self.target = "classification"
    self.ph_output_type = "per_token_squad"

    self.doc_stride = doc_stride
    self.max_query_length = max_query_length

    super(SquadProcessor, self).__init__(
        tokenizer=tokenizer,
        max_seq_len=max_seq_len,
        train_filename=train_filename,
        dev_filename=dev_filename,
        test_filename=test_filename,
        dev_split=dev_split,
        data_dir=data_dir,
        tasks={},
    )

    if metric and label_list:
        self.add_task("question_answering", metric, label_list)
    else:
        logger.info(
            "Initialized processor without tasks. Supply `metric` and `label_list` to the constructor for "
            "using the default task or add a custom task later via processor.add_task()"
        )