From 3a0125de10eb7ad58b9794e51c2a0bbeffbc21e0 Mon Sep 17 00:00:00 2001 From: Sanjay Date: Tue, 12 Mar 2024 13:03:44 +0530 Subject: [PATCH 01/20] Initial changes to 3 files --- ludwig/api.py | 13 ++++++ ludwig/experiment.py | 13 ++++++ .../test_model_training_options.py | 40 +++++++++++++++++++ 3 files changed, 66 insertions(+) diff --git a/ludwig/api.py b/ludwig/api.py index 4df24eda93a..55e475ca29d 100644 --- a/ludwig/api.py +++ b/ludwig/api.py @@ -65,6 +65,7 @@ from ludwig.globals import ( LUDWIG_VERSION, MODEL_HYPERPARAMETERS_FILE_NAME, + MODEL_WEIGHTS_FILE_NAME, set_disable_progressbar, TRAIN_SET_METADATA_FILE_NAME, ) @@ -375,6 +376,7 @@ def train( skip_save_processed_input: bool = False, output_directory: Optional[str] = "results", random_seed: int = default_random_seed, + save_ludwig_config_with_model_weights: bool = False, **kwargs, ) -> TrainingResults: """This function is used to perform a full training of the model on the specified dataset. @@ -456,6 +458,9 @@ def train( :param random_seed: (int, default: `42`) a random seed that will be used anywhere there is a call to a random number generator: data splitting, parameter initialization and training set shuffling + :param save_ludwig_config_with_model_weights: (bool, default: False) indicates + whether the user-provided ludwig-config should be saved along with + the model weights (to be eventually uploaded to HF) :param kwargs: (dict, default: {}) a dictionary of optional parameters. # Return @@ -766,6 +771,9 @@ def on_epoch_end(self, trainer, progress_tracker, save_path): # Ensure model weights are saved to the driver if training was done remotely if self.backend.is_coordinator() and not skip_save_model: self.model.save(model_dir) + if save_ludwig_config_with_model_weights: + weights_save_path = os.path.join(model_dir, MODEL_WEIGHTS_FILE_NAME, 'ludwig_config.json') + self.save_config(weights_save_path) if self.is_merge_and_unload_set(): # For an LLM model trained with a LoRA adapter, handle merge and unload postprocessing directives. @@ -1428,6 +1436,7 @@ def experiment( skip_collect_overall_stats: bool = False, output_directory: str = "results", random_seed: int = default_random_seed, + save_ludwig_config_with_model_weights: bool = False, **kwargs, ) -> Tuple[Optional[dict], TrainingStats, PreprocessedDataset, str]: """Trains a model on a dataset's training and validation splits and uses it to predict on the test split. @@ -1516,6 +1525,9 @@ def experiment( model and the training progress files. :param random_seed: (int: default: 42) random seed used for weights initialization, splits and any other random function. + :param save_ludwig_config_with_model_weights: (bool, default: False) indicates + whether the user-provided ludwig-config should be saved along with + the model weights (to be eventually uploaded to HF) # Return :return: (Tuple[dict, dict, tuple, str)) @@ -1551,6 +1563,7 @@ def experiment( skip_save_unprocessed_output=skip_save_unprocessed_output, output_directory=output_directory, random_seed=random_seed, + save_ludwig_config_with_model_weights=save_ludwig_config_with_model_weights ) (training_set, validation_set, test_set, training_set_metadata) = preprocessed_data diff --git a/ludwig/experiment.py b/ludwig/experiment.py index 73e5a3fafa0..ce36c4897f6 100644 --- a/ludwig/experiment.py +++ b/ludwig/experiment.py @@ -65,6 +65,7 @@ def experiment_cli( callbacks: List[Callback] = None, backend: Union[Backend, str] = None, random_seed: int = default_random_seed, + save_ludwig_config_with_model_weights: bool = False, logging_level: int = logging.INFO, **kwargs, ): @@ -172,6 +173,9 @@ def experiment_cli( of backend to use to execute preprocessing / training steps. :param random_seed: (int: default: 42) random seed used for weights initialization, splits and any other random function. + :param save_ludwig_config_with_model_weights: (bool, default: False) indicates + whether the user-provided ludwig-config should be saved along with + the model weights (to be eventually uploaded to HF) :param logging_level: (int) Log level that will be sent to stderr. # Return @@ -238,6 +242,7 @@ def experiment_cli( skip_collect_overall_stats=skip_collect_overall_stats, output_directory=output_directory, random_seed=random_seed, + save_ludwig_config_with_model_weights=save_ludwig_config_with_model_weights, ) return model, eval_stats, train_stats, preprocessed_data, output_directory @@ -466,6 +471,14 @@ def cli(sys_argv): "can slightly increase the overall speed", ) + parser.add_argument( + "-slcwmw", + "--save_ludwig_config_with_model_weights", + action="store_true", + default=False, + help="save ludwig config with model weights" + ) + # ------------------ # Runtime parameters # ------------------ diff --git a/tests/integration_tests/test_model_training_options.py b/tests/integration_tests/test_model_training_options.py index 96c1903e33e..1a471ab02b4 100644 --- a/tests/integration_tests/test_model_training_options.py +++ b/tests/integration_tests/test_model_training_options.py @@ -139,6 +139,46 @@ def test_model_progress_save(skip_save_progress, skip_save_model, tmp_path): assert len(training_checkpoints) > 0 +@pytest.mark.parametrize("save_ludwig_config_with_model_weights", [False, True]) +def test_ludwig_config_save(save_ludwig_config_with_model_weights, tmp_path): + input_features, output_features = synthetic_test_data.get_feature_configs() + + config = { + "input_features": input_features, + "output_features": output_features, + "combiner": {"type": "concat"}, + TRAINER: {"epochs": 1, BATCH_SIZE: 128}, + } + + # create sub-directory to store results + results_dir = tmp_path / "results" + results_dir.mkdir() + + # run experiment + generated_data = synthetic_test_data.get_generated_data() + _, _, _, _, output_dir = experiment_cli( + training_set=generated_data.train_df, + validation_set=generated_data.validation_df, + test_set=generated_data.test_df, + output_directory=str(results_dir), + config=config, + skip_save_processed_input=True, + skip_save_progress=False, + skip_save_unprocessed_output=True, + skip_save_model=False, + skip_save_log=True, + save_ludwig_config_with_model_weights=save_ludwig_config_with_model_weights, + ) + + # ========== Check for required ludwig-config file ============= + model_weights_dir = os.path.join(output_dir, "model", "model_weights") + files = [f for f in os.listdir(model_weights_dir) if re.match(r"ludwig_config", f)] + if save_ludwig_config_with_model_weights: + assert len(files) == 1 + else: + assert len(files) == 0 + + @pytest.mark.parametrize("optimizer", ["sgd", "adam"]) def test_resume_training(optimizer, tmp_path): input_features, output_features = synthetic_test_data.get_feature_configs() From 06c3492fea45b0b10ebaf80a04e51d3e5d10e4e6 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 12 Mar 2024 08:24:36 +0000 Subject: [PATCH 02/20] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- ludwig/api.py | 4 ++-- ludwig/experiment.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ludwig/api.py b/ludwig/api.py index 55e475ca29d..094d64c27a8 100644 --- a/ludwig/api.py +++ b/ludwig/api.py @@ -772,7 +772,7 @@ def on_epoch_end(self, trainer, progress_tracker, save_path): if self.backend.is_coordinator() and not skip_save_model: self.model.save(model_dir) if save_ludwig_config_with_model_weights: - weights_save_path = os.path.join(model_dir, MODEL_WEIGHTS_FILE_NAME, 'ludwig_config.json') + weights_save_path = os.path.join(model_dir, MODEL_WEIGHTS_FILE_NAME, "ludwig_config.json") self.save_config(weights_save_path) if self.is_merge_and_unload_set(): @@ -1563,7 +1563,7 @@ def experiment( skip_save_unprocessed_output=skip_save_unprocessed_output, output_directory=output_directory, random_seed=random_seed, - save_ludwig_config_with_model_weights=save_ludwig_config_with_model_weights + save_ludwig_config_with_model_weights=save_ludwig_config_with_model_weights, ) (training_set, validation_set, test_set, training_set_metadata) = preprocessed_data diff --git a/ludwig/experiment.py b/ludwig/experiment.py index ce36c4897f6..eb7b6597414 100644 --- a/ludwig/experiment.py +++ b/ludwig/experiment.py @@ -476,7 +476,7 @@ def cli(sys_argv): "--save_ludwig_config_with_model_weights", action="store_true", default=False, - help="save ludwig config with model weights" + help="save ludwig config with model weights", ) # ------------------ From 021eac1cdc56f133eb2774d9e81f771ee89b5f5d Mon Sep 17 00:00:00 2001 From: Sanjay Date: Tue, 12 Mar 2024 15:05:12 +0530 Subject: [PATCH 03/20] Tweaked integration test --- tests/integration_tests/test_model_training_options.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/integration_tests/test_model_training_options.py b/tests/integration_tests/test_model_training_options.py index 1a471ab02b4..1ea5b727b59 100644 --- a/tests/integration_tests/test_model_training_options.py +++ b/tests/integration_tests/test_model_training_options.py @@ -147,7 +147,7 @@ def test_ludwig_config_save(save_ludwig_config_with_model_weights, tmp_path): "input_features": input_features, "output_features": output_features, "combiner": {"type": "concat"}, - TRAINER: {"epochs": 1, BATCH_SIZE: 128}, + TRAINER: {"epochs": 5, BATCH_SIZE: 128}, } # create sub-directory to store results From ce451a4454b1bc62e8801a75939c4da651829092 Mon Sep 17 00:00:00 2001 From: Sanjay Date: Tue, 12 Mar 2024 22:37:22 +0530 Subject: [PATCH 04/20] Corrected error in 'api.py' --- ludwig/api.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ludwig/api.py b/ludwig/api.py index 094d64c27a8..98b91284346 100644 --- a/ludwig/api.py +++ b/ludwig/api.py @@ -773,7 +773,7 @@ def on_epoch_end(self, trainer, progress_tracker, save_path): self.model.save(model_dir) if save_ludwig_config_with_model_weights: weights_save_path = os.path.join(model_dir, MODEL_WEIGHTS_FILE_NAME, "ludwig_config.json") - self.save_config(weights_save_path) + save_json(weights_save_path, self.config_obj.to_dict()) if self.is_merge_and_unload_set(): # For an LLM model trained with a LoRA adapter, handle merge and unload postprocessing directives. From 111dca0e6048ca816c30d9cac08ca768189ad9dd Mon Sep 17 00:00:00 2001 From: Sanjay Date: Wed, 13 Mar 2024 20:58:48 +0530 Subject: [PATCH 05/20] Revert "Corrected error in 'api.py'" This reverts commit ce451a4454b1bc62e8801a75939c4da651829092. --- ludwig/api.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ludwig/api.py b/ludwig/api.py index 98b91284346..094d64c27a8 100644 --- a/ludwig/api.py +++ b/ludwig/api.py @@ -773,7 +773,7 @@ def on_epoch_end(self, trainer, progress_tracker, save_path): self.model.save(model_dir) if save_ludwig_config_with_model_weights: weights_save_path = os.path.join(model_dir, MODEL_WEIGHTS_FILE_NAME, "ludwig_config.json") - save_json(weights_save_path, self.config_obj.to_dict()) + self.save_config(weights_save_path) if self.is_merge_and_unload_set(): # For an LLM model trained with a LoRA adapter, handle merge and unload postprocessing directives. From 53a7a50c6bba5556bfbe529d2b24c35c59f23cdf Mon Sep 17 00:00:00 2001 From: Sanjay Date: Wed, 13 Mar 2024 20:59:15 +0530 Subject: [PATCH 06/20] Revert "Tweaked integration test" This reverts commit 021eac1cdc56f133eb2774d9e81f771ee89b5f5d. --- tests/integration_tests/test_model_training_options.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/integration_tests/test_model_training_options.py b/tests/integration_tests/test_model_training_options.py index 1ea5b727b59..1a471ab02b4 100644 --- a/tests/integration_tests/test_model_training_options.py +++ b/tests/integration_tests/test_model_training_options.py @@ -147,7 +147,7 @@ def test_ludwig_config_save(save_ludwig_config_with_model_weights, tmp_path): "input_features": input_features, "output_features": output_features, "combiner": {"type": "concat"}, - TRAINER: {"epochs": 5, BATCH_SIZE: 128}, + TRAINER: {"epochs": 1, BATCH_SIZE: 128}, } # create sub-directory to store results From f482466e7000ffb180730735dde56c3f4b287ea8 Mon Sep 17 00:00:00 2001 From: Sanjay Date: Wed, 13 Mar 2024 21:22:57 +0530 Subject: [PATCH 07/20] Reverting all changes on branch --- ludwig/api.py | 13 ------ ludwig/experiment.py | 13 ------ .../test_model_training_options.py | 40 ------------------- 3 files changed, 66 deletions(-) diff --git a/ludwig/api.py b/ludwig/api.py index 094d64c27a8..4df24eda93a 100644 --- a/ludwig/api.py +++ b/ludwig/api.py @@ -65,7 +65,6 @@ from ludwig.globals import ( LUDWIG_VERSION, MODEL_HYPERPARAMETERS_FILE_NAME, - MODEL_WEIGHTS_FILE_NAME, set_disable_progressbar, TRAIN_SET_METADATA_FILE_NAME, ) @@ -376,7 +375,6 @@ def train( skip_save_processed_input: bool = False, output_directory: Optional[str] = "results", random_seed: int = default_random_seed, - save_ludwig_config_with_model_weights: bool = False, **kwargs, ) -> TrainingResults: """This function is used to perform a full training of the model on the specified dataset. @@ -458,9 +456,6 @@ def train( :param random_seed: (int, default: `42`) a random seed that will be used anywhere there is a call to a random number generator: data splitting, parameter initialization and training set shuffling - :param save_ludwig_config_with_model_weights: (bool, default: False) indicates - whether the user-provided ludwig-config should be saved along with - the model weights (to be eventually uploaded to HF) :param kwargs: (dict, default: {}) a dictionary of optional parameters. # Return @@ -771,9 +766,6 @@ def on_epoch_end(self, trainer, progress_tracker, save_path): # Ensure model weights are saved to the driver if training was done remotely if self.backend.is_coordinator() and not skip_save_model: self.model.save(model_dir) - if save_ludwig_config_with_model_weights: - weights_save_path = os.path.join(model_dir, MODEL_WEIGHTS_FILE_NAME, "ludwig_config.json") - self.save_config(weights_save_path) if self.is_merge_and_unload_set(): # For an LLM model trained with a LoRA adapter, handle merge and unload postprocessing directives. @@ -1436,7 +1428,6 @@ def experiment( skip_collect_overall_stats: bool = False, output_directory: str = "results", random_seed: int = default_random_seed, - save_ludwig_config_with_model_weights: bool = False, **kwargs, ) -> Tuple[Optional[dict], TrainingStats, PreprocessedDataset, str]: """Trains a model on a dataset's training and validation splits and uses it to predict on the test split. @@ -1525,9 +1516,6 @@ def experiment( model and the training progress files. :param random_seed: (int: default: 42) random seed used for weights initialization, splits and any other random function. - :param save_ludwig_config_with_model_weights: (bool, default: False) indicates - whether the user-provided ludwig-config should be saved along with - the model weights (to be eventually uploaded to HF) # Return :return: (Tuple[dict, dict, tuple, str)) @@ -1563,7 +1551,6 @@ def experiment( skip_save_unprocessed_output=skip_save_unprocessed_output, output_directory=output_directory, random_seed=random_seed, - save_ludwig_config_with_model_weights=save_ludwig_config_with_model_weights, ) (training_set, validation_set, test_set, training_set_metadata) = preprocessed_data diff --git a/ludwig/experiment.py b/ludwig/experiment.py index eb7b6597414..73e5a3fafa0 100644 --- a/ludwig/experiment.py +++ b/ludwig/experiment.py @@ -65,7 +65,6 @@ def experiment_cli( callbacks: List[Callback] = None, backend: Union[Backend, str] = None, random_seed: int = default_random_seed, - save_ludwig_config_with_model_weights: bool = False, logging_level: int = logging.INFO, **kwargs, ): @@ -173,9 +172,6 @@ def experiment_cli( of backend to use to execute preprocessing / training steps. :param random_seed: (int: default: 42) random seed used for weights initialization, splits and any other random function. - :param save_ludwig_config_with_model_weights: (bool, default: False) indicates - whether the user-provided ludwig-config should be saved along with - the model weights (to be eventually uploaded to HF) :param logging_level: (int) Log level that will be sent to stderr. # Return @@ -242,7 +238,6 @@ def experiment_cli( skip_collect_overall_stats=skip_collect_overall_stats, output_directory=output_directory, random_seed=random_seed, - save_ludwig_config_with_model_weights=save_ludwig_config_with_model_weights, ) return model, eval_stats, train_stats, preprocessed_data, output_directory @@ -471,14 +466,6 @@ def cli(sys_argv): "can slightly increase the overall speed", ) - parser.add_argument( - "-slcwmw", - "--save_ludwig_config_with_model_weights", - action="store_true", - default=False, - help="save ludwig config with model weights", - ) - # ------------------ # Runtime parameters # ------------------ diff --git a/tests/integration_tests/test_model_training_options.py b/tests/integration_tests/test_model_training_options.py index 1a471ab02b4..96c1903e33e 100644 --- a/tests/integration_tests/test_model_training_options.py +++ b/tests/integration_tests/test_model_training_options.py @@ -139,46 +139,6 @@ def test_model_progress_save(skip_save_progress, skip_save_model, tmp_path): assert len(training_checkpoints) > 0 -@pytest.mark.parametrize("save_ludwig_config_with_model_weights", [False, True]) -def test_ludwig_config_save(save_ludwig_config_with_model_weights, tmp_path): - input_features, output_features = synthetic_test_data.get_feature_configs() - - config = { - "input_features": input_features, - "output_features": output_features, - "combiner": {"type": "concat"}, - TRAINER: {"epochs": 1, BATCH_SIZE: 128}, - } - - # create sub-directory to store results - results_dir = tmp_path / "results" - results_dir.mkdir() - - # run experiment - generated_data = synthetic_test_data.get_generated_data() - _, _, _, _, output_dir = experiment_cli( - training_set=generated_data.train_df, - validation_set=generated_data.validation_df, - test_set=generated_data.test_df, - output_directory=str(results_dir), - config=config, - skip_save_processed_input=True, - skip_save_progress=False, - skip_save_unprocessed_output=True, - skip_save_model=False, - skip_save_log=True, - save_ludwig_config_with_model_weights=save_ludwig_config_with_model_weights, - ) - - # ========== Check for required ludwig-config file ============= - model_weights_dir = os.path.join(output_dir, "model", "model_weights") - files = [f for f in os.listdir(model_weights_dir) if re.match(r"ludwig_config", f)] - if save_ludwig_config_with_model_weights: - assert len(files) == 1 - else: - assert len(files) == 0 - - @pytest.mark.parametrize("optimizer", ["sgd", "adam"]) def test_resume_training(optimizer, tmp_path): input_features, output_features = synthetic_test_data.get_feature_configs() From 877cbd97a7d33a1464ea6b85b4ad8969b247cc18 Mon Sep 17 00:00:00 2001 From: sanjay Date: Fri, 15 Mar 2024 10:33:38 +0530 Subject: [PATCH 08/20] Added code to upload model-config file after uploading model-weights --- ludwig/utils/upload_utils.py | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/ludwig/utils/upload_utils.py b/ludwig/utils/upload_utils.py index efa09a1c91a..8c859645c43 100644 --- a/ludwig/utils/upload_utils.py +++ b/ludwig/utils/upload_utils.py @@ -3,6 +3,7 @@ import logging import os from abc import ABC, abstractmethod +from ludwig.globals import MODEL_HYPERPARAMETERS_FILE_NAME from huggingface_hub import HfApi, login @@ -256,17 +257,32 @@ def upload( ) # Upload all artifacts in model weights folder - upload_path = self.api.upload_folder( + commit_message_weights = f"{commit_message} (weights)" if commit_message else commit_message + commit_description_weights = f"{commit_description} (weights)" if commit_description else commit_description + upload_path_weights = self.api.upload_folder( folder_path=os.path.join(model_path, "model", "model_weights"), repo_id=repo_id, repo_type=repo_type, - commit_message=commit_message, - commit_description=commit_description, + commit_message=commit_message_weights, + commit_description=commit_description_weights, ) - if upload_path: - logger.info(f"Model uploaded to `{upload_path}` with repository name `{repo_id}`") - return True + if upload_path_weights: + logger.info(f"Model weights uploaded to `{upload_path_weights}` with repository name `{repo_id}`") + commit_message_config = f"{commit_message} (config)" if commit_message else commit_message + commit_description_config = f"{commit_description} (config)" if commit_description else commit_description + upload_path_config = self.api.upload_file( + path_or_fileobj=os.path.join(model_path, "model", MODEL_HYPERPARAMETERS_FILE_NAME), + path_in_repo="ludwig_config.json", + repo_id=repo_id, + repo_type=repo_type, + commit_message=commit_message_config, + commit_description=commit_description_config, + ) + + if upload_path_config: + logger.info(f"Model config uploaded to `{upload_path_config}` with repository name `{repo_id}`") + return True return False From 4f7b84be8570c2fb8e90cbcedf99f9d6ca7c8482 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 15 Mar 2024 05:13:02 +0000 Subject: [PATCH 09/20] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- ludwig/utils/upload_utils.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ludwig/utils/upload_utils.py b/ludwig/utils/upload_utils.py index 8c859645c43..d6bd29c7b39 100644 --- a/ludwig/utils/upload_utils.py +++ b/ludwig/utils/upload_utils.py @@ -3,10 +3,11 @@ import logging import os from abc import ABC, abstractmethod -from ludwig.globals import MODEL_HYPERPARAMETERS_FILE_NAME from huggingface_hub import HfApi, login +from ludwig.globals import MODEL_HYPERPARAMETERS_FILE_NAME + logger = logging.getLogger(__name__) From 34243ee7116b0b838de3ca0e38d5b4d0346b3483 Mon Sep 17 00:00:00 2001 From: Sanjay Date: Fri, 15 Mar 2024 12:35:37 +0530 Subject: [PATCH 10/20] Added type hints in changed/added code --- ludwig/utils/upload_utils.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/ludwig/utils/upload_utils.py b/ludwig/utils/upload_utils.py index d6bd29c7b39..766ada92d2e 100644 --- a/ludwig/utils/upload_utils.py +++ b/ludwig/utils/upload_utils.py @@ -258,8 +258,9 @@ def upload( ) # Upload all artifacts in model weights folder - commit_message_weights = f"{commit_message} (weights)" if commit_message else commit_message - commit_description_weights = f"{commit_description} (weights)" if commit_description else commit_description + commit_message_weights: str | None = f"{commit_message} (weights)" if commit_message else commit_message + commit_description_weights: str | None = f"{commit_description} (weights)" if commit_description else \ + commit_description upload_path_weights = self.api.upload_folder( folder_path=os.path.join(model_path, "model", "model_weights"), repo_id=repo_id, @@ -270,8 +271,10 @@ def upload( if upload_path_weights: logger.info(f"Model weights uploaded to `{upload_path_weights}` with repository name `{repo_id}`") - commit_message_config = f"{commit_message} (config)" if commit_message else commit_message - commit_description_config = f"{commit_description} (config)" if commit_description else commit_description + # Upload the ludwig configuration file + commit_message_config: str | None = f"{commit_message} (config)" if commit_message else commit_message + commit_description_config: str | None = f"{commit_description} (config)" if commit_description else \ + commit_description upload_path_config = self.api.upload_file( path_or_fileobj=os.path.join(model_path, "model", MODEL_HYPERPARAMETERS_FILE_NAME), path_in_repo="ludwig_config.json", From d1ff3c0b93d568b8cf3d10cda56240c3c5641585 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 15 Mar 2024 07:07:17 +0000 Subject: [PATCH 11/20] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- ludwig/utils/upload_utils.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/ludwig/utils/upload_utils.py b/ludwig/utils/upload_utils.py index 766ada92d2e..09d0aa361bb 100644 --- a/ludwig/utils/upload_utils.py +++ b/ludwig/utils/upload_utils.py @@ -259,8 +259,9 @@ def upload( # Upload all artifacts in model weights folder commit_message_weights: str | None = f"{commit_message} (weights)" if commit_message else commit_message - commit_description_weights: str | None = f"{commit_description} (weights)" if commit_description else \ - commit_description + commit_description_weights: str | None = ( + f"{commit_description} (weights)" if commit_description else commit_description + ) upload_path_weights = self.api.upload_folder( folder_path=os.path.join(model_path, "model", "model_weights"), repo_id=repo_id, @@ -273,8 +274,9 @@ def upload( logger.info(f"Model weights uploaded to `{upload_path_weights}` with repository name `{repo_id}`") # Upload the ludwig configuration file commit_message_config: str | None = f"{commit_message} (config)" if commit_message else commit_message - commit_description_config: str | None = f"{commit_description} (config)" if commit_description else \ - commit_description + commit_description_config: str | None = ( + f"{commit_description} (config)" if commit_description else commit_description + ) upload_path_config = self.api.upload_file( path_or_fileobj=os.path.join(model_path, "model", MODEL_HYPERPARAMETERS_FILE_NAME), path_in_repo="ludwig_config.json", From 968941aa84175f2db083521d79b4e990d612d7ce Mon Sep 17 00:00:00 2001 From: Sanjay Date: Fri, 15 Mar 2024 21:55:04 +0530 Subject: [PATCH 12/20] Updated to check for 'ludwig_config.json' --- tests/ludwig/utils/test_upload_utils.py | 126 +++++++++++++++++++++--- 1 file changed, 113 insertions(+), 13 deletions(-) diff --git a/tests/ludwig/utils/test_upload_utils.py b/tests/ludwig/utils/test_upload_utils.py index ef016e24d44..ab0637c1b07 100644 --- a/tests/ludwig/utils/test_upload_utils.py +++ b/tests/ludwig/utils/test_upload_utils.py @@ -57,79 +57,179 @@ def output_directory_manager(tmpdir) -> str: [ pytest.param( [ + "ludwig_config.json", "pytorch_model.bin", ], None, - id="pretrained_model_weights_bin", + id="ludwig_config_and_pretrained_model_weights_bin", ), pytest.param( [ + "pytorch_model.bin", + ], + ( + ValueError, + "Can't find ludwig config at {model_weights_path}. ludwig config should be saved as`ludwig_config.json`", # noqa E501 + ), + id="pretrained_model_weights_bin_and_ludwig_config_missing", + ), + pytest.param( + [ + "ludwig_config.json", "adapter_model.bin", ], None, - id="adapter_model_weights_bin_unmerged", # backward compatibility for peft versions < 0.7.0 + id="ludwig_config_and_adapter_model_weights_bin_unmerged", # backward compatibility for peft versions < 0.7.0 + ), + pytest.param( + [ + "adapter_model.bin", + ], + ( + ValueError, + "Can't find ludwig config at {model_weights_path}. ludwig config should be saved as`ludwig_config.json`", # noqa E501 + ), + id="adapter_model_weights_bin_unmerged_and_ludwig_config_missing", # backward compatibility for peft versions < 0.7.0 ), pytest.param( [ + "ludwig_config.json", "adapter_model.safetensors", ], None, - id="adapter_model_weights_safetensors_unmerged", + id="ludwig_config_and_adapter_model_weights_safetensors_unmerged", + ), + pytest.param( + [ + "adapter_model.safetensors", + ], + ( + ValueError, + "Can't find ludwig config at {model_weights_path}. ludwig config should be saved as`ludwig_config.json`", # noqa E501 + ), + id="adapter_model_weights_safetensors_unmerged_and_ludwig_config_missing", ), pytest.param( [ + "ludwig_config.json", "adapter_model.bin", "adapter_model.safetensors", ], None, - id="adapter_model_weights_bin_and_safetensors_unmerged", # backward compatibility for peft versions < 0.7.0 + id="ludwig_config_and_adapter_model_weights_bin_and_safetensors_unmerged", # backward compatibility for peft versions < 0.7.0 + ), + pytest.param( + [ + "adapter_model.bin", + "adapter_model.safetensors", + ], + ( + ValueError, + "Can't find ludwig config at {model_weights_path}. ludwig config should be saved as`ludwig_config.json`", # noqa E501 + ), + id="adapter_model_weights_bin_and_safetensors_unmerged_and_ludwig_config_missing", # backward compatibility for peft versions < 0.7.0 ), pytest.param( [ + "ludwig_config.json", "pytorch_model.bin", "adapter_model.safetensors", ], None, - id="pretrained_model_weights_bin_and_adapter_model_weights_safetensors_merged", + id="ludwig_config_and_pretrained_model_weights_bin_and_adapter_model_weights_safetensors_merged", + ), + pytest.param( + [ + "pytorch_model.bin", + "adapter_model.safetensors", + ], + ( + ValueError, + "Can't find ludwig config at {model_weights_path}. ludwig config should be saved as`ludwig_config.json`", # noqa E501 + ), + id="pretrained_model_weights_bin_and_adapter_model_weights_safetensors_merged_and_ludwig_config_missing", + ), + pytest.param( + [ + "ludwig_config.json" + ], + ( + ValueError, + "Can't find model weights at {model_weights_path}. Trained model weights should either be saved as `pytorch_model.bin` for regular model training, or have `adapter_model.bin`or `adapter_model.safetensors` if using parameter efficient fine-tuning methods like LoRA.", # noqa E501 + ), + id="model_weights_missing", ), pytest.param( [], ( ValueError, - "Can't find model weights at {model_weights_path}. Trained model weights should either be saved as `pytorch_model.bin` for regular model training, or have `adapter_model.bin`or `adapter_model.safetensors` if using parameter efficient fine-tuning methods like LoRA.", # noqa E501 + "Can't find model weights and ludwig config at {model_weights_path}. Trained model weights should either be saved as `pytorch_model.bin` for regular model training, or have `adapter_model.bin`or `adapter_model.safetensors` if using parameter efficient fine-tuning methods like LoRA.", # noqa E501 ), - id="model_weights_missing", + id="model_weights_missing_and_ludwig_config_missing", ), pytest.param( [ + "ludwig_config.json", "pytorch_model.safetensors", ], ( - ValueError, - "Can't find model weights at {model_weights_path}. Trained model weights should either be saved as `pytorch_model.bin` for regular model training, or have `adapter_model.bin`or `adapter_model.safetensors` if using parameter efficient fine-tuning methods like LoRA.", # noqa E501 + ValueError, + "Can't find model weights at {model_weights_path}. Trained model weights should either be saved as `pytorch_model.bin` for regular model training, or have `adapter_model.bin`or `adapter_model.safetensors` if using parameter efficient fine-tuning methods like LoRA.", # noqa E501 ), id="model_weights_unexpected_name_format_combination", ), pytest.param( [ - "pytorch_model.unkn", + "pytorch_model.safetensors", ], ( ValueError, - "Can't find model weights at {model_weights_path}. Trained model weights should either be saved as `pytorch_model.bin` for regular model training, or have `adapter_model.bin`or `adapter_model.safetensors` if using parameter efficient fine-tuning methods like LoRA.", # noqa E501 + "Can't find model weights and ludwig config at {model_weights_path}. Trained model weights should either be saved as `pytorch_model.bin` for regular model training, or have `adapter_model.bin`or `adapter_model.safetensors` if using parameter efficient fine-tuning methods like LoRA.", # noqa E501 + ), + id="model_weights_unexpected_name_format_combination_and_ludwig_config_missing", + ), + pytest.param( + [ + "ludwig_config.json", + "pytorch_model.unkn", + ], + ( + ValueError, + "Can't find model weights at {model_weights_path}. Trained model weights should either be saved as `pytorch_model.bin` for regular model training, or have `adapter_model.bin`or `adapter_model.safetensors` if using parameter efficient fine-tuning methods like LoRA.", # noqa E501 ), id="model_weights_unrecognized_format", ), pytest.param( [ - "unknown_model.safetensors", + "pytorch_model.unkn", ], ( ValueError, - "Can't find model weights at {model_weights_path}. Trained model weights should either be saved as `pytorch_model.bin` for regular model training, or have `adapter_model.bin`or `adapter_model.safetensors` if using parameter efficient fine-tuning methods like LoRA.", # noqa E501 + "Can't find model weights and ludwig config at {model_weights_path}. Trained model weights should either be saved as `pytorch_model.bin` for regular model training, or have `adapter_model.bin`or `adapter_model.safetensors` if using parameter efficient fine-tuning methods like LoRA.", # noqa E501 + ), + id="model_weights_unrecognized_format_and_ludwig_config_missing", + ), + pytest.param( + [ + "ludwig_config.json", + "unknown_model.safetensors", + ], + ( + ValueError, + "Can't find model weights at {model_weights_path}. Trained model weights should either be saved as `pytorch_model.bin` for regular model training, or have `adapter_model.bin`or `adapter_model.safetensors` if using parameter efficient fine-tuning methods like LoRA.", # noqa E501 ), id="model_weights_unrecognized_name", ), + pytest.param( + [ + "unknown_model.safetensors", + ], + ( + ValueError, + "Can't find model weights and ludwig config at {model_weights_path}. Trained model weights should either be saved as `pytorch_model.bin` for regular model training, or have `adapter_model.bin`or `adapter_model.safetensors` if using parameter efficient fine-tuning methods like LoRA.", # noqa E501 + ), + id="model_weights_unrecognized_name_and_ludwig_config_missing", + ), ], ) @pytest.mark.unit From c23291473f733203232b07468025aba66bdb7ba8 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 15 Mar 2024 16:28:39 +0000 Subject: [PATCH 13/20] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- tests/ludwig/utils/test_upload_utils.py | 40 ++++++++++++------------- 1 file changed, 19 insertions(+), 21 deletions(-) diff --git a/tests/ludwig/utils/test_upload_utils.py b/tests/ludwig/utils/test_upload_utils.py index ab0637c1b07..5f37a3ae763 100644 --- a/tests/ludwig/utils/test_upload_utils.py +++ b/tests/ludwig/utils/test_upload_utils.py @@ -68,8 +68,8 @@ def output_directory_manager(tmpdir) -> str: "pytorch_model.bin", ], ( - ValueError, - "Can't find ludwig config at {model_weights_path}. ludwig config should be saved as`ludwig_config.json`", # noqa E501 + ValueError, + "Can't find ludwig config at {model_weights_path}. ludwig config should be saved as`ludwig_config.json`", # noqa E501 ), id="pretrained_model_weights_bin_and_ludwig_config_missing", ), @@ -86,8 +86,8 @@ def output_directory_manager(tmpdir) -> str: "adapter_model.bin", ], ( - ValueError, - "Can't find ludwig config at {model_weights_path}. ludwig config should be saved as`ludwig_config.json`", # noqa E501 + ValueError, + "Can't find ludwig config at {model_weights_path}. ludwig config should be saved as`ludwig_config.json`", # noqa E501 ), id="adapter_model_weights_bin_unmerged_and_ludwig_config_missing", # backward compatibility for peft versions < 0.7.0 ), @@ -104,8 +104,8 @@ def output_directory_manager(tmpdir) -> str: "adapter_model.safetensors", ], ( - ValueError, - "Can't find ludwig config at {model_weights_path}. ludwig config should be saved as`ludwig_config.json`", # noqa E501 + ValueError, + "Can't find ludwig config at {model_weights_path}. ludwig config should be saved as`ludwig_config.json`", # noqa E501 ), id="adapter_model_weights_safetensors_unmerged_and_ludwig_config_missing", ), @@ -124,8 +124,8 @@ def output_directory_manager(tmpdir) -> str: "adapter_model.safetensors", ], ( - ValueError, - "Can't find ludwig config at {model_weights_path}. ludwig config should be saved as`ludwig_config.json`", # noqa E501 + ValueError, + "Can't find ludwig config at {model_weights_path}. ludwig config should be saved as`ludwig_config.json`", # noqa E501 ), id="adapter_model_weights_bin_and_safetensors_unmerged_and_ludwig_config_missing", # backward compatibility for peft versions < 0.7.0 ), @@ -144,18 +144,16 @@ def output_directory_manager(tmpdir) -> str: "adapter_model.safetensors", ], ( - ValueError, - "Can't find ludwig config at {model_weights_path}. ludwig config should be saved as`ludwig_config.json`", # noqa E501 + ValueError, + "Can't find ludwig config at {model_weights_path}. ludwig config should be saved as`ludwig_config.json`", # noqa E501 ), id="pretrained_model_weights_bin_and_adapter_model_weights_safetensors_merged_and_ludwig_config_missing", ), pytest.param( - [ - "ludwig_config.json" - ], + ["ludwig_config.json"], ( - ValueError, - "Can't find model weights at {model_weights_path}. Trained model weights should either be saved as `pytorch_model.bin` for regular model training, or have `adapter_model.bin`or `adapter_model.safetensors` if using parameter efficient fine-tuning methods like LoRA.", # noqa E501 + ValueError, + "Can't find model weights at {model_weights_path}. Trained model weights should either be saved as `pytorch_model.bin` for regular model training, or have `adapter_model.bin`or `adapter_model.safetensors` if using parameter efficient fine-tuning methods like LoRA.", # noqa E501 ), id="model_weights_missing", ), @@ -173,8 +171,8 @@ def output_directory_manager(tmpdir) -> str: "pytorch_model.safetensors", ], ( - ValueError, - "Can't find model weights at {model_weights_path}. Trained model weights should either be saved as `pytorch_model.bin` for regular model training, or have `adapter_model.bin`or `adapter_model.safetensors` if using parameter efficient fine-tuning methods like LoRA.", # noqa E501 + ValueError, + "Can't find model weights at {model_weights_path}. Trained model weights should either be saved as `pytorch_model.bin` for regular model training, or have `adapter_model.bin`or `adapter_model.safetensors` if using parameter efficient fine-tuning methods like LoRA.", # noqa E501 ), id="model_weights_unexpected_name_format_combination", ), @@ -194,8 +192,8 @@ def output_directory_manager(tmpdir) -> str: "pytorch_model.unkn", ], ( - ValueError, - "Can't find model weights at {model_weights_path}. Trained model weights should either be saved as `pytorch_model.bin` for regular model training, or have `adapter_model.bin`or `adapter_model.safetensors` if using parameter efficient fine-tuning methods like LoRA.", # noqa E501 + ValueError, + "Can't find model weights at {model_weights_path}. Trained model weights should either be saved as `pytorch_model.bin` for regular model training, or have `adapter_model.bin`or `adapter_model.safetensors` if using parameter efficient fine-tuning methods like LoRA.", # noqa E501 ), id="model_weights_unrecognized_format", ), @@ -215,8 +213,8 @@ def output_directory_manager(tmpdir) -> str: "unknown_model.safetensors", ], ( - ValueError, - "Can't find model weights at {model_weights_path}. Trained model weights should either be saved as `pytorch_model.bin` for regular model training, or have `adapter_model.bin`or `adapter_model.safetensors` if using parameter efficient fine-tuning methods like LoRA.", # noqa E501 + ValueError, + "Can't find model weights at {model_weights_path}. Trained model weights should either be saved as `pytorch_model.bin` for regular model training, or have `adapter_model.bin`or `adapter_model.safetensors` if using parameter efficient fine-tuning methods like LoRA.", # noqa E501 ), id="model_weights_unrecognized_name", ), From d50bd57bb1211358fa9208e527c812e061a9633b Mon Sep 17 00:00:00 2001 From: Sanjay Date: Sat, 16 Mar 2024 07:46:30 +0530 Subject: [PATCH 14/20] Added 'model_hyperparameters.json' to output directory --- tests/ludwig/utils/test_upload_utils.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/tests/ludwig/utils/test_upload_utils.py b/tests/ludwig/utils/test_upload_utils.py index ab0637c1b07..1f29b6699bb 100644 --- a/tests/ludwig/utils/test_upload_utils.py +++ b/tests/ludwig/utils/test_upload_utils.py @@ -7,6 +7,7 @@ import pytest from ludwig.utils.upload_utils import HuggingFaceHub +from pathlib import Path logger = logging.getLogger(__name__) @@ -26,14 +27,15 @@ def _build_fake_model_repo( names must be leaf file names, not paths). """ # Create a temporary folder designating training output directory. - model_directory: str = pathlib.Path(destination_directory) / experiment_name / model_directory_name - model_weights_directory: str = model_directory / model_weights_directory_name + model_directory: Path = pathlib.Path(destination_directory) / experiment_name / model_directory_name + model_weights_directory: Path = model_directory / model_weights_directory_name model_weights_directory.mkdir(parents=True, exist_ok=True) # Create files within the "model_weights" subdirectory. file_name: str for file_name in file_names: pathlib.Path(model_weights_directory / file_name).touch() + pathlib.Path(model_directory / "model_hyperparameters.json").touch() @pytest.fixture @@ -79,7 +81,7 @@ def output_directory_manager(tmpdir) -> str: "adapter_model.bin", ], None, - id="ludwig_config_and_adapter_model_weights_bin_unmerged", # backward compatibility for peft versions < 0.7.0 + id="ludwig_config_and_adapter_model_weights_bin_unmerged", # backward compatibility for peft versions < 0.7.0 # noqa E501 ), pytest.param( [ @@ -89,7 +91,7 @@ def output_directory_manager(tmpdir) -> str: ValueError, "Can't find ludwig config at {model_weights_path}. ludwig config should be saved as`ludwig_config.json`", # noqa E501 ), - id="adapter_model_weights_bin_unmerged_and_ludwig_config_missing", # backward compatibility for peft versions < 0.7.0 + id="adapter_model_weights_bin_unmerged_and_ludwig_config_missing", # backward compatibility for peft versions < 0.7.0 # noqa E501 ), pytest.param( [ @@ -116,7 +118,7 @@ def output_directory_manager(tmpdir) -> str: "adapter_model.safetensors", ], None, - id="ludwig_config_and_adapter_model_weights_bin_and_safetensors_unmerged", # backward compatibility for peft versions < 0.7.0 + id="ludwig_config_and_adapter_model_weights_bin_and_safetensors_unmerged", # backward compatibility for peft versions < 0.7.0 # noqa E501 ), pytest.param( [ @@ -127,7 +129,7 @@ def output_directory_manager(tmpdir) -> str: ValueError, "Can't find ludwig config at {model_weights_path}. ludwig config should be saved as`ludwig_config.json`", # noqa E501 ), - id="adapter_model_weights_bin_and_safetensors_unmerged_and_ludwig_config_missing", # backward compatibility for peft versions < 0.7.0 + id="adapter_model_weights_bin_and_safetensors_unmerged_and_ludwig_config_missing", # backward compatibility for peft versions < 0.7.0 # noqa E501 ), pytest.param( [ From d536a82f8b60aba132a41240fee0a9cf6b124980 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sat, 16 Mar 2024 02:19:11 +0000 Subject: [PATCH 15/20] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- tests/ludwig/utils/test_upload_utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/ludwig/utils/test_upload_utils.py b/tests/ludwig/utils/test_upload_utils.py index 9647daad0d3..1a034b3c70a 100644 --- a/tests/ludwig/utils/test_upload_utils.py +++ b/tests/ludwig/utils/test_upload_utils.py @@ -3,11 +3,11 @@ import logging import pathlib import shutil +from pathlib import Path import pytest from ludwig.utils.upload_utils import HuggingFaceHub -from pathlib import Path logger = logging.getLogger(__name__) From a205d21ab8f8d52a0696d8ffe3fbd3905e87edf2 Mon Sep 17 00:00:00 2001 From: Sanjay Date: Sat, 16 Mar 2024 13:43:45 +0530 Subject: [PATCH 16/20] upload_utils.py: augmented '_validate_upload_parameters()' to check for presence of 'model_hyperparameters.json' test_upload_utils.py: augmented '_build_fake_model_repo()' to add 'model_hyperparameters.json' at expected location --- ludwig/utils/upload_utils.py | 9 +- tests/ludwig/utils/test_upload_utils.py | 118 ++---------------------- 2 files changed, 17 insertions(+), 110 deletions(-) diff --git a/ludwig/utils/upload_utils.py b/ludwig/utils/upload_utils.py index 09d0aa361bb..f0f7e7f4673 100644 --- a/ludwig/utils/upload_utils.py +++ b/ludwig/utils/upload_utils.py @@ -195,17 +195,22 @@ def _validate_upload_parameters( """ files = set(os.listdir(trained_model_artifacts_path)) - acceptable_model_artifact_file_nanes: set[str] = { + acceptable_model_artifact_file_names: set[str] = { "pytorch_model.bin", "adapter_model.bin", # Delete per formal deprecation policy TBD (per above comment). "adapter_model.safetensors", # New format as of PEFT version "0.7.0" (per above comment). } - if not (files & acceptable_model_artifact_file_nanes): + if not (files & acceptable_model_artifact_file_names): raise ValueError( f"Can't find model weights at {trained_model_artifacts_path}. Trained model weights should " "either be saved as `pytorch_model.bin` for regular model training, or have `adapter_model.bin`" "or `adapter_model.safetensors` if using parameter efficient fine-tuning methods like LoRA." ) + model_hyperparameters_path = os.path.join(model_path, "model") + if MODEL_HYPERPARAMETERS_FILE_NAME not in os.listdir(model_hyperparameters_path): + raise ValueError( + f"Can't find '{MODEL_HYPERPARAMETERS_FILE_NAME}' at {model_hyperparameters_path}." + ) def upload( self, diff --git a/tests/ludwig/utils/test_upload_utils.py b/tests/ludwig/utils/test_upload_utils.py index 9647daad0d3..672488459fc 100644 --- a/tests/ludwig/utils/test_upload_utils.py +++ b/tests/ludwig/utils/test_upload_utils.py @@ -6,8 +6,8 @@ import pytest +from ludwig.globals import MODEL_HYPERPARAMETERS_FILE_NAME from ludwig.utils.upload_utils import HuggingFaceHub -from pathlib import Path logger = logging.getLogger(__name__) @@ -27,15 +27,15 @@ def _build_fake_model_repo( names must be leaf file names, not paths). """ # Create a temporary folder designating training output directory. - model_directory: Path = pathlib.Path(destination_directory) / experiment_name / model_directory_name - model_weights_directory: Path = model_directory / model_weights_directory_name + model_directory: pathlib.Path = pathlib.Path(destination_directory) / experiment_name / model_directory_name + model_weights_directory: pathlib.Path = model_directory / model_weights_directory_name model_weights_directory.mkdir(parents=True, exist_ok=True) # Create files within the "model_weights" subdirectory. file_name: str for file_name in file_names: pathlib.Path(model_weights_directory / file_name).touch() - pathlib.Path(model_directory / "model_hyperparameters.json").touch() + pathlib.Path(model_directory / MODEL_HYPERPARAMETERS_FILE_NAME).touch() @pytest.fixture @@ -59,117 +59,51 @@ def output_directory_manager(tmpdir) -> str: [ pytest.param( [ - "ludwig_config.json", "pytorch_model.bin", ], None, - id="ludwig_config_and_pretrained_model_weights_bin", + id="pretrained_model_weights_bin", ), pytest.param( [ - "pytorch_model.bin", - ], - ( - ValueError, - "Can't find ludwig config at {model_weights_path}. ludwig config should be saved as`ludwig_config.json`", # noqa E501 - ), - id="pretrained_model_weights_bin_and_ludwig_config_missing", - ), - pytest.param( - [ - "ludwig_config.json", "adapter_model.bin", ], None, - id="ludwig_config_and_adapter_model_weights_bin_unmerged", # backward compatibility for peft versions < 0.7.0 # noqa E501 + id="adapter_model_weights_bin_unmerged", # backward compatibility for peft versions < 0.7.0 ), pytest.param( [ - "adapter_model.bin", - ], - ( - ValueError, - "Can't find ludwig config at {model_weights_path}. ludwig config should be saved as`ludwig_config.json`", # noqa E501 - ), - id="adapter_model_weights_bin_unmerged_and_ludwig_config_missing", # backward compatibility for peft versions < 0.7.0 # noqa E501 - ), - pytest.param( - [ - "ludwig_config.json", "adapter_model.safetensors", ], None, - id="ludwig_config_and_adapter_model_weights_safetensors_unmerged", + id="adapter_model_weights_safetensors_unmerged", ), pytest.param( [ - "adapter_model.safetensors", - ], - ( - ValueError, - "Can't find ludwig config at {model_weights_path}. ludwig config should be saved as`ludwig_config.json`", # noqa E501 - ), - id="adapter_model_weights_safetensors_unmerged_and_ludwig_config_missing", - ), - pytest.param( - [ - "ludwig_config.json", "adapter_model.bin", "adapter_model.safetensors", ], None, - id="ludwig_config_and_adapter_model_weights_bin_and_safetensors_unmerged", # backward compatibility for peft versions < 0.7.0 # noqa E501 - ), - pytest.param( - [ - "adapter_model.bin", - "adapter_model.safetensors", - ], - ( - ValueError, - "Can't find ludwig config at {model_weights_path}. ludwig config should be saved as`ludwig_config.json`", # noqa E501 - ), - id="adapter_model_weights_bin_and_safetensors_unmerged_and_ludwig_config_missing", # backward compatibility for peft versions < 0.7.0 # noqa E501 + id="adapter_model_weights_bin_and_safetensors_unmerged", # backward compatibility for peft versions < 0.7.0 ), pytest.param( [ - "ludwig_config.json", "pytorch_model.bin", "adapter_model.safetensors", ], None, - id="ludwig_config_and_pretrained_model_weights_bin_and_adapter_model_weights_safetensors_merged", + id="pretrained_model_weights_bin_and_adapter_model_weights_safetensors_merged", ), pytest.param( - [ - "pytorch_model.bin", - "adapter_model.safetensors", - ], - ( - ValueError, - "Can't find ludwig config at {model_weights_path}. ludwig config should be saved as`ludwig_config.json`", # noqa E501 - ), - id="pretrained_model_weights_bin_and_adapter_model_weights_safetensors_merged_and_ludwig_config_missing", - ), - pytest.param( - ["ludwig_config.json"], + [], ( ValueError, "Can't find model weights at {model_weights_path}. Trained model weights should either be saved as `pytorch_model.bin` for regular model training, or have `adapter_model.bin`or `adapter_model.safetensors` if using parameter efficient fine-tuning methods like LoRA.", # noqa E501 ), id="model_weights_missing", ), - pytest.param( - [], - ( - ValueError, - "Can't find model weights and ludwig config at {model_weights_path}. Trained model weights should either be saved as `pytorch_model.bin` for regular model training, or have `adapter_model.bin`or `adapter_model.safetensors` if using parameter efficient fine-tuning methods like LoRA.", # noqa E501 - ), - id="model_weights_missing_and_ludwig_config_missing", - ), pytest.param( [ - "ludwig_config.json", "pytorch_model.safetensors", ], ( @@ -180,17 +114,6 @@ def output_directory_manager(tmpdir) -> str: ), pytest.param( [ - "pytorch_model.safetensors", - ], - ( - ValueError, - "Can't find model weights and ludwig config at {model_weights_path}. Trained model weights should either be saved as `pytorch_model.bin` for regular model training, or have `adapter_model.bin`or `adapter_model.safetensors` if using parameter efficient fine-tuning methods like LoRA.", # noqa E501 - ), - id="model_weights_unexpected_name_format_combination_and_ludwig_config_missing", - ), - pytest.param( - [ - "ludwig_config.json", "pytorch_model.unkn", ], ( @@ -201,17 +124,6 @@ def output_directory_manager(tmpdir) -> str: ), pytest.param( [ - "pytorch_model.unkn", - ], - ( - ValueError, - "Can't find model weights and ludwig config at {model_weights_path}. Trained model weights should either be saved as `pytorch_model.bin` for regular model training, or have `adapter_model.bin`or `adapter_model.safetensors` if using parameter efficient fine-tuning methods like LoRA.", # noqa E501 - ), - id="model_weights_unrecognized_format_and_ludwig_config_missing", - ), - pytest.param( - [ - "ludwig_config.json", "unknown_model.safetensors", ], ( @@ -220,16 +132,6 @@ def output_directory_manager(tmpdir) -> str: ), id="model_weights_unrecognized_name", ), - pytest.param( - [ - "unknown_model.safetensors", - ], - ( - ValueError, - "Can't find model weights and ludwig config at {model_weights_path}. Trained model weights should either be saved as `pytorch_model.bin` for regular model training, or have `adapter_model.bin`or `adapter_model.safetensors` if using parameter efficient fine-tuning methods like LoRA.", # noqa E501 - ), - id="model_weights_unrecognized_name_and_ludwig_config_missing", - ), ], ) @pytest.mark.unit From f353038f3e386f52d674fe592d85904affc906ba Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sat, 16 Mar 2024 08:15:37 +0000 Subject: [PATCH 17/20] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- ludwig/utils/upload_utils.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/ludwig/utils/upload_utils.py b/ludwig/utils/upload_utils.py index f0f7e7f4673..6f329a33a4c 100644 --- a/ludwig/utils/upload_utils.py +++ b/ludwig/utils/upload_utils.py @@ -208,9 +208,7 @@ def _validate_upload_parameters( ) model_hyperparameters_path = os.path.join(model_path, "model") if MODEL_HYPERPARAMETERS_FILE_NAME not in os.listdir(model_hyperparameters_path): - raise ValueError( - f"Can't find '{MODEL_HYPERPARAMETERS_FILE_NAME}' at {model_hyperparameters_path}." - ) + raise ValueError(f"Can't find '{MODEL_HYPERPARAMETERS_FILE_NAME}' at {model_hyperparameters_path}.") def upload( self, From 902989d2b8e56ccb4d19724c07a439c9513966b3 Mon Sep 17 00:00:00 2001 From: Sanjay Date: Sat, 16 Mar 2024 14:24:50 +0530 Subject: [PATCH 18/20] test_upload_utils.py: removed unused import --- tests/ludwig/utils/test_upload_utils.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/ludwig/utils/test_upload_utils.py b/tests/ludwig/utils/test_upload_utils.py index 2ceeb84ee7e..672488459fc 100644 --- a/tests/ludwig/utils/test_upload_utils.py +++ b/tests/ludwig/utils/test_upload_utils.py @@ -3,7 +3,6 @@ import logging import pathlib import shutil -from pathlib import Path import pytest From 05c97fd7fc2beafead86d40b8b09192abef83aad Mon Sep 17 00:00:00 2001 From: Sanjay Date: Sat, 16 Mar 2024 22:24:52 +0530 Subject: [PATCH 19/20] upload_utils.py: added some type hints --- ludwig/utils/upload_utils.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ludwig/utils/upload_utils.py b/ludwig/utils/upload_utils.py index 6f329a33a4c..5bb7fe3254c 100644 --- a/ludwig/utils/upload_utils.py +++ b/ludwig/utils/upload_utils.py @@ -5,7 +5,7 @@ from abc import ABC, abstractmethod from huggingface_hub import HfApi, login - +from huggingface_hub.hf_api import CommitInfo from ludwig.globals import MODEL_HYPERPARAMETERS_FILE_NAME logger = logging.getLogger(__name__) @@ -206,7 +206,7 @@ def _validate_upload_parameters( "either be saved as `pytorch_model.bin` for regular model training, or have `adapter_model.bin`" "or `adapter_model.safetensors` if using parameter efficient fine-tuning methods like LoRA." ) - model_hyperparameters_path = os.path.join(model_path, "model") + model_hyperparameters_path: str = os.path.join(model_path, "model") if MODEL_HYPERPARAMETERS_FILE_NAME not in os.listdir(model_hyperparameters_path): raise ValueError(f"Can't find '{MODEL_HYPERPARAMETERS_FILE_NAME}' at {model_hyperparameters_path}.") @@ -265,7 +265,7 @@ def upload( commit_description_weights: str | None = ( f"{commit_description} (weights)" if commit_description else commit_description ) - upload_path_weights = self.api.upload_folder( + upload_path_weights: CommitInfo = self.api.upload_folder( folder_path=os.path.join(model_path, "model", "model_weights"), repo_id=repo_id, repo_type=repo_type, @@ -280,7 +280,7 @@ def upload( commit_description_config: str | None = ( f"{commit_description} (config)" if commit_description else commit_description ) - upload_path_config = self.api.upload_file( + upload_path_config: CommitInfo = self.api.upload_file( path_or_fileobj=os.path.join(model_path, "model", MODEL_HYPERPARAMETERS_FILE_NAME), path_in_repo="ludwig_config.json", repo_id=repo_id, From 7dcc2b4778ad9145a200cd98e92668b185f38222 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sat, 16 Mar 2024 16:56:36 +0000 Subject: [PATCH 20/20] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- ludwig/utils/upload_utils.py | 1 + 1 file changed, 1 insertion(+) diff --git a/ludwig/utils/upload_utils.py b/ludwig/utils/upload_utils.py index 5bb7fe3254c..bdcc6df9c13 100644 --- a/ludwig/utils/upload_utils.py +++ b/ludwig/utils/upload_utils.py @@ -6,6 +6,7 @@ from huggingface_hub import HfApi, login from huggingface_hub.hf_api import CommitInfo + from ludwig.globals import MODEL_HYPERPARAMETERS_FILE_NAME logger = logging.getLogger(__name__)