Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reorganize tests to make them easier to find #768

Merged
merged 32 commits into from
Dec 2, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
774c62e
Add eval loader to eval script
aspfohl Nov 16, 2023
6c7af31
small input tests
aspfohl Nov 16, 2023
0797a6c
Merge branch 'main' into anna/evalloader
aspfohl Nov 16, 2023
13cbc13
updates
aspfohl Nov 27, 2023
204d2f7
fix typing and formatting
aspfohl Nov 27, 2023
5b85218
fixes, add tests
aspfohl Nov 28, 2023
1a0a3da
Merge branch 'main' into anna/evalloader
aspfohl Nov 28, 2023
972ed96
remove circular dependency
aspfohl Nov 28, 2023
9840589
tests pass
aspfohl Nov 28, 2023
bc1c7c7
nits + small fixes
aspfohl Nov 29, 2023
1050def
add metrics at the end, refactor to put icl/gauntlet as helpers
aspfohl Nov 30, 2023
beefdc3
Merge branch 'main' into anna/evalloader
aspfohl Nov 30, 2023
549abb6
NOT
aspfohl Nov 30, 2023
084d8b6
metrics instead of models, add unit tests
aspfohl Nov 30, 2023
89237da
Move tests into directories
aspfohl Nov 30, 2023
2cef8cc
add copyright to inits
aspfohl Nov 30, 2023
49adcac
fix relative paths
aspfohl Nov 30, 2023
cde6d48
Merge branch 'main' into anna/tests
aspfohl Nov 30, 2023
1ace566
fixes
aspfohl Dec 1, 2023
93e97a7
revert gauntlet test change
aspfohl Dec 1, 2023
b4f7172
Support inputs_embeds (#687)
samhavens Dec 1, 2023
f08e014
Better error message when test does not complete (#769)
aspfohl Dec 1, 2023
7f14676
Merge branch 'main' into anna/tests
aspfohl Dec 1, 2023
0dcaf76
run script tests first
aspfohl Dec 1, 2023
559f37c
comment out
aspfohl Dec 1, 2023
eb98366
Merge branch 'main' into anna/tests
aspfohl Dec 1, 2023
6e50b33
ascripts -> scripts
aspfohl Dec 1, 2023
8d8b900
bad dirs
aspfohl Dec 1, 2023
656fb51
try this
aspfohl Dec 1, 2023
7f3fa7e
hacks
aspfohl Dec 2, 2023
f1a8c2d
merge
aspfohl Dec 2, 2023
46d2f4c
add a note about a_scripts
aspfohl Dec 2, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 21 additions & 9 deletions scripts/inference/convert_composer_to_hf.py
Original file line number Diff line number Diff line change
Expand Up @@ -168,19 +168,11 @@ def parse_args() -> Namespace:
return parser.parse_args()


def convert_composer_to_hf(args: Namespace) -> None:
def _convert_composer_to_hf(args: Namespace) -> None:
print()
print('#' * 30)
print('Converting Composer checkpoint to HuggingFace checkpoint format...')

# Register MPT auto classes so that this script works with MPT
# This script will not work without modification for other custom models,
# but will work for other HuggingFace causal LMs
from transformers.models.auto.configuration_auto import CONFIG_MAPPING
CONFIG_MAPPING._extra_content['mpt'] = MPTConfig
MPTConfig.register_for_auto_class()
MPTForCausalLM.register_for_auto_class('AutoModelForCausalLM')

_, _, local_folder_path = parse_uri(args.hf_output_path)

config, tokenizer = write_huggingface_pretrained_from_composer_checkpoint(
Expand Down Expand Up @@ -296,5 +288,25 @@ def convert_composer_to_hf(args: Namespace) -> None:
)


def convert_composer_to_hf(args: Namespace) -> None:
# Register MPT auto classes so that this script works with MPT
# This script will not work without modification for other custom models,
# but will work for other HuggingFace causal LMs
from transformers.models.auto.configuration_auto import CONFIG_MAPPING
CONFIG_MAPPING._extra_content['mpt'] = MPTConfig
MPTConfig.register_for_auto_class()
MPTForCausalLM.register_for_auto_class('AutoModelForCausalLM')

try:
_convert_composer_to_hf(args)
except Exception as e:
raise e
finally:
# Undo auto registration after running the script
del CONFIG_MAPPING._extra_content['mpt']
delattr(MPTConfig, '_auto_class')
delattr(MPTForCausalLM, '_auto_class')


if __name__ == '__main__':
convert_composer_to_hf(parse_args())
6 changes: 6 additions & 0 deletions tests/a_scripts/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Copyright 2022 MosaicML LLM Foundry authors
aspfohl marked this conversation as resolved.
Show resolved Hide resolved
# SPDX-License-Identifier: Apache-2.0

# TODO: This test directory is called "a_scripts" to enforce that these tests are run
# first. More clean up should be done to ensure tests can be run in any order and
# don't leave around artifacts
2 changes: 2 additions & 0 deletions tests/a_scripts/data_prep/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Copyright 2022 MosaicML LLM Foundry authors
# SPDX-License-Identifier: Apache-2.0
28 changes: 28 additions & 0 deletions tests/a_scripts/data_prep/test_convert_dataset_hf.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Copyright 2022 MosaicML LLM Foundry authors
# SPDX-License-Identifier: Apache-2.0

import os
from argparse import Namespace
from pathlib import Path

from scripts.data_prep.convert_dataset_hf import main as main_hf


def test_download_script_from_api(tmp_path: Path):
# test calling it directly
path = os.path.join(tmp_path, 'my-copy-c4-1')
main_hf(
Namespace(
**{
'dataset': 'c4',
'data_subset': 'en',
'splits': ['val_xsmall'],
'out_root': path,
'compression': None,
'concat_tokens': None,
'bos_text': None,
'eos_text': None,
'no_wrap': False,
'num_workers': None
}))
assert os.path.exists(path)
27 changes: 27 additions & 0 deletions tests/a_scripts/data_prep/test_convert_dataset_json.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Copyright 2022 MosaicML LLM Foundry authors
# SPDX-License-Identifier: Apache-2.0

import os
from argparse import Namespace
from pathlib import Path

from scripts.data_prep.convert_dataset_json import main as main_json


def test_json_script_from_api(tmp_path: Path):
# test calling it directly
path = os.path.join(tmp_path, 'my-copy-arxiv-1')
main_json(
Namespace(
**{
'path': 'scripts/data_prep/example_data/arxiv.jsonl',
'out_root': path,
'compression': None,
'split': 'train',
'concat_tokens': None,
'bos_text': None,
'eos_text': None,
'no_wrap': False,
'num_workers': None
}))
assert os.path.exists(path)
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,14 @@
# SPDX-License-Identifier: Apache-2.0

import os
import sys

import pytest

# Add repo root to path so we can import scripts and test it
repo_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))
sys.path.append(repo_dir)
import pathlib
from concurrent.futures import ProcessPoolExecutor
from glob import glob
from typing import Callable, Iterable, List
from unittest.mock import Mock, patch

import numpy as np
import pytest
from streaming import StreamingDataset
from transformers import AutoTokenizer

Expand Down
2 changes: 2 additions & 0 deletions tests/a_scripts/eval/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Copyright 2022 MosaicML LLM Foundry authors
# SPDX-License-Identifier: Apache-2.0
34 changes: 16 additions & 18 deletions tests/test_eval.py → tests/a_scripts/eval/test_eval.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@
import copy
import os
import pathlib
import sys
from typing import Any
from typing import Any, Union

import omegaconf as om
import pytest
Expand All @@ -14,15 +13,10 @@

from llmfoundry import COMPOSER_MODEL_REGISTRY
from llmfoundry.utils import build_tokenizer
from scripts.eval.eval import main # noqa: E402
from tests.data_utils import (create_arxiv_dataset, create_c4_dataset_xxsmall,
gpt_tiny_cfg)

# Add repo root to path so we can import scripts and test it
repo_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))
sys.path.append(repo_dir)

from scripts.eval.eval import main # noqa: E402


@pytest.fixture(autouse=True)
def set_correct_cwd():
Expand All @@ -35,11 +29,16 @@ def set_correct_cwd():
os.chdir('..')


@pytest.fixture()
def mock_saved_model_path():
# load the eval and model config
with open('eval/yamls/test_eval.yaml', 'r', encoding='utf-8') as f:
@pytest.fixture
def eval_cfg(foundry_dir: str) -> Union[om.ListConfig, om.DictConfig]:
yaml_path = os.path.join(foundry_dir, 'scripts/eval/yamls/test_eval.yaml')
with open(yaml_path, 'r', encoding='utf-8') as f:
eval_cfg = om.OmegaConf.load(f)
return eval_cfg


@pytest.fixture()
def mock_saved_model_path(eval_cfg: Union[om.ListConfig, om.DictConfig]):
model_cfg = eval_cfg.models[0]
# set device to cpu
device = 'cpu'
Expand All @@ -60,12 +59,11 @@ def mock_saved_model_path():
os.remove(saved_model_path)


def test_icl_eval(capfd: Any, mock_saved_model_path: Any):
with open('eval/yamls/test_eval.yaml', 'r', encoding='utf-8') as f:
test_cfg = om.OmegaConf.load(f)
test_cfg.models[0].load_path = mock_saved_model_path
assert isinstance(test_cfg, om.DictConfig)
main(test_cfg)
def test_icl_eval(eval_cfg: Union[om.ListConfig, om.DictConfig], capfd: Any,
mock_saved_model_path: Any):
eval_cfg.models[0].load_path = mock_saved_model_path
assert isinstance(eval_cfg, om.DictConfig)
main(eval_cfg)
out, _ = capfd.readouterr()
expected_results = '| Category | Benchmark | Subtask | Accuracy | Number few shot | Model |\n|:----------------------------|:---------------|:----------|-----------:|:------------------|:---------|\n| language_understanding_lite | lambada_openai | | 0 | 0-shot | tiny_mpt |'
assert expected_results in out
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,29 +2,26 @@
# SPDX-License-Identifier: Apache-2.0
import copy
import os
import sys
import warnings

import omegaconf
import pytest
from omegaconf import DictConfig
from omegaconf import OmegaConf as om

# Add repo root to path so we can import scripts and test it
repo_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))
sys.path.append(repo_dir)

from scripts.eval.eval import main # noqa: E402


class TestHuggingFaceEvalYAMLInputs:
"""Validate and tests error handling for the input YAML file."""

@pytest.fixture
def cfg(self) -> DictConfig:
def cfg(self, foundry_dir: str) -> DictConfig:
"""Create YAML cfg fixture for testing purposes."""
conf_path: str = os.path.join(repo_dir,
'scripts/eval/yamls/hf_eval.yaml')
conf_path: str = os.path.join(
foundry_dir,
'scripts/eval/yamls/hf_eval.yaml',
)
with open(conf_path, 'r', encoding='utf-8') as config:
test_cfg = om.load(config)
assert isinstance(test_cfg, DictConfig)
Expand Down Expand Up @@ -78,15 +75,17 @@ def test_optional_mispelled_params_raise_warning(self,
class TestMPTEvalYAMLInputs:

@pytest.fixture
def cfg(self) -> DictConfig:
def cfg(self, foundry_dir: str) -> DictConfig:
"""Create YAML cfg fixture for testing purposes."""
conf_path: str = os.path.join(repo_dir,
'scripts/eval/yamls/mpt_eval.yaml')
conf_path: str = os.path.join(
foundry_dir,
'scripts/eval/yamls/mpt_eval.yaml',
)
with open(conf_path, 'r', encoding='utf-8') as config:
test_cfg = om.load(config)

test_cfg.icl_tasks[0].dataset_uri = os.path.join(
repo_dir, 'scripts', test_cfg.icl_tasks[0].dataset_uri)
foundry_dir, 'scripts', test_cfg.icl_tasks[0].dataset_uri)

# make tests use cpu initialized transformer models only
test_cfg.models[0].model.init_device = 'cpu'
Expand Down
2 changes: 2 additions & 0 deletions tests/a_scripts/inference/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Copyright 2022 MosaicML LLM Foundry authors
# SPDX-License-Identifier: Apache-2.0
Original file line number Diff line number Diff line change
Expand Up @@ -4,34 +4,26 @@
import math
import os
import pathlib
import sys
from typing import Callable
from unittest.mock import ANY, MagicMock, patch

from composer import Trainer
from composer.loggers import MLFlowLogger
from composer.utils import dist, get_device, using_torch_2

from llmfoundry.callbacks import HuggingFaceCheckpointer
from llmfoundry.models.mpt.modeling_mpt import ComposerMPTCausalLM

# Add repo root to path so we can import scripts and test it
repo_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))
sys.path.append(repo_dir)
import shutil
from argparse import Namespace
from typing import Optional, cast
from typing import Callable, Optional, cast
from unittest.mock import ANY, MagicMock, patch

import pytest
import torch
import transformers
from composer import Trainer
from composer.loggers import MLFlowLogger
from composer.utils import dist, get_device, using_torch_2
from omegaconf import DictConfig
from omegaconf import OmegaConf as om
from torch.utils.data import DataLoader
from transformers import PreTrainedModel, PreTrainedTokenizerBase

from llmfoundry import COMPOSER_MODEL_REGISTRY
from llmfoundry.callbacks import HuggingFaceCheckpointer
from llmfoundry.data.finetuning import build_finetuning_dataloader
from llmfoundry.models.mpt.modeling_mpt import ComposerMPTCausalLM
from llmfoundry.utils.builders import build_optimizer, build_tokenizer
from scripts.inference.convert_composer_to_hf import convert_composer_to_hf
from tests.data_utils import make_tiny_ft_dataset
Expand Down
2 changes: 2 additions & 0 deletions tests/a_scripts/train/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Copyright 2022 MosaicML LLM Foundry authors
# SPDX-License-Identifier: Apache-2.0
21 changes: 4 additions & 17 deletions tests/test_training.py → tests/a_scripts/train/test_train.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
# Copyright 2022 MosaicML LLM Foundry authors
# SPDX-License-Identifier: Apache-2.0
import copy
import os
import pathlib
from typing import Any, Optional
from typing import Optional

import pytest
from composer.loggers import InMemoryLogger
Expand All @@ -16,22 +15,10 @@
gpt_tiny_cfg)


@pytest.fixture(autouse=False)
def set_correct_cwd():
if not os.getcwd().endswith('llm-foundry/scripts'):
os.chdir('scripts')

yield

if os.getcwd().endswith('llm-foundry/scripts'):
os.chdir('..')


@pytest.mark.parametrize('averages', [{
'core_average': ['language_understanding_lite']
}, None])
def test_train_gauntlet(averages: Optional[dict], set_correct_cwd: Any,
tmp_path: pathlib.Path):
def test_train_gauntlet(averages: Optional[dict], tmp_path: pathlib.Path):
"""Test training run with a small dataset."""
dataset_name = create_c4_dataset_xxsmall(tmp_path)
test_cfg = gpt_tiny_cfg(dataset_name, 'cpu')
Expand All @@ -40,7 +27,7 @@ def test_train_gauntlet(averages: Optional[dict], set_correct_cwd: Any,
'label':
'lambada_openai',
'dataset_uri':
'eval/local_data/language_understanding/lambada_openai_small.jsonl',
'scripts/eval/local_data/language_understanding/lambada_openai_small.jsonl',
'num_fewshot': [0],
'icl_task_type':
'language_modeling'
Expand Down Expand Up @@ -110,7 +97,7 @@ def test_train_gauntlet(averages: Optional[dict], set_correct_cwd: Any,
-1][-1] == 0


def test_train_multi_eval(set_correct_cwd: Any, tmp_path: pathlib.Path):
def test_train_multi_eval(tmp_path: pathlib.Path):
"""Test training run with multiple eval datasets."""
c4_dataset_name = create_c4_dataset_xxsmall(tmp_path)
test_cfg = gpt_tiny_cfg(c4_dataset_name, 'cpu')
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,13 @@
import copy
import json
import os
import sys
import warnings

import omegaconf
import pytest
from omegaconf import DictConfig
from omegaconf import OmegaConf as om

# Add repo root to path so we can import scripts and test it
repo_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))
sys.path.append(repo_dir)

from scripts.train.train import main # noqa: E402


Expand Down Expand Up @@ -54,10 +49,10 @@ class TestTrainingYAMLInputs:
"""Validate and tests error handling for the input YAML file."""

@pytest.fixture
def cfg(self) -> DictConfig:
def cfg(self, foundry_dir: str) -> DictConfig:
"""Create YAML cfg fixture for testing purposes."""
conf_path: str = os.path.join(
repo_dir, 'scripts/train/yamls/pretrain/testing.yaml')
foundry_dir, 'scripts/train/yamls/pretrain/testing.yaml')
with open(conf_path, 'r', encoding='utf-8') as config:
test_cfg = om.load(config)
assert isinstance(test_cfg, DictConfig)
Expand Down
2 changes: 2 additions & 0 deletions tests/callbacks/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Copyright 2022 MosaicML LLM Foundry authors
# SPDX-License-Identifier: Apache-2.0
Loading
Loading