From beba6ef25322a79514bbec90ce1f750c2a80a5d2 Mon Sep 17 00:00:00 2001 From: YizhenJia Date: Sat, 22 Feb 2025 20:37:13 +0800 Subject: [PATCH 01/61] [usability] accelerate support initial commit --- configs/iterative_dpo.yaml | 1 - examples/benchmarking.py | 2 +- examples/chatbot.py | 3 +- examples/chatbot_gradio.py | 2 +- examples/evaluation.py | 3 +- examples/finetune_multi_modal.py | 2 +- examples/inference.py | 3 +- examples/merge_lora.py | 2 +- examples/rm_inference.py | 2 +- examples/vis_chatbot.py | 2 +- examples/vis_chatbot_gradio.py | 2 +- examples/vllm_inference.py | 2 +- requirements.txt | 1 - scripts/run_chatbot.sh | 1 - scripts/run_evaluation_accelerator.sh | 1 - scripts/run_inference.sh | 1 - scripts/run_rm_inference.sh | 1 - service/app.py | 2 +- setup.py | 3 +- src/lmflow/args.py | 23 ++++++++-- src/lmflow/models/hf_decoder_model.py | 31 ++++--------- src/lmflow/models/hf_model_mixin.py | 46 ++++++++----------- src/lmflow/models/hf_text_regression_model.py | 40 ++++------------ src/lmflow/pipeline/evaluator.py | 45 +++++++++++++----- src/lmflow/pipeline/finetuner.py | 6 +-- src/lmflow/pipeline/inferencer.py | 31 ++++++++----- src/lmflow/pipeline/iterative_dpo_aligner.py | 5 +- src/lmflow/pipeline/rm_inferencer.py | 17 +++---- .../utils/memory_safe_vllm_inference.py | 2 +- src/lmflow/pipeline/utils/raft_trainer.py | 7 ++- src/lmflow/utils/envs.py | 7 +++ src/lmflow/utils/versioning.py | 6 ++- tests/models/test_hf_decoder_model.py | 4 +- 33 files changed, 158 insertions(+), 148 deletions(-) create mode 100644 src/lmflow/utils/envs.py diff --git a/configs/iterative_dpo.yaml b/configs/iterative_dpo.yaml index 1b18e1d03..d70a41ead 100644 --- a/configs/iterative_dpo.yaml +++ b/configs/iterative_dpo.yaml @@ -17,7 +17,6 @@ preprocessing_num_workers: 16 output_dir: ./output_models/iterative_dpo run_name: iterative_dpo random_seed: 42 -use_accelerator: True enable_distributed_inference: True distributed_inference_num_instances: 8 initial_iter_idx: 0 # 0 refers to the first dataset in dataset_path_list diff --git a/examples/benchmarking.py b/examples/benchmarking.py index 2b1d57741..3becf2e91 100644 --- a/examples/benchmarking.py +++ b/examples/benchmarking.py @@ -214,7 +214,7 @@ def main(): dataset_name = benchmarking_args.dataset_name # metric = pipeline_args.metric if is_lmflow_local_benchmarking(dataset_name): # TODO (@Jipeng) - model = AutoModel.get_model(model_args, tune_strategy='none', ds_config=ds_config) + model = AutoModel.get_model(model_args, do_train=False, ds_config=ds_config) run_lmflow_local_benchmarking(dataset_name,pipeline_name,model_args,pipeline_args,model) # Pass args TODO (@Jipeng) elif is_lm_evaluation_benchmarking(dataset_name): model = model_args.model_name_or_path diff --git a/examples/chatbot.py b/examples/chatbot.py index b6d8138e7..34e1587de 100644 --- a/examples/chatbot.py +++ b/examples/chatbot.py @@ -64,10 +64,9 @@ def main(): model = AutoModel.get_model( model_args, - tune_strategy='none', + do_train=False, ds_config=ds_config, device=pipeline_args.device, - use_accelerator=True, ) # We don't need input data, we will read interactively from stdin diff --git a/examples/chatbot_gradio.py b/examples/chatbot_gradio.py index d522497a1..b3259221e 100644 --- a/examples/chatbot_gradio.py +++ b/examples/chatbot_gradio.py @@ -110,7 +110,7 @@ class ChatbotArguments: model = AutoModel.get_model( model_args, - tune_strategy='none', + do_train=False, ds_config=ds_config, device=pipeline_args.device, torch_dtype=torch.float16 diff --git a/examples/evaluation.py b/examples/evaluation.py index b9360763c..a1224769a 100644 --- a/examples/evaluation.py +++ b/examples/evaluation.py @@ -36,9 +36,8 @@ model = AutoModel.get_model( model_args, - tune_strategy='none', + do_train=False, ds_config=ds_config, - use_accelerator=pipeline_args.use_accelerator_for_evaluator ) dataset = Dataset(data_args) diff --git a/examples/finetune_multi_modal.py b/examples/finetune_multi_modal.py index 90fecc2a3..cacab7144 100644 --- a/examples/finetune_multi_modal.py +++ b/examples/finetune_multi_modal.py @@ -59,7 +59,7 @@ def main(): # do not resiger deepspeed in the model. # with_deepspeed flag may be removed # by modifying the tune strategy in the future. - model = AutoModel.get_model(model_args, tune_strategy='none', + model = AutoModel.get_model(model_args, do_train=True, ds_config=pipeline_args.deepspeed, custom_model=True, with_deepspeed=False, diff --git a/examples/inference.py b/examples/inference.py index 6381aa86d..cbee351ba 100644 --- a/examples/inference.py +++ b/examples/inference.py @@ -39,10 +39,9 @@ def main(): model = AutoModel.get_model( model_args, - tune_strategy='none', + do_train=False, ds_config=ds_config, device=pipeline_args.device, - use_accelerator=True, ) # We don't need input data, we will read interactively from stdin diff --git a/examples/merge_lora.py b/examples/merge_lora.py index cd52363a8..3bbdb1dde 100644 --- a/examples/merge_lora.py +++ b/examples/merge_lora.py @@ -62,7 +62,7 @@ def main(): model_args.use_lora = True model = AutoModel.get_model( model_args, - tune_strategy='none', + do_train=False, device=merge_lora_args.device, ds_config=merge_lora_args.ds_config ) diff --git a/examples/rm_inference.py b/examples/rm_inference.py index 0f8acf7ce..9c999e988 100644 --- a/examples/rm_inference.py +++ b/examples/rm_inference.py @@ -40,7 +40,7 @@ def main(): model_args, data_args, pipeline_args = parser.parse_args_into_dataclasses() dataset = Dataset(data_args) - model = AutoModel.get_model(model_args, tune_strategy='none', use_accelerator=pipeline_args.use_accelerator) + model = AutoModel.get_model(model_args, do_train=False) inferencer = AutoPipeline.get_pipeline( pipeline_name=pipeline_name, model_args=model_args, diff --git a/examples/vis_chatbot.py b/examples/vis_chatbot.py index d313ef9f9..3cb2491fd 100644 --- a/examples/vis_chatbot.py +++ b/examples/vis_chatbot.py @@ -105,7 +105,7 @@ def main(): ds_config = json.load(f) model = AutoModel.get_model( model_args, - tune_strategy='none', + do_train=False, ds_config=ds_config, device=pipeline_args.device, custom_model=model_args.custom_model, diff --git a/examples/vis_chatbot_gradio.py b/examples/vis_chatbot_gradio.py index e86a29c6a..4326d7950 100644 --- a/examples/vis_chatbot_gradio.py +++ b/examples/vis_chatbot_gradio.py @@ -245,7 +245,7 @@ def start_inferencer( model = AutoModel.get_model( model_args, - tune_strategy='none', + do_train=False, ds_config=ds_config, device=pipeline_args.device, custom_model=model_args.custom_model, diff --git a/examples/vllm_inference.py b/examples/vllm_inference.py index d6e4b7859..1e06f9db9 100644 --- a/examples/vllm_inference.py +++ b/examples/vllm_inference.py @@ -40,7 +40,7 @@ def main(): model_args, data_args, pipeline_args = parser.parse_args_into_dataclasses() dataset = Dataset(data_args) - model = AutoModel.get_model(model_args, tune_strategy='none') + model = AutoModel.get_model(model_args, do_train=False) inferencer = AutoPipeline.get_pipeline( pipeline_name=pipeline_name, model_args=model_args, diff --git a/requirements.txt b/requirements.txt index 66e885d6c..3db38164d 100644 --- a/requirements.txt +++ b/requirements.txt @@ -5,7 +5,6 @@ tokenizers>=0.13.3 peft>=0.10.0 torch>=2.0.1 wandb -deepspeed>=0.14.4 sentencepiece transformers>=4.31.0 cpm_kernels==1.0.11 diff --git a/scripts/run_chatbot.sh b/scripts/run_chatbot.sh index 8e1c49be0..a5a58f77b 100755 --- a/scripts/run_chatbot.sh +++ b/scripts/run_chatbot.sh @@ -16,7 +16,6 @@ accelerate launch --config_file configs/accelerator_multigpu_config.yaml \ examples/chatbot.py \ --deepspeed configs/ds_config_chatbot.json \ --model_name_or_path ${model} \ - --use_accelerator True \ --max_new_tokens 256 \ --temperature 1.0 \ --end_string "#" \ diff --git a/scripts/run_evaluation_accelerator.sh b/scripts/run_evaluation_accelerator.sh index 8959f6f4b..f5411398c 100644 --- a/scripts/run_evaluation_accelerator.sh +++ b/scripts/run_evaluation_accelerator.sh @@ -13,5 +13,4 @@ CUDA_VISIBLE_DEVICES=0 accelerate launch --config_file configs/accelerator_singl --metric accuracy \ --output_dir output_dir/accelerator_1_card \ --inference_batch_size_per_device 1 \ - --use_accelerator_for_evaluator True \ --torch_dtype bfloat16 diff --git a/scripts/run_inference.sh b/scripts/run_inference.sh index 1a3241c1f..03fc60a94 100755 --- a/scripts/run_inference.sh +++ b/scripts/run_inference.sh @@ -15,7 +15,6 @@ accelerate launch --config_file configs/accelerator_multigpu_config.yaml \ examples/inference.py \ --deepspeed configs/ds_config_chatbot.json \ --model_name_or_path ${model} \ - --use_accelerator True \ --max_new_tokens 256 \ --temperature 1.0 \ ${lora_args} diff --git a/scripts/run_rm_inference.sh b/scripts/run_rm_inference.sh index 701daf120..32d68dff1 100644 --- a/scripts/run_rm_inference.sh +++ b/scripts/run_rm_inference.sh @@ -61,7 +61,6 @@ accelerate launch --config_file configs/accelerator_multigpu_config.yaml \ --trust_remote_code ${trust_remote_code} \ --model_name_or_path ${model_name_or_path} \ --arch_type text_regression \ - --use_accelerator True \ --block_size 4096 \ --inference_batch_size 16 \ --dataset_path ${dataset_path} \ diff --git a/service/app.py b/service/app.py index 7580ac39e..29b92daa9 100644 --- a/service/app.py +++ b/service/app.py @@ -54,7 +54,7 @@ class AppArguments: local_rank = int(os.getenv("LOCAL_RANK", "0")) world_size = int(os.getenv("WORLD_SIZE", "1")) torch.cuda.set_device(local_rank) -model = AutoModel.get_model(model_args, tune_strategy='none', ds_config=ds_config, use_accelerator=True) +model = AutoModel.get_model(model_args, do_train=False, ds_config=ds_config) accelerator = Accelerator() def stream_generate(inputs,context_len = 1024, max_new_tokens=128, end_string="##"): diff --git a/setup.py b/setup.py index 37ee0e965..e6d894e49 100644 --- a/setup.py +++ b/setup.py @@ -22,7 +22,8 @@ "gradio": ["gradio"], "flask": ["flask", "flask_cors"], "flash_attn": ["flash-attn>=2.0.2"], - "trl": ["trl==0.8.0"] + "trl": ["trl==0.8.0"], + "deepspeed": ["deepspeed>=0.14.4"], } readme_path = os.path.join(folder, "README.md") diff --git a/src/lmflow/args.py b/src/lmflow/args.py index 518957db6..22425e2bf 100644 --- a/src/lmflow/args.py +++ b/src/lmflow/args.py @@ -924,8 +924,8 @@ class EvaluatorArguments: ), }, ) - use_accelerator_for_evaluator: bool = field( - default=False, metadata={"help": "Whether to use Huggingface Accelerator instead of Deepspeed"}, + use_accelerator_for_evaluator: Optional[bool] = field( + default=None, metadata={"help": "[Deprecated] Whether to use Huggingface Accelerator instead of Deepspeed"}, ) temperature: float = field( @@ -942,6 +942,14 @@ class EvaluatorArguments: default=100, metadata={"help": "Maximum length during inference."}, ) + + def __post_init__(self): + if self.use_accelerator_for_evaluator is not None: + logger.warning( + "You've specified `use_accelerator_for_evaluator`. This argument is deprecated. " + "It will not take effect and will be removed in a future version, " + "since LMFlow now can automatically detect whether is in Accelerate or Deepspeed environment." + ) @dataclass @@ -1061,8 +1069,8 @@ class InferencerArguments: "help": "whether turn on true random sampling during inference." }, ) - use_accelerator: bool = field( - default=False, metadata={"help": "Whether to use Huggingface Accelerator instead of Deepspeed"}, + use_accelerator: Optional[bool] = field( + default=None, metadata={"help": "[Deprecated] Whether to use Huggingface Accelerator instead of Deepspeed"}, ) use_beam_search: Optional[bool] = field( default=False, @@ -1131,6 +1139,13 @@ class InferencerArguments: ) def __post_init__(self): + if self.use_accelerator is not None: + logger.warning( + "You've specified `use_accelerator`. This argument is deprecated. " + "It will not take effect and will be removed in a future version, " + "since LMFlow now can automatically detect whether is in Accelerate or Deepspeed environment." + ) + if self.save_results: if self.results_path is None: raise ValueError("Need to specify results_path when save_results is True.") diff --git a/src/lmflow/models/hf_decoder_model.py b/src/lmflow/models/hf_decoder_model.py index 0fd6da2f0..30c70e73d 100644 --- a/src/lmflow/models/hf_decoder_model.py +++ b/src/lmflow/models/hf_decoder_model.py @@ -3,16 +3,12 @@ """This is a class called HFDecoderModel which is a wrapper around transformers model and tokenizer classes. It has several methods such as __init__, tokenize, and train that are used for training and fine-tuning the model. The __init__ method takes in several arguments -such as model_args, tune_strategy, and ds_config, which are used to load the pretrained +such as model_args which are used to load the pretrained model and tokenizer, and initialize the training settings. The tokenize method is used to tokenize the input text and return the input IDs and attention masks that can be fed to the model for training or inference. -This class supports different tune_strategy options such as 'normal', 'none', 'lora', and -'adapter', which allow for different fine-tuning settings of the model. However, the 'lora' -and 'adapter' strategies are not yet implemented. - Overall, this class provides a convenient interface for loading and fine-tuning transformer models and can be used for various NLP tasks such as language modeling, text classification, and question answering. @@ -46,6 +42,7 @@ conversation_tokenize_function ) from lmflow.utils.versioning import is_ray_available, is_vllm_available, is_flash_attn_available +from lmflow.utils.envs import is_accelerate_env logger = logging.getLogger(__name__) @@ -74,11 +71,9 @@ class HFDecoderModel(DecoderModel, HFModelMixin, Tunable): model_args : Model arguments such as model name, path, revision, etc. - tune_strategy : str or none, default="normal". - A string representing the dataset backend. Defaults to "huggingface". - - ds_config : - Deepspeed configuations. + do_train : bool, default True + Determines whether to prepare the model for training, including distribtued env, model placement, quantization, + lora, etc. args : Optional. Positional arguments. @@ -90,26 +85,16 @@ class HFDecoderModel(DecoderModel, HFModelMixin, Tunable): def __init__( self, model_args, - tune_strategy='normal', - ds_config=None, + do_train=True, device="gpu", - use_accelerator=False, *args, **kwargs ): - """ - Initializes a HFDecoderModel instance. - :param model_args: dictionary with model arguments such as model name, path, revision, etc. - :param tune_strategy: tuning strategy: normal, none, lora or adapter - :param ds_config: deepspeed configuration for distributed training - """ HFModelMixin.__init__( self, model_args=model_args, - do_train=True if tune_strategy == "normal" else False, - ds_config=ds_config, + do_train=do_train, device=device, - use_accelerator=use_accelerator, *args, **kwargs ) @@ -384,7 +369,7 @@ def __inference(self, inputs, *args, **kwargs): The generated sequence output """ with torch.no_grad(): - if self.use_accelerator: + if is_accelerate_env(): outputs = self.backend_model.generate( input_ids=inputs, pad_token_id=self.tokenizer.pad_token_id, diff --git a/src/lmflow/models/hf_model_mixin.py b/src/lmflow/models/hf_model_mixin.py index 45f414292..251761e2e 100644 --- a/src/lmflow/models/hf_model_mixin.py +++ b/src/lmflow/models/hf_model_mixin.py @@ -1,14 +1,13 @@ #!/usr/bin/env python # coding=utf-8 # Copyright 2024 Statistics and Machine Learning Research Group. All rights reserved. +import copy import gc -import os import logging +from contextlib import nullcontext from typing import Union, Optional, Dict, List -import copy import torch -import deepspeed from transformers import ( CONFIG_MAPPING, AutoConfig, @@ -33,7 +32,8 @@ LMFLOW_LORA_TARGET_MODULES_MAPPING ) from lmflow.args import ModelArguments -from lmflow.utils.versioning import is_vllm_available +from lmflow.utils.versioning import is_vllm_available, is_deepspeed_available +from lmflow.utils.envs import is_accelerate_env if is_vllm_available(): from vllm import LLM, SamplingParams @@ -61,9 +61,7 @@ def __init__( self, model_args: ModelArguments, do_train: bool, - ds_config=None, device: Optional[str]="gpu", - use_accelerator: bool=False, hf_auto_model_additional_args: Optional[Dict]=None, *args, **kwargs @@ -76,12 +74,8 @@ def __init__( Dictionary with model arguments such as model name, path, revision, etc. do_train : bool To prepare the model for training or inference. - ds_config : optional - Deepspeed configuration for distributed training, by default None device : str, optional By default "gpu" - use_accelerator : bool, optional - By default False """ # See more about loading any type of standard or custom dataset (from @@ -96,8 +90,6 @@ def __init__( self.device = device self.model_args = model_args self.hf_auto_model = HF_AUTOMODEL_MAPPING[model_args.arch_type] - self.use_accelerator = use_accelerator - self.ds_config = ds_config self.do_train = do_train self.tokenizer = self.__prepare_tokenizer(model_args) @@ -380,9 +372,15 @@ def __prepare_model_for_training( # We resize the embeddings only when necessary to avoid index errors. # If you are creating a model from scratch on a small vocab and want a # smaller embedding size, remove this test. - with deepspeed.zero.GatheredParameters(model.get_input_embeddings().weight, modifier_rank=None): + resize_embedding_context = nullcontext() + if is_deepspeed_available() and not is_accelerate_env(): + import deepspeed + resize_embedding_context = deepspeed.zero.GatheredParameters(model.get_input_embeddings().weight, modifier_rank=None) + + with resize_embedding_context: weights = model.get_input_embeddings().weight embedding_size = weights.shape[0] + if len(self.tokenizer) > embedding_size: model.resize_token_embeddings(len(self.tokenizer)) @@ -394,8 +392,6 @@ def __prepare_model_for_inference( self, model_args: ModelArguments, hf_auto_model: HF_AUTOMODEL_TYPE, - use_accelerator: bool, - ds_config ): logger.info(f"Backend model already initialized, moving to device: {self.device}") if hasattr(self, "backend_model"): @@ -413,12 +409,8 @@ def __prepare_model_for_inference( "offload_state_dict": True, } - if use_accelerator or model_args.use_ram_optimized_load: + if model_args.use_ram_optimized_load: inference_load_kwargs.update(ram_optimized_load_kwargs) - - if not use_accelerator: - from transformers.integrations import HfDeepSpeedConfig - dschf = HfDeepSpeedConfig(ds_config) try: self.backend_model = hf_auto_model.from_pretrained( @@ -448,10 +440,14 @@ def __prepare_model_for_inference( model_args.lora_model_path, ) - if (not use_accelerator) and self.device == "gpu": - deepspeed.init_distributed() - self.ds_engine = deepspeed.initialize(model=self.backend_model, config_params=ds_config)[0] - self.ds_engine.module.eval() + if self.device == "gpu" and not is_accelerate_env(): + if is_deepspeed_available(): + import deepspeed + deepspeed.init_distributed() + self.ds_engine = deepspeed.initialize(model=self.backend_model)[0] + self.ds_engine.module.eval() + else: + raise ImportError("Deepspeed is not available. Please install via `pip install -e '.[deepspeed]'`.") self.__prepare_model_post_process() @@ -517,8 +513,6 @@ def activate_model_for_inference( self.__prepare_model_for_inference( model_args=self.model_args, hf_auto_model=self.hf_auto_model, - use_accelerator=self.use_accelerator, - ds_config=self.ds_config, ) self._activated = True diff --git a/src/lmflow/models/hf_text_regression_model.py b/src/lmflow/models/hf_text_regression_model.py index 46904cdbd..8ab95cb75 100644 --- a/src/lmflow/models/hf_text_regression_model.py +++ b/src/lmflow/models/hf_text_regression_model.py @@ -1,22 +1,12 @@ #!/usr/bin/env python # coding=utf-8 # Copyright 2024 Statistics and Machine Learning Research Group. All rights reserved. -import os import copy import hashlib import logging -from pathlib import Path from typing import List, Union, Dict, Optional import torch -from peft import ( - LoraConfig, - PeftModel, - TaskType, - get_peft_config, - get_peft_model, - prepare_model_for_kbit_training -) from transformers.modeling_outputs import SequenceClassifierOutputWithPast from lmflow.args import ModelArguments @@ -40,6 +30,7 @@ ) from lmflow.utils.data_utils import RewardModelInferenceResultWithInput from lmflow.utils.versioning import is_ray_available, is_vllm_available +from lmflow.utils.envs import is_accelerate_env if is_ray_available(): import ray @@ -62,11 +53,9 @@ class HFTextRegressionModel(TextRegressionModel, HFModelMixin, Tunable): model_args : Model arguments such as model name, path, revision, etc. - tune_strategy : str or none, default="normal". - A string representing the dataset backend. Defaults to "huggingface". - - ds_config : - Deepspeed configuations. + do_train : bool, default True + Determines whether to prepare the model for training, including distribtued env, model placement, quantization, + lora, etc. args : Optional. Positional arguments. @@ -78,19 +67,11 @@ class HFTextRegressionModel(TextRegressionModel, HFModelMixin, Tunable): def __init__( self, model_args: ModelArguments, - tune_strategy: str='normal', - ds_config=None, - device="gpu", - use_accelerator=False, + do_train: bool = False, + device = "gpu", *args, **kwargs ): - """ - Initializes a HFTextRegressionModel instance. - :param model_args: dictionary with model arguments such as model name, path, revision, etc. - :param tune_strategy: tuning strategy: normal, none, lora or adapter - :param ds_config: deepspeed configuration for distributed training - """ assert model_args.arch_type == "text_regression", ( f"Invalid model architecture type: {model_args.arch_type}. " f"Expected: text_regression" @@ -99,10 +80,8 @@ def __init__( HFModelMixin.__init__( self, model_args=model_args, - do_train=True if tune_strategy == "normal" else False, - ds_config=ds_config, + do_train=do_train, device=device, - use_accelerator=use_accelerator, hf_auto_model_additional_args=config_additional_args, *args, **kwargs @@ -331,13 +310,14 @@ def __inference( The generated sequence output """ with torch.no_grad(): - if self.use_accelerator: + if is_accelerate_env(): outputs = self.backend_model( input_ids=inputs, **kwargs, ) else: - if self.device == "gpu": + if self.device == "gpu": + # for scripts that run using 'deepspeed script.py' outputs = self.ds_engine.module( input_ids=inputs, synced_gpus=True, diff --git a/src/lmflow/pipeline/evaluator.py b/src/lmflow/pipeline/evaluator.py index 6ca98fbf8..fc144e03b 100644 --- a/src/lmflow/pipeline/evaluator.py +++ b/src/lmflow/pipeline/evaluator.py @@ -2,23 +2,29 @@ The class has two methods: create_dataloader() that loads the data from the test file, creates a data loader, and returns it with the size of the data, and evaluate(model) that generates output text given input text. It uses the create_dataloader() method to load the data, iterates over the data in mini-batches, and encodes the input text with the encode() method of the HFDecoderModel class. Then, it generates output text using the evaluate() method of the HFDecoderModel class, decodes the generated output text using the decode() method of the HFDecoderModel class, and writes the output to a file in the output directory. The method also logs some information to the console and Weights and Biases if the use_wandb argument is True. """ +import datetime +import json import os + +import numpy as np import torch +import torch.distributed as dist import wandb -import deepspeed -import sys -import numpy as np -import datetime -import json # TODO: remove later from accelerate import Accelerator from transformers import AutoConfig -import torch.distributed as dist +from lmflow.args import ( + ModelArguments, + DatasetArguments, + EvaluatorArguments +) from lmflow.datasets.dataset import Dataset from lmflow.pipeline.base_pipeline import BasePipeline from lmflow.models.hf_decoder_model import HFDecoderModel from lmflow.utils.data_utils import set_random_seed, batchlize, answer_extraction +from lmflow.utils.versioning import is_deepspeed_available +from lmflow.utils.envs import is_accelerate_env os.environ["TOKENIZERS_PARALLELISM"] = "false" # To avoid warnings about parallelism in tokenizers class Evaluator(BasePipeline): @@ -38,7 +44,12 @@ class Evaluator(BasePipeline): """ - def __init__(self, model_args, data_args, evaluator_args): + def __init__( + self, + model_args: ModelArguments, + data_args: DatasetArguments, + evaluator_args: EvaluatorArguments, + ): # our method self.data_args = data_args self.evaluator_args = evaluator_args @@ -53,10 +64,14 @@ def __init__(self, model_args, data_args, evaluator_args): self.world_size = int(os.getenv("WORLD_SIZE", "1")) torch.cuda.set_device(self.local_rank) # NOTE: cpu-only machine will have error - if evaluator_args.use_accelerator_for_evaluator: + if is_accelerate_env(): self.accelerator = Accelerator() self.accelerator.wait_for_everyone() else: + if is_deepspeed_available(): + import deepspeed + else: + raise ImportError("Deepspeed is not available, please install using `pip install -e \".[deepspeed]\"`") deepspeed.init_distributed() self.config = AutoConfig.from_pretrained(model_args.model_name_or_path) @@ -135,8 +150,8 @@ def evaluate( """ if metric in ["acc", "accuracy"]: - if self.evaluator_args.use_accelerator_for_evaluator: - acc = self._evaluate_acc_with_accelerator(model, dataset, verbose=verbose) + if is_accelerate_env(): + acc = self._evaluate_acc_with_accelerate(model, dataset, verbose=verbose) else: acc = self._evaluate_acc_with_deepspeed(model, dataset, verbose=verbose) print(f"Evaluating final accuracy: {acc}") @@ -153,7 +168,7 @@ def evaluate( raise NotImplementedError(f"metric {metric} is not supported") - def _evaluate_acc_with_accelerator(self, model, dataset, verbose=True): + def _evaluate_acc_with_accelerate(self, model, dataset, verbose=True): dataloader, data_size = self.create_dataloader(dataset) if self.accelerator.is_local_main_process: if not os.path.exists(self.evaluator_args.output_dir): @@ -176,7 +191,13 @@ def _evaluate_acc_with_accelerator(self, model, dataset, verbose=True): inputs = batch_input['input_ids'] mask = batch_input['attention_mask'] with self.accelerator.autocast(): - outputs = model.inference(inputs, max_new_tokens=self.evaluator_args.max_new_tokens,attention_mask=mask,temperature=self.evaluator_args.temperature, repetition_penalty=self.evaluator_args.repetition_penalty,use_accelerator=self.evaluator_args.use_accelerator_for_evaluator) + outputs = model.inference( + inputs, + max_new_tokens=self.evaluator_args.max_new_tokens, + attention_mask=mask, + temperature=self.evaluator_args.temperature, + repetition_penalty=self.evaluator_args.repetition_penalty, + ) text_out = model.decode(outputs, skip_special_tokens=True) decoded_input = model.decode(inputs, skip_special_tokens=True,) prompt_length = [len(i) for i in decoded_input] diff --git a/src/lmflow/pipeline/finetuner.py b/src/lmflow/pipeline/finetuner.py index a19886189..2d132d0ee 100644 --- a/src/lmflow/pipeline/finetuner.py +++ b/src/lmflow/pipeline/finetuner.py @@ -10,15 +10,16 @@ from typing import Any, Iterable, Optional, Tuple, Union import datasets -import transformers import evaluate +import numpy as np +import transformers +from copy import deepcopy from itertools import chain from transformers import ( Trainer, default_data_collator, set_seed, ) -from copy import deepcopy from transformers import PreTrainedModel, TrainingArguments from transformers.trainer_utils import get_last_checkpoint from transformers.trainer_callback import ( @@ -30,7 +31,6 @@ is_sagemaker_mp_enabled, send_example_telemetry, ) -import numpy as np import lmflow.optim.optimizers as optim from lmflow.args import OptimizerNames, DatasetArguments, ModelArguments, FinetunerArguments diff --git a/src/lmflow/pipeline/inferencer.py b/src/lmflow/pipeline/inferencer.py index 855284fa7..e74bd1683 100644 --- a/src/lmflow/pipeline/inferencer.py +++ b/src/lmflow/pipeline/inferencer.py @@ -6,7 +6,6 @@ import os import torch import wandb -import deepspeed import sys import numpy as np import datetime @@ -22,13 +21,19 @@ import torch.distributed as dist import torch.nn.functional as F -from lmflow.args import DatasetArguments +from lmflow.args import ( + DatasetArguments, + ModelArguments, + InferencerArguments, +) from lmflow.datasets.dataset import Dataset from lmflow.pipeline.base_pipeline import BasePipeline from lmflow.models.hf_decoder_model import HFDecoderModel from lmflow.utils.data_utils import (set_random_seed, batchlize, answer_extraction, process_image_flag) from lmflow.utils.constants import IMAGE_TOKEN_INDEX +from lmflow.utils.versioning import is_deepspeed_available +from lmflow.utils.envs import is_accelerate_env os.environ["TOKENIZERS_PARALLELISM"] = "false" # To avoid warnings about parallelism in tokenizers def rstrip_partial_utf8(string): return string.replace("\ufffd", "") @@ -57,7 +62,12 @@ class Inferencer(BasePipeline): """ - def __init__(self, model_args, data_args, inferencer_args): + def __init__( + self, + model_args: ModelArguments, + data_args: DatasetArguments, + inferencer_args: InferencerArguments, + ): self.data_args = data_args self.inferencer_args = inferencer_args self.model_args = model_args @@ -66,9 +76,11 @@ def __init__(self, model_args, data_args, inferencer_args): self.local_rank = int(os.getenv("LOCAL_RANK", "0")) self.world_size = int(os.getenv("WORLD_SIZE", "1")) - if inferencer_args.device == "gpu": + if inferencer_args.device == "gpu": # FIXME: a bit weird here torch.cuda.set_device(self.local_rank) # NOTE: cpu-only machine will have error - deepspeed.init_distributed() + if not is_accelerate_env() and is_deepspeed_available(): + import deepspeed + deepspeed.init_distributed() else: os.environ["MASTER_ADDR"] = "localhost" os.environ["MASTER_PORT"] = "15000" @@ -83,7 +95,7 @@ def __init__(self, model_args, data_args, inferencer_args): print("Error in setting hidden size, use the default size 1024") self.model_hidden_size = 1024 # gpt2 seems do not have hidden_size in config - if inferencer_args.use_accelerator: + if is_accelerate_env(): self.accelerator = Accelerator() self.accelerator.wait_for_everyone() @@ -226,7 +238,7 @@ def inference( f"device \"{self.inferencer_args.device}\" is not supported" ) - if self.inferencer_args.use_accelerator: + if is_accelerate_env(): inputs = inputs.to(self.accelerator.device) @@ -234,7 +246,7 @@ def inference( inputs["image_token_indexes"] = image_token_indexes inputs["one_sample_multiple_images"] = True - if self.inferencer_args.use_accelerator: + if is_accelerate_env(): with self.accelerator.autocast(): outputs = model.inference( inputs, @@ -242,7 +254,6 @@ def inference( temperature=self.inferencer_args.temperature, repetition_penalty=self.inferencer_args.repetition_penalty, do_sample=self.inferencer_args.do_sample, - use_accelerator=True, ) else: outputs = model.inference( @@ -413,7 +424,6 @@ def predict_next_token(model: HFDecoderModel, input_ids: torch.Tensor, num_new_t """Predict the next token given the input_ids. """ output = model.inference(input_ids, - use_accelerator=True, max_new_tokens=num_new_tokens, return_dict_in_generate=True, output_scores=True, @@ -631,7 +641,6 @@ def inference( input_length = input_id.shape[1] output_id = model.inference( input_id, - use_accelerator=True, max_new_tokens=max_new_tokens, # pad_token_id=model.tokenizer.eos_token_id, ) diff --git a/src/lmflow/pipeline/iterative_dpo_aligner.py b/src/lmflow/pipeline/iterative_dpo_aligner.py index 59d122545..f0d0510cc 100644 --- a/src/lmflow/pipeline/iterative_dpo_aligner.py +++ b/src/lmflow/pipeline/iterative_dpo_aligner.py @@ -83,7 +83,7 @@ def _align_single_iteration( print_banner(f'Iterative DPO {iteration_name}: Generate responses') model = HFDecoderModel( model_args=target_model_args, - tune_strategy='none' + do_train=False ) self._do_target_model_inference( model=model, @@ -97,8 +97,7 @@ def _align_single_iteration( print_banner(f'Iterative DPO {iteration_name}: Reward model scoring') reward_model = HFTextRegressionModel( model_args=reward_model_args, - tune_strategy='none', - use_accelerator=self.aligner_args.use_accelerator, + do_train=False, ) target_model_inference_result_data_args = copy.deepcopy(dataset.data_args) target_model_inference_result_data_args.dataset_path = str(self.workspace_path/iteration_name/"target_model_inference_result") diff --git a/src/lmflow/pipeline/rm_inferencer.py b/src/lmflow/pipeline/rm_inferencer.py index 890e4ee20..160f83b77 100644 --- a/src/lmflow/pipeline/rm_inferencer.py +++ b/src/lmflow/pipeline/rm_inferencer.py @@ -5,7 +5,6 @@ import os import torch import wandb -import deepspeed import sys import numpy as np import datetime @@ -36,7 +35,8 @@ RewardModelInferenceResultWithInput, ) from lmflow.datasets.dataset import KEY_SCORE -from lmflow.utils.versioning import is_ray_available +from lmflow.utils.versioning import is_ray_available, is_deepspeed_available +from lmflow.utils.envs import is_accelerate_env if is_ray_available(): import ray @@ -78,15 +78,17 @@ def __init__( self.local_rank = int(os.getenv("LOCAL_RANK", "0")) self.world_size = int(os.getenv("WORLD_SIZE", "1")) - if inferencer_args.device == "gpu": + if inferencer_args.device == "gpu": # FIXME: a bit weird here torch.cuda.set_device(self.local_rank) # NOTE: cpu-only machine will have error - deepspeed.init_distributed() + if not is_accelerate_env() and is_deepspeed_available(): + import deepspeed + deepspeed.init_distributed() else: dist.init_process_group( "gloo", rank=self.local_rank, world_size=self.world_size ) - if inferencer_args.use_accelerator: + if is_accelerate_env(): self.accelerator: Accelerator = kwargs.get('accelerator', Accelerator()) @@ -194,7 +196,7 @@ def __inference( ): # len(batch) = batch_size, and batch element is dataset sample model_input_tensor = torch.LongTensor(batched_input_ids).to("cpu" if model.device == "cpu" else "cuda") - if self.inferencer_args.use_accelerator: + if is_accelerate_env(): with self.accelerator.autocast(): batch_output = model.inference( inputs=model_input_tensor, @@ -256,8 +258,7 @@ def __init__( ): self.model = HFTextRegressionModel( model_args=model_args, - tune_strategy='none', - use_accelerator=True + do_train=False, ) self.model.activate_model_for_inference(use_vllm=False) diff --git a/src/lmflow/pipeline/utils/memory_safe_vllm_inference.py b/src/lmflow/pipeline/utils/memory_safe_vllm_inference.py index d7859d9a1..59ab69eba 100644 --- a/src/lmflow/pipeline/utils/memory_safe_vllm_inference.py +++ b/src/lmflow/pipeline/utils/memory_safe_vllm_inference.py @@ -47,7 +47,7 @@ def main(): model_args, data_args, pipeline_args = parser.parse_args_into_dataclasses() dataset = Dataset(data_args) - model = AutoModel.get_model(model_args, tune_strategy='none') + model = AutoModel.get_model(model_args, do_train=False) inferencer = VLLMInferencer(model_args, data_args, pipeline_args) res = inferencer.inference( diff --git a/src/lmflow/pipeline/utils/raft_trainer.py b/src/lmflow/pipeline/utils/raft_trainer.py index c3a5253f7..a28c659d7 100644 --- a/src/lmflow/pipeline/utils/raft_trainer.py +++ b/src/lmflow/pipeline/utils/raft_trainer.py @@ -62,7 +62,6 @@ from transformers.configuration_utils import PretrainedConfig from transformers.data.data_collator import DataCollator, DataCollatorWithPadding, default_data_collator from transformers.debug_utils import DebugOption, DebugUnderflowOverflow -from transformers.deepspeed import deepspeed_init, is_deepspeed_zero3_enabled from transformers.dependency_versions_check import dep_version_check from transformers.modelcard import TrainingSummary from transformers.modeling_utils import PreTrainedModel, load_sharded_checkpoint, unwrap_model @@ -150,6 +149,12 @@ ) from transformers.utils.generic import ContextManagers +from lmflow.utils.versioning import is_package_version_at_least +if is_package_version_at_least("transformers", "4.46.0"): + from transformers.integrations.deepspeed import deepspeed_init, is_deepspeed_zero3_enabled +else: + from transformers.deepspeed import deepspeed_init, is_deepspeed_zero3_enabled + _is_native_cpu_amp_available = is_torch_greater_or_equal_than_1_10 diff --git a/src/lmflow/utils/envs.py b/src/lmflow/utils/envs.py new file mode 100644 index 000000000..3736f7433 --- /dev/null +++ b/src/lmflow/utils/envs.py @@ -0,0 +1,7 @@ +import os + +def is_accelerate_env(): + for key, _ in os.environ.items(): + if key.startswith('ACCELERATE_'): + return True + return False \ No newline at end of file diff --git a/src/lmflow/utils/versioning.py b/src/lmflow/utils/versioning.py index bce50b6b8..d57567eba 100644 --- a/src/lmflow/utils/versioning.py +++ b/src/lmflow/utils/versioning.py @@ -75,4 +75,8 @@ def is_trl_available(): def is_multimodal_available(): - return _is_packages_available(["PIL"]) \ No newline at end of file + return _is_packages_available(["PIL"]) + + +def is_deepspeed_available(): + return _is_package_available("deepspeed") \ No newline at end of file diff --git a/tests/models/test_hf_decoder_model.py b/tests/models/test_hf_decoder_model.py index c6e8d096d..4a07c32ff 100644 --- a/tests/models/test_hf_decoder_model.py +++ b/tests/models/test_hf_decoder_model.py @@ -18,7 +18,6 @@ import json import os from pathlib import Path -from transformers.deepspeed import HfDeepSpeedConfig from lmflow.args import DatasetArguments, ModelArguments from lmflow.datasets.dataset import Dataset @@ -653,13 +652,12 @@ def test_inference(self): ds_config_path = "examples/ds_config.json" with open (ds_config_path, "r") as f: ds_config = json.load(f) - dschf = HfDeepSpeedConfig(ds_config) model_name = 'gpt2' model_args = ModelArguments( model_name_or_path=model_name, use_ram_optimized_load=False ) - model = HFDecoderModel(model_args, tune_strategy='none', ds_config=ds_config) + model = HFDecoderModel(model_args, do_train=False, ds_config=ds_config) self.local_rank = int(os.getenv("LOCAL_RANK", "0")) self.world_size = int(os.getenv("WORLD_SIZE", "1")) torch.cuda.set_device(self.local_rank) From ef083b6b18016cb9215d19167e952298bb07b1a6 Mon Sep 17 00:00:00 2001 From: YizhenJia Date: Fri, 28 Feb 2025 00:14:01 +0800 Subject: [PATCH 02/61] [usability] accelerate support - scripts update --- configs/accelerate_fsdp_config.yaml | 29 ++ .../accelerate_multigpu_config.yaml} | 0 .../accelerate_singlegpu_config.yaml} | 0 {examples => configs/archive}/ds_config.json | 0 configs/{ => archive}/ds_config_chatbot.json | 0 configs/{ => archive}/ds_config_eval.json | 0 .../{ => archive}/ds_config_multimodal.json | 0 .../{ => archive}/ds_config_vis_chatbot.json | 0 .../ds_config_zero0_no_offload.json | 0 configs/{ => archive}/ds_config_zero2.json | 0 .../ds_config_zero2_no_offload.json | 0 configs/{ => archive}/ds_config_zero3.json | 0 .../ds_config_zero3_for_eval.json | 0 .../ds_config_zero3_no_offload.json | 0 contrib/rlhflow/run_reward_modeling.sh | 2 +- .../run_function_call_finetune.sh | 2 +- examples/merge_lora.py | 7 - experimental/Hymba/run_finetune_hymba.sh | 2 +- scripts/{ => archive}/bash.sh | 0 .../convert_llama_weights_to_hf.py | 0 .../export_llama_state_dict_checkpoint.py | 0 scripts/{ => archive}/run_all_benchmark.sh | 6 +- scripts/{ => archive}/run_app.sh | 2 +- scripts/{ => archive}/run_benchmark.sh | 0 scripts/{ => archive}/run_chatbot.sh | 4 +- scripts/{ => archive}/run_chatbot_chatglm.sh | 2 +- scripts/{ => archive}/run_chatbot_cpu.sh | 2 +- .../{ => archive}/run_detail_gpu_memory.sh | 0 scripts/{ => archive}/run_dpo_align.sh | 0 scripts/archive/run_dpov2_align.sh | 81 +++++ scripts/{ => archive}/run_evaluation.sh | 0 .../run_evaluation_accelerator.sh | 2 +- .../{ => archive}/run_evaluation_with_lora.sh | 0 scripts/archive/run_finetune.sh | 78 +++++ .../archive/run_finetune_with_custom_optim.sh | 330 ++++++++++++++++++ scripts/archive/run_finetune_with_lisa.sh | 128 +++++++ scripts/archive/run_finetune_with_lora.sh | 78 +++++ scripts/archive/run_finetune_with_qlora.sh | 77 ++++ scripts/archive/run_inference.sh | 20 ++ .../run_inference_multimodal_model.sh | 2 +- .../{ => archive}/run_multistage_finetune.sh | 2 +- scripts/archive/run_raft_align.sh | 49 +++ scripts/archive/run_reward_modeling.sh | 93 +++++ .../archive/run_reward_modeling_with_lisa.sh | 105 ++++++ .../archive/run_reward_modeling_with_lora.sh | 94 +++++ scripts/{ => archive}/run_tool.sh | 0 .../run_finetune_multi_modal_stage1.sh | 2 +- .../run_finetune_multi_modal_stage2.sh | 2 +- scripts/multimodal/run_vis_chatbot_blip2.sh | 2 +- .../run_vis_chatbot_gradio_minigpt4.sh | 4 +- scripts/multimodal/run_vis_chatbot_llava.sh | 2 +- .../multimodal/run_vis_chatbot_minigpt4.sh | 2 +- scripts/run_finetune.sh | 24 +- scripts/run_finetune_with_lisa.sh | 30 +- scripts/run_finetune_with_lora.sh | 27 +- scripts/run_finetune_with_qlora.sh | 27 +- scripts/run_inference.sh | 3 +- scripts/run_merge_lora.sh | 9 - scripts/run_raft_align.sh | 2 +- scripts/run_reward_modeling.sh | 9 +- scripts/run_reward_modeling_with_lisa.sh | 11 +- scripts/run_reward_modeling_with_lora.sh | 11 +- 62 files changed, 1229 insertions(+), 135 deletions(-) create mode 100644 configs/accelerate_fsdp_config.yaml rename configs/{accelerator_multigpu_config.yaml => archive/accelerate_multigpu_config.yaml} (100%) rename configs/{accelerator_singlegpu_config.yaml => archive/accelerate_singlegpu_config.yaml} (100%) rename {examples => configs/archive}/ds_config.json (100%) rename configs/{ => archive}/ds_config_chatbot.json (100%) rename configs/{ => archive}/ds_config_eval.json (100%) rename configs/{ => archive}/ds_config_multimodal.json (100%) rename configs/{ => archive}/ds_config_vis_chatbot.json (100%) rename configs/{ => archive}/ds_config_zero0_no_offload.json (100%) rename configs/{ => archive}/ds_config_zero2.json (100%) rename configs/{ => archive}/ds_config_zero2_no_offload.json (100%) rename configs/{ => archive}/ds_config_zero3.json (100%) rename configs/{ => archive}/ds_config_zero3_for_eval.json (100%) rename configs/{ => archive}/ds_config_zero3_no_offload.json (100%) rename scripts/{ => archive}/bash.sh (100%) rename scripts/{ => archive}/convert_llama_weights_to_hf.py (100%) rename scripts/{ => archive}/export_llama_state_dict_checkpoint.py (100%) rename scripts/{ => archive}/run_all_benchmark.sh (71%) rename scripts/{ => archive}/run_app.sh (73%) rename scripts/{ => archive}/run_benchmark.sh (100%) rename scripts/{ => archive}/run_chatbot.sh (75%) rename scripts/{ => archive}/run_chatbot_chatglm.sh (83%) rename scripts/{ => archive}/run_chatbot_cpu.sh (82%) rename scripts/{ => archive}/run_detail_gpu_memory.sh (100%) rename scripts/{ => archive}/run_dpo_align.sh (100%) create mode 100644 scripts/archive/run_dpov2_align.sh rename scripts/{ => archive}/run_evaluation.sh (100%) rename scripts/{ => archive}/run_evaluation_accelerator.sh (88%) rename scripts/{ => archive}/run_evaluation_with_lora.sh (100%) create mode 100755 scripts/archive/run_finetune.sh create mode 100644 scripts/archive/run_finetune_with_custom_optim.sh create mode 100755 scripts/archive/run_finetune_with_lisa.sh create mode 100755 scripts/archive/run_finetune_with_lora.sh create mode 100644 scripts/archive/run_finetune_with_qlora.sh create mode 100755 scripts/archive/run_inference.sh rename scripts/{ => archive}/run_inference_multimodal_model.sh (84%) rename scripts/{ => archive}/run_multistage_finetune.sh (95%) create mode 100755 scripts/archive/run_raft_align.sh create mode 100644 scripts/archive/run_reward_modeling.sh create mode 100644 scripts/archive/run_reward_modeling_with_lisa.sh create mode 100644 scripts/archive/run_reward_modeling_with_lora.sh rename scripts/{ => archive}/run_tool.sh (100%) diff --git a/configs/accelerate_fsdp_config.yaml b/configs/accelerate_fsdp_config.yaml new file mode 100644 index 000000000..fc271c9f8 --- /dev/null +++ b/configs/accelerate_fsdp_config.yaml @@ -0,0 +1,29 @@ +compute_environment: LOCAL_MACHINE +debug: false +distributed_type: FSDP + +fsdp_config: + fsdp_auto_wrap_policy: "SIZE" + fsdp_min_num_params: 1000000 + fsdp_backward_prefetch: BACKWARD_PRE + fsdp_forward_prefetch: false + fsdp_cpu_ram_efficient_loading: true + fsdp_offload_params: false + fsdp_sharding_strategy: FULL_SHARD + fsdp_state_dict_type: FULL_STATE_DICT + fsdp_sync_module_states: true + fsdp_use_orig_params: true + +downcast_bf16: true +machine_rank: 0 +main_training_function: main +mixed_precision: bf16 +num_machines: 1 +num_processes: 8 +rdzv_backend: static +same_network: true +tpu_env: [] +tpu_use_cluster: false +tpu_use_sudo: false +use_cpu: false +main_process_port: 1204 \ No newline at end of file diff --git a/configs/accelerator_multigpu_config.yaml b/configs/archive/accelerate_multigpu_config.yaml similarity index 100% rename from configs/accelerator_multigpu_config.yaml rename to configs/archive/accelerate_multigpu_config.yaml diff --git a/configs/accelerator_singlegpu_config.yaml b/configs/archive/accelerate_singlegpu_config.yaml similarity index 100% rename from configs/accelerator_singlegpu_config.yaml rename to configs/archive/accelerate_singlegpu_config.yaml diff --git a/examples/ds_config.json b/configs/archive/ds_config.json similarity index 100% rename from examples/ds_config.json rename to configs/archive/ds_config.json diff --git a/configs/ds_config_chatbot.json b/configs/archive/ds_config_chatbot.json similarity index 100% rename from configs/ds_config_chatbot.json rename to configs/archive/ds_config_chatbot.json diff --git a/configs/ds_config_eval.json b/configs/archive/ds_config_eval.json similarity index 100% rename from configs/ds_config_eval.json rename to configs/archive/ds_config_eval.json diff --git a/configs/ds_config_multimodal.json b/configs/archive/ds_config_multimodal.json similarity index 100% rename from configs/ds_config_multimodal.json rename to configs/archive/ds_config_multimodal.json diff --git a/configs/ds_config_vis_chatbot.json b/configs/archive/ds_config_vis_chatbot.json similarity index 100% rename from configs/ds_config_vis_chatbot.json rename to configs/archive/ds_config_vis_chatbot.json diff --git a/configs/ds_config_zero0_no_offload.json b/configs/archive/ds_config_zero0_no_offload.json similarity index 100% rename from configs/ds_config_zero0_no_offload.json rename to configs/archive/ds_config_zero0_no_offload.json diff --git a/configs/ds_config_zero2.json b/configs/archive/ds_config_zero2.json similarity index 100% rename from configs/ds_config_zero2.json rename to configs/archive/ds_config_zero2.json diff --git a/configs/ds_config_zero2_no_offload.json b/configs/archive/ds_config_zero2_no_offload.json similarity index 100% rename from configs/ds_config_zero2_no_offload.json rename to configs/archive/ds_config_zero2_no_offload.json diff --git a/configs/ds_config_zero3.json b/configs/archive/ds_config_zero3.json similarity index 100% rename from configs/ds_config_zero3.json rename to configs/archive/ds_config_zero3.json diff --git a/configs/ds_config_zero3_for_eval.json b/configs/archive/ds_config_zero3_for_eval.json similarity index 100% rename from configs/ds_config_zero3_for_eval.json rename to configs/archive/ds_config_zero3_for_eval.json diff --git a/configs/ds_config_zero3_no_offload.json b/configs/archive/ds_config_zero3_no_offload.json similarity index 100% rename from configs/ds_config_zero3_no_offload.json rename to configs/archive/ds_config_zero3_no_offload.json diff --git a/contrib/rlhflow/run_reward_modeling.sh b/contrib/rlhflow/run_reward_modeling.sh index d83fe789f..fcee04ef5 100644 --- a/contrib/rlhflow/run_reward_modeling.sh +++ b/contrib/rlhflow/run_reward_modeling.sh @@ -30,7 +30,7 @@ deepspeed ${deepspeed_args} \ --block_size 512 \ --per_device_train_batch_size 1 \ --per_device_eval_batch_size 1\ - --deepspeed configs/ds_config_zero2.json \ + --deepspeed configs/archive/ds_config_zero2.json \ --bf16 \ --run_name rm_test \ --validation_split_percentage 10 \ diff --git a/contrib/tool-finetune/run_function_call_finetune.sh b/contrib/tool-finetune/run_function_call_finetune.sh index 220abee9a..185ca72ea 100755 --- a/contrib/tool-finetune/run_function_call_finetune.sh +++ b/contrib/tool-finetune/run_function_call_finetune.sh @@ -65,7 +65,7 @@ deepspeed ${deepspeed_args} \ --disable_group_texts 1 \ --block_size 1024 \ --per_device_train_batch_size 1 \ - --deepspeed configs/ds_config_zero3.json \ + --deepspeed configs/archive/ds_config_zero3.json \ --fp16 \ --run_name finetune \ --validation_split_percentage 0 \ diff --git a/examples/merge_lora.py b/examples/merge_lora.py index 3bbdb1dde..8a95e415a 100644 --- a/examples/merge_lora.py +++ b/examples/merge_lora.py @@ -29,12 +29,6 @@ class MergeLoraArguments: "help": "device to merge model on", }, ) - ds_config: str = field( - default='configs/ds_config_eval.json', - metadata={ - "help": "deepspeed config file path", - }, - ) output_model_path: Optional[str] = field( default=None, metadata={ @@ -64,7 +58,6 @@ def main(): model_args, do_train=False, device=merge_lora_args.device, - ds_config=merge_lora_args.ds_config ) model.activate_model_for_inference() model.merge_lora_weights() diff --git a/experimental/Hymba/run_finetune_hymba.sh b/experimental/Hymba/run_finetune_hymba.sh index 37b6b05b5..4f141b452 100644 --- a/experimental/Hymba/run_finetune_hymba.sh +++ b/experimental/Hymba/run_finetune_hymba.sh @@ -66,7 +66,7 @@ deepspeed ${deepspeed_args} \ --block_size 256 \ --trust_remote_code True \ --per_device_train_batch_size 1 \ - --deepspeed configs/ds_config_zero2_no_offload.json \ + --deepspeed configs/archive/ds_config_zero2_no_offload.json \ --bf16 \ --run_name hymba_finetune \ --validation_split_percentage 0 \ diff --git a/scripts/bash.sh b/scripts/archive/bash.sh similarity index 100% rename from scripts/bash.sh rename to scripts/archive/bash.sh diff --git a/scripts/convert_llama_weights_to_hf.py b/scripts/archive/convert_llama_weights_to_hf.py similarity index 100% rename from scripts/convert_llama_weights_to_hf.py rename to scripts/archive/convert_llama_weights_to_hf.py diff --git a/scripts/export_llama_state_dict_checkpoint.py b/scripts/archive/export_llama_state_dict_checkpoint.py similarity index 100% rename from scripts/export_llama_state_dict_checkpoint.py rename to scripts/archive/export_llama_state_dict_checkpoint.py diff --git a/scripts/run_all_benchmark.sh b/scripts/archive/run_all_benchmark.sh similarity index 71% rename from scripts/run_all_benchmark.sh rename to scripts/archive/run_all_benchmark.sh index 102d1d623..0516766c1 100644 --- a/scripts/run_all_benchmark.sh +++ b/scripts/archive/run_all_benchmark.sh @@ -36,14 +36,14 @@ fi log_dir=output_dir/${model_name}_lmflow_chat_nll_eval mkdir -p ${log_dir} echo "[Evaluating] Evaluate on LMFlow_chat" -./scripts/run_benchmark.sh ${extra_args} --dataset_name lmflow_chat_nll_eval | tee ${log_dir}/benchmark.log 2> ${log_dir}/benchmark.err +./scripts/archive/run_benchmark.sh ${extra_args} --dataset_name lmflow_chat_nll_eval | tee ${log_dir}/benchmark.log 2> ${log_dir}/benchmark.err log_dir=output_dir/${model_name}_all_nll_eval mkdir -p ${log_dir} echo "[Evaluating] Evaluate on [commonsense, wiki, instruction_following (gpt4) ] nll evaluation" -./scripts/run_benchmark.sh ${extra_args} --dataset_name all_nll_eval | tee ${log_dir}/benchmark.log 2> ${log_dir}/benchmark.err +./scripts/archive/run_benchmark.sh ${extra_args} --dataset_name all_nll_eval | tee ${log_dir}/benchmark.log 2> ${log_dir}/benchmark.err log_dir=output_dir/${model_name}_commonsense_qa_eval mkdir -p ${log_dir} echo "[Evaluating] Evaluate on commonsense QA Accuracy evaluation" -./scripts/run_benchmark.sh ${extra_args} --dataset_name commonsense_qa_eval | tee ${log_dir}/benchmark.log 2> ${log_dir}/benchmark.err \ No newline at end of file +./scripts/archive/run_benchmark.sh ${extra_args} --dataset_name commonsense_qa_eval | tee ${log_dir}/benchmark.log 2> ${log_dir}/benchmark.err \ No newline at end of file diff --git a/scripts/run_app.sh b/scripts/archive/run_app.sh similarity index 73% rename from scripts/run_app.sh rename to scripts/archive/run_app.sh index 6b81bf68c..7d9146630 100644 --- a/scripts/run_app.sh +++ b/scripts/archive/run_app.sh @@ -1,6 +1,6 @@ #!/bin/bash -CUDA_VISIBLE_DEVICES=0 accelerate launch --config_file configs/accelerator_singlegpu_config.yaml service/app.py \ +CUDA_VISIBLE_DEVICES=0 accelerate launch --config_file configs/archive/accelerate_singlegpu_config.yaml service/app.py \ --model_name_or_path gpt2 \ --torch_dtype bfloat16 \ --max_new_tokens 200 \ No newline at end of file diff --git a/scripts/run_benchmark.sh b/scripts/archive/run_benchmark.sh similarity index 100% rename from scripts/run_benchmark.sh rename to scripts/archive/run_benchmark.sh diff --git a/scripts/run_chatbot.sh b/scripts/archive/run_chatbot.sh similarity index 75% rename from scripts/run_chatbot.sh rename to scripts/archive/run_chatbot.sh index a5a58f77b..634e7b117 100755 --- a/scripts/run_chatbot.sh +++ b/scripts/archive/run_chatbot.sh @@ -12,9 +12,9 @@ if [ $# -ge 2 ]; then fi # --temperature 0.7 \ -accelerate launch --config_file configs/accelerator_multigpu_config.yaml \ +accelerate launch --config_file configs/archive/accelerate_multigpu_config.yaml \ examples/chatbot.py \ - --deepspeed configs/ds_config_chatbot.json \ + --deepspeed configs/archive/ds_config_chatbot.json \ --model_name_or_path ${model} \ --max_new_tokens 256 \ --temperature 1.0 \ diff --git a/scripts/run_chatbot_chatglm.sh b/scripts/archive/run_chatbot_chatglm.sh similarity index 83% rename from scripts/run_chatbot_chatglm.sh rename to scripts/archive/run_chatbot_chatglm.sh index af2fe4064..efaa40f47 100755 --- a/scripts/run_chatbot_chatglm.sh +++ b/scripts/archive/run_chatbot_chatglm.sh @@ -12,6 +12,6 @@ fi CUDA_VISIBLE_DEVICES=0 \ deepspeed examples/chatbot.py \ --arch_type encoder_decoder \ - --deepspeed configs/ds_config_chatbot.json \ + --deepspeed configs/archive/ds_config_chatbot.json \ --model_name_or_path ${model} \ ${lora_args} \ No newline at end of file diff --git a/scripts/run_chatbot_cpu.sh b/scripts/archive/run_chatbot_cpu.sh similarity index 82% rename from scripts/run_chatbot_cpu.sh rename to scripts/archive/run_chatbot_cpu.sh index 300c0fdc3..a53f63a55 100755 --- a/scripts/run_chatbot_cpu.sh +++ b/scripts/archive/run_chatbot_cpu.sh @@ -11,7 +11,7 @@ fi CUDA_VISIBLE_DEVICES="" \ python examples/chatbot.py \ - --deepspeed configs/ds_config_chatbot.json \ + --deepspeed configs/archive/ds_config_chatbot.json \ --model_name_or_path ${model} \ --device "cpu" \ ${lora_args} diff --git a/scripts/run_detail_gpu_memory.sh b/scripts/archive/run_detail_gpu_memory.sh similarity index 100% rename from scripts/run_detail_gpu_memory.sh rename to scripts/archive/run_detail_gpu_memory.sh diff --git a/scripts/run_dpo_align.sh b/scripts/archive/run_dpo_align.sh similarity index 100% rename from scripts/run_dpo_align.sh rename to scripts/archive/run_dpo_align.sh diff --git a/scripts/archive/run_dpov2_align.sh b/scripts/archive/run_dpov2_align.sh new file mode 100644 index 000000000..d96908931 --- /dev/null +++ b/scripts/archive/run_dpov2_align.sh @@ -0,0 +1,81 @@ +#!/bin/bash + +# Parses arguments +run_name=dpov2_align +model_name_or_path=meta-llama/Meta-Llama-3-8B-Instruct +reference_model_name_or_path=meta-llama/Meta-Llama-3-8B-Instruct +dataset_path=data/iterative-prompt/train +eval_dataset_path=data/iterative-prompt/eval +output_dir=output_models/${run_name} + +while [[ $# -ge 1 ]]; do + key="$1" + case ${key} in + -r|--run_name) + run_name="$2" + shift + ;; + --model_name_or_path) + model_name_or_path="$2" + shift + ;; + --reference_model_name_or_path) + reference_model_name_or_path="$2" + shift + ;; + --dataset_path) + dataset_path="$2" + shift + ;; + --eval_dataset_path) + eval_dataset_path="$2" + shift + ;; + -o|--output_dir) + output_dir="$2" + shift + ;; + *) + echo "error: unknown option \"${key}\"" 1>&2 + exit 1 + esac + shift +done + +project_dir=$(cd "$(dirname $0)"/..; pwd) +log_dir=${project_dir}/log/${run_name} +mkdir -p ${output_dir} ${log_dir} + +accelerate launch --config_file configs/accelerate_dsz3_config.yaml \ + examples/dpov2_train.py \ + --model_name_or_path ${model_name_or_path} \ + --reference_model_name_or_path ${reference_model_name_or_path} \ + --do_train True \ + --dataset_path ${dataset_path} \ + --eval_dataset_path ${eval_dataset_path} \ + --bf16 True \ + --learning_rate 5e-7 \ + --lr_scheduler_type cosine \ + --warmup_steps 100 \ + --optim paged_adamw_32bit \ + --per_device_train_batch_size 1 \ + --per_device_eval_batch_size 1 \ + --gradient_accumulation_steps 16 \ + --gradient_checkpointing True \ + --margin_scale 1.0 \ + --max_prompt_length 1000 \ + --num_train_epochs 2 \ + --logging_steps 2 \ + --save_strategy epoch \ + --save_steps 5000 \ + --evaluation_strategy steps \ + --eval_steps 100 \ + --loss_type sigmoid \ + --output_dir ${output_dir} \ + --run_name ${run_name} \ + --sampling_paired_method max_min \ + --report_to wandb \ + --mask_prompt True \ + --length_penalty 0 \ + | tee ${log_dir}/train.log \ + 2> ${log_dir}/train.err \ No newline at end of file diff --git a/scripts/run_evaluation.sh b/scripts/archive/run_evaluation.sh similarity index 100% rename from scripts/run_evaluation.sh rename to scripts/archive/run_evaluation.sh diff --git a/scripts/run_evaluation_accelerator.sh b/scripts/archive/run_evaluation_accelerator.sh similarity index 88% rename from scripts/run_evaluation_accelerator.sh rename to scripts/archive/run_evaluation_accelerator.sh index f5411398c..252793e2c 100644 --- a/scripts/run_evaluation_accelerator.sh +++ b/scripts/archive/run_evaluation_accelerator.sh @@ -4,7 +4,7 @@ if [ ! -d data/MedQA-USMLE ]; then cd data && ./download.sh MedQA-USMLE && cd - fi -CUDA_VISIBLE_DEVICES=0 accelerate launch --config_file configs/accelerator_singlegpu_config.yaml examples/evaluation.py \ +CUDA_VISIBLE_DEVICES=0 accelerate launch --config_file configs/archive/accelerate_singlegpu_config.yaml examples/evaluation.py \ --answer_type usmle \ --model_name_or_path gpt2-large \ --dataset_path data/MedQA-USMLE/validation \ diff --git a/scripts/run_evaluation_with_lora.sh b/scripts/archive/run_evaluation_with_lora.sh similarity index 100% rename from scripts/run_evaluation_with_lora.sh rename to scripts/archive/run_evaluation_with_lora.sh diff --git a/scripts/archive/run_finetune.sh b/scripts/archive/run_finetune.sh new file mode 100755 index 000000000..9bd3d5793 --- /dev/null +++ b/scripts/archive/run_finetune.sh @@ -0,0 +1,78 @@ +#!/bin/bash +# Please run this script under ${project_id} in project directory of +# https://github.com/shizhediao/llm-ft +# COMMIT: d5fecf30ba8011067b10cf51fede53a5ab6574e4 + +# Parses arguments +model_name_or_path=gpt2 +dataset_path=data/alpaca/train_conversation +output_dir=output_models/finetune +deepspeed_args="--master_port=11000" +conversation_template=llama2 + +# Safety related arguments +trust_remote_code=0 + +while [[ $# -ge 1 ]]; do + key="$1" + case ${key} in + -m|--model_name_or_path) + model_name_or_path="$2" + shift + ;; + -d|--dataset_path) + dataset_path="$2" + shift + ;; + -o|--output_model_path) + output_dir="$2" + shift + ;; + --conversation_template) + conversation_template="$2" + shift + ;; + --deepspeed_args) + deepspeed_args="$2" + shift + ;; + --trust_remote_code) + trust_remote_code="$2" + shift + ;; + *) + echo "error: unknown option \"${key}\"" 1>&2 + exit 1 + esac + shift +done + +# Finetune +exp_id=finetune +project_dir=$(cd "$(dirname $0)"/..; pwd) +log_dir=${project_dir}/log/${exp_id} +mkdir -p ${output_dir} ${log_dir} + +deepspeed ${deepspeed_args} \ + examples/finetune.py \ + --model_name_or_path ${model_name_or_path} \ + --trust_remote_code ${trust_remote_code} \ + --dataset_path ${dataset_path} \ + --output_dir ${output_dir} --overwrite_output_dir \ + --conversation_template ${conversation_template} \ + --num_train_epochs 0.01 \ + --learning_rate 2e-5 \ + --disable_group_texts 1 \ + --block_size 256 \ + --per_device_train_batch_size 1 \ + --deepspeed configs/archive/ds_config_zero3.json \ + --fp16 \ + --run_name finetune \ + --validation_split_percentage 0 \ + --logging_steps 20 \ + --do_train \ + --ddp_timeout 72000 \ + --save_steps 5000 \ + --dataloader_num_workers 1 \ + > >(tee ${log_dir}/train.log) \ + 2> >(tee ${log_dir}/train.err >&2) diff --git a/scripts/archive/run_finetune_with_custom_optim.sh b/scripts/archive/run_finetune_with_custom_optim.sh new file mode 100644 index 000000000..09315d4d3 --- /dev/null +++ b/scripts/archive/run_finetune_with_custom_optim.sh @@ -0,0 +1,330 @@ +#!/bin/bash +# Please run this script under ${project_id} in project directory of +# https://github.com/shizhediao/llm-ft +# COMMIT: d5fecf30ba8011067b10cf51fede53a5ab6574e4 +# Parses arguments +model_name_or_path=gpt2 +dataset_path=data/alpaca/train_conversation + +# Other optional arguments that can improve memory saving +gradient_checkpointing=True +use_flash_attention=0 +gradient_accumulation_steps=1 +batch_size=1 +block_size=256 +per_device_train_batch_size=1 +conversation_template=llama2 +optim=dummy +# Select an optimizer from the following options: +# - 'adamw_torch' +# - 'adafactor' +# - 'sgd' +# - 'lion_8bit' +# - 'lion_32bit' +# - 'rmsprop' +# Additional optimizers are shown below +learning_rate=1e-5 +lr_schedule=cosine +beta1=0.9 +beta2=0.999 +beta3=0.99 +weight_decay=0 +momentum=0 +num_epoch=0.01 +use_deepspeed=1 +seed=42 + +# Safety related arguments +trust_remote_code=0 + +# Enable model parallelism for multiple gpus, modify this if you prefer +# customized deepspeed zero-redundancy optimization settings +num_gpu=$(python -c "import torch; print(torch.cuda.device_count())") +ds_config_file=configs/archive/ds_config_zero0_no_offload.json +if [[ ${num_gpu} -ge 2 ]]; then + ds_config_file=configs/archive/ds_config_zero2_no_offload.json +fi + +while [[ $# -ge 1 ]]; do + key="$1" + case ${key} in + -m|--model_name_or_path) + model_name_or_path="$2" + shift + ;; + -d|--dataset_path) + dataset_path="$2" + shift + ;; + -o|--output_model_path) + output_dir="$2" + shift + ;; + --lisa_activated_layers) + lisa_activated_layers="$2" + shift + ;; + --lisa_interval_steps) + lisa_interval_steps="$2" + shift + ;; + --gradient_checkpointing) + gradient_checkpointing="$2" + shift + ;; + --deepspeed) + ds_config_file="$2" + shift + ;; + --use_flash_attention) + use_flash_attention="$2" + shift + ;; + --gradient_accumulation_steps) + gradient_accumulation_steps="$2" + shift + ;; + --block_size) + block_size="$2" + shift + ;; + --conversation_template) + conversation_template="$2" + shift + ;; + --per_device_train_batch_size|--batch_size) + per_device_train_batch_size="$2" + batch_size="$2" + shift + ;; + --trust_remote_code) + trust_remote_code="$2" + shift + ;; + --run_name) + run_name="$2" + shift + ;; + --optim) + optim="$2" + shift + ;; + --lr) + learning_rate="$2" + shift + ;; + --beta1) + beta1="$2" + shift + ;; + --beta2) + beta2="$2" + shift + ;; + --beta3) + beta3="$2" + shift + ;; + --weight_decay) + weight_decay="$2" + shift + ;; + --momentum) + momentum="$2" + shift + ;; + -n|--num_epoch) + num_epoch="$2" + shift + ;; + --lr_schedule) + lr_schedule="$2" + shift + ;; + --use_deepspeed) + use_deepspeed="$2" + shift + ;; + --seed) + seed="$2" + shift + ;; + *) + echo "error: unknown option \"${key}\"" 1>&2 + exit 1 + esac + shift +done + +deepspeed_args="--master_port=1103" + +optim_suffix_args="" +if [ "${optim}" == "dummy" ]; then + optim_suffix_args="--use_customized_optim 1" + optim_suffix_args+=" --customized_optim ${optim}" + optim_suffix_args+=" --optim_dummy_beta1 ${beta1}" + optim_suffix_args+=" --optim_dummy_beta2 ${beta2}" +elif [ "${optim}" == "adabelief" ]; then + optim_suffix_args="--use_customized_optim 1" + optim_suffix_args+=" --customized_optim ${optim}" + optim_suffix_args+=" --optim_beta1 ${beta1}" + optim_suffix_args+=" --optim_beta2 ${beta2}" + optim_suffix_args+=" --optim_weight_decay ${weight_decay}" +elif [ "${optim}" == "adabound" ]; then + optim_suffix_args="--use_customized_optim 1" + optim_suffix_args+=" --customized_optim ${optim}" + optim_suffix_args+=" --optim_beta1 ${beta1}" + optim_suffix_args+=" --optim_beta2 ${beta2}" + optim_suffix_args+=" --optim_weight_decay ${weight_decay}" +elif [ "${optim}" == "lars" ]; then + optim_suffix_args="--use_customized_optim 1" + optim_suffix_args+=" --customized_optim ${optim}" + optim_suffix_args+=" --optim_momentum ${momentum}" + optim_suffix_args+=" --optim_weight_decay ${weight_decay}" +elif [ "${optim}" == "lamb" ]; then + optim_suffix_args="--use_customized_optim 1" + optim_suffix_args+=" --customized_optim ${optim}" + optim_suffix_args+=" --optim_beta1 ${beta1}" + optim_suffix_args+=" --optim_beta2 ${beta2}" + optim_suffix_args+=" --optim_weight_decay ${weight_decay}" +elif [ "${optim}" == "adamax" ]; then + optim_suffix_args="--use_customized_optim 1" + optim_suffix_args+=" --customized_optim ${optim}" + optim_suffix_args+=" --optim_beta1 ${beta1}" + optim_suffix_args+=" --optim_beta2 ${beta2}" + optim_suffix_args+=" --optim_weight_decay ${weight_decay}" +elif [ "${optim}" == "nadam" ]; then + optim_suffix_args="--use_customized_optim 1" + optim_suffix_args+=" --customized_optim ${optim}" + optim_suffix_args+=" --optim_beta1 ${beta1}" + optim_suffix_args+=" --optim_beta2 ${beta2}" + optim_suffix_args+=" --optim_weight_decay ${weight_decay}" +elif [ "${optim}" == "radam" ]; then + optim_suffix_args="--use_customized_optim 1" + optim_suffix_args+=" --customized_optim ${optim}" + optim_suffix_args+=" --optim_beta1 ${beta1}" + optim_suffix_args+=" --optim_beta2 ${beta2}" + optim_suffix_args+=" --optim_weight_decay ${weight_decay}" +elif [ "${optim}" == "adamp" ]; then + optim_suffix_args="--use_customized_optim 1" + optim_suffix_args+=" --customized_optim ${optim}" + optim_suffix_args+=" --optim_beta1 ${beta1}" + optim_suffix_args+=" --optim_beta2 ${beta2}" + optim_suffix_args+=" --optim_weight_decay ${weight_decay}" +elif [ "${optim}" == "sgdp" ]; then + optim_suffix_args="--use_customized_optim 1" + optim_suffix_args+=" --customized_optim ${optim}" + optim_suffix_args+=" --optim_momentum ${momentum}" + optim_suffix_args+=" --optim_weight_decay ${weight_decay}" +elif [ "${optim}" == "yogi" ]; then + optim_suffix_args="--use_customized_optim 1" + optim_suffix_args+=" --customized_optim ${optim}" + optim_suffix_args+=" --optim_beta1 ${beta1}" + optim_suffix_args+=" --optim_beta2 ${beta2}" + optim_suffix_args+=" --optim_weight_decay ${weight_decay}" +elif [ "${optim}" == "sophia" ]; then + optim_suffix_args="--use_customized_optim 1" + optim_suffix_args+=" --customized_optim ${optim}" + optim_suffix_args+=" --optim_beta1 ${beta1}" + optim_suffix_args+=" --optim_beta2 ${beta2}" + optim_suffix_args+=" --optim_weight_decay ${weight_decay}" +elif [ "${optim}" == "adan" ]; then + optim_suffix_args="--use_customized_optim 1" + optim_suffix_args+=" --customized_optim ${optim}" + optim_suffix_args+=" --optim_beta1 ${beta1}" + optim_suffix_args+=" --optim_beta2 ${beta2}" + optim_suffix_args+=" --optim_beta3 ${beta3}" + optim_suffix_args+=" --optim_weight_decay ${weight_decay}" +elif [ "${optim}" == "adam" ]; then + optim_suffix_args="--use_customized_optim 1" + optim_suffix_args+=" --customized_optim ${optim}" + optim_suffix_args+=" --optim_beta1 ${beta1}" + optim_suffix_args+=" --optim_beta2 ${beta2}" +elif [ "${optim}" == "novograd" ]; then + optim_suffix_args="--use_customized_optim 1" + optim_suffix_args+=" --customized_optim ${optim}" + optim_suffix_args+=" --optim_beta1 ${beta1}" + optim_suffix_args+=" --optim_beta2 ${beta2}" + optim_suffix_args+=" --optim_weight_decay ${weight_decay}" +elif [ "${optim}" == "adadelta" ]; then + optim_suffix_args="--use_customized_optim 1" + optim_suffix_args+=" --customized_optim ${optim}" +elif [ "${optim}" == "adagrad" ]; then + optim_suffix_args="--use_customized_optim 1" + optim_suffix_args+=" --customized_optim ${optim}" +elif [ "${optim}" == "adamw_schedule_free" ]; then + optim_suffix_args="--use_customized_optim 1" + optim_suffix_args+=" --customized_optim ${optim}" + optim_suffix_args+=" --optim_beta1 ${beta1}" + optim_suffix_args+=" --optim_beta2 ${beta2}" + optim_suffix_args+=" --optim_weight_decay ${weight_decay}" +elif [ "${optim}" == "sgd_schedule_free" ]; then + optim_suffix_args="--use_customized_optim 1" + optim_suffix_args+=" --customized_optim ${optim}" + optim_suffix_args+=" --optim_momentum ${momentum}" + optim_suffix_args+=" --optim_weight_decay ${weight_decay}" +else + optim_suffix_args="--optim ${optim}" + optim_suffix_args+=" --adam_beta1 ${beta1}" + optim_suffix_args+=" --adam_beta2 ${beta2}" +fi + +# Finetune +exp_id=alpaca_${optim}_lr-${learning_rate}_beta1-${beta1}_beta2-${beta2}_lr-sched-${lr_schedule}_model-$(basename ${model_name_or_path})_batch-size-${batch_size}x${gradient_accumulation_steps}_seed-${seed} +echo "$(date): ${exp_id}..." + +tmp_dir=tmp +mkdir -p ${tmp_dir} + +prefix=${exp_id} +if [ -f ${tmp_dir}/${prefix}.mark ]; then + exit 0 +fi + +trap "rm -f ${tmp_dir}/${prefix}.mark" SIGINT SIGTERM SIGKILL +touch ${tmp_dir}/${prefix}.mark + +project_dir=$(cd "$(dirname $0)"/..; pwd) +log_dir=${project_dir}/log/${exp_id} +output_dir=output_models/${exp_id} +mkdir -p ${output_dir} ${log_dir} + +exe="deepspeed ${deepspeed_args}" +if [[ ${use_deepspeed} -eq 0 ]]; then + exe=python +fi +${exe} examples/finetune.py \ + --model_name_or_path ${model_name_or_path} \ + --trust_remote_code ${trust_remote_code} \ + --dataset_path ${dataset_path} \ + --output_dir ${output_dir} --overwrite_output_dir \ + --conversation_template ${conversation_template} \ + --num_train_epochs ${num_epoch} \ + --learning_rate ${learning_rate} \ + --lr_scheduler_type ${lr_schedule} \ + --disable_group_texts 1 \ + --block_size ${block_size} \ + --per_device_train_batch_size ${per_device_train_batch_size} \ + --bf16 \ + --deepspeed configs/archive/ds_config_zero2_no_offload.json \ + --torch_dtype bfloat16 \ + --run_name ${exp_id} \ + --validation_split_percentage 0 \ + --logging_steps 1 \ + --do_train \ + --ddp_timeout 72000 \ + --save_steps 5000 \ + --dataloader_num_workers 1 \ + --gradient_checkpointing ${gradient_checkpointing} \ + --use_flash_attention ${use_flash_attention} \ + --gradient_accumulation_steps ${gradient_accumulation_steps} \ + --seed ${seed} \ + ${optim_suffix_args} \ + | tee ${log_dir}/train.log \ + 2> ${log_dir}/train.err + + +if [[ $? -ne 0 ]]; then + echo "$(date): failed" + rm -f ${tmp_dir}/${prefix}.mark +fi diff --git a/scripts/archive/run_finetune_with_lisa.sh b/scripts/archive/run_finetune_with_lisa.sh new file mode 100755 index 000000000..3b020445b --- /dev/null +++ b/scripts/archive/run_finetune_with_lisa.sh @@ -0,0 +1,128 @@ +#!/bin/bash +# Please run this script under ${project_id} in project directory of +# https://github.com/shizhediao/llm-ft +# COMMIT: d5fecf30ba8011067b10cf51fede53a5ab6574e4 + +# Parses arguments +model_name_or_path=meta-llama/Llama-2-7b-hf +dataset_path=data/alpaca/train_conversation +output_dir=output_models/finetune_lisa +lisa_activated_layers=1 +lisa_interval_steps=20 + +# Other optional arguments that can improve memory saving +gradient_checkpointing=True +use_flash_attention=0 +gradient_accumulation_steps=1 +block_size=256 +per_device_train_batch_size=1 +conversation_template=llama2 + +# Safety related arguments +trust_remote_code=0 + +# Enable model parallelism for multiple gpus, modify this if you prefer +# customized deepspeed zero-redundancy optimization settings +num_gpu=$(python -c "import torch; print(torch.cuda.device_count())") +ds_config_file=configs/archive/ds_config_zero0_no_offload.json +if [ ${num_gpu} -ge 2 ]; then + ds_config_file=configs/archive/ds_config_zero2_no_offload.json +fi + +while [[ $# -ge 1 ]]; do + key="$1" + case ${key} in + -m|--model_name_or_path) + model_name_or_path="$2" + shift + ;; + -d|--dataset_path) + dataset_path="$2" + shift + ;; + -o|--output_model_path) + output_dir="$2" + shift + ;; + --lisa_activated_layers) + lisa_activated_layers="$2" + shift + ;; + --lisa_interval_steps) + lisa_interval_steps="$2" + shift + ;; + --gradient_checkpointing) + gradient_checkpointing="$2" + shift + ;; + --deepspeed) + ds_config_file="$2" + shift + ;; + --use_flash_attention) + use_flash_attention="$2" + shift + ;; + --gradient_accumulation_steps) + gradient_accumulation_steps="$2" + shift + ;; + --block_size) + block_size="$2" + shift + ;; + --conversation_template) + conversation_template="$2" + shift + ;; + --per_device_train_batch_size|--batch_size) + per_device_train_batch_size="$2" + shift + ;; + --trust_remote_code) + trust_remote_code="$2" + shift + ;; + *) + echo "error: unknown option \"${key}\"" 1>&2 + exit 1 + esac + shift +done + +# Finetune +exp_id=finetune +project_dir=$(cd "$(dirname $0)"/..; pwd) +log_dir=${project_dir}/log/${exp_id} +mkdir -p ${output_dir} ${log_dir} + +python examples/finetune.py \ + --model_name_or_path ${model_name_or_path} \ + --trust_remote_code ${trust_remote_code} \ + --dataset_path ${dataset_path} \ + --output_dir ${output_dir} --overwrite_output_dir \ + --conversation_template ${conversation_template} \ + --num_train_epochs 1 \ + --learning_rate 1e-5 \ + --disable_group_texts 1 \ + --block_size ${block_size} \ + --per_device_train_batch_size ${per_device_train_batch_size} \ + --bf16 \ + --torch_dtype bfloat16 \ + --run_name finetune \ + --optim paged_adamw_32bit \ + --validation_split_percentage 0 \ + --logging_steps 20 \ + --do_train \ + --ddp_timeout 72000 \ + --save_steps 5000 \ + --dataloader_num_workers 1 \ + --gradient_checkpointing ${gradient_checkpointing} \ + --use_flash_attention ${use_flash_attention} \ + --gradient_accumulation_steps ${gradient_accumulation_steps} \ + --use_lisa 1 \ + --lisa_activated_layers ${lisa_activated_layers} \ + --lisa_interval_steps ${lisa_interval_steps} \ + | tee ${log_dir}/train.log \ + 2> ${log_dir}/train.err diff --git a/scripts/archive/run_finetune_with_lora.sh b/scripts/archive/run_finetune_with_lora.sh new file mode 100755 index 000000000..c2ab0372e --- /dev/null +++ b/scripts/archive/run_finetune_with_lora.sh @@ -0,0 +1,78 @@ +#!/bin/bash +# Please run this script under ${project_id} in project directory of + +# Parses arguments +model_name_or_path=gpt2 +dataset_path=data/alpaca/train_conversation +conversation_template=llama2 +output_dir=output_models/finetune +deepspeed_args="--master_port=11000" + +# Safety related arguments +trust_remote_code=0 + +while [[ $# -ge 1 ]]; do + key="$1" + case ${key} in + -m|--model_name_or_path) + model_name_or_path="$2" + shift + ;; + -d|--dataset_path) + dataset_path="$2" + shift + ;; + --conversation_template) + conversation_template="$2" + shift + ;; + -o|--output_lora_path) + output_dir="$2" + shift + ;; + --deepspeed_args) + deepspeed_args="$2" + shift + ;; + --trust_remote_code) + trust_remote_code="$2" + shift + ;; + *) + echo "error: unknown option \"${key}\"" 1>&2 + exit 1 + esac + shift +done + +# Finetune +exp_id=finetune_with_lora +project_dir=$(cd "$(dirname $0)"/..; pwd) +log_dir=${project_dir}/log/${exp_id} +mkdir -p ${output_dir} ${log_dir} + +deepspeed ${deepspeed_args} \ + examples/finetune.py \ + --model_name_or_path ${model_name_or_path} \ + --trust_remote_code ${trust_remote_code} \ + --dataset_path ${dataset_path} \ + --conversation_template ${conversation_template} \ + --output_dir ${output_dir} --overwrite_output_dir \ + --num_train_epochs 0.01 \ + --learning_rate 1e-4 \ + --block_size 512 \ + --per_device_train_batch_size 1 \ + --use_lora 1 \ + --lora_r 8 \ + --save_aggregated_lora 0\ + --deepspeed configs/archive/ds_config_zero2.json \ + --fp16 \ + --run_name ${exp_id} \ + --validation_split_percentage 0 \ + --logging_steps 20 \ + --do_train \ + --ddp_timeout 72000 \ + --save_steps 5000 \ + --dataloader_num_workers 1 \ + | tee ${log_dir}/train.log \ + 2> ${log_dir}/train.err diff --git a/scripts/archive/run_finetune_with_qlora.sh b/scripts/archive/run_finetune_with_qlora.sh new file mode 100644 index 000000000..c620580de --- /dev/null +++ b/scripts/archive/run_finetune_with_qlora.sh @@ -0,0 +1,77 @@ +#!/bin/bash +# Please run this script under ${project_id} in project directory of + +# Parses arguments +model_name_or_path=meta-llama/Llama-2-13b-hf +dataset_path=data/alpaca/train_conversation +conversation_template=llama2 +output_dir=output_models/finetune +deepspeed_args="--master_port=11000" + +# Safety related arguments +trust_remote_code=0 + +while [[ $# -ge 1 ]]; do + key="$1" + case ${key} in + -m|--model_name_or_path) + model_name_or_path="$2" + shift + ;; + -d|--dataset_path) + dataset_path="$2" + shift + ;; + --conversation_template) + conversation_template="$2" + shift + ;; + -o|--output_model_path) + output_dir="$2" + shift + ;; + --deepspeed_args) + deepspeed_args="$2" + shift + ;; + --trust_remote_code) + trust_remote_code="$2" + shift + ;; + *) + echo "error: unknown option \"${key}\"" 1>&2 + exit 1 + esac + shift +done + +# Finetune +exp_id=finetune_with_lora +project_dir=$(cd "$(dirname $0)"/..; pwd) +log_dir=${project_dir}/log/${exp_id} +mkdir -p ${output_dir} ${log_dir} + +deepspeed ${deepspeed_args} \ + examples/finetune.py \ + --model_name_or_path ${model_name_or_path} \ + --trust_remote_code ${trust_remote_code} \ + --dataset_path ${dataset_path} \ + --conversation_template ${conversation_template} \ + --output_dir ${output_dir} --overwrite_output_dir \ + --num_train_epochs 0.01 \ + --learning_rate 1e-4 \ + --block_size 512 \ + --per_device_train_batch_size 1 \ + --use_qlora 1 \ + --save_aggregated_lora 0 \ + --deepspeed configs/archive/ds_config_zero2.json \ + --fp16 \ + --run_name ${exp_id} \ + --validation_split_percentage 0 \ + --logging_steps 20 \ + --do_train \ + --ddp_timeout 72000 \ + --save_steps 5000 \ + --dataloader_num_workers 1 \ + | tee ${log_dir}/train.log \ + 2> ${log_dir}/train.err \ No newline at end of file diff --git a/scripts/archive/run_inference.sh b/scripts/archive/run_inference.sh new file mode 100755 index 000000000..7ae978f64 --- /dev/null +++ b/scripts/archive/run_inference.sh @@ -0,0 +1,20 @@ +#!/bin/bash +# An interactive inference script without context history, i.e. the chatbot +# won't have conversation memory. + +model=gpt2 +lora_args="" +if [ $# -ge 1 ]; then + model=$1 +fi +if [ $# -ge 2 ]; then + lora_args="--lora_model_path $2" +fi + +accelerate launch --config_file configs/accelerator_multigpu_config.yaml \ + examples/inference.py \ + --deepspeed configs/archive/ds_config_chatbot.json \ + --model_name_or_path ${model} \ + --max_new_tokens 256 \ + --temperature 1.0 \ + ${lora_args} diff --git a/scripts/run_inference_multimodal_model.sh b/scripts/archive/run_inference_multimodal_model.sh similarity index 84% rename from scripts/run_inference_multimodal_model.sh rename to scripts/archive/run_inference_multimodal_model.sh index ba150fa03..df54d192b 100755 --- a/scripts/run_inference_multimodal_model.sh +++ b/scripts/archive/run_inference_multimodal_model.sh @@ -11,7 +11,7 @@ fi CUDA_VISIBLE_DEVICES=0 \ deepspeed examples/inference.py \ - --deepspeed configs/ds_config_multimodal.json \ + --deepspeed configs/archive/ds_config_multimodal.json \ --model_name_or_path ${model} \ --arch_type vision_encoder_decoder \ ${lora_args} diff --git a/scripts/run_multistage_finetune.sh b/scripts/archive/run_multistage_finetune.sh similarity index 95% rename from scripts/run_multistage_finetune.sh rename to scripts/archive/run_multistage_finetune.sh index 701540e8f..096c9e1e1 100755 --- a/scripts/run_multistage_finetune.sh +++ b/scripts/archive/run_multistage_finetune.sh @@ -31,7 +31,7 @@ deepspeed ${deepspeed_args} \ --use_lora 1 \ --lora_r 8 \ --save_aggregated_lora 1 \ - --deepspeed configs/ds_config_zero2.json \ + --deepspeed configs/archive/ds_config_zero2.json \ --bf16 \ --run_name finetune_with_lora \ --validation_split_percentage 0 \ diff --git a/scripts/archive/run_raft_align.sh b/scripts/archive/run_raft_align.sh new file mode 100755 index 000000000..1215d33cf --- /dev/null +++ b/scripts/archive/run_raft_align.sh @@ -0,0 +1,49 @@ +#!/bin/bash +# Please run this script under project directory. + +deepspeed_args="--master_port=11110" # Default argument +if [ $# -ge 1 ]; then + deepspeed_args="$1" +fi + +exp_id=raft_align +project_dir=$(cd "$(dirname $0)"/..; pwd) +output_dir=${project_dir}/output_models/${exp_id} +log_dir=${project_dir}/log/${exp_id} + +if [ ! -d data/hh_rlhf ]; then + cd data && ./download.sh hh_rlhf && cd - +fi + +mkdir -p ${output_dir} ${log_dir} + +export PYTHONPATH=. +deepspeed ${deepspeed_args} \ + examples/raft_align.py \ + --model_name_or_path gpt2 \ + --num_raft_iteration 20 \ + --learning_rate 2e-5 \ + --lr_scheduler_type "constant" \ + --bf16 \ + --deepspeed configs/archive/ds_config_zero2.json \ + --dataset_path ${project_dir}/data/hh_rlhf/rlhf_prompt \ + --output_reward_path ${project_dir}/tmp/raft_aligner/reward.txt \ + --output_dir ${output_dir} --overwrite_output_dir \ + --run_name ${exp_id} \ + --num_train_epochs 4 \ + --per_device_train_batch_size 1 \ + --per_device_eval_batch_size 1 \ + --validation_split_percentage 0 \ + --logging_steps 1 \ + --do_train \ + --ddp_timeout 72000 \ + --save_steps 7777 \ + --dataloader_num_workers 1 \ + --preprocessing_num_workers 12 \ + --inference_batch_size_per_device 1 \ + --collection_strategy "local" \ + --raft_batch_size 1024 \ + --output_min_length 96 \ + --top_reward_percentage 0.125 \ + | tee ${log_dir}/raft_align.log \ + 2> ${log_dir}/raft_align.err diff --git a/scripts/archive/run_reward_modeling.sh b/scripts/archive/run_reward_modeling.sh new file mode 100644 index 000000000..1dc0eaf04 --- /dev/null +++ b/scripts/archive/run_reward_modeling.sh @@ -0,0 +1,93 @@ +#!/bin/bash +# Copyright 2024 Statistics and Machine Learning Research Group. All rights reserved. +# Parses arguments +model_name_or_path=google/gemma-2b-it +train_dataset_path=data/ultrafeedback-binarized-preferences-cleaned/train +eval_dataset_path=data/ultrafeedback-binarized-preferences-cleaned/train +output_dir=output_models/reward_modeling +deepspeed_args="--master_port=11345 --include localhost:6" +conversation_template=gemma + +# Safety related arguments +trust_remote_code=0 + +while [[ $# -ge 1 ]]; do + key="$1" + case ${key} in + -m|--model_name_or_path) + model_name_or_path="$2" + shift + ;; + --train_dataset_path) + train_dataset_path="$2" + shift + ;; + --eval_dataset_path) + eval_dataset_path="$2" + shift + ;; + -o|--output_model_path) + output_dir="$2" + shift + ;; + --conversation_template) + conversation_template="$2" + shift + ;; + --deepspeed_args) + deepspeed_args="$2" + shift + ;; + --trust_remote_code) + trust_remote_code="$2" + shift + ;; + *) + echo "error: unknown option \"${key}\"" 1>&2 + exit 1 + esac + shift +done + +# Finetune +exp_id=reward_modeling +project_dir=$(cd "$(dirname $0)"/..; pwd) +log_dir=${project_dir}/log/${exp_id} +mkdir -p ${output_dir} ${log_dir} + +deepspeed ${deepspeed_args} \ + examples/reward_modeling.py \ + --deepspeed configs/archive/ds_config_zero3.json \ + --model_name_or_path ${model_name_or_path} \ + --arch_type "text_regression" \ + --do_train True \ + --dataset_path ${train_dataset_path} \ + --conversation_template ${conversation_template} \ + --output_dir ${output_dir} --overwrite_output_dir \ + --use_flash_attention True \ + --block_size 4096 \ + --learning_rate 1e-5 \ + --per_device_train_batch_size 1 \ + --per_device_eval_batch_size 1 \ + --num_train_epochs 0.001 \ + --weight_decay 0.001 \ + --evaluation_strategy "steps" \ + --save_strategy "steps" \ + --save_steps 999999 \ + --gradient_accumulation_steps 32 \ + --gradient_checkpointing True \ + --remove_unused_columns False \ + --bf16 True \ + --logging_strategy "steps" \ + --logging_steps 10 \ + --optim "paged_adamw_32bit" \ + --lr_scheduler_type "cosine" \ + --warmup_ratio 0.03 \ + --report_to 'wandb' \ + --run_name ${exp_id} \ + --do_eval True \ + --eval_dataset_path ${eval_dataset_path} \ + --eval_steps 999999 \ + --preprocessing_num_workers 4 \ + | tee ${log_dir}/train.log \ + 2> ${log_dir}/train.err \ No newline at end of file diff --git a/scripts/archive/run_reward_modeling_with_lisa.sh b/scripts/archive/run_reward_modeling_with_lisa.sh new file mode 100644 index 000000000..9b7e4f2f5 --- /dev/null +++ b/scripts/archive/run_reward_modeling_with_lisa.sh @@ -0,0 +1,105 @@ +#!/bin/bash +# Copyright 2024 Statistics and Machine Learning Research Group. All rights reserved. +# Parses arguments +model_name_or_path=google/gemma-2b-it +train_dataset_path=data/ultrafeedback-binarized-preferences-cleaned/train +eval_dataset_path=data/ultrafeedback-binarized-preferences-cleaned/train +output_dir=output_models/reward_modeling_lisa +deepspeed_args="--master_port=11345 --include localhost:6" +conversation_template=gemma +lisa_activated_layers=1 +lisa_interval_steps=20 + +# Safety related arguments +trust_remote_code=0 + +while [[ $# -ge 1 ]]; do + key="$1" + case ${key} in + -m|--model_name_or_path) + model_name_or_path="$2" + shift + ;; + --train_dataset_path) + train_dataset_path="$2" + shift + ;; + --eval_dataset_path) + eval_dataset_path="$2" + shift + ;; + --lisa_activated_layers) + lisa_activated_layers="$2" + shift + ;; + --lisa_interval_steps) + lisa_interval_steps="$2" + shift + ;; + -o|--output_model_path) + output_dir="$2" + shift + ;; + --conversation_template) + conversation_template="$2" + shift + ;; + --deepspeed_args) + deepspeed_args="$2" + shift + ;; + --trust_remote_code) + trust_remote_code="$2" + shift + ;; + *) + echo "error: unknown option \"${key}\"" 1>&2 + exit 1 + esac + shift +done + +# Finetune +exp_id=reward_modeling +project_dir=$(cd "$(dirname $0)"/..; pwd) +log_dir=${project_dir}/log/${exp_id} +mkdir -p ${output_dir} ${log_dir} + +deepspeed ${deepspeed_args} \ + examples/reward_modeling.py \ + --deepspeed configs/archive/ds_config_zero3.json \ + --model_name_or_path ${model_name_or_path} \ + --arch_type "text_regression" \ + --do_train True \ + --dataset_path ${train_dataset_path} \ + --conversation_template ${conversation_template} \ + --output_dir ${output_dir} --overwrite_output_dir \ + --use_flash_attention True \ + --block_size 4096 \ + --learning_rate 1e-5 \ + --per_device_train_batch_size 1 \ + --per_device_eval_batch_size 1 \ + --num_train_epochs 2 \ + --weight_decay 0.001 \ + --evaluation_strategy "steps" \ + --save_strategy "steps" \ + --save_steps 999999 \ + --gradient_accumulation_steps 32 \ + --gradient_checkpointing True \ + --remove_unused_columns False \ + --bf16 True \ + --logging_strategy "steps" \ + --logging_steps 10 \ + --optim "paged_adamw_32bit" \ + --lr_scheduler_type "cosine" \ + --warmup_ratio 0.03 \ + --report_to 'wandb' \ + --run_name ${exp_id} \ + --do_eval True \ + --eval_dataset_path ${eval_dataset_path} \ + --eval_steps 999999 \ + --use_lisa True \ + --lisa_activated_layers ${lisa_activated_layers} \ + --lisa_interval_steps ${lisa_interval_steps} \ + | tee ${log_dir}/train.log \ + 2> ${log_dir}/train.err \ No newline at end of file diff --git a/scripts/archive/run_reward_modeling_with_lora.sh b/scripts/archive/run_reward_modeling_with_lora.sh new file mode 100644 index 000000000..addd50263 --- /dev/null +++ b/scripts/archive/run_reward_modeling_with_lora.sh @@ -0,0 +1,94 @@ +#!/bin/bash +# Copyright 2024 Statistics and Machine Learning Research Group. All rights reserved. +# Parses arguments +model_name_or_path=google/gemma-2b-it +train_dataset_path=data/ultrafeedback-binarized-preferences-cleaned/train +eval_dataset_path=data/ultrafeedback-binarized-preferences-cleaned/train +output_dir=output_models/reward_modeling_lora +deepspeed_args="--master_port=11345 --include localhost:6" +conversation_template=gemma + +# Safety related arguments +trust_remote_code=0 + +while [[ $# -ge 1 ]]; do + key="$1" + case ${key} in + -m|--model_name_or_path) + model_name_or_path="$2" + shift + ;; + --train_dataset_path) + train_dataset_path="$2" + shift + ;; + --eval_dataset_path) + eval_dataset_path="$2" + shift + ;; + -o|--output_model_path) + output_dir="$2" + shift + ;; + --conversation_template) + conversation_template="$2" + shift + ;; + --deepspeed_args) + deepspeed_args="$2" + shift + ;; + --trust_remote_code) + trust_remote_code="$2" + shift + ;; + *) + echo "error: unknown option \"${key}\"" 1>&2 + exit 1 + esac + shift +done + +# Finetune +exp_id=reward_modeling +project_dir=$(cd "$(dirname $0)"/..; pwd) +log_dir=${project_dir}/log/${exp_id} +mkdir -p ${output_dir} ${log_dir} + +deepspeed ${deepspeed_args} \ + examples/reward_modeling.py \ + --deepspeed configs/archive/ds_config_zero3.json \ + --model_name_or_path ${model_name_or_path} \ + --arch_type "text_regression" \ + --do_train True \ + --dataset_path ${train_dataset_path} \ + --conversation_template ${conversation_template} \ + --output_dir ${output_dir} --overwrite_output_dir \ + --use_flash_attention True \ + --block_size 4096 \ + --learning_rate 1e-5 \ + --per_device_train_batch_size 1 \ + --per_device_eval_batch_size 1 \ + --num_train_epochs 2 \ + --weight_decay 0.001 \ + --evaluation_strategy "steps" \ + --save_strategy "steps" \ + --save_steps 999999 \ + --gradient_accumulation_steps 32 \ + --gradient_checkpointing True \ + --remove_unused_columns False \ + --bf16 True \ + --logging_strategy "steps" \ + --logging_steps 10 \ + --optim "paged_adamw_32bit" \ + --lr_scheduler_type "cosine" \ + --warmup_ratio 0.03 \ + --report_to 'wandb' \ + --run_name ${exp_id} \ + --do_eval True \ + --eval_dataset_path ${eval_dataset_path} \ + --eval_steps 999999 \ + --use_lora True \ + --lora_r 8 \ + | tee ${log_dir}/train.log \ + 2> ${log_dir}/train.err \ No newline at end of file diff --git a/scripts/run_tool.sh b/scripts/archive/run_tool.sh similarity index 100% rename from scripts/run_tool.sh rename to scripts/archive/run_tool.sh diff --git a/scripts/multimodal/run_finetune_multi_modal_stage1.sh b/scripts/multimodal/run_finetune_multi_modal_stage1.sh index 743301b21..8e0180d04 100755 --- a/scripts/multimodal/run_finetune_multi_modal_stage1.sh +++ b/scripts/multimodal/run_finetune_multi_modal_stage1.sh @@ -51,7 +51,7 @@ mkdir -p ${output_dir} ${log_dir} deepspeed ${deepspeed_args} \ examples/finetune_multi_modal.py \ - --deepspeed configs/ds_config_multimodal.json \ + --deepspeed configs/archive/ds_config_multimodal.json \ --arch_type vision_encoder_decoder \ --llava_loading True \ --model_name_or_path ${model_name_or_path} \ diff --git a/scripts/multimodal/run_finetune_multi_modal_stage2.sh b/scripts/multimodal/run_finetune_multi_modal_stage2.sh index 3884c3c99..f0ea10f92 100755 --- a/scripts/multimodal/run_finetune_multi_modal_stage2.sh +++ b/scripts/multimodal/run_finetune_multi_modal_stage2.sh @@ -66,7 +66,7 @@ mkdir -p ${output_dir} ${log_dir} # default in llava is 16 deepspeed ${deepspeed_args} \ examples/finetune_multi_modal.py \ - --deepspeed configs/ds_config_zero2.json \ + --deepspeed configs/archive/ds_config_zero2.json \ --arch_type vision_encoder_decoder \ --llava_loading True \ --model_name_or_path ${model_name_or_path} \ diff --git a/scripts/multimodal/run_vis_chatbot_blip2.sh b/scripts/multimodal/run_vis_chatbot_blip2.sh index 0c0b803f3..492409a88 100755 --- a/scripts/multimodal/run_vis_chatbot_blip2.sh +++ b/scripts/multimodal/run_vis_chatbot_blip2.sh @@ -1,6 +1,6 @@ model=Salesforce/blip2-opt-2.7b deepspeed examples/vis_chatbot.py --model_name_or_path ${model} \ - --deepspeed configs/ds_config_vis_chatbot.json \ + --deepspeed configs/archive/ds_config_vis_chatbot.json \ --arch_type vision_encoder_decoder \ --task vqa \ ${@:1} diff --git a/scripts/multimodal/run_vis_chatbot_gradio_minigpt4.sh b/scripts/multimodal/run_vis_chatbot_gradio_minigpt4.sh index 0e0556e81..280461f1e 100755 --- a/scripts/multimodal/run_vis_chatbot_gradio_minigpt4.sh +++ b/scripts/multimodal/run_vis_chatbot_gradio_minigpt4.sh @@ -14,7 +14,7 @@ model=Salesforce/blip2-flan-t5-xxl # # deepspeed --master_port=11005 examples/vis_chatbot_gradio.py \ # --model_name_or_path ${model} \ -# --deepspeed configs/ds_config_multimodal.json \ +# --deepspeed configs/archive/ds_config_multimodal.json \ # --arch_type vision_encoder_decoder \ # --task vqa \ # --custom_model \ @@ -37,7 +37,7 @@ fi deepspeed --master_port=11005 examples/vis_chatbot_gradio.py \ --model_name_or_path ${model} \ - --deepspeed configs/ds_config_vis_chatbot.json \ + --deepspeed configs/archive/ds_config_vis_chatbot.json \ --arch_type vision_encoder_decoder \ --task vqa \ --custom_model \ diff --git a/scripts/multimodal/run_vis_chatbot_llava.sh b/scripts/multimodal/run_vis_chatbot_llava.sh index 028cbaecb..79c358d64 100755 --- a/scripts/multimodal/run_vis_chatbot_llava.sh +++ b/scripts/multimodal/run_vis_chatbot_llava.sh @@ -18,7 +18,7 @@ fi deepspeed ${deepspeed_args} \ examples/vis_chatbot.py \ - --deepspeed configs/ds_config_vis_chatbot.json \ + --deepspeed configs/archive/ds_config_vis_chatbot.json \ --arch_type vision_encoder_decoder \ --task vqa \ --custom_model True \ diff --git a/scripts/multimodal/run_vis_chatbot_minigpt4.sh b/scripts/multimodal/run_vis_chatbot_minigpt4.sh index e5a445da5..2d3e6bab3 100755 --- a/scripts/multimodal/run_vis_chatbot_minigpt4.sh +++ b/scripts/multimodal/run_vis_chatbot_minigpt4.sh @@ -12,7 +12,7 @@ if [ ! -f output_models/pretrained_minigpt4_7b_converted.pth ]; then --save_path output_models/pretrained_minigpt4_7b_converted.pth fi -deepspeed ${deepspeed_args} examples/vis_chatbot.py --model_name_or_path ${model} --deepspeed configs/ds_config_vis_chatbot.json --arch_type vision_encoder_decoder --task vqa --custom_model \ +deepspeed ${deepspeed_args} examples/vis_chatbot.py --model_name_or_path ${model} --deepspeed configs/archive/ds_config_vis_chatbot.json --arch_type vision_encoder_decoder --task vqa --custom_model \ --chatbot_type mini_gpt \ --prompt_structure "{input_text}###Assistant:" \ --pretrained_language_projection_path output_models/pretrained_minigpt4_7b_converted.pth \ diff --git a/scripts/run_finetune.sh b/scripts/run_finetune.sh index d78458e20..e705c399a 100755 --- a/scripts/run_finetune.sh +++ b/scripts/run_finetune.sh @@ -1,14 +1,9 @@ #!/bin/bash -# Please run this script under ${project_id} in project directory of -# https://github.com/shizhediao/llm-ft -# COMMIT: d5fecf30ba8011067b10cf51fede53a5ab6574e4 - # Parses arguments -model_name_or_path=gpt2 +model_name_or_path=meta-llama/Llama-3.2-3B-Instruct dataset_path=data/alpaca/train_conversation +conversation_template=llama3 output_dir=output_models/finetune -deepspeed_args="--master_port=11000" -conversation_template=llama2 # Safety related arguments trust_remote_code=0 @@ -32,10 +27,6 @@ while [[ $# -ge 1 ]]; do conversation_template="$2" shift ;; - --deepspeed_args) - deepspeed_args="$2" - shift - ;; --trust_remote_code) trust_remote_code="$2" shift @@ -53,7 +44,7 @@ project_dir=$(cd "$(dirname $0)"/..; pwd) log_dir=${project_dir}/log/${exp_id} mkdir -p ${output_dir} ${log_dir} -deepspeed ${deepspeed_args} \ +accelerate launch --config_file configs/accelerate_fsdp_config.yaml \ examples/finetune.py \ --model_name_or_path ${model_name_or_path} \ --trust_remote_code ${trust_remote_code} \ @@ -65,14 +56,15 @@ deepspeed ${deepspeed_args} \ --disable_group_texts 1 \ --block_size 256 \ --per_device_train_batch_size 1 \ - --deepspeed configs/ds_config_zero3.json \ - --fp16 \ - --run_name finetune \ + --bf16 \ + --torch_dtype bfloat16 \ --validation_split_percentage 0 \ --logging_steps 20 \ --do_train \ --ddp_timeout 72000 \ --save_steps 5000 \ - --dataloader_num_workers 1 \ + --dataloader_num_workers 8 \ + --report_to wandb \ + --run_name ${exp_id} \ > >(tee ${log_dir}/train.log) \ 2> >(tee ${log_dir}/train.err >&2) diff --git a/scripts/run_finetune_with_lisa.sh b/scripts/run_finetune_with_lisa.sh index a7e2268dc..6aa095bd9 100755 --- a/scripts/run_finetune_with_lisa.sh +++ b/scripts/run_finetune_with_lisa.sh @@ -1,11 +1,8 @@ #!/bin/bash -# Please run this script under ${project_id} in project directory of -# https://github.com/shizhediao/llm-ft -# COMMIT: d5fecf30ba8011067b10cf51fede53a5ab6574e4 - # Parses arguments -model_name_or_path=meta-llama/Llama-2-7b-hf +model_name_or_path=meta-llama/Llama-3.2-3B-Instruct dataset_path=data/alpaca/train_conversation +conversation_template=llama3 output_dir=output_models/finetune_lisa lisa_activated_layers=1 lisa_interval_steps=20 @@ -16,19 +13,10 @@ use_flash_attention=0 gradient_accumulation_steps=1 block_size=256 per_device_train_batch_size=1 -conversation_template=llama2 # Safety related arguments trust_remote_code=0 -# Enable model parallelism for multiple gpus, modify this if you prefer -# customized deepspeed zero-redundancy optimization settings -num_gpu=$(python -c "import torch; print(torch.cuda.device_count())") -ds_config_file=configs/ds_config_zero0_no_offload.json -if [ ${num_gpu} -ge 2 ]; then - ds_config_file=configs/ds_config_zero2_no_offload.json -fi - while [[ $# -ge 1 ]]; do key="$1" case ${key} in @@ -56,10 +44,6 @@ while [[ $# -ge 1 ]]; do gradient_checkpointing="$2" shift ;; - --deepspeed) - ds_config_file="$2" - shift - ;; --use_flash_attention) use_flash_attention="$2" shift @@ -92,12 +76,13 @@ while [[ $# -ge 1 ]]; do done # Finetune -exp_id=finetune +exp_id=finetune_lisa project_dir=$(cd "$(dirname $0)"/..; pwd) log_dir=${project_dir}/log/${exp_id} mkdir -p ${output_dir} ${log_dir} -python examples/finetune.py \ +accelerate launch --config_file configs/accelerate_fsdp_config.yaml \ + examples/finetune.py \ --model_name_or_path ${model_name_or_path} \ --trust_remote_code ${trust_remote_code} \ --dataset_path ${dataset_path} \ @@ -110,19 +95,20 @@ python examples/finetune.py \ --per_device_train_batch_size ${per_device_train_batch_size} \ --bf16 \ --torch_dtype bfloat16 \ - --run_name finetune \ --optim paged_adamw_32bit \ --validation_split_percentage 0 \ --logging_steps 20 \ --do_train \ --ddp_timeout 72000 \ --save_steps 5000 \ - --dataloader_num_workers 1 \ + --dataloader_num_workers 8 \ --gradient_checkpointing ${gradient_checkpointing} \ --use_flash_attention ${use_flash_attention} \ --gradient_accumulation_steps ${gradient_accumulation_steps} \ --use_lisa 1 \ --lisa_activated_layers ${lisa_activated_layers} \ --lisa_interval_steps ${lisa_interval_steps} \ + --report_to wandb \ + --run_name ${exp_id} \ | tee ${log_dir}/train.log \ 2> ${log_dir}/train.err diff --git a/scripts/run_finetune_with_lora.sh b/scripts/run_finetune_with_lora.sh index c921ff744..c5d36540e 100755 --- a/scripts/run_finetune_with_lora.sh +++ b/scripts/run_finetune_with_lora.sh @@ -1,12 +1,9 @@ #!/bin/bash -# Please run this script under ${project_id} in project directory of - # Parses arguments -model_name_or_path=gpt2 +model_name_or_path=meta-llama/Llama-3.2-3B-Instruct dataset_path=data/alpaca/train_conversation -conversation_template=llama2 -output_dir=output_models/finetune -deepspeed_args="--master_port=11000" +conversation_template=llama3 +output_dir=output_models/finetune_lora # Safety related arguments trust_remote_code=0 @@ -30,10 +27,6 @@ while [[ $# -ge 1 ]]; do output_dir="$2" shift ;; - --deepspeed_args) - deepspeed_args="$2" - shift - ;; --trust_remote_code) trust_remote_code="$2" shift @@ -51,7 +44,7 @@ project_dir=$(cd "$(dirname $0)"/..; pwd) log_dir=${project_dir}/log/${exp_id} mkdir -p ${output_dir} ${log_dir} -deepspeed ${deepspeed_args} \ +accelerate launch --config_file configs/accelerate_fsdp_config.yaml \ examples/finetune.py \ --model_name_or_path ${model_name_or_path} \ --trust_remote_code ${trust_remote_code} \ @@ -59,20 +52,20 @@ deepspeed ${deepspeed_args} \ --conversation_template ${conversation_template} \ --output_dir ${output_dir} --overwrite_output_dir \ --num_train_epochs 0.01 \ - --learning_rate 1e-4 \ + --learning_rate 2e-5 \ --block_size 512 \ --per_device_train_batch_size 1 \ --use_lora 1 \ --lora_r 8 \ - --save_aggregated_lora 0\ - --deepspeed configs/ds_config_zero2.json \ - --fp16 \ - --run_name ${exp_id} \ + --bf16 \ + --torch_dtype bfloat16 \ --validation_split_percentage 0 \ --logging_steps 20 \ --do_train \ --ddp_timeout 72000 \ --save_steps 5000 \ - --dataloader_num_workers 1 \ + --dataloader_num_workers 8 \ + --report_to wandb \ + --run_name ${exp_id} \ | tee ${log_dir}/train.log \ 2> ${log_dir}/train.err diff --git a/scripts/run_finetune_with_qlora.sh b/scripts/run_finetune_with_qlora.sh index d1cfdf5aa..1f43144fc 100644 --- a/scripts/run_finetune_with_qlora.sh +++ b/scripts/run_finetune_with_qlora.sh @@ -1,12 +1,9 @@ #!/bin/bash -# Please run this script under ${project_id} in project directory of - # Parses arguments -model_name_or_path=meta-llama/Llama-2-13b-hf +model_name_or_path=meta-llama/Llama-3.2-3B-Instruct dataset_path=data/alpaca/train_conversation -conversation_template=llama2 -output_dir=output_models/finetune -deepspeed_args="--master_port=11000" +conversation_template=llama3 +output_dir=output_models/finetune_qlora # Safety related arguments trust_remote_code=0 @@ -30,10 +27,6 @@ while [[ $# -ge 1 ]]; do output_dir="$2" shift ;; - --deepspeed_args) - deepspeed_args="$2" - shift - ;; --trust_remote_code) trust_remote_code="$2" shift @@ -51,7 +44,7 @@ project_dir=$(cd "$(dirname $0)"/..; pwd) log_dir=${project_dir}/log/${exp_id} mkdir -p ${output_dir} ${log_dir} -deepspeed ${deepspeed_args} \ +accelerate launch --config_file configs/accelerate_fsdp_config.yaml \ examples/finetune.py \ --model_name_or_path ${model_name_or_path} \ --trust_remote_code ${trust_remote_code} \ @@ -59,19 +52,19 @@ deepspeed ${deepspeed_args} \ --conversation_template ${conversation_template} \ --output_dir ${output_dir} --overwrite_output_dir \ --num_train_epochs 0.01 \ - --learning_rate 1e-4 \ + --learning_rate 2e-5 \ --block_size 512 \ --per_device_train_batch_size 1 \ --use_qlora 1 \ - --save_aggregated_lora 0 \ - --deepspeed configs/ds_config_zero2.json \ - --fp16 \ - --run_name ${exp_id} \ + --bf16 \ + --torch_dtype bfloat16 \ --validation_split_percentage 0 \ --logging_steps 20 \ --do_train \ --ddp_timeout 72000 \ --save_steps 5000 \ - --dataloader_num_workers 1 \ + --dataloader_num_workers 8 \ + --report_to wandb \ + --run_name ${exp_id} \ | tee ${log_dir}/train.log \ 2> ${log_dir}/train.err \ No newline at end of file diff --git a/scripts/run_inference.sh b/scripts/run_inference.sh index 03fc60a94..3e89ac3e4 100755 --- a/scripts/run_inference.sh +++ b/scripts/run_inference.sh @@ -11,9 +11,8 @@ if [ $# -ge 2 ]; then lora_args="--lora_model_path $2" fi -accelerate launch --config_file configs/accelerator_multigpu_config.yaml \ +accelerate launch --config_file configs/accelerate_fsdp_config.yaml \ examples/inference.py \ - --deepspeed configs/ds_config_chatbot.json \ --model_name_or_path ${model} \ --max_new_tokens 256 \ --temperature 1.0 \ diff --git a/scripts/run_merge_lora.sh b/scripts/run_merge_lora.sh index d4a28ae91..5c6a3a388 100644 --- a/scripts/run_merge_lora.sh +++ b/scripts/run_merge_lora.sh @@ -1,14 +1,10 @@ #!/bin/bash - # Parses arguments model_name_or_path=gpt2 lora_model_path=output_models/lora output_model_path=output_models/merge_lora device=cpu -# if gpu -deepspeed_args="--master_port=11000" - while [[ $# -ge 1 ]]; do key="$1" case ${key} in @@ -28,10 +24,6 @@ while [[ $# -ge 1 ]]; do device="$2" shift ;; - --deepspeed_args) - deepspeed_args="$2" - shift - ;; *) echo "error: unknown option \"${key}\"" 1>&2 exit 1 @@ -46,7 +38,6 @@ if [ ${device} == "cpu" ]; then --lora_model_path ${lora_model_path} \ --output_model_path ${output_model_path} \ --device ${device} \ - --ds_config configs/ds_config_eval.json elif [ ${device} == "gpu" ]; then echo "Error: Merging LoRA weights using gpu not supported yet. Please use cpu." else diff --git a/scripts/run_raft_align.sh b/scripts/run_raft_align.sh index 9cb5a9717..1215d33cf 100755 --- a/scripts/run_raft_align.sh +++ b/scripts/run_raft_align.sh @@ -25,7 +25,7 @@ deepspeed ${deepspeed_args} \ --learning_rate 2e-5 \ --lr_scheduler_type "constant" \ --bf16 \ - --deepspeed configs/ds_config_zero2.json \ + --deepspeed configs/archive/ds_config_zero2.json \ --dataset_path ${project_dir}/data/hh_rlhf/rlhf_prompt \ --output_reward_path ${project_dir}/tmp/raft_aligner/reward.txt \ --output_dir ${output_dir} --overwrite_output_dir \ diff --git a/scripts/run_reward_modeling.sh b/scripts/run_reward_modeling.sh index 311384576..9b8c2b9d6 100644 --- a/scripts/run_reward_modeling.sh +++ b/scripts/run_reward_modeling.sh @@ -5,7 +5,6 @@ model_name_or_path=google/gemma-2b-it train_dataset_path=data/ultrafeedback-binarized-preferences-cleaned/train eval_dataset_path=data/ultrafeedback-binarized-preferences-cleaned/train output_dir=output_models/reward_modeling -deepspeed_args="--master_port=11345 --include localhost:6" conversation_template=gemma # Safety related arguments @@ -34,10 +33,6 @@ while [[ $# -ge 1 ]]; do conversation_template="$2" shift ;; - --deepspeed_args) - deepspeed_args="$2" - shift - ;; --trust_remote_code) trust_remote_code="$2" shift @@ -55,9 +50,8 @@ project_dir=$(cd "$(dirname $0)"/..; pwd) log_dir=${project_dir}/log/${exp_id} mkdir -p ${output_dir} ${log_dir} -deepspeed ${deepspeed_args} \ +accelerate launch --config_file configs/accelerate_fsdp_config.yaml \ examples/reward_modeling.py \ - --deepspeed configs/ds_config_zero3.json \ --model_name_or_path ${model_name_or_path} \ --arch_type "text_regression" \ --do_train True \ @@ -78,6 +72,7 @@ deepspeed ${deepspeed_args} \ --gradient_checkpointing True \ --remove_unused_columns False \ --bf16 True \ + --torch_dtype bfloat16 \ --logging_strategy "steps" \ --logging_steps 10 \ --optim "paged_adamw_32bit" \ diff --git a/scripts/run_reward_modeling_with_lisa.sh b/scripts/run_reward_modeling_with_lisa.sh index 64716259a..f3ad3ea2f 100644 --- a/scripts/run_reward_modeling_with_lisa.sh +++ b/scripts/run_reward_modeling_with_lisa.sh @@ -5,7 +5,6 @@ model_name_or_path=google/gemma-2b-it train_dataset_path=data/ultrafeedback-binarized-preferences-cleaned/train eval_dataset_path=data/ultrafeedback-binarized-preferences-cleaned/train output_dir=output_models/reward_modeling_lisa -deepspeed_args="--master_port=11345 --include localhost:6" conversation_template=gemma lisa_activated_layers=1 lisa_interval_steps=20 @@ -44,10 +43,6 @@ while [[ $# -ge 1 ]]; do conversation_template="$2" shift ;; - --deepspeed_args) - deepspeed_args="$2" - shift - ;; --trust_remote_code) trust_remote_code="$2" shift @@ -60,14 +55,13 @@ while [[ $# -ge 1 ]]; do done # Finetune -exp_id=reward_modeling +exp_id=reward_modeling_lisa project_dir=$(cd "$(dirname $0)"/..; pwd) log_dir=${project_dir}/log/${exp_id} mkdir -p ${output_dir} ${log_dir} -deepspeed ${deepspeed_args} \ +accelerate launch --config_file configs/accelerate_fsdp_config.yaml \ examples/reward_modeling.py \ - --deepspeed configs/ds_config_zero3.json \ --model_name_or_path ${model_name_or_path} \ --arch_type "text_regression" \ --do_train True \ @@ -88,6 +82,7 @@ deepspeed ${deepspeed_args} \ --gradient_checkpointing True \ --remove_unused_columns False \ --bf16 True \ + --torch_dtype bfloat16 \ --logging_strategy "steps" \ --logging_steps 10 \ --optim "paged_adamw_32bit" \ diff --git a/scripts/run_reward_modeling_with_lora.sh b/scripts/run_reward_modeling_with_lora.sh index 1afbd9784..f0fe44622 100644 --- a/scripts/run_reward_modeling_with_lora.sh +++ b/scripts/run_reward_modeling_with_lora.sh @@ -5,7 +5,6 @@ model_name_or_path=google/gemma-2b-it train_dataset_path=data/ultrafeedback-binarized-preferences-cleaned/train eval_dataset_path=data/ultrafeedback-binarized-preferences-cleaned/train output_dir=output_models/reward_modeling_lora -deepspeed_args="--master_port=11345 --include localhost:6" conversation_template=gemma # Safety related arguments @@ -34,10 +33,6 @@ while [[ $# -ge 1 ]]; do conversation_template="$2" shift ;; - --deepspeed_args) - deepspeed_args="$2" - shift - ;; --trust_remote_code) trust_remote_code="$2" shift @@ -50,14 +45,13 @@ while [[ $# -ge 1 ]]; do done # Finetune -exp_id=reward_modeling +exp_id=reward_modeling_lora project_dir=$(cd "$(dirname $0)"/..; pwd) log_dir=${project_dir}/log/${exp_id} mkdir -p ${output_dir} ${log_dir} -deepspeed ${deepspeed_args} \ +accelerate launch --config_file configs/accelerate_fsdp_config.yaml \ examples/reward_modeling.py \ - --deepspeed configs/ds_config_zero3.json \ --model_name_or_path ${model_name_or_path} \ --arch_type "text_regression" \ --do_train True \ @@ -78,6 +72,7 @@ deepspeed ${deepspeed_args} \ --gradient_checkpointing True \ --remove_unused_columns False \ --bf16 True \ + --torch_dtype bfloat16 \ --logging_strategy "steps" \ --logging_steps 10 \ --optim "paged_adamw_32bit" \ From f7ab42b825400c2fa89cf259770f23809f163d5d Mon Sep 17 00:00:00 2001 From: YizhenJia Date: Tue, 4 Mar 2025 14:37:09 +0800 Subject: [PATCH 03/61] change ruff target ver --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 723e5e1e2..7463c8ae1 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -3,7 +3,7 @@ requires = ["setuptools >= 64"] build-backend = "setuptools.build_meta" [tool.ruff] -target-version = "py39" +target-version = ["py39"] indent-width = 4 [tool.ruff.lint.isort] From 19586d1344206bb9b0be471ed6d96c696b4495f5 Mon Sep 17 00:00:00 2001 From: YizhenJia Date: Tue, 4 Mar 2025 15:29:12 +0800 Subject: [PATCH 04/61] separate lisa and custom optims --- src/lmflow/optim/__init__.py | 1 + src/lmflow/optim/utils.py | 206 ++++++++++++++++ src/lmflow/pipeline/finetuner.py | 272 +--------------------- src/lmflow/pipeline/utils/lisa_trainer.py | 66 ++++++ 4 files changed, 281 insertions(+), 264 deletions(-) create mode 100644 src/lmflow/optim/utils.py create mode 100644 src/lmflow/pipeline/utils/lisa_trainer.py diff --git a/src/lmflow/optim/__init__.py b/src/lmflow/optim/__init__.py index e69de29bb..f3bad7a3e 100644 --- a/src/lmflow/optim/__init__.py +++ b/src/lmflow/optim/__init__.py @@ -0,0 +1 @@ +from .utils import create_customized_optimizer \ No newline at end of file diff --git a/src/lmflow/optim/utils.py b/src/lmflow/optim/utils.py new file mode 100644 index 000000000..909c1ab72 --- /dev/null +++ b/src/lmflow/optim/utils.py @@ -0,0 +1,206 @@ +from typing import Optional, Any, Tuple + +from transformers import PreTrainedModel +from transformers.utils import is_sagemaker_mp_enabled + +import lmflow.optim.optimizers as optim +from lmflow.args import OptimizerNames, TrainingArguments + +def create_customized_optimizer(self, base_trainer_class, model_args): + class CustomizedOptimTrainer(base_trainer_class): + + @staticmethod + def get_optimizer_cls_and_kwargs( + args: TrainingArguments, + model: Optional[PreTrainedModel] = None, + ) -> Tuple[Any, Any]: + # parse args.optim_args + optim_args = {} + if args.customized_optim_args: + for mapping in args.customized_optim_args.replace(" ", "").split(","): + key, value = mapping.split("=") + optim_args[key] = value + + optimizer_kwargs = {"lr": args.learning_rate} + + if args.customized_optim == OptimizerNames.DUMMY: + optimizer_cls = optim.Dummy + dummy_kwargs = { + "betas": (args.optim_dummy_beta1, args.optim_dummy_beta2), + } + optimizer_kwargs.update(dummy_kwargs) + elif args.customized_optim == OptimizerNames.ADABELIEF: + optimizer_cls = optim.AdaBelief + adabelief_kwargs = { + "betas": (args.optim_beta1, args.optim_beta2), + "weight_decay": (args.optim_weight_decay) + } + optimizer_kwargs.update(adabelief_kwargs) + elif args.customized_optim == OptimizerNames.ADABOUND: + optimizer_cls = optim.AdaBound + adabound_kwargs = { + "betas": (args.optim_beta1, args.optim_beta2), + "weight_decay": (args.optim_weight_decay) + } + optimizer_kwargs.update(adabound_kwargs) + elif args.customized_optim == OptimizerNames.LARS: + optimizer_cls = optim.LARS + lars_kwargs = { + "momentum": (args.optim_momentum), + "weight_decay": (args.optim_weight_decay), + } + optimizer_kwargs.update(lars_kwargs) + elif args.customized_optim == OptimizerNames.LAMB: + optimizer_cls = optim.Lamb + lamb_kwargs = { + "betas": (args.optim_beta1, args.optim_beta2), + "weight_decay": (args.optim_weight_decay), + } + optimizer_kwargs.update(lamb_kwargs) + elif args.customized_optim == OptimizerNames.ADAMAX: + optimizer_cls = optim.Adamax + adamax_kwargs = { + "betas": (args.optim_beta1, args.optim_beta2), + "weight_decay": (args.optim_weight_decay), + } + optimizer_kwargs.update(adamax_kwargs) + elif args.customized_optim == OptimizerNames.NADAM: + optimizer_cls = optim.NAdam + nadam_kwargs = { + "betas": (args.optim_beta1, args.optim_beta2), + "weight_decay": (args.optim_weight_decay), + } + optimizer_kwargs.update(nadam_kwargs) + elif args.customized_optim == OptimizerNames.RADAM: + optimizer_cls = optim.RAdam + radam_kwargs = { + "betas": (args.optim_beta1, args.optim_beta2), + "weight_decay": (args.optim_weight_decay), + } + optimizer_kwargs.update(radam_kwargs) + elif args.customized_optim == OptimizerNames.ADAMP: + optimizer_cls = optim.AdamP + adamp_kwargs = { + "betas": (args.optim_beta1, args.optim_beta2), + "weight_decay": (args.optim_weight_decay), + } + optimizer_kwargs.update(adamp_kwargs) + elif args.customized_optim == OptimizerNames.SGDP: + optimizer_cls = optim.SGDP + sgdp_kwargs = { + "momentum": (args.optim_momentum), + "weight_decay": (args.optim_weight_decay), + } + optimizer_kwargs.update(sgdp_kwargs) + elif args.customized_optim == OptimizerNames.YOGI: + optimizer_cls = optim.Yogi + yogi_kwargs = { + "betas": (args.optim_beta1, args.optim_beta2), + "weight_decay": (args.optim_weight_decay), + } + optimizer_kwargs.update(yogi_kwargs) + elif args.customized_optim == OptimizerNames.SOPHIA: + optimizer_cls = optim.SophiaG + sophia_kwargs = { + "betas": (args.optim_beta1, args.optim_beta2), + "weight_decay": (args.optim_weight_decay), + } + optimizer_kwargs.update(sophia_kwargs) + elif args.customized_optim == OptimizerNames.ADAM: + optimizer_cls = optim.Adam + adam_kwargs = { + "betas": (args.optim_beta1, args.optim_beta2), + } + optimizer_kwargs.update(adam_kwargs) + elif args.customized_optim == OptimizerNames.NOVOGRAD: + optimizer_cls = optim.NovoGrad + novograd_kwargs = { + "betas": (args.optim_beta1, args.optim_beta2), + "weight_decay": (args.optim_weight_decay), + } + optimizer_kwargs.update(novograd_kwargs) + elif args.customized_optim == OptimizerNames.ADADELTA: + optimizer_cls = optim.Adadelta + adadelta_kwargs = { + } + optimizer_kwargs.update(adadelta_kwargs) + elif args.customized_optim == OptimizerNames.ADAGRAD: + optimizer_cls = optim.AdaGrad + adagrad_kwargs = { + } + optimizer_kwargs.update(adagrad_kwargs) + elif args.customized_optim == OptimizerNames.ADAMW_SCHEDULE_FREE: + optimizer_cls = optim.AdamWScheduleFree + adamw_schedule_free_kwargs = { + "betas": (args.optim_beta1, args.optim_beta2), + "weight_decay": (args.optim_weight_decay), + } + optimizer_kwargs.update(adamw_schedule_free_kwargs) + elif args.customized_optim == OptimizerNames.SGD_SCHEDULE_FREE: + optimizer_cls = optim.SGDScheduleFree + sgd_schedule_free_kwargs = { + "momentum": (args.optim_momentum), + "weight_decay": (args.optim_weight_decay), + } + optimizer_kwargs.update(sgd_schedule_free_kwargs) + elif args.customized_optim == OptimizerNames.ADAN: + optimizer_cls = optim.Adan + adan_kwargs = { + "betas": (args.optim_beta1, args.optim_beta2, args.optim_beta3), + "weight_decay": (args.optim_weight_decay), + } + optimizer_kwargs.update(adan_kwargs) + else: + raise ValueError( + f"Trainer cannot instantiate unsupported optimizer: " + f" {args.customized_optim}" + ) + return optimizer_cls, optimizer_kwargs + + def create_optimizer(self): + opt_model = self.model_wrapped if is_sagemaker_mp_enabled() else self.model + + if self.optimizer is None: + decay_parameters = self.get_decay_parameter_names(opt_model) + optimizer_grouped_parameters = [ + { + "params": [ + p for n, p in opt_model.named_parameters() + if (n in decay_parameters and p.requires_grad) + ], + "weight_decay": self.args.weight_decay, + }, + { + "params": [ + p for n, p in opt_model.named_parameters() + if (n not in decay_parameters and p.requires_grad) + ], + "weight_decay": 0.0, + }, + ] + + optimizer_cls, optimizer_kwargs = CustomizedOptimTrainer.get_optimizer_cls_and_kwargs(self.args, opt_model) + + # Overwrite `params` in case it's created by + # `get_optimizer_cls_and_kwargs` e.g. for GaLore optimizer. + if "params" in optimizer_kwargs: + optimizer_grouped_parameters = optimizer_kwargs.pop( + "params" + ) + + # For layer-wise dummy optimizers we overwrite + # optimizer_grouped_parameters with `optimizer_dict` to + # avoid arguments conflicts. + if "optimizer_dict" in optimizer_kwargs: + optimizer_grouped_parameters = optimizer_kwargs.pop( + "optimizer_dict" + ) + + self.optimizer = optimizer_cls( + optimizer_grouped_parameters, + **optimizer_kwargs + ) + if is_sagemaker_mp_enabled(): + self.optimizer = smp.DistributedOptimizer(self.optimizer) + + return CustomizedOptimTrainer \ No newline at end of file diff --git a/src/lmflow/pipeline/finetuner.py b/src/lmflow/pipeline/finetuner.py index 2d132d0ee..c57567f33 100644 --- a/src/lmflow/pipeline/finetuner.py +++ b/src/lmflow/pipeline/finetuner.py @@ -7,11 +7,10 @@ import logging import os import sys -from typing import Any, Iterable, Optional, Tuple, Union +from typing import Union import datasets import evaluate -import numpy as np import transformers from copy import deepcopy from itertools import chain @@ -20,26 +19,20 @@ default_data_collator, set_seed, ) -from transformers import PreTrainedModel, TrainingArguments from transformers.trainer_utils import get_last_checkpoint -from transformers.trainer_callback import ( - TrainerCallback, - TrainerControl, - TrainerState, -) from transformers.utils import ( - is_sagemaker_mp_enabled, send_example_telemetry, ) -import lmflow.optim.optimizers as optim -from lmflow.args import OptimizerNames, DatasetArguments, ModelArguments, FinetunerArguments +from lmflow.args import DatasetArguments, ModelArguments, FinetunerArguments from lmflow.datasets.dataset import Dataset from lmflow.models.hf_decoder_model import HFDecoderModel from lmflow.models.hf_encoder_decoder_model import HFEncoderDecoderModel from lmflow.models.hf_text_regression_model import HFTextRegressionModel +from lmflow.optim import create_customized_optimizer from lmflow.pipeline.base_tuner import BaseTuner from lmflow.pipeline.utils.peft_trainer import PeftTrainer, PeftSavingCallback +from lmflow.pipeline.utils.lisa_trainer import DynamicLayerActivationCallback logger = logging.getLogger(__name__) @@ -221,204 +214,6 @@ def group_texts(examples): return lm_datasets - def create_customized_optimizer(self, base_trainer_class, model_args): - class CustomizedOptimTrainer(base_trainer_class): - - @staticmethod - def get_optimizer_cls_and_kwargs( - args: TrainingArguments, - model: Optional[PreTrainedModel] = None, - ) -> Tuple[Any, Any]: - # parse args.optim_args - optim_args = {} - if args.customized_optim_args: - for mapping in args.customized_optim_args.replace(" ", "").split(","): - key, value = mapping.split("=") - optim_args[key] = value - - optimizer_kwargs = {"lr": args.learning_rate} - - if args.customized_optim == OptimizerNames.DUMMY: - optimizer_cls = optim.Dummy - dummy_kwargs = { - "betas": (args.optim_dummy_beta1, args.optim_dummy_beta2), - } - optimizer_kwargs.update(dummy_kwargs) - elif args.customized_optim == OptimizerNames.ADABELIEF: - optimizer_cls = optim.AdaBelief - adabelief_kwargs = { - "betas": (args.optim_beta1, args.optim_beta2), - "weight_decay": (args.optim_weight_decay) - } - optimizer_kwargs.update(adabelief_kwargs) - elif args.customized_optim == OptimizerNames.ADABOUND: - optimizer_cls = optim.AdaBound - adabound_kwargs = { - "betas": (args.optim_beta1, args.optim_beta2), - "weight_decay": (args.optim_weight_decay) - } - optimizer_kwargs.update(adabound_kwargs) - elif args.customized_optim == OptimizerNames.LARS: - optimizer_cls = optim.LARS - lars_kwargs = { - "momentum": (args.optim_momentum), - "weight_decay": (args.optim_weight_decay), - } - optimizer_kwargs.update(lars_kwargs) - elif args.customized_optim == OptimizerNames.LAMB: - optimizer_cls = optim.Lamb - lamb_kwargs = { - "betas": (args.optim_beta1, args.optim_beta2), - "weight_decay": (args.optim_weight_decay), - } - optimizer_kwargs.update(lamb_kwargs) - elif args.customized_optim == OptimizerNames.ADAMAX: - optimizer_cls = optim.Adamax - adamax_kwargs = { - "betas": (args.optim_beta1, args.optim_beta2), - "weight_decay": (args.optim_weight_decay), - } - optimizer_kwargs.update(adamax_kwargs) - elif args.customized_optim == OptimizerNames.NADAM: - optimizer_cls = optim.NAdam - nadam_kwargs = { - "betas": (args.optim_beta1, args.optim_beta2), - "weight_decay": (args.optim_weight_decay), - } - optimizer_kwargs.update(nadam_kwargs) - elif args.customized_optim == OptimizerNames.RADAM: - optimizer_cls = optim.RAdam - radam_kwargs = { - "betas": (args.optim_beta1, args.optim_beta2), - "weight_decay": (args.optim_weight_decay), - } - optimizer_kwargs.update(radam_kwargs) - elif args.customized_optim == OptimizerNames.ADAMP: - optimizer_cls = optim.AdamP - adamp_kwargs = { - "betas": (args.optim_beta1, args.optim_beta2), - "weight_decay": (args.optim_weight_decay), - } - optimizer_kwargs.update(adamp_kwargs) - elif args.customized_optim == OptimizerNames.SGDP: - optimizer_cls = optim.SGDP - sgdp_kwargs = { - "momentum": (args.optim_momentum), - "weight_decay": (args.optim_weight_decay), - } - optimizer_kwargs.update(sgdp_kwargs) - elif args.customized_optim == OptimizerNames.YOGI: - optimizer_cls = optim.Yogi - yogi_kwargs = { - "betas": (args.optim_beta1, args.optim_beta2), - "weight_decay": (args.optim_weight_decay), - } - optimizer_kwargs.update(yogi_kwargs) - elif args.customized_optim == OptimizerNames.SOPHIA: - optimizer_cls = optim.SophiaG - sophia_kwargs = { - "betas": (args.optim_beta1, args.optim_beta2), - "weight_decay": (args.optim_weight_decay), - } - optimizer_kwargs.update(sophia_kwargs) - elif args.customized_optim == OptimizerNames.ADAM: - optimizer_cls = optim.Adam - adam_kwargs = { - "betas": (args.optim_beta1, args.optim_beta2), - } - optimizer_kwargs.update(adam_kwargs) - elif args.customized_optim == OptimizerNames.NOVOGRAD: - optimizer_cls = optim.NovoGrad - novograd_kwargs = { - "betas": (args.optim_beta1, args.optim_beta2), - "weight_decay": (args.optim_weight_decay), - } - optimizer_kwargs.update(novograd_kwargs) - elif args.customized_optim == OptimizerNames.ADADELTA: - optimizer_cls = optim.Adadelta - adadelta_kwargs = { - } - optimizer_kwargs.update(adadelta_kwargs) - elif args.customized_optim == OptimizerNames.ADAGRAD: - optimizer_cls = optim.AdaGrad - adagrad_kwargs = { - } - optimizer_kwargs.update(adagrad_kwargs) - elif args.customized_optim == OptimizerNames.ADAMW_SCHEDULE_FREE: - optimizer_cls = optim.AdamWScheduleFree - adamw_schedule_free_kwargs = { - "betas": (args.optim_beta1, args.optim_beta2), - "weight_decay": (args.optim_weight_decay), - } - optimizer_kwargs.update(adamw_schedule_free_kwargs) - elif args.customized_optim == OptimizerNames.SGD_SCHEDULE_FREE: - optimizer_cls = optim.SGDScheduleFree - sgd_schedule_free_kwargs = { - "momentum": (args.optim_momentum), - "weight_decay": (args.optim_weight_decay), - } - optimizer_kwargs.update(sgd_schedule_free_kwargs) - elif args.customized_optim == OptimizerNames.ADAN: - optimizer_cls = optim.Adan - adan_kwargs = { - "betas": (args.optim_beta1, args.optim_beta2, args.optim_beta3), - "weight_decay": (args.optim_weight_decay), - } - optimizer_kwargs.update(adan_kwargs) - else: - raise ValueError( - f"Trainer cannot instantiate unsupported optimizer: " - f" {args.customized_optim}" - ) - return optimizer_cls, optimizer_kwargs - - def create_optimizer(self): - opt_model = self.model_wrapped if is_sagemaker_mp_enabled() else self.model - - if self.optimizer is None: - decay_parameters = self.get_decay_parameter_names(opt_model) - optimizer_grouped_parameters = [ - { - "params": [ - p for n, p in opt_model.named_parameters() - if (n in decay_parameters and p.requires_grad) - ], - "weight_decay": self.args.weight_decay, - }, - { - "params": [ - p for n, p in opt_model.named_parameters() - if (n not in decay_parameters and p.requires_grad) - ], - "weight_decay": 0.0, - }, - ] - - optimizer_cls, optimizer_kwargs = CustomizedOptimTrainer.get_optimizer_cls_and_kwargs(self.args, opt_model) - - # Overwrite `params` in case it's created by - # `get_optimizer_cls_and_kwargs` e.g. for GaLore optimizer. - if "params" in optimizer_kwargs: - optimizer_grouped_parameters = optimizer_kwargs.pop( - "params" - ) - - # For layer-wise dummy optimizers we overwrite - # optimizer_grouped_parameters with `optimizer_dict` to - # avoid arguments conflicts. - if "optimizer_dict" in optimizer_kwargs: - optimizer_grouped_parameters = optimizer_kwargs.pop( - "optimizer_dict" - ) - - self.optimizer = optimizer_cls( - optimizer_grouped_parameters, - **optimizer_kwargs - ) - if is_sagemaker_mp_enabled(): - self.optimizer = smp.DistributedOptimizer(self.optimizer) - - return CustomizedOptimTrainer def tune(self, model: Union[HFDecoderModel, HFTextRegressionModel, HFEncoderDecoderModel], @@ -509,74 +304,23 @@ def compute_metrics(eval_preds): else: FinetuningTrainer = Trainer trainer_callbacks = [] + if data_collator is None: data_collator = default_data_collator if training_args.use_customized_optim: BaseTrainer = FinetuningTrainer - FinetuningTrainer = self.create_customized_optimizer( + FinetuningTrainer = create_customized_optimizer( BaseTrainer, model_args ) if training_args.use_lisa: - class DynamicLayerActivationCallback(TrainerCallback): - def __init__(self, n_layers, interval_steps, model): - super().__init__() - self.n_layers = n_layers - self.interval_steps = interval_steps - self.model = model - - # Determine the way to access layers based on the model type - class_to_layers_map = { - 'LlamaForCausalLM': 'model.model.layers', - 'Qwen2ForCausalLM': 'model.model.layers', - 'MistralForCausalLM': 'model.model.layers', - 'MixtralForCausalLM': 'model.model.layers', - 'GemmaForCausalLM': 'model.model.layers', - 'GPT2LMHeadModel': 'model.transformer.h', - 'HymbaForCausalLM': 'model.model.layers', - } - model_class_name = self.model.__class__.__name__ - if model_class_name in class_to_layers_map: - self.layers_attribute = class_to_layers_map[model_class_name] - else: - self.layers_attribute = training_args.lisa_layers_attribute - self.total_layers = len(eval('self.' + self.layers_attribute)) # Dynamically execute to get the number of layers - - self.active_layers_indices = [] - - def freeze_all_layers(self): - layers = eval('self.' + self.layers_attribute) # Dynamically execute to get layers - for layer in layers: - for param in layer.parameters(): - param.requires_grad = False - - def on_step_begin(self, args, state, control, **kwargs): - # Check if it's time to switch active layers, including at step 0 - if state.global_step % self.interval_steps == 0: - self.switch_active_layers() - - def switch_active_layers(self): - # First, disable gradients for all layers - self.freeze_all_layers() - - # Randomly select n_layers to activate - layers = eval('self.' + self.layers_attribute) # Re-fetch layer references - self.active_layers_indices = np.random.choice(range(self.total_layers), self.n_layers, replace=False) - print(f"Activating layers at indices: {self.active_layers_indices} for the next steps.", flush=True) - - # Enable gradients only for the selected layers - for idx in self.active_layers_indices: - for param in layers[idx].parameters(): - param.requires_grad = True - - # Instantiate the callback dynamic_layer_activation_callback = DynamicLayerActivationCallback( n_layers=training_args.lisa_activated_layers, # Number of layers to activate interval_steps=training_args.lisa_interval_steps, # Step interval to update active layers - model=model.get_backend_model() + model=model.get_backend_model(), + lisa_layers_attribute=training_args.lisa_layers_attribute, # Attribute to access layers of the model ) - trainer_callbacks.append(dynamic_layer_activation_callback) trainer = FinetuningTrainer( diff --git a/src/lmflow/pipeline/utils/lisa_trainer.py b/src/lmflow/pipeline/utils/lisa_trainer.py new file mode 100644 index 000000000..533e2beaf --- /dev/null +++ b/src/lmflow/pipeline/utils/lisa_trainer.py @@ -0,0 +1,66 @@ +from typing import Optional + +import numpy as np +from transformers import PreTrainedModel +from transformers.trainer_callback import TrainerCallback + + +class DynamicLayerActivationCallback(TrainerCallback): + def __init__( + self, + n_layers: int, + interval_steps: int, + model: PreTrainedModel, + lisa_layers_attribute: Optional[str] = None, + ): + super().__init__() + self.n_layers = n_layers + self.interval_steps = interval_steps + self.model = model + + # Determine the way to access layers based on the model type + class_to_layers_map = { + 'LlamaForCausalLM': 'model.model.layers', + 'Qwen2ForCausalLM': 'model.model.layers', + 'MistralForCausalLM': 'model.model.layers', + 'MixtralForCausalLM': 'model.model.layers', + 'GemmaForCausalLM': 'model.model.layers', + 'GPT2LMHeadModel': 'model.transformer.h', + 'HymbaForCausalLM': 'model.model.layers', + } + model_class_name = self.model.__class__.__name__ + if model_class_name in class_to_layers_map: + self.layers_attribute = class_to_layers_map[model_class_name] + else: + assert lisa_layers_attribute is not None, ( + "Please provide the attribute to access the layers of the model." + ) + self.layers_attribute = lisa_layers_attribute + self.total_layers = len(eval('self.' + self.layers_attribute)) # Dynamically execute to get the number of layers + + self.active_layers_indices = [] + + def freeze_all_layers(self): + layers = eval('self.' + self.layers_attribute) # Dynamically execute to get layers + for layer in layers: + for param in layer.parameters(): + param.requires_grad = False + + def on_step_begin(self, args, state, control, **kwargs): + # Check if it's time to switch active layers, including at step 0 + if state.global_step % self.interval_steps == 0: + self.switch_active_layers() + + def switch_active_layers(self): + # First, disable gradients for all layers + self.freeze_all_layers() + + # Randomly select n_layers to activate + layers = eval('self.' + self.layers_attribute) # Re-fetch layer references + self.active_layers_indices = np.random.choice(range(self.total_layers), self.n_layers, replace=False) + print(f"Activating layers at indices: {self.active_layers_indices} for the next steps.", flush=True) + + # Enable gradients only for the selected layers + for idx in self.active_layers_indices: + for param in layers[idx].parameters(): + param.requires_grad = True \ No newline at end of file From e12e25a6c2b507e54f054c329c1889d03a232823 Mon Sep 17 00:00:00 2001 From: YizhenJia Date: Tue, 4 Mar 2025 15:40:23 +0800 Subject: [PATCH 05/61] add decorator for base methods --- src/lmflow/pipeline/base_aligner.py | 2 ++ src/lmflow/pipeline/base_tuner.py | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/lmflow/pipeline/base_aligner.py b/src/lmflow/pipeline/base_aligner.py index c2a640a5d..128fa0036 100644 --- a/src/lmflow/pipeline/base_aligner.py +++ b/src/lmflow/pipeline/base_aligner.py @@ -2,6 +2,7 @@ # coding=utf-8 """ BaseTuner: a subclass of BasePipeline. """ +from abc import abstractmethod from lmflow.pipeline.base_pipeline import BasePipeline @@ -17,5 +18,6 @@ def _check_if_alignable(self, model, dataset, reward_model): # TODO: add reward_model pass + @abstractmethod def align(self, model, dataset, reward_model): raise NotImplementedError(".align is not implemented") diff --git a/src/lmflow/pipeline/base_tuner.py b/src/lmflow/pipeline/base_tuner.py index d73340d8f..754ae09b5 100644 --- a/src/lmflow/pipeline/base_tuner.py +++ b/src/lmflow/pipeline/base_tuner.py @@ -2,6 +2,7 @@ # coding=utf-8 """ BaseTuner: a subclass of BasePipeline. """ +from abc import abstractmethod from lmflow.pipeline.base_pipeline import BasePipeline @@ -16,5 +17,6 @@ def _check_if_tunable(self, model, dataset): # TODO: check if the model is tunable and dataset is compatible pass + @abstractmethod def tune(self, model, dataset): raise NotImplementedError(".tune is not implemented") From edc923610003e6f960378eed9415de167d3a8d18 Mon Sep 17 00:00:00 2001 From: YizhenJia Date: Tue, 4 Mar 2025 15:59:15 +0800 Subject: [PATCH 06/61] encoder_decoder model temporarily disabled --- src/lmflow/args.py | 5 + src/lmflow/models/auto_model.py | 8 +- src/lmflow/models/hf_encoder_decoder_model.py | 522 ------------------ src/lmflow/pipeline/finetuner.py | 4 +- tests/models/test_auto_model.py | 2 +- 5 files changed, 12 insertions(+), 529 deletions(-) delete mode 100644 src/lmflow/models/hf_encoder_decoder_model.py diff --git a/src/lmflow/args.py b/src/lmflow/args.py index 22425e2bf..312a02725 100644 --- a/src/lmflow/args.py +++ b/src/lmflow/args.py @@ -367,6 +367,11 @@ def __post_init__(self): if self.lora_target_modules is not None: self.lora_target_modules: List[str] = split_args(self.lora_target_modules) + + if "encoder_decoder" in self.arch_type: + raise NotImplementedError( + "The encoder-decoder model is not fully implemented yet." + ) @dataclass diff --git a/src/lmflow/models/auto_model.py b/src/lmflow/models/auto_model.py index c21790f57..a2466aa04 100644 --- a/src/lmflow/models/auto_model.py +++ b/src/lmflow/models/auto_model.py @@ -5,7 +5,7 @@ from lmflow.models.hf_decoder_model import HFDecoderModel from lmflow.models.hf_text_regression_model import HFTextRegressionModel -from lmflow.models.hf_encoder_decoder_model import HFEncoderDecoderModel +# from lmflow.models.hf_encoder_decoder_model import HFEncoderDecoderModel class AutoModel: @@ -16,9 +16,9 @@ def get_model(self, model_args, *args, **kwargs): return HFDecoderModel(model_args, *args, **kwargs) elif arch_type == "text_regression": return HFTextRegressionModel(model_args, *args, **kwargs) - elif arch_type == "encoder_decoder" or \ - arch_type == "vision_encoder_decoder": - return HFEncoderDecoderModel(model_args, *args, **kwargs) + # elif arch_type == "encoder_decoder" or \ + # arch_type == "vision_encoder_decoder": + # return HFEncoderDecoderModel(model_args, *args, **kwargs) else: raise NotImplementedError( f"model architecture type \"{arch_type}\" is not supported" diff --git a/src/lmflow/models/hf_encoder_decoder_model.py b/src/lmflow/models/hf_encoder_decoder_model.py deleted file mode 100644 index 6eb6ff2f7..000000000 --- a/src/lmflow/models/hf_encoder_decoder_model.py +++ /dev/null @@ -1,522 +0,0 @@ -#!/usr/bin/env python -# coding=utf-8 -"""This is a class called HFDecoderModel which is a wrapper around transformers model and -tokenizer classes. It has several methods such as __init__, tokenize, and train that are -used for training and fine-tuning the model. The __init__ method takes in several arguments -such as model_args, tune_strategy, and ds_config, which are used to load the pretrained -model and tokenizer, and initialize the training settings. - -The tokenize method is used to tokenize the input text and return the input IDs and attention -masks that can be fed to the model for training or inference. - -This class supports different tune_strategy options such as 'normal', 'none', 'lora', and -'adapter', which allow for different fine-tuning settings of the model. However, the 'lora' -and 'adapter' strategies are not yet implemented. - -Overall, this class provides a convenient interface for loading and fine-tuning transformer -models and can be used for various NLP tasks such as language modeling, text classification, -and question answering. -""" - -import copy -import logging -import time -from typing import List, Union - -import deepspeed -import torch -from peft import ( - LoraConfig, - PeftModel, - TaskType, - get_peft_config, - get_peft_model, -) -from transformers import ( - CONFIG_MAPPING, - AutoConfig, - AutoTokenizer, - AutoModelForSeq2SeqLM, - AutoModelForVision2Seq, - AutoModel, - AutoProcessor, - LlamaConfig -) -from transformers.testing_utils import CaptureLogger - -from lmflow.datasets.dataset import Dataset -from lmflow.models.encoder_decoder_model import EncoderDecoderModel -from lmflow.models.interfaces.tunable import Tunable -from lmflow.models.vision2seq_model import CustomAutoVision2SeqModel -from lmflow.utils.multimodal import update_custom_config, load_llava_pretrain_model -from lmflow.utils.versioning import is_package_version_at_least - -if is_package_version_at_least("transformers", "4.46.0"): - from transformers.integrations.deepspeed import HfDeepSpeedConfig, HfTrainerDeepSpeedConfig -else: - from transformers.deepspeed import HfDeepSpeedConfig, HfTrainerDeepSpeedConfig - - -logger = logging.getLogger(__name__) - - -class HFEncoderDecoderModel(EncoderDecoderModel, Tunable): - r""" - Initializes a HFEncoderDecoderModel instance. - - Parameters - ------------ - - model_args : - Model arguments such as model name, path, revision, etc. - - tune_strategy : str or none, default="normal". - A string representing the dataset backend. Defaults to "huggingface". - - ds_config : - Deepspeed configuations. - - args : Optional. - Positional arguments. - - kwargs : Optional. - Keyword arguments. - """ - - def __init__( - self, - model_args, - tune_strategy='normal', - ds_config=None, - device="gpu", - use_accelerator=False, - custom_model=False, - with_deepspeed=True, - pipeline_args=None, - *args, - **kwargs - ): - """ - Initializes a HFDecoderModel instance. - :param model_args: dictionary with model arguments such as model name, path, revision, etc. - :param tune_strategy: tuning strategy: normal, none, lora or adapter - :param ds_config: deepspeed configuration for distributed training - """ - - # See more about loading any type of standard or custom dataset (from - # files, python dict, pandas DataFrame, etc) at - # https://huggingface.co/docs/datasets/loading_datasets.html. - - # Load pretrained model and tokenizer - # - # Distributed training: The .from_pretrained methods guarantee that - # only one local process can concurrently download model & vocab. - - self.device = device - - if tune_strategy == 'normal': - raise NotImplementedError( - f"tune_strategy \"{tune_strategy}\" is not supported" - ) - elif tune_strategy == 'none': - if use_accelerator: - raise NotImplementedError( - f"Currently encoder2decoder model is not supported with accelerator" - ) - # dschf = HfDeepSpeedConfig(ds_config) - dschf = HfTrainerDeepSpeedConfig(ds_config) - if pipeline_args is not None: - dschf.trainer_config_process(pipeline_args) - peft_model_id = model_args.lora_model_path - # NOTE: Currently offload is not supported by llama - if "llama" in model_args.model_name_or_path and model_args.use_ram_optimized_load: - logger.warning( - "llama does not support RAM optimized load. Automatically" - " use original load instead." - ) - model_args.use_ram_optimized_load = False - - # get model register - self.arch_type = model_args.arch_type - if self.arch_type == "encoder_decoder": - if model_args.model_name_or_path == 'THUDM/chatglm-6b': - model_register = AutoModel - else: - model_register = AutoModelForSeq2SeqLM - elif self.arch_type == "vision_encoder_decoder": - if not custom_model: - model_register = AutoModelForVision2Seq - else: - model_register = CustomAutoVision2SeqModel - else: - raise NotImplementedError - if not custom_model: - if model_args.model_name_or_path == 'THUDM/chatglm-6b': - self.backend_model = model_register.from_pretrained(model_args.model_name_or_path, trust_remote_code=True) - - elif model_args.use_ram_optimized_load and peft_model_id is None: - try: - # RAM-optimized load - self.backend_model = model_register.from_pretrained( - model_args.model_name_or_path, - device_map="auto", - offload_folder="offload", - offload_state_dict=True, - ) - except: - logger.warning( - "Failed to use RAM optimized load. Automatically" - " use original load instead." - ) - # Normal load - self.backend_model = model_register.from_pretrained( - model_args.model_name_or_path, - ) - else: - if peft_model_id is not None: - logger.warning( - "LoRA does not support RAM optimized load currently." - " Automatically use original load instead." - ) - self.backend_model = model_register.from_pretrained( - model_args.model_name_or_path, - ) - # else: - # self.backend_model = model_register.from_pretrained( - # model_args.model_name_or_path) - else: - if model_args.llava_loading is False: - # FIXME remove the following from_pretrained code by - # creating a unified pretrained model. - model = CustomAutoVision2SeqModel.from_pretrained(model_args.model_name_or_path) - if model_args.llm_model_name_or_path is not None: - text_config = LlamaConfig.from_pretrained(model_args.llm_model_name_or_path) - model.config.text_config = text_config - model.language_model_from_pretrained(model_args.llm_model_name_or_path, - low_resource=model_args.low_resource) - state_dict = torch.load( - model_args.pretrained_language_projection_path, - map_location="cpu") - model.load_state_dict(state_dict, strict=False) - else: - config = AutoConfig.from_pretrained( - model_args.model_name_or_path) - if model_args.low_resource: - kwargs = dict( - torch_dtype=torch.float16, - load_in_8bit=True, - device_map="auto", - ) - else: - # kwargs = dict(torch_dtype=torch.float16) - kwargs = dict(device_map="auto") - if (model_args.image_encoder_name_or_path is None and - model_args.qformer_name_or_path is None and - model_args.llm_model_name_or_path is None): - config = AutoConfig.from_pretrained( - model_args.model_name_or_path) - model = CustomAutoVision2SeqModel.from_pretrained( - model_args.model_name_or_path, **kwargs) - else: - config = update_custom_config(config, model_args) - model = CustomAutoVision2SeqModel( - config, - image_encoder_name_or_path=model_args.image_encoder_name_or_path, - qformer_name_or_path=model_args.qformer_name_or_path, - language_model_name_or_path=model_args.llm_model_name_or_path, - low_resource=model_args.low_resource) - if model_args.pretrained_language_projection_path is not None: - state_dict = torch.load( - model_args.pretrained_language_projection_path, map_location="cpu") - new_state_dict = {} - new_state_dict['model.language_projection.weight'] = \ - state_dict['model.mm_projector.weight'] - new_state_dict['model.language_projection.bias'] = \ - state_dict['model.mm_projector.bias'] - if model_args.llava_pretrain_model_path is not None: - # used for inference that directly load the preatrain model - model = load_llava_pretrain_model( - model, model_args.llava_pretrain_model_path) - if model_args.save_pretrain_model_path is not None: - model.save_pretrained( - model_args.save_pretrain_model_path) - self.backend_model = model - # init tokenizer - if self.arch_type == "encoder_decoder": - self.tokenizer = AutoTokenizer.from_pretrained( - model_args.model_name_or_path, trust_remote_code=True) - elif self.arch_type == "vision_encoder_decoder": - if model_args.llava_loading is False: - # blip2 image and token processor - self.tokenizer = AutoProcessor.from_pretrained( - model_args.model_name_or_path, trust_remote_code=True) - if model_args.llm_model_name_or_path is not None: - # update the tokenizer from the custom llm. - self.tokenizer.tokenizer = ( - AutoTokenizer.from_pretrained( - model_args.llm_model_name_or_path) - ) - self.image_processor = self.tokenizer.image_processor - - else: - # image processor is stored in the vision encoder - if model_args.llm_model_name_or_path is not None: - self.tokenizer = AutoTokenizer.from_pretrained( - model_args.llm_model_name_or_path) - else: - self.tokenizer = AutoTokenizer.from_pretrained( - config.text_config._name_or_path) - self.image_processor = self.backend_model.image_processor - else: - raise NotImplementedError - - self.backend_model_full = self.backend_model - if peft_model_id is not None: - self.backend_model = PeftModel.from_pretrained( - self.backend_model, peft_model_id - ) - if tune_strategy == "none" and with_deepspeed is True: - # when load the model with 4bit / 8bit. - # fail to use deepspeed. - if device == "gpu": - deepspeed.init_distributed() - self.ds_engine = deepspeed.initialize(model=self.backend_model, config_params=ds_config)[0] - self.ds_engine.module.eval() - - self.tokenizer.padding_side = "left" # necessary for auto-gressive inference - - elif tune_strategy == 'adapter': - raise NotImplementedError('adapter tune strategy not implemented') - - if self.arch_type == "encoder_decoder": - if self.tokenizer.eos_token_id is None: - self.tokenizer.eos_token_id = self.backend_model.config.eos_token_id - if self.tokenizer.pad_token is None: - self.tokenizer.pad_token_id = self.tokenizer.eos_token_id - - def tokenize(self, dataset, *args, **kwargs): - """ - Tokenize the full dataset. - - Parameters - ------------ - dataset : - Text dataset. - - args : Optional. - Positional arguments. - - kwargs : Optional. - Keyword arguments. - - Returns - ------------ - tokenized_datasets : - The tokenized dataset. - """ - raise NotImplementedError('tokenize not implemented') - - def encode(self, input: Union[str, List[str]], *args, **kwargs ) -> Union[List[int], List[List[int]]]: - """ - Perform encoding process of the tokenizer. - - Parameters - ------------ - inputs : str or list. - The text sequence. - - args : Optional. - Positional arguments. - - kwargs : Optional. - Keyword arguments. - - Returns - ------------ - outputs : - The tokenized inputs. - """ - # check how to handle the image processor - if isinstance(input, dict): - # TODO refactor the input type to make it elegant. - kwargs.update(input) - if "images" not in input: - tokens = self.tokenizer(*args, **kwargs) - else: - if getattr(self.tokenizer, "image_processor", None) is not None: - tokens = self.tokenizer(*args, **kwargs) - elif getattr(self, "image_processor", None) is not None: - images = kwargs.pop("images") - tokens = self.tokenizer(*args, **kwargs) - images = self.image_processor.preprocess( - images, return_tensors='pt')['pixel_values'][0] - tokens['pixel_values'] = images - else: - print("Can not find the image processor") - raise NotImplementedError - return tokens - elif isinstance(input, list): - return self.tokenizer(text=input, *args, **kwargs)#batch encode,will automatically do left padding - elif isinstance(input, str): - return self.tokenizer.encode(text=input, *args, **kwargs) - else: - raise NotImplementedError(f'type "{type(input)}" cannot be encoded') - - - def decode(self, input, *args, **kwargs ) -> Union[str, List[str]]: - """ - Perform decoding process of the tokenizer. - - Parameters - ------------ - inputs : list. - The token sequence. - - args : Optional. - Positional arguments. - - kwargs : Optional. - Keyword arguments. - - Returns - ------------ - outputs : - The text decoded from the token inputs. - """ - if isinstance(input, List): - input=torch.tensor(input) - if input.dim()==2: - return self.tokenizer.batch_decode(input, *args, **kwargs)#batch_decode - else: - # Can be list of ints or a Tensor - return self.tokenizer.decode(input, *args, **kwargs) - - - def inference(self, inputs, *args, **kwargs): - """ - Perform generation process of the model. - - Parameters - ------------ - inputs : - The sequence used as a prompt for the generation or as model inputs to the model. - - args : Optional. - Positional arguments. - - kwargs : Optional. - Keyword arguments. - - Returns - ------------ - outputs : - The generated sequence output - """ - # current_time = time.strftime("%H:%M:%S", time.localtime()) - # print(f"{current_time}: model.inference: start", flush=True) - - # TODO need to discuss how to handle pad_token_id - if self.arch_type == "encoder_decoder": - kwargs.update(pad_token_id=self.tokenizer.pad_token_id) - elif self.arch_type == "vision_encoder_decoder": - # TODO disucss how to modify the interface to remove this part. - inputs = copy.deepcopy(inputs) - input_ids = inputs.pop('input_ids') - kwargs.update(**inputs) - inputs = input_ids - - # current_time = time.strftime("%H:%M:%S", time.localtime()) - # print(f"{current_time}: model.inference: kwargs update end", flush=True) - - with torch.no_grad(): - if self.device == "gpu": - if getattr(self, "ds_engine", None) is not None: - outputs = self.ds_engine.module.generate( - input_ids=inputs, - synced_gpus=True, - *args, - **kwargs - ) - else: - outputs = self.backend_model.generate( - input_ids=inputs, - synced_gpus=True, - *args, - **kwargs, - ) - elif self.device == "cpu": - outputs = self.backend_model.generate( - input_ids=inputs, - synced_gpus=True, - *args, - **kwargs - ) - else: - raise NotImplementedError( - f"device \"{self.device}\" is not supported" - ) - - # current_time = time.strftime("%H:%M:%S", time.localtime()) - # print(f"{current_time}: model.inference: end", flush=True) - - return outputs - - - def merge_lora_weights(self): - if self.model_args.use_lora: - self.get_backend_model().merge_and_unload() - else: - logger.warning("LoRA training is NOT enabled. Merging LoRA weights is not applicable.") - - - def save(self, dir, save_full_model=False, *args, **kwargs): - """ - Perform generation process of the model. - - Parameters - ------------ - dir : - The directory to save model and tokenizer - - save_full_model : Optional. - Whether to save full model. - - kwargs : Optional. - Keyword arguments. - - Returns - ------------ - outputs : - The generated sequence output - """ - self.get_tokenizer().save_pretrained(dir) - if save_full_model and self.model_args.use_lora: - self.backend_model_full.save_pretrained(dir) - else: - self.get_backend_model().save_pretrained(dir) - - - def get_max_length(self): - """ - Return max acceptable input length in terms of tokens. - """ - if "tokenizer" not in self.tokenizer.__dict__: - return self.tokenizer.model_max_length - else: - # for the multi-modality processor, - # the max length is stored in the inner text tokenizer - return self.tokenizer.tokenizer.model_max_length - - - def get_tokenizer(self): - """ - Return the tokenizer of the model. - """ - return self.tokenizer - - - def get_backend_model(self): - """ - Return the backend model. - """ - return self.backend_model diff --git a/src/lmflow/pipeline/finetuner.py b/src/lmflow/pipeline/finetuner.py index c57567f33..47dacff1d 100644 --- a/src/lmflow/pipeline/finetuner.py +++ b/src/lmflow/pipeline/finetuner.py @@ -27,7 +27,7 @@ from lmflow.args import DatasetArguments, ModelArguments, FinetunerArguments from lmflow.datasets.dataset import Dataset from lmflow.models.hf_decoder_model import HFDecoderModel -from lmflow.models.hf_encoder_decoder_model import HFEncoderDecoderModel +# from lmflow.models.hf_encoder_decoder_model import HFEncoderDecoderModel from lmflow.models.hf_text_regression_model import HFTextRegressionModel from lmflow.optim import create_customized_optimizer from lmflow.pipeline.base_tuner import BaseTuner @@ -216,7 +216,7 @@ def group_texts(examples): def tune(self, - model: Union[HFDecoderModel, HFTextRegressionModel, HFEncoderDecoderModel], + model: Union[HFDecoderModel, HFTextRegressionModel], dataset: Dataset, transform_dataset_in_place=True, data_collator=None): diff --git a/tests/models/test_auto_model.py b/tests/models/test_auto_model.py index 7c86bbecf..c727fefde 100644 --- a/tests/models/test_auto_model.py +++ b/tests/models/test_auto_model.py @@ -4,7 +4,7 @@ from lmflow.models.auto_model import AutoModel from lmflow.models.hf_decoder_model import HFDecoderModel from lmflow.models.text_regression_model import TextRegressionModel -from lmflow.models.hf_encoder_decoder_model import HFEncoderDecoderModel +# from lmflow.models.hf_encoder_decoder_model import HFEncoderDecoderModel MODEL_NAME = "gpt2" From 05e26a9b2643752b42dc599ff50dade0b279e781 Mon Sep 17 00:00:00 2001 From: YizhenJia Date: Tue, 4 Mar 2025 16:42:11 +0800 Subject: [PATCH 07/61] future support for trainer --- src/lmflow/pipeline/finetuner.py | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/src/lmflow/pipeline/finetuner.py b/src/lmflow/pipeline/finetuner.py index 47dacff1d..9c4726345 100644 --- a/src/lmflow/pipeline/finetuner.py +++ b/src/lmflow/pipeline/finetuner.py @@ -33,6 +33,7 @@ from lmflow.pipeline.base_tuner import BaseTuner from lmflow.pipeline.utils.peft_trainer import PeftTrainer, PeftSavingCallback from lmflow.pipeline.utils.lisa_trainer import DynamicLayerActivationCallback +from lmflow.utils.versioning import is_package_version_at_least logger = logging.getLogger(__name__) @@ -322,19 +323,24 @@ def compute_metrics(eval_preds): lisa_layers_attribute=training_args.lisa_layers_attribute, # Attribute to access layers of the model ) trainer_callbacks.append(dynamic_layer_activation_callback) + + trainer_kwargs = { + "model": model.get_backend_model(), + "args": training_args, + "train_dataset": train_dataset if training_args.do_train else None, + "eval_dataset": eval_dataset if training_args.do_eval else None, + "data_collator": data_collator, + "compute_metrics": compute_metrics if training_args.do_eval else None, + "preprocess_logits_for_metrics": preprocess_logits_for_metrics if training_args.do_eval else None, + "callbacks": trainer_callbacks + } + if is_package_version_at_least('transformers', '4.46.0'): + # https://github.com/huggingface/transformers/pull/32385 + trainer_kwargs["processing_class"] = model.get_tokenizer() + else: + trainer_kwargs["tokenizer"] = model.get_tokenizer() + trainer = FinetuningTrainer(**trainer_kwargs) - trainer = FinetuningTrainer( - model=model.get_backend_model(), - args=training_args, - train_dataset=train_dataset if training_args.do_train else None, - eval_dataset=eval_dataset if training_args.do_eval else None, - tokenizer=model.get_tokenizer(), - # Data collator will default to DataCollatorWithPadding, so we change it. - data_collator=data_collator, - compute_metrics=compute_metrics if training_args.do_eval else None, - preprocess_logits_for_metrics=preprocess_logits_for_metrics if training_args.do_eval else None, - callbacks=trainer_callbacks - ) # Training if training_args.do_train: checkpoint = None From 593f44b0a66331f7ace9437871717da7826ea672 Mon Sep 17 00:00:00 2001 From: YizhenJia Date: Tue, 4 Mar 2025 16:53:08 +0800 Subject: [PATCH 08/61] fix fsdp cfg warp policy --- configs/accelerate_fsdp_config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configs/accelerate_fsdp_config.yaml b/configs/accelerate_fsdp_config.yaml index fc271c9f8..6341b6762 100644 --- a/configs/accelerate_fsdp_config.yaml +++ b/configs/accelerate_fsdp_config.yaml @@ -3,7 +3,7 @@ debug: false distributed_type: FSDP fsdp_config: - fsdp_auto_wrap_policy: "SIZE" + fsdp_auto_wrap_policy: SIZE_BASED_WRAP fsdp_min_num_params: 1000000 fsdp_backward_prefetch: BACKWARD_PRE fsdp_forward_prefetch: false From 16eefe0084556ba807f82e426965b1c42f80fc9b Mon Sep 17 00:00:00 2001 From: YizhenJia Date: Tue, 4 Mar 2025 17:04:13 +0800 Subject: [PATCH 09/61] add note for single gpu --- configs/accelerate_fsdp_config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configs/accelerate_fsdp_config.yaml b/configs/accelerate_fsdp_config.yaml index 6341b6762..a379b24fb 100644 --- a/configs/accelerate_fsdp_config.yaml +++ b/configs/accelerate_fsdp_config.yaml @@ -19,7 +19,7 @@ machine_rank: 0 main_training_function: main mixed_precision: bf16 num_machines: 1 -num_processes: 8 +num_processes: 8 # NOTE: distributed_type should be `NO` if you're training on a single GPU rdzv_backend: static same_network: true tpu_env: [] From 29f10d813eba8388341fa8ee9c848fede27bd768 Mon Sep 17 00:00:00 2001 From: YizhenJia Date: Tue, 4 Mar 2025 17:27:49 +0800 Subject: [PATCH 10/61] add accelerate singlegpu config --- configs/accelerate_singlegpu_config.yaml | 29 ++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 configs/accelerate_singlegpu_config.yaml diff --git a/configs/accelerate_singlegpu_config.yaml b/configs/accelerate_singlegpu_config.yaml new file mode 100644 index 000000000..d74fc4e63 --- /dev/null +++ b/configs/accelerate_singlegpu_config.yaml @@ -0,0 +1,29 @@ +compute_environment: LOCAL_MACHINE +debug: false +distributed_type: 'NO' + +fsdp_config: + fsdp_auto_wrap_policy: SIZE_BASED_WRAP + fsdp_min_num_params: 1000000 + fsdp_backward_prefetch: BACKWARD_PRE + fsdp_forward_prefetch: false + fsdp_cpu_ram_efficient_loading: true + fsdp_offload_params: false + fsdp_sharding_strategy: 'NO_SHARD' + fsdp_state_dict_type: FULL_STATE_DICT + fsdp_sync_module_states: true + fsdp_use_orig_params: true + +downcast_bf16: true +machine_rank: 0 +main_training_function: main +mixed_precision: bf16 +num_machines: 1 +num_processes: 1 +rdzv_backend: static +same_network: true +tpu_env: [] +tpu_use_cluster: false +tpu_use_sudo: false +use_cpu: false +main_process_port: 1204 \ No newline at end of file From 8194d36757a20311752ea68831539f44e847ed38 Mon Sep 17 00:00:00 2001 From: YizhenJia Date: Thu, 6 Mar 2025 10:15:47 +0800 Subject: [PATCH 11/61] fix qlora script --- scripts/run_finetune_with_qlora.sh | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/scripts/run_finetune_with_qlora.sh b/scripts/run_finetune_with_qlora.sh index 1f43144fc..fe272b743 100644 --- a/scripts/run_finetune_with_qlora.sh +++ b/scripts/run_finetune_with_qlora.sh @@ -56,8 +56,7 @@ accelerate launch --config_file configs/accelerate_fsdp_config.yaml \ --block_size 512 \ --per_device_train_batch_size 1 \ --use_qlora 1 \ - --bf16 \ - --torch_dtype bfloat16 \ + --bits 4 \ --validation_split_percentage 0 \ --logging_steps 20 \ --do_train \ From 0faa453cbeee3ee759b142cf7c664fab6fd007d4 Mon Sep 17 00:00:00 2001 From: YizhenJia Date: Thu, 6 Mar 2025 15:12:28 +0800 Subject: [PATCH 12/61] [usability] simplify shell scripts --- scripts/run_finetune.sh | 47 +---- scripts/run_finetune_with_custom_optim.sh | 218 +++------------------- scripts/run_finetune_with_lisa.sh | 100 ++-------- scripts/run_finetune_with_lora.sh | 61 ++---- scripts/run_finetune_with_qlora.sh | 67 +++---- 5 files changed, 99 insertions(+), 394 deletions(-) diff --git a/scripts/run_finetune.sh b/scripts/run_finetune.sh index e705c399a..e8f7e1c08 100755 --- a/scripts/run_finetune.sh +++ b/scripts/run_finetune.sh @@ -1,43 +1,9 @@ #!/bin/bash -# Parses arguments model_name_or_path=meta-llama/Llama-3.2-3B-Instruct dataset_path=data/alpaca/train_conversation conversation_template=llama3 output_dir=output_models/finetune -# Safety related arguments -trust_remote_code=0 - -while [[ $# -ge 1 ]]; do - key="$1" - case ${key} in - -m|--model_name_or_path) - model_name_or_path="$2" - shift - ;; - -d|--dataset_path) - dataset_path="$2" - shift - ;; - -o|--output_model_path) - output_dir="$2" - shift - ;; - --conversation_template) - conversation_template="$2" - shift - ;; - --trust_remote_code) - trust_remote_code="$2" - shift - ;; - *) - echo "error: unknown option \"${key}\"" 1>&2 - exit 1 - esac - shift -done - # Finetune exp_id=finetune project_dir=$(cd "$(dirname $0)"/..; pwd) @@ -47,15 +13,17 @@ mkdir -p ${output_dir} ${log_dir} accelerate launch --config_file configs/accelerate_fsdp_config.yaml \ examples/finetune.py \ --model_name_or_path ${model_name_or_path} \ - --trust_remote_code ${trust_remote_code} \ + --trust_remote_code 0 \ --dataset_path ${dataset_path} \ --output_dir ${output_dir} --overwrite_output_dir \ --conversation_template ${conversation_template} \ - --num_train_epochs 0.01 \ - --learning_rate 2e-5 \ --disable_group_texts 1 \ - --block_size 256 \ + --num_train_epochs 1 \ + --block_size 512 \ --per_device_train_batch_size 1 \ + --gradient_accumulation_steps 1 \ + --learning_rate 2e-5 \ + --lr_scheduler_type cosine \ --bf16 \ --torch_dtype bfloat16 \ --validation_split_percentage 0 \ @@ -63,8 +31,11 @@ accelerate launch --config_file configs/accelerate_fsdp_config.yaml \ --do_train \ --ddp_timeout 72000 \ --save_steps 5000 \ + --use_flash_attention 0 \ + --gradient_checkpointing 0 \ --dataloader_num_workers 8 \ --report_to wandb \ --run_name ${exp_id} \ + --seed 42 \ > >(tee ${log_dir}/train.log) \ 2> >(tee ${log_dir}/train.err >&2) diff --git a/scripts/run_finetune_with_custom_optim.sh b/scripts/run_finetune_with_custom_optim.sh index dadef185d..e66f127f2 100644 --- a/scripts/run_finetune_with_custom_optim.sh +++ b/scripts/run_finetune_with_custom_optim.sh @@ -1,20 +1,9 @@ #!/bin/bash -# Please run this script under ${project_id} in project directory of -# https://github.com/shizhediao/llm-ft -# COMMIT: d5fecf30ba8011067b10cf51fede53a5ab6574e4 -# Parses arguments -model_name_or_path=gpt2 +model_name_or_path=meta-llama/Llama-3.2-3B-Instruct dataset_path=data/alpaca/train_conversation +conversation_template=llama3 +output_dir=output_models/finetune_custom_optim -# Other optional arguments that can improve memory saving -gradient_checkpointing=True -use_flash_attention=0 -gradient_accumulation_steps=1 -batch_size=1 -block_size=256 -per_device_train_batch_size=1 -conversation_template=llama2 -optim=dummy # Select an optimizer from the following options: # - 'adamw_torch' # - 'adafactor' @@ -23,140 +12,18 @@ optim=dummy # - 'lion_32bit' # - 'rmsprop' # Additional optimizers are shown below -learning_rate=1e-5 -lr_schedule=cosine +optim=dummy beta1=0.9 beta2=0.999 beta3=0.99 weight_decay=0 momentum=0 -num_epoch=0.01 -use_deepspeed=1 -seed=42 -# Safety related arguments -trust_remote_code=0 - -# Enable model parallelism for multiple gpus, modify this if you prefer -# customized deepspeed zero-redundancy optimization settings -num_gpu=$(python -c "import torch; print(torch.cuda.device_count())") -ds_config_file=configs/ds_config_zero0_no_offload.json -if [[ ${num_gpu} -ge 2 ]]; then - ds_config_file=configs/ds_config_zero2_no_offload.json -fi - -while [[ $# -ge 1 ]]; do - key="$1" - case ${key} in - -m|--model_name_or_path) - model_name_or_path="$2" - shift - ;; - -d|--dataset_path) - dataset_path="$2" - shift - ;; - -o|--output_model_path) - output_dir="$2" - shift - ;; - --lisa_activated_layers) - lisa_activated_layers="$2" - shift - ;; - --lisa_interval_steps) - lisa_interval_steps="$2" - shift - ;; - --gradient_checkpointing) - gradient_checkpointing="$2" - shift - ;; - --deepspeed) - ds_config_file="$2" - shift - ;; - --use_flash_attention) - use_flash_attention="$2" - shift - ;; - --gradient_accumulation_steps) - gradient_accumulation_steps="$2" - shift - ;; - --block_size) - block_size="$2" - shift - ;; - --conversation_template) - conversation_template="$2" - shift - ;; - --per_device_train_batch_size|--batch_size) - per_device_train_batch_size="$2" - batch_size="$2" - shift - ;; - --trust_remote_code) - trust_remote_code="$2" - shift - ;; - --run_name) - run_name="$2" - shift - ;; - --optim) - optim="$2" - shift - ;; - --lr) - learning_rate="$2" - shift - ;; - --beta1) - beta1="$2" - shift - ;; - --beta2) - beta2="$2" - shift - ;; - --beta3) - beta3="$2" - shift - ;; - --weight_decay) - weight_decay="$2" - shift - ;; - --momentum) - momentum="$2" - shift - ;; - -n|--num_epoch) - num_epoch="$2" - shift - ;; - --lr_schedule) - lr_schedule="$2" - shift - ;; - --use_deepspeed) - use_deepspeed="$2" - shift - ;; - --seed) - seed="$2" - shift - ;; - *) - echo "error: unknown option \"${key}\"" 1>&2 - exit 1 - esac - shift -done - -deepspeed_args="--master_port=1103 --hostfile configs/hostfile" +# Finetune +exp_id=finetune_custom_optim +project_dir=$(cd "$(dirname $0)"/..; pwd) +log_dir=${project_dir}/log/${exp_id} +mkdir -p ${output_dir} ${log_dir} optim_suffix_args="" if [ "${optim}" == "dummy" ]; then @@ -269,62 +136,33 @@ else optim_suffix_args+=" --adam_beta2 ${beta2}" fi -# Finetune -exp_id=alpaca_${optim}_lr-${learning_rate}_beta1-${beta1}_beta2-${beta2}_lr-sched-${lr_schedule}_model-$(basename ${model_name_or_path})_batch-size-${batch_size}x${gradient_accumulation_steps}_seed-${seed} -echo "$(date): ${exp_id}..." - -tmp_dir=tmp -mkdir -p ${tmp_dir} - -prefix=${exp_id} -if [ -f ${tmp_dir}/${prefix}.mark ]; then - exit 0 -fi - -trap "rm -f ${tmp_dir}/${prefix}.mark" SIGINT SIGTERM SIGKILL -touch ${tmp_dir}/${prefix}.mark - -project_dir=$(cd "$(dirname $0)"/..; pwd) -log_dir=${project_dir}/log/${exp_id} -output_dir=output_models/${exp_id} -mkdir -p ${output_dir} ${log_dir} - -exe="deepspeed ${deepspeed_args}" -if [[ ${use_deepspeed} -eq 0 ]]; then - exe=python -fi -${exe} examples/finetune.py \ +accelerate launch --config_file configs/accelerate_fsdp_config.yaml \ + examples/finetune.py \ --model_name_or_path ${model_name_or_path} \ - --trust_remote_code ${trust_remote_code} \ + --trust_remote_code 0 \ --dataset_path ${dataset_path} \ --output_dir ${output_dir} --overwrite_output_dir \ --conversation_template ${conversation_template} \ - --num_train_epochs ${num_epoch} \ - --learning_rate ${learning_rate} \ - --lr_scheduler_type ${lr_schedule} \ + ${optim_suffix_args} \ --disable_group_texts 1 \ - --block_size ${block_size} \ - --per_device_train_batch_size ${per_device_train_batch_size} \ + --num_train_epochs 1 \ + --block_size 512 \ + --per_device_train_batch_size 1 \ + --gradient_accumulation_steps 1 \ + --learning_rate 2e-5 \ + --lr_scheduler_type cosine \ --bf16 \ - --deepspeed configs/ds_config_zero2_no_offload.json \ --torch_dtype bfloat16 \ - --run_name ${exp_id} \ --validation_split_percentage 0 \ - --logging_steps 1 \ + --logging_steps 20 \ --do_train \ --ddp_timeout 72000 \ --save_steps 5000 \ - --dataloader_num_workers 1 \ - --gradient_checkpointing ${gradient_checkpointing} \ - --use_flash_attention ${use_flash_attention} \ - --gradient_accumulation_steps ${gradient_accumulation_steps} \ - --seed ${seed} \ - ${optim_suffix_args} \ - | tee ${log_dir}/train.log \ - 2> ${log_dir}/train.err - - -if [[ $? -ne 0 ]]; then - echo "$(date): failed" - rm -f ${tmp_dir}/${prefix}.mark -fi + --use_flash_attention 0 \ + --gradient_checkpointing 0 \ + --dataloader_num_workers 8 \ + --report_to wandb \ + --run_name ${exp_id} \ + --seed 42 \ + > >(tee ${log_dir}/train.log) \ + 2> >(tee ${log_dir}/train.err >&2) diff --git a/scripts/run_finetune_with_lisa.sh b/scripts/run_finetune_with_lisa.sh index 6aa095bd9..97259dec9 100755 --- a/scripts/run_finetune_with_lisa.sh +++ b/scripts/run_finetune_with_lisa.sh @@ -1,80 +1,13 @@ #!/bin/bash -# Parses arguments model_name_or_path=meta-llama/Llama-3.2-3B-Instruct dataset_path=data/alpaca/train_conversation conversation_template=llama3 output_dir=output_models/finetune_lisa + +# LISA related arguments lisa_activated_layers=1 lisa_interval_steps=20 -# Other optional arguments that can improve memory saving -gradient_checkpointing=True -use_flash_attention=0 -gradient_accumulation_steps=1 -block_size=256 -per_device_train_batch_size=1 - -# Safety related arguments -trust_remote_code=0 - -while [[ $# -ge 1 ]]; do - key="$1" - case ${key} in - -m|--model_name_or_path) - model_name_or_path="$2" - shift - ;; - -d|--dataset_path) - dataset_path="$2" - shift - ;; - -o|--output_model_path) - output_dir="$2" - shift - ;; - --lisa_activated_layers) - lisa_activated_layers="$2" - shift - ;; - --lisa_interval_steps) - lisa_interval_steps="$2" - shift - ;; - --gradient_checkpointing) - gradient_checkpointing="$2" - shift - ;; - --use_flash_attention) - use_flash_attention="$2" - shift - ;; - --gradient_accumulation_steps) - gradient_accumulation_steps="$2" - shift - ;; - --block_size) - block_size="$2" - shift - ;; - --conversation_template) - conversation_template="$2" - shift - ;; - --per_device_train_batch_size|--batch_size) - per_device_train_batch_size="$2" - shift - ;; - --trust_remote_code) - trust_remote_code="$2" - shift - ;; - *) - echo "error: unknown option \"${key}\"" 1>&2 - exit 1 - esac - shift -done - # Finetune exp_id=finetune_lisa project_dir=$(cd "$(dirname $0)"/..; pwd) @@ -84,31 +17,32 @@ mkdir -p ${output_dir} ${log_dir} accelerate launch --config_file configs/accelerate_fsdp_config.yaml \ examples/finetune.py \ --model_name_or_path ${model_name_or_path} \ - --trust_remote_code ${trust_remote_code} \ + --trust_remote_code 0 \ --dataset_path ${dataset_path} \ --output_dir ${output_dir} --overwrite_output_dir \ --conversation_template ${conversation_template} \ - --num_train_epochs 1 \ - --learning_rate 1e-5 \ + --use_lisa 1 \ + --lisa_activated_layers ${lisa_activated_layers} \ + --lisa_interval_steps ${lisa_interval_steps} \ --disable_group_texts 1 \ - --block_size ${block_size} \ - --per_device_train_batch_size ${per_device_train_batch_size} \ + --num_train_epochs 1 \ + --block_size 512 \ + --per_device_train_batch_size 1 \ + --gradient_accumulation_steps 1 \ + --learning_rate 2e-5 \ + --lr_scheduler_type cosine \ --bf16 \ --torch_dtype bfloat16 \ - --optim paged_adamw_32bit \ --validation_split_percentage 0 \ --logging_steps 20 \ --do_train \ --ddp_timeout 72000 \ --save_steps 5000 \ + --use_flash_attention 0 \ + --gradient_checkpointing 0 \ --dataloader_num_workers 8 \ - --gradient_checkpointing ${gradient_checkpointing} \ - --use_flash_attention ${use_flash_attention} \ - --gradient_accumulation_steps ${gradient_accumulation_steps} \ - --use_lisa 1 \ - --lisa_activated_layers ${lisa_activated_layers} \ - --lisa_interval_steps ${lisa_interval_steps} \ --report_to wandb \ --run_name ${exp_id} \ - | tee ${log_dir}/train.log \ - 2> ${log_dir}/train.err + --seed 42 \ + > >(tee ${log_dir}/train.log) \ + 2> >(tee ${log_dir}/train.err >&2) diff --git a/scripts/run_finetune_with_lora.sh b/scripts/run_finetune_with_lora.sh index c5d36540e..d47d363c5 100755 --- a/scripts/run_finetune_with_lora.sh +++ b/scripts/run_finetune_with_lora.sh @@ -1,42 +1,13 @@ #!/bin/bash -# Parses arguments model_name_or_path=meta-llama/Llama-3.2-3B-Instruct dataset_path=data/alpaca/train_conversation conversation_template=llama3 output_dir=output_models/finetune_lora -# Safety related arguments -trust_remote_code=0 - -while [[ $# -ge 1 ]]; do - key="$1" - case ${key} in - -m|--model_name_or_path) - model_name_or_path="$2" - shift - ;; - -d|--dataset_path) - dataset_path="$2" - shift - ;; - --conversation_template) - conversation_template="$2" - shift - ;; - -o|--output_lora_path) - output_dir="$2" - shift - ;; - --trust_remote_code) - trust_remote_code="$2" - shift - ;; - *) - echo "error: unknown option \"${key}\"" 1>&2 - exit 1 - esac - shift -done +# LoRA related arguments +lora_rank=8 +lora_alpha=32 +lora_dropout=0.1 # Finetune exp_id=finetune_with_lora @@ -47,16 +18,21 @@ mkdir -p ${output_dir} ${log_dir} accelerate launch --config_file configs/accelerate_fsdp_config.yaml \ examples/finetune.py \ --model_name_or_path ${model_name_or_path} \ - --trust_remote_code ${trust_remote_code} \ + --trust_remote_code 0 \ --dataset_path ${dataset_path} \ - --conversation_template ${conversation_template} \ --output_dir ${output_dir} --overwrite_output_dir \ - --num_train_epochs 0.01 \ - --learning_rate 2e-5 \ + --conversation_template ${conversation_template} \ + --use_lora 1 \ + --lora_r ${lora_rank} \ + --lora_alpha ${lora_alpha} \ + --lora_dropout ${lora_dropout} \ + --disable_group_texts 1 \ + --num_train_epochs 1 \ --block_size 512 \ --per_device_train_batch_size 1 \ - --use_lora 1 \ - --lora_r 8 \ + --gradient_accumulation_steps 1 \ + --learning_rate 2e-5 \ + --lr_scheduler_type cosine \ --bf16 \ --torch_dtype bfloat16 \ --validation_split_percentage 0 \ @@ -64,8 +40,11 @@ accelerate launch --config_file configs/accelerate_fsdp_config.yaml \ --do_train \ --ddp_timeout 72000 \ --save_steps 5000 \ + --use_flash_attention 0 \ + --gradient_checkpointing 0 \ --dataloader_num_workers 8 \ --report_to wandb \ --run_name ${exp_id} \ - | tee ${log_dir}/train.log \ - 2> ${log_dir}/train.err + --seed 42 \ + > >(tee ${log_dir}/train.log) \ + 2> >(tee ${log_dir}/train.err >&2) diff --git a/scripts/run_finetune_with_qlora.sh b/scripts/run_finetune_with_qlora.sh index fe272b743..446dad5ea 100644 --- a/scripts/run_finetune_with_qlora.sh +++ b/scripts/run_finetune_with_qlora.sh @@ -1,45 +1,17 @@ #!/bin/bash -# Parses arguments model_name_or_path=meta-llama/Llama-3.2-3B-Instruct dataset_path=data/alpaca/train_conversation conversation_template=llama3 output_dir=output_models/finetune_qlora -# Safety related arguments -trust_remote_code=0 - -while [[ $# -ge 1 ]]; do - key="$1" - case ${key} in - -m|--model_name_or_path) - model_name_or_path="$2" - shift - ;; - -d|--dataset_path) - dataset_path="$2" - shift - ;; - --conversation_template) - conversation_template="$2" - shift - ;; - -o|--output_model_path) - output_dir="$2" - shift - ;; - --trust_remote_code) - trust_remote_code="$2" - shift - ;; - *) - echo "error: unknown option \"${key}\"" 1>&2 - exit 1 - esac - shift -done +# QLoRA related arguments +bits=4 +lora_rank=8 +lora_alpha=32 +lora_dropout=0.1 # Finetune -exp_id=finetune_with_lora +exp_id=finetune_with_qlora project_dir=$(cd "$(dirname $0)"/..; pwd) log_dir=${project_dir}/log/${exp_id} mkdir -p ${output_dir} ${log_dir} @@ -47,23 +19,34 @@ mkdir -p ${output_dir} ${log_dir} accelerate launch --config_file configs/accelerate_fsdp_config.yaml \ examples/finetune.py \ --model_name_or_path ${model_name_or_path} \ - --trust_remote_code ${trust_remote_code} \ + --trust_remote_code 0 \ --dataset_path ${dataset_path} \ - --conversation_template ${conversation_template} \ --output_dir ${output_dir} --overwrite_output_dir \ - --num_train_epochs 0.01 \ - --learning_rate 2e-5 \ + --conversation_template ${conversation_template} \ + --use_qlora 1 \ + --bits ${bits} \ + --lora_r ${lora_rank} \ + --lora_alpha ${lora_alpha} \ + --lora_dropout ${lora_dropout} \ + --disable_group_texts 1 \ + --num_train_epochs 1 \ --block_size 512 \ --per_device_train_batch_size 1 \ - --use_qlora 1 \ - --bits 4 \ + --gradient_accumulation_steps 1 \ + --learning_rate 2e-5 \ + --lr_scheduler_type cosine \ + --bf16 \ + --torch_dtype bfloat16 \ --validation_split_percentage 0 \ --logging_steps 20 \ --do_train \ --ddp_timeout 72000 \ --save_steps 5000 \ + --use_flash_attention 0 \ + --gradient_checkpointing 0 \ --dataloader_num_workers 8 \ --report_to wandb \ --run_name ${exp_id} \ - | tee ${log_dir}/train.log \ - 2> ${log_dir}/train.err \ No newline at end of file + --seed 42 \ + > >(tee ${log_dir}/train.log) \ + 2> >(tee ${log_dir}/train.err >&2) From 43ff3071119962b38fc89aa4919d99614747279c Mon Sep 17 00:00:00 2001 From: YizhenJia Date: Thu, 6 Mar 2025 15:12:49 +0800 Subject: [PATCH 13/61] [usability] add hint for flash_attn --- src/lmflow/args.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/lmflow/args.py b/src/lmflow/args.py index 312a02725..ebd662e92 100644 --- a/src/lmflow/args.py +++ b/src/lmflow/args.py @@ -363,7 +363,9 @@ def __post_init__(self): if self.use_flash_attention: if not is_flash_attn_available(): self.use_flash_attention = False - logger.warning("Flash attention is not available in the current environment. Disabling flash attention.") + logger.warning("Flash attention is not available in the current environment. Disabling flash attention. If you want to use flash attention, please install by `pip install -e '.[flash_attn]'`.") + else: + logger.warning("Flash attention is not enabled. We recommend enabling flash attention by `--use_flash_attention 1` for better performance.") if self.lora_target_modules is not None: self.lora_target_modules: List[str] = split_args(self.lora_target_modules) From 0ba9b60dc8408658086094d440e890977d81e393 Mon Sep 17 00:00:00 2001 From: YizhenJia Date: Thu, 6 Mar 2025 16:00:29 +0800 Subject: [PATCH 14/61] [fix] fix create_customized_optimizer arg --- src/lmflow/optim/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lmflow/optim/utils.py b/src/lmflow/optim/utils.py index 909c1ab72..f76d7ee0c 100644 --- a/src/lmflow/optim/utils.py +++ b/src/lmflow/optim/utils.py @@ -6,7 +6,7 @@ import lmflow.optim.optimizers as optim from lmflow.args import OptimizerNames, TrainingArguments -def create_customized_optimizer(self, base_trainer_class, model_args): +def create_customized_optimizer(base_trainer_class, model_args): class CustomizedOptimTrainer(base_trainer_class): @staticmethod From 16d7af6cc9ab66c8a8adeb5c677c2dbe1b795ae7 Mon Sep 17 00:00:00 2001 From: YizhenJia Date: Thu, 6 Mar 2025 16:10:33 +0800 Subject: [PATCH 15/61] [usability] simplify dpov2 script --- scripts/run_dpov2_align.sh | 72 +++++++++++++------------------------- 1 file changed, 24 insertions(+), 48 deletions(-) diff --git a/scripts/run_dpov2_align.sh b/scripts/run_dpov2_align.sh index d96908931..d9430abff 100644 --- a/scripts/run_dpov2_align.sh +++ b/scripts/run_dpov2_align.sh @@ -1,59 +1,40 @@ #!/bin/bash - -# Parses arguments -run_name=dpov2_align model_name_or_path=meta-llama/Meta-Llama-3-8B-Instruct -reference_model_name_or_path=meta-llama/Meta-Llama-3-8B-Instruct dataset_path=data/iterative-prompt/train -eval_dataset_path=data/iterative-prompt/eval -output_dir=output_models/${run_name} +output_dir=output_models/dpov2_align -while [[ $# -ge 1 ]]; do - key="$1" - case ${key} in - -r|--run_name) - run_name="$2" - shift - ;; - --model_name_or_path) - model_name_or_path="$2" - shift - ;; - --reference_model_name_or_path) - reference_model_name_or_path="$2" - shift - ;; - --dataset_path) - dataset_path="$2" - shift - ;; - --eval_dataset_path) - eval_dataset_path="$2" - shift - ;; - -o|--output_dir) - output_dir="$2" - shift - ;; - *) - echo "error: unknown option \"${key}\"" 1>&2 - exit 1 - esac - shift -done +# DPO related arguments +reference_model_name_or_path=meta-llama/Meta-Llama-3-8B-Instruct +eval_dataset_path=data/iterative-prompt/eval +margin_scale=1.0 +max_prompt_length=1000 +loss_type=sigmoid +sampling_paired_method=max_min +mask_prompt=True +length_penalty=0 +# Align +exp_id=dpov2_align project_dir=$(cd "$(dirname $0)"/..; pwd) -log_dir=${project_dir}/log/${run_name} +log_dir=${project_dir}/log/${exp_id} mkdir -p ${output_dir} ${log_dir} -accelerate launch --config_file configs/accelerate_dsz3_config.yaml \ +accelerate launch --config_file configs/accelerate_fsdp_config.yaml \ examples/dpov2_train.py \ --model_name_or_path ${model_name_or_path} \ + --trust_remote_code 0 \ --reference_model_name_or_path ${reference_model_name_or_path} \ --do_train True \ --dataset_path ${dataset_path} \ --eval_dataset_path ${eval_dataset_path} \ + --margin_scale ${margin_scale} \ + --max_prompt_length ${max_prompt_length} \ + --loss_type ${loss_type} \ + --sampling_paired_method ${sampling_paired_method} \ + --mask_prompt ${mask_prompt} \ + --length_penalty ${length_penalty} \ --bf16 True \ + --torch_dtype bfloat16 \ --learning_rate 5e-7 \ --lr_scheduler_type cosine \ --warmup_steps 100 \ @@ -62,20 +43,15 @@ accelerate launch --config_file configs/accelerate_dsz3_config.yaml \ --per_device_eval_batch_size 1 \ --gradient_accumulation_steps 16 \ --gradient_checkpointing True \ - --margin_scale 1.0 \ - --max_prompt_length 1000 \ --num_train_epochs 2 \ --logging_steps 2 \ --save_strategy epoch \ --save_steps 5000 \ --evaluation_strategy steps \ --eval_steps 100 \ - --loss_type sigmoid \ --output_dir ${output_dir} \ - --run_name ${run_name} \ - --sampling_paired_method max_min \ + --run_name ${exp_id} \ --report_to wandb \ - --mask_prompt True \ - --length_penalty 0 \ + --seed 42 \ | tee ${log_dir}/train.log \ 2> ${log_dir}/train.err \ No newline at end of file From c78ac26e8f9a84007a6955b613c52f95efaacba4 Mon Sep 17 00:00:00 2001 From: YizhenJia Date: Tue, 11 Mar 2025 09:12:14 +0800 Subject: [PATCH 16/61] change fsdp default wrap policy to transformer based --- configs/accelerate_fsdp_config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configs/accelerate_fsdp_config.yaml b/configs/accelerate_fsdp_config.yaml index a379b24fb..9b0199849 100644 --- a/configs/accelerate_fsdp_config.yaml +++ b/configs/accelerate_fsdp_config.yaml @@ -3,7 +3,7 @@ debug: false distributed_type: FSDP fsdp_config: - fsdp_auto_wrap_policy: SIZE_BASED_WRAP + fsdp_auto_wrap_policy: TRANSFORMER_BASED_WRAP fsdp_min_num_params: 1000000 fsdp_backward_prefetch: BACKWARD_PRE fsdp_forward_prefetch: false From e7712f1f253754242832d93e6e15c635df3825d2 Mon Sep 17 00:00:00 2001 From: YizhenJia Date: Tue, 11 Mar 2025 09:22:41 +0800 Subject: [PATCH 17/61] streamlining --- docker/Dockerfile | 21 - docker/README.md | 74 - scripts/archive/run_dpov2_align.sh | 72 +- scripts/archive/run_inference.sh | 3 +- scripts/{ => archive}/run_iterative_dpo.sh | 0 scripts/archive/run_reward_modeling.sh | 9 +- .../archive/run_reward_modeling_with_lisa.sh | 11 +- .../archive/run_reward_modeling_with_lora.sh | 11 +- scripts/{ => archive}/run_rm_inference.sh | 0 scripts/{ => archive}/run_vllm_inference.sh | 0 scripts/data_preprocess/add_end_mark.py | 85 - scripts/data_preprocess/add_prompt.py | 81 - scripts/data_preprocess/concat.py | 79 - .../data_preprocess/concat_shuffle_split.py | 149 - scripts/data_preprocess/count.py | 57 - scripts/data_preprocess/merge.py | 87 - scripts/data_preprocess/raw2textonly.py | 81 - .../data_preprocess/run_data_preprocess.sh | 31 - scripts/data_preprocess/sample.py | 79 - scripts/data_preprocess/shuffle.py | 72 - scripts/run_dpov2_align.sh | 57 - scripts/run_inference.sh | 19 - scripts/run_raft_align.sh | 49 - scripts/run_reward_modeling.sh | 88 - scripts/run_reward_modeling_with_lisa.sh | 100 - scripts/run_reward_modeling_with_lora.sh | 89 - scripts/speculative_decoding/README.md | 69 - scripts/tools/print_model_architecture.py | 22 - scripts/vocab_extension/README.md | 23 - .../vocab_extension/convert_json_to_txt.sh | 7 - scripts/vocab_extension/merge_tokenizer.sh | 5 - .../vocab_extension/train_merge_tokenizer.sh | 24 - scripts/vocab_extension/train_tokenizer.sh | 8 - service/app.py | 149 - service/static/assets/background.png | Bin 244372 -> 0 bytes service/static/assets/logo.png | Bin 139180 -> 0 bytes service/static/utils/vue-spinner.js | 3858 ----------------- service/templates/index.html | 198 - utils/apply_delta.py | 165 - utils/convert_json_to_txt.py | 43 - utils/convert_minigpt4_checkpoints.py | 35 - utils/download_hf_file.py | 28 - utils/lm_evaluator.py | 108 - utils/make_delta.py | 48 - utils/merge_tokenizer.py | 97 - utils/preprocess_multimodal_data.py | 25 - utils/train_tokenizer.py | 39 - 47 files changed, 33 insertions(+), 6322 deletions(-) delete mode 100644 docker/Dockerfile delete mode 100644 docker/README.md rename scripts/{ => archive}/run_iterative_dpo.sh (100%) rename scripts/{ => archive}/run_rm_inference.sh (100%) rename scripts/{ => archive}/run_vllm_inference.sh (100%) delete mode 100644 scripts/data_preprocess/add_end_mark.py delete mode 100644 scripts/data_preprocess/add_prompt.py delete mode 100644 scripts/data_preprocess/concat.py delete mode 100644 scripts/data_preprocess/concat_shuffle_split.py delete mode 100644 scripts/data_preprocess/count.py delete mode 100644 scripts/data_preprocess/merge.py delete mode 100644 scripts/data_preprocess/raw2textonly.py delete mode 100644 scripts/data_preprocess/run_data_preprocess.sh delete mode 100644 scripts/data_preprocess/sample.py delete mode 100644 scripts/data_preprocess/shuffle.py delete mode 100644 scripts/run_dpov2_align.sh delete mode 100755 scripts/run_inference.sh delete mode 100755 scripts/run_raft_align.sh delete mode 100644 scripts/run_reward_modeling.sh delete mode 100644 scripts/run_reward_modeling_with_lisa.sh delete mode 100644 scripts/run_reward_modeling_with_lora.sh delete mode 100644 scripts/speculative_decoding/README.md delete mode 100644 scripts/tools/print_model_architecture.py delete mode 100644 scripts/vocab_extension/README.md delete mode 100644 scripts/vocab_extension/convert_json_to_txt.sh delete mode 100644 scripts/vocab_extension/merge_tokenizer.sh delete mode 100644 scripts/vocab_extension/train_merge_tokenizer.sh delete mode 100644 scripts/vocab_extension/train_tokenizer.sh delete mode 100644 service/app.py delete mode 100644 service/static/assets/background.png delete mode 100644 service/static/assets/logo.png delete mode 100644 service/static/utils/vue-spinner.js delete mode 100644 service/templates/index.html delete mode 100644 utils/apply_delta.py delete mode 100644 utils/convert_json_to_txt.py delete mode 100644 utils/convert_minigpt4_checkpoints.py delete mode 100644 utils/download_hf_file.py delete mode 100644 utils/lm_evaluator.py delete mode 100644 utils/make_delta.py delete mode 100644 utils/merge_tokenizer.py delete mode 100644 utils/preprocess_multimodal_data.py delete mode 100644 utils/train_tokenizer.py diff --git a/docker/Dockerfile b/docker/Dockerfile deleted file mode 100644 index 60b1d5712..000000000 --- a/docker/Dockerfile +++ /dev/null @@ -1,21 +0,0 @@ -FROM nvidia/cuda:11.3.0-cudnn8-devel-ubuntu20.04 - -ENV TZ=Etc/UTC -RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone - -RUN apt-get update --fix-missing && apt-get install -y fontconfig --fix-missing -RUN apt-get install -y libopenmpi-dev -RUN apt-get install -y git python3.9 python3.9-dev python3.9-venv -RUN python3.9 -m venv /venv -ENV PATH=/venv/bin:$PATH -RUN pip install mpi4py - -ARG SRCDIR - -RUN mkdir /LMFlow/ -WORKDIR /LMFlow/ - -COPY $SRCDIR/ /LMFlow/ - -RUN pip install wheel -RUN pip install -e . diff --git a/docker/README.md b/docker/README.md deleted file mode 100644 index 5e7fa482f..000000000 --- a/docker/README.md +++ /dev/null @@ -1,74 +0,0 @@ -# Docker - -LMFlow is available as a docker image in Docker Hub, built from the Dockerfile -in this directory, with cuda:11.3.0-cudnn8 (source docker: -nvidia/cuda:11.3.0-cudnn8-devel-ubuntu20.04). You need to have at least a -Nvidia 3090 GPU on your machine with cuda driver compatible with cuda:11.3.0 to -run this docker image. - -## Install docker with nvidia support - -First you may need to install docker with nvidia support. This step requires -root permission. If you don't have one, you may need to contact the system -adminstrator to do that for you. - -We provide an example in Ubuntu 20.04. For other operating systems, you may -refer to Nvidia's [Install -Guide](https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/install-guide.html#docker). - -```sh -curl https://get.docker.com | sh && sudo systemctl --now enable docker - -distribution=$(. /etc/os-release;echo $ID$VERSION_ID) \ - && curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey \ - | sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg \ - && curl -s -L https://nvidia.github.io/libnvidia-container/$distribution/libnvidia-container.list \ - | sed 's#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g' \ - | sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list - -sudo apt-get update -sudo apt-get install -y nvidia-container-toolkit -sudo nvidia-ctk runtime configure --runtime=docker -sudo systemctl restart docker -``` - -## Pull docker image and run - -Use the following command to pull our docker image. - -```sh -docker pull optimalscale/lmflow -``` - -The working directory in docker is `/LMFlow`, where LMFlow (commit: -[fa0e66f94](https://github.com/OptimalScale/LMFlow/tree/fa0e66f94eb5b7bfd624afdf9826b054641e3373)) -is cloned and installed. Use the following command to enter the docker -container, where `./LMFlow/log/finetune` in the container will be mapped to -`./output_dir/log/finetune` on the host machine. You may add more directory -mappings in a similar manner. - -```sh -docker run \ - -v ./output_dir/log/finetune:/LMFlow/log/finetune \ - --gpus=all \ - --shm-size=64g \ - -e WANDB_DISABLED=true \ - -it \ - --rm \ - optimalscale/lmflow \ - bash -``` - -Then you will be able to work inside the docker, just like in a physical -machine. Notice that to use multiple gpus, you need to allocate enough -shared memory. We have setup the dependency for you, so you can directly -run our scripts, e.g. - -``` -./scripts/run_chatbot.sh -./scripts/run_evaluation.sh - -# May need a GPU with --bf16 support, or you can remove --bf16 -# and use --fp16 instead -./scripts/run_finetune.sh -``` diff --git a/scripts/archive/run_dpov2_align.sh b/scripts/archive/run_dpov2_align.sh index d96908931..d9430abff 100644 --- a/scripts/archive/run_dpov2_align.sh +++ b/scripts/archive/run_dpov2_align.sh @@ -1,59 +1,40 @@ #!/bin/bash - -# Parses arguments -run_name=dpov2_align model_name_or_path=meta-llama/Meta-Llama-3-8B-Instruct -reference_model_name_or_path=meta-llama/Meta-Llama-3-8B-Instruct dataset_path=data/iterative-prompt/train -eval_dataset_path=data/iterative-prompt/eval -output_dir=output_models/${run_name} +output_dir=output_models/dpov2_align -while [[ $# -ge 1 ]]; do - key="$1" - case ${key} in - -r|--run_name) - run_name="$2" - shift - ;; - --model_name_or_path) - model_name_or_path="$2" - shift - ;; - --reference_model_name_or_path) - reference_model_name_or_path="$2" - shift - ;; - --dataset_path) - dataset_path="$2" - shift - ;; - --eval_dataset_path) - eval_dataset_path="$2" - shift - ;; - -o|--output_dir) - output_dir="$2" - shift - ;; - *) - echo "error: unknown option \"${key}\"" 1>&2 - exit 1 - esac - shift -done +# DPO related arguments +reference_model_name_or_path=meta-llama/Meta-Llama-3-8B-Instruct +eval_dataset_path=data/iterative-prompt/eval +margin_scale=1.0 +max_prompt_length=1000 +loss_type=sigmoid +sampling_paired_method=max_min +mask_prompt=True +length_penalty=0 +# Align +exp_id=dpov2_align project_dir=$(cd "$(dirname $0)"/..; pwd) -log_dir=${project_dir}/log/${run_name} +log_dir=${project_dir}/log/${exp_id} mkdir -p ${output_dir} ${log_dir} -accelerate launch --config_file configs/accelerate_dsz3_config.yaml \ +accelerate launch --config_file configs/accelerate_fsdp_config.yaml \ examples/dpov2_train.py \ --model_name_or_path ${model_name_or_path} \ + --trust_remote_code 0 \ --reference_model_name_or_path ${reference_model_name_or_path} \ --do_train True \ --dataset_path ${dataset_path} \ --eval_dataset_path ${eval_dataset_path} \ + --margin_scale ${margin_scale} \ + --max_prompt_length ${max_prompt_length} \ + --loss_type ${loss_type} \ + --sampling_paired_method ${sampling_paired_method} \ + --mask_prompt ${mask_prompt} \ + --length_penalty ${length_penalty} \ --bf16 True \ + --torch_dtype bfloat16 \ --learning_rate 5e-7 \ --lr_scheduler_type cosine \ --warmup_steps 100 \ @@ -62,20 +43,15 @@ accelerate launch --config_file configs/accelerate_dsz3_config.yaml \ --per_device_eval_batch_size 1 \ --gradient_accumulation_steps 16 \ --gradient_checkpointing True \ - --margin_scale 1.0 \ - --max_prompt_length 1000 \ --num_train_epochs 2 \ --logging_steps 2 \ --save_strategy epoch \ --save_steps 5000 \ --evaluation_strategy steps \ --eval_steps 100 \ - --loss_type sigmoid \ --output_dir ${output_dir} \ - --run_name ${run_name} \ - --sampling_paired_method max_min \ + --run_name ${exp_id} \ --report_to wandb \ - --mask_prompt True \ - --length_penalty 0 \ + --seed 42 \ | tee ${log_dir}/train.log \ 2> ${log_dir}/train.err \ No newline at end of file diff --git a/scripts/archive/run_inference.sh b/scripts/archive/run_inference.sh index 7ae978f64..3e89ac3e4 100755 --- a/scripts/archive/run_inference.sh +++ b/scripts/archive/run_inference.sh @@ -11,9 +11,8 @@ if [ $# -ge 2 ]; then lora_args="--lora_model_path $2" fi -accelerate launch --config_file configs/accelerator_multigpu_config.yaml \ +accelerate launch --config_file configs/accelerate_fsdp_config.yaml \ examples/inference.py \ - --deepspeed configs/archive/ds_config_chatbot.json \ --model_name_or_path ${model} \ --max_new_tokens 256 \ --temperature 1.0 \ diff --git a/scripts/run_iterative_dpo.sh b/scripts/archive/run_iterative_dpo.sh similarity index 100% rename from scripts/run_iterative_dpo.sh rename to scripts/archive/run_iterative_dpo.sh diff --git a/scripts/archive/run_reward_modeling.sh b/scripts/archive/run_reward_modeling.sh index 1dc0eaf04..9b8c2b9d6 100644 --- a/scripts/archive/run_reward_modeling.sh +++ b/scripts/archive/run_reward_modeling.sh @@ -5,7 +5,6 @@ model_name_or_path=google/gemma-2b-it train_dataset_path=data/ultrafeedback-binarized-preferences-cleaned/train eval_dataset_path=data/ultrafeedback-binarized-preferences-cleaned/train output_dir=output_models/reward_modeling -deepspeed_args="--master_port=11345 --include localhost:6" conversation_template=gemma # Safety related arguments @@ -34,10 +33,6 @@ while [[ $# -ge 1 ]]; do conversation_template="$2" shift ;; - --deepspeed_args) - deepspeed_args="$2" - shift - ;; --trust_remote_code) trust_remote_code="$2" shift @@ -55,9 +50,8 @@ project_dir=$(cd "$(dirname $0)"/..; pwd) log_dir=${project_dir}/log/${exp_id} mkdir -p ${output_dir} ${log_dir} -deepspeed ${deepspeed_args} \ +accelerate launch --config_file configs/accelerate_fsdp_config.yaml \ examples/reward_modeling.py \ - --deepspeed configs/archive/ds_config_zero3.json \ --model_name_or_path ${model_name_or_path} \ --arch_type "text_regression" \ --do_train True \ @@ -78,6 +72,7 @@ deepspeed ${deepspeed_args} \ --gradient_checkpointing True \ --remove_unused_columns False \ --bf16 True \ + --torch_dtype bfloat16 \ --logging_strategy "steps" \ --logging_steps 10 \ --optim "paged_adamw_32bit" \ diff --git a/scripts/archive/run_reward_modeling_with_lisa.sh b/scripts/archive/run_reward_modeling_with_lisa.sh index 9b7e4f2f5..f3ad3ea2f 100644 --- a/scripts/archive/run_reward_modeling_with_lisa.sh +++ b/scripts/archive/run_reward_modeling_with_lisa.sh @@ -5,7 +5,6 @@ model_name_or_path=google/gemma-2b-it train_dataset_path=data/ultrafeedback-binarized-preferences-cleaned/train eval_dataset_path=data/ultrafeedback-binarized-preferences-cleaned/train output_dir=output_models/reward_modeling_lisa -deepspeed_args="--master_port=11345 --include localhost:6" conversation_template=gemma lisa_activated_layers=1 lisa_interval_steps=20 @@ -44,10 +43,6 @@ while [[ $# -ge 1 ]]; do conversation_template="$2" shift ;; - --deepspeed_args) - deepspeed_args="$2" - shift - ;; --trust_remote_code) trust_remote_code="$2" shift @@ -60,14 +55,13 @@ while [[ $# -ge 1 ]]; do done # Finetune -exp_id=reward_modeling +exp_id=reward_modeling_lisa project_dir=$(cd "$(dirname $0)"/..; pwd) log_dir=${project_dir}/log/${exp_id} mkdir -p ${output_dir} ${log_dir} -deepspeed ${deepspeed_args} \ +accelerate launch --config_file configs/accelerate_fsdp_config.yaml \ examples/reward_modeling.py \ - --deepspeed configs/archive/ds_config_zero3.json \ --model_name_or_path ${model_name_or_path} \ --arch_type "text_regression" \ --do_train True \ @@ -88,6 +82,7 @@ deepspeed ${deepspeed_args} \ --gradient_checkpointing True \ --remove_unused_columns False \ --bf16 True \ + --torch_dtype bfloat16 \ --logging_strategy "steps" \ --logging_steps 10 \ --optim "paged_adamw_32bit" \ diff --git a/scripts/archive/run_reward_modeling_with_lora.sh b/scripts/archive/run_reward_modeling_with_lora.sh index addd50263..f0fe44622 100644 --- a/scripts/archive/run_reward_modeling_with_lora.sh +++ b/scripts/archive/run_reward_modeling_with_lora.sh @@ -5,7 +5,6 @@ model_name_or_path=google/gemma-2b-it train_dataset_path=data/ultrafeedback-binarized-preferences-cleaned/train eval_dataset_path=data/ultrafeedback-binarized-preferences-cleaned/train output_dir=output_models/reward_modeling_lora -deepspeed_args="--master_port=11345 --include localhost:6" conversation_template=gemma # Safety related arguments @@ -34,10 +33,6 @@ while [[ $# -ge 1 ]]; do conversation_template="$2" shift ;; - --deepspeed_args) - deepspeed_args="$2" - shift - ;; --trust_remote_code) trust_remote_code="$2" shift @@ -50,14 +45,13 @@ while [[ $# -ge 1 ]]; do done # Finetune -exp_id=reward_modeling +exp_id=reward_modeling_lora project_dir=$(cd "$(dirname $0)"/..; pwd) log_dir=${project_dir}/log/${exp_id} mkdir -p ${output_dir} ${log_dir} -deepspeed ${deepspeed_args} \ +accelerate launch --config_file configs/accelerate_fsdp_config.yaml \ examples/reward_modeling.py \ - --deepspeed configs/archive/ds_config_zero3.json \ --model_name_or_path ${model_name_or_path} \ --arch_type "text_regression" \ --do_train True \ @@ -78,6 +72,7 @@ deepspeed ${deepspeed_args} \ --gradient_checkpointing True \ --remove_unused_columns False \ --bf16 True \ + --torch_dtype bfloat16 \ --logging_strategy "steps" \ --logging_steps 10 \ --optim "paged_adamw_32bit" \ diff --git a/scripts/run_rm_inference.sh b/scripts/archive/run_rm_inference.sh similarity index 100% rename from scripts/run_rm_inference.sh rename to scripts/archive/run_rm_inference.sh diff --git a/scripts/run_vllm_inference.sh b/scripts/archive/run_vllm_inference.sh similarity index 100% rename from scripts/run_vllm_inference.sh rename to scripts/archive/run_vllm_inference.sh diff --git a/scripts/data_preprocess/add_end_mark.py b/scripts/data_preprocess/add_end_mark.py deleted file mode 100644 index 900bf1646..000000000 --- a/scripts/data_preprocess/add_end_mark.py +++ /dev/null @@ -1,85 +0,0 @@ -#!/usr/bin/env python -# coding=utf-8 -# Copyright 2023 Statistics and Machine Learning Research Group at HKUST. All rights reserved. -""" -Adds prompt structure to a text2text dataset. -""" -from __future__ import absolute_import - -import argparse -import json -import textwrap -import sys - -def parse_argument(sys_argv): - """Parses arguments from command line. - Args: - sys_argv: the list of arguments (strings) from command line. - Returns: - A struct whose member corresponds to the required (optional) variable. - For example, - ``` - args = parse_argument(['main.py' '--input', 'a.txt', '--num', '10']) - args.input # 'a.txt' - args.num # 10 - ``` - """ - parser = argparse.ArgumentParser( - formatter_class=argparse.RawTextHelpFormatter) - - # Training parameters - parser.add_argument( - "--dataset_path", type=str, - default=None, - help=textwrap.dedent("input dataset path, reads from stdin by default") - ) - parser.add_argument( - "--output_path", type=str, - default=None, - help=textwrap.dedent("output dataset path, writes to stdout by default") - ) - parser.add_argument( - "--end_mark", type=str, - default="###", - help=textwrap.dedent("end mark that append to the end of output") - ) - - # Parses from commandline - args = parser.parse_args(sys_argv[1:]) - - return args - - -def main(): - args = parse_argument(sys.argv) - if args.dataset_path is not None: - with open(args.dataset_path, "r") as fin: - data_dict = json.load(fin) - else: - data_dict = json.load(sys.stdin) - - output_field_map = { - "text_only": "text", - "text2text": "output", - } - data_dict_type = data_dict["type"] - if not data_dict_type in output_field_map: - raise NotImplementedError( - "only support text_only or text2text dataset" - ) - - output_field = output_field_map[data_dict_type] - - num_instances = len(data_dict["instances"]) - for i in range(num_instances): - data_dict["instances"][i][output_field] += args.end_mark - - if args.output_path is not None: - with open(args.output_path, "w") as fout: - json.dump(data_dict, fout, indent=4, ensure_ascii=False) - else: - json.dump(data_dict, sys.stdout, indent=4, ensure_ascii=False) - - -if __name__ == "__main__": - main() diff --git a/scripts/data_preprocess/add_prompt.py b/scripts/data_preprocess/add_prompt.py deleted file mode 100644 index ee477e105..000000000 --- a/scripts/data_preprocess/add_prompt.py +++ /dev/null @@ -1,81 +0,0 @@ -#!/usr/bin/env python -# coding=utf-8 -# Copyright 2023 Statistics and Machine Learning Research Group at HKUST. All rights reserved. -""" -Adds prompt structure to a text2text dataset. -""" -from __future__ import absolute_import - -import argparse -import json -import textwrap -import sys - -def parse_argument(sys_argv): - """Parses arguments from command line. - Args: - sys_argv: the list of arguments (strings) from command line. - Returns: - A struct whose member corresponds to the required (optional) variable. - For example, - ``` - args = parse_argument(['main.py' '--input', 'a.txt', '--num', '10']) - args.input # 'a.txt' - args.num # 10 - ``` - """ - parser = argparse.ArgumentParser( - formatter_class=argparse.RawTextHelpFormatter) - - # Training parameters - parser.add_argument( - "--dataset_path", type=str, - default=None, - help=textwrap.dedent("input dataset path, reads from stdin by default") - ) - parser.add_argument( - "--output_path", type=str, - default=None, - help=textwrap.dedent("output dataset path, writes to stdout by default") - ) - parser.add_argument( - "--prompt_structure", type=str, - default="{input}", - help=textwrap.dedent("prompt structure to augment input") - ) - - # Parses from commandline - args = parser.parse_args(sys_argv[1:]) - - return args - - -def main(): - args = parse_argument(sys.argv) - if args.dataset_path is not None: - with open(args.dataset_path, "r") as fin: - data_dict = json.load(fin) - else: - data_dict = json.load(sys.stdin) - - if data_dict["type"] != "text2text": - raise NotImplementedError( - "only support text2text prompt augmentation" - ) - - data_dict["instances"] = [ - { - "input": args.prompt_structure.format(input=instance["input"]), - "output": instance["output"], - } - for instance in data_dict["instances"] - ] - if args.output_path is not None: - with open(args.output_path, "w") as fout: - json.dump(data_dict, fout, indent=4, ensure_ascii=False) - else: - json.dump(data_dict, sys.stdout, indent=4, ensure_ascii=False) - - -if __name__ == "__main__": - main() diff --git a/scripts/data_preprocess/concat.py b/scripts/data_preprocess/concat.py deleted file mode 100644 index 7cafd7c9c..000000000 --- a/scripts/data_preprocess/concat.py +++ /dev/null @@ -1,79 +0,0 @@ -#!/usr/bin/env python -# coding=utf-8 -# Copyright 2023 Statistics and Machine Learning Research Group at HKUST. All rights reserved. -""" -Merges an extra dataset into current dataset. -""" -from __future__ import absolute_import - -import argparse -import json -import textwrap -import sys - -def parse_argument(sys_argv): - """Parses arguments from command line. - Args: - sys_argv: the list of arguments (strings) from command line. - Returns: - A struct whose member corresponds to the required (optional) variable. - For example, - ``` - args = parse_argument(['main.py' '--input', 'a.txt', '--num', '10']) - args.input # 'a.txt' - args.num # 10 - ``` - """ - parser = argparse.ArgumentParser( - formatter_class=argparse.RawTextHelpFormatter) - - # Training parameters - parser.add_argument( - "--output_path", type=str, - default=None, - help=textwrap.dedent("output dataset path, writes to stdout by default") - ) - parser.add_argument( - "--merge_from_path", type=str, - nargs="+", - help=textwrap.dedent( - "dataset path of the extra dataset that will be merged" - " into input dataset" - ) - ) - - # Parses from commandline - args = parser.parse_args(sys_argv[1:]) - - return args - - -def main(): - args = parse_argument(sys.argv) - - if args.merge_from_path is not None: - for i in range(0, len(args.merge_from_path)): - with open(args.merge_from_path[i], "r") as fin: - extra_data_dict = json.load(fin) - if i == 0: - data_dict = extra_data_dict - else: - if data_dict["type"] != extra_data_dict["type"]: - raise ValueError( - 'two dataset have different types:' - f' input dataset: "{data_dict["type"]}";' - f' merge from dataset: "{extra_data_dict["type"]}"' - ) - data_dict["instances"].extend(extra_data_dict["instances"]) - else: - raise ValueError("No merge files specified") - - if args.output_path is not None: - with open(args.output_path, "w") as fout: - json.dump(data_dict, fout, indent=4, ensure_ascii=False) - else: - json.dump(data_dict, sys.stdout, indent=4, ensure_ascii=False) - - -if __name__ == "__main__": - main() diff --git a/scripts/data_preprocess/concat_shuffle_split.py b/scripts/data_preprocess/concat_shuffle_split.py deleted file mode 100644 index d83dfc98e..000000000 --- a/scripts/data_preprocess/concat_shuffle_split.py +++ /dev/null @@ -1,149 +0,0 @@ -#!/usr/bin/env python -# coding=utf-8 -# Copyright 2023 Statistics and Machine Learning Research Group at HKUST. All rights reserved. -""" -This script is designed for handling large datasets. -It merges multiple datasets located in the same directory, shuffles them, and splits them into training, evaluation, and testing sets. -The training set is further divided into 10 folds. -""" -from __future__ import absolute_import - -import argparse -import json -import textwrap -import sys -import os -import random -import gc - -def parse_argument(sys_argv): - """Parses arguments from command line. - Args: - sys_argv: the list of arguments (strings) from command line. - Returns: - A struct whose member corresponds to the required (optional) variable. - For example, - ``` - args = parse_argument(['main.py' '--input', 'a.txt', '--num', '10']) - args.input # 'a.txt' - args.num # 10 - ``` - """ - parser = argparse.ArgumentParser( - formatter_class=argparse.RawTextHelpFormatter) - - # Training parameters - parser.add_argument( - "--output_path", type=str, - default=None, - help=textwrap.dedent("output dataset path, writes to stdout by default") - ) - parser.add_argument( - "--merge_from_path", type=str, - nargs="+", - help=textwrap.dedent( - "dataset path of the extra dataset that will be merged" - " into input dataset" - ) - ) - parser.add_argument( - "--seed", type=int, default=42, - help=textwrap.dedent("pseudorandom seed") - ) - parser.add_argument( - "--eval_size", type=int, default=200, - help=textwrap.dedent("size of eval dataset") - ) - parser.add_argument( - "--test_size", type=int, default=1000, - help=textwrap.dedent("size of test dataset") - ) - parser.add_argument( - "--k", type=int, default=10, - help=textwrap.dedent("the train dataset will be divide into k folds") - ) - # Parses from commandline - args = parser.parse_args(sys_argv[1:]) - - return args - - -def main(): - args = parse_argument(sys.argv) - - # concat - if args.merge_from_path is not None: - for i in range(0, len(args.merge_from_path)): - with open(args.merge_from_path[i], "r") as fin: - extra_data_dict = json.load(fin) - if i == 0: - data_dict = extra_data_dict - else: - if data_dict["type"] != extra_data_dict["type"]: - raise ValueError( - 'two dataset have different types:' - f' input dataset: "{data_dict["type"]}";' - f' merge from dataset: "{extra_data_dict["type"]}"' - ) - data_dict["instances"].extend(extra_data_dict["instances"]) - else: - raise ValueError("No merge files specified") - del extra_data_dict - gc.collect() - print('finish concat') - - # shuffle - random.seed(args.seed) - random.shuffle(data_dict["instances"]) - print('finish shuffle') - # split to train, eval, test - train_data_dict = {"type":data_dict["type"],"instances":data_dict["instances"][args.eval_size:-args.test_size]} - eval_data_dict = {"type":data_dict["type"],"instances":data_dict["instances"][:args.eval_size]} - test_data_dict = {"type":data_dict["type"],"instances":data_dict["instances"][-args.test_size:]} - del data_dict - gc.collect() - - # divide train in 10 folds - num_instances = len(train_data_dict["instances"]) - split_size = num_instances // args.k - split_data = [] - for i in range(args.k): - if i < args.k-1: - split = train_data_dict["instances"][i*split_size : (i+1)*split_size] - else: - # Last split may have remaining instances - split = train_data_dict["instances"][i*split_size:] - split_data.append({'type': train_data_dict["type"], 'instances': split}) - - del train_data_dict - gc.collect() - - print('finish split') - # save dataset under output_path - - if args.output_path is None: - args.output_path = sys.stdout - - train_save_path=os.path.join(args.output_path,"train_{k}_folds".format(k=args.k)) - if not os.path.exists(train_save_path): - os.makedirs(train_save_path) - for i in range(args.k): - with open(train_save_path+"/train_"+str(i)+".json", 'w') as f: - json.dump(split_data[i], f, indent=4, ensure_ascii=False) - - eval_save_path=os.path.join(args.output_path,"eval") - if not os.path.exists(eval_save_path): - os.makedirs(eval_save_path) - with open(eval_save_path+'/eval.json','w') as f: - json.dump(eval_data_dict,f,indent=4,ensure_ascii=False) - - test_save_path=os.path.join(args.output_path,"test") - if not os.path.exists(test_save_path): - os.makedirs(test_save_path) - with open(test_save_path+'/test.json','w') as f: - json.dump(test_data_dict,f,indent=4,ensure_ascii=False) - - - -if __name__ == "__main__": - main() diff --git a/scripts/data_preprocess/count.py b/scripts/data_preprocess/count.py deleted file mode 100644 index ab3df108d..000000000 --- a/scripts/data_preprocess/count.py +++ /dev/null @@ -1,57 +0,0 @@ -#!/usr/bin/env python -# coding=utf-8 -# Copyright 2023 Statistics and Machine Learning Research Group at HKUST. All rights reserved. -""" -Counts number of instances in a dataset. -""" -from __future__ import absolute_import - -import argparse -import json -import random -import sys -import textwrap - -def parse_argument(sys_argv): - """Parses arguments from command line. - Args: - sys_argv: the list of arguments (strings) from command line. - Returns: - A struct whose member corresponds to the required (optional) variable. - For example, - ``` - args = parse_argument(['main.py' '--input', 'a.txt', '--num', '10']) - args.input # 'a.txt' - args.num # 10 - ``` - """ - parser = argparse.ArgumentParser( - formatter_class=argparse.RawTextHelpFormatter) - - # Training parameters - parser.add_argument( - "--dataset_path", type=str, - default=None, - help="input dataset path, reads from stdin by default" - ) - - # Parses from commandline - args = parser.parse_args(sys_argv[1:]) - - return args - - -def main(): - args = parse_argument(sys.argv) - if args.dataset_path is not None: - with open(args.dataset_path, "r") as fin: - data_dict = json.load(fin) - else: - data_dict = json.load(sys.stdin) - - num_instances = len(data_dict["instances"]) - print(num_instances) - - -if __name__ == "__main__": - main() diff --git a/scripts/data_preprocess/merge.py b/scripts/data_preprocess/merge.py deleted file mode 100644 index 2dcb99512..000000000 --- a/scripts/data_preprocess/merge.py +++ /dev/null @@ -1,87 +0,0 @@ -#!/usr/bin/env python -# coding=utf-8 -# Copyright 2023 Statistics and Machine Learning Research Group at HKUST. All rights reserved. -""" -Merges an extra dataset into current dataset. -""" -from __future__ import absolute_import - -import argparse -import json -import textwrap -import sys - -def parse_argument(sys_argv): - """Parses arguments from command line. - Args: - sys_argv: the list of arguments (strings) from command line. - Returns: - A struct whose member corresponds to the required (optional) variable. - For example, - ``` - args = parse_argument(['main.py' '--input', 'a.txt', '--num', '10']) - args.input # 'a.txt' - args.num # 10 - ``` - """ - parser = argparse.ArgumentParser( - formatter_class=argparse.RawTextHelpFormatter) - - parser.add_argument( - "--dataset_path", type=str, - default=None, - help=textwrap.dedent("input dataset path, reads from stdin by default") - ) - # Training parameters - parser.add_argument( - "--output_path", type=str, - default=None, - help=textwrap.dedent("output dataset path, writes to stdout by default") - ) - parser.add_argument( - "--merge_from_path", type=str, - nargs="+", - help=textwrap.dedent( - "dataset path of the extra dataset that will be merged" - " into input dataset" - ) - ) - - # Parses from commandline - args = parser.parse_args(sys_argv[1:]) - - return args - - -def main(): - args = parse_argument(sys.argv) - - if args.dataset_path is not None: - with open(args.dataset_path, "r") as fin: - data_dict = json.load(fin) - else: - data_dict = json.load(sys.stdin) - - if args.merge_from_path is not None: - for i in range(0, len(args.merge_from_path)): - with open(args.merge_from_path[i], "r") as fin: - extra_data_dict = json.load(fin) - - if data_dict["type"] != extra_data_dict["type"]: - raise ValueError( - 'two dataset have different types:' - f' input dataset: "{data_dict["type"]}";' - f' merge from dataset: "{extra_data_dict["type"]}"' - ) - data_dict["instances"].extend(extra_data_dict["instances"]) - - - if args.output_path is not None: - with open(args.output_path, "w") as fout: - json.dump(data_dict, fout, indent=4, ensure_ascii=False) - else: - json.dump(data_dict, sys.stdout, indent=4, ensure_ascii=False) - - -if __name__ == "__main__": - main() diff --git a/scripts/data_preprocess/raw2textonly.py b/scripts/data_preprocess/raw2textonly.py deleted file mode 100644 index eb64c512d..000000000 --- a/scripts/data_preprocess/raw2textonly.py +++ /dev/null @@ -1,81 +0,0 @@ -#!/usr/bin/env python -# coding=utf-8 -# Copyright 2023 Statistics and Machine Learning Research Group at HKUST. All rights reserved. -""" -Converts a raw text file, separated by lines, into a "text-only" formatted json. -""" -from __future__ import absolute_import - -import argparse -import json -import textwrap -import sys - -def parse_argument(sys_argv): - """Parses arguments from command line. - Args: - sys_argv: the list of arguments (strings) from command line. - Returns: - A struct whose member corresponds to the required (optional) variable. - For example, - ``` - args = parse_argument(['main.py' '--input', 'a.txt', '--num', '10']) - args.input # 'a.txt' - args.num # 10 - ``` - """ - parser = argparse.ArgumentParser( - formatter_class=argparse.RawTextHelpFormatter) - - # Training parameters - parser.add_argument( - "--dataset_path", type=str, - default=None, - help=textwrap.dedent("input dataset path, reads from stdin by default") - ) - parser.add_argument( - "--output_path", type=str, - default=None, - help=textwrap.dedent("output dataset path, writes to stdout by default") - ) - - # Parses from commandline - args = parser.parse_args(sys_argv[1:]) - - return args - - -def raw2textonly(fin): - """ - Converts raw text to text-only format. - - Args: - fin: the input file description of the raw text file. - Returns: - a dict with "text-only" format. - """ - data_dict = { - "type": "text_only", - "instances": [ { "text": line.strip() } for line in fin ], - } - return data_dict - - -def main(): - args = parse_argument(sys.argv) - - if args.dataset_path is not None: - with open(args.dataset_path, "r") as fin: - data_dict = raw2textonly(fin) - else: - data_dict = raw2textonly(sys.stdin) - - if args.output_path is not None: - with open(args.output_path, "w") as fout: - json.dump(data_dict, fout, indent=4, ensure_ascii=False) - else: - json.dump(data_dict, sys.stdout, indent=4, ensure_ascii=False) - - -if __name__ == "__main__": - main() diff --git a/scripts/data_preprocess/run_data_preprocess.sh b/scripts/data_preprocess/run_data_preprocess.sh deleted file mode 100644 index 8b515de9a..000000000 --- a/scripts/data_preprocess/run_data_preprocess.sh +++ /dev/null @@ -1,31 +0,0 @@ -#!/bin/bash -# Run this shell script under project directory - -# For sample.py -python scripts/data_preprocess/sample.py \ - --dataset_path ./data/example_dataset/train/train_50.json \ - --output_path ./data/example_dataset/train/train_50_sample.json \ - --ratio 0.5 - -# For shuffle.py -python scripts/data_preprocess/shuffle.py \ - --dataset_path ./data/example_dataset/train/train_50_sample.json \ - --output_path ./data/example_dataset/train/train_50_sample_shuffle.json - -# For merge.py : you can specify multiple files to merge -python scripts/data_preprocess/merge.py \ - --dataset_path ./data/example_dataset/train/train_50.json \ - --merge_from_path ./data/example_dataset/train/train_50_sample_shuffle.json \ - ./data/example_dataset/train/train_50_sample.json \ - --output_path ./data/example_dataset/train/train_merge.json \ - -# For concat.py: if you simply want to merge multiple files or a directory, use following. -# You can also specify multiple files after --merge_from_path -python scripts/data_preprocess/concat.py \ - --merge_from_path ./data/example_dataset/train/*.json \ - --output_path ./data/example_dataset/train/train_merge.json \ - -# For concat_shuffle_split.py: if you simply want to merge multiple files or a directory, use following. -python scripts/data_preprocess/concat_shuffle_split.py \ - --merge_from_path ./data/example_dataset/train/*.json \ - --output_path ./data/processed_dataset/ \ \ No newline at end of file diff --git a/scripts/data_preprocess/sample.py b/scripts/data_preprocess/sample.py deleted file mode 100644 index 0a503d872..000000000 --- a/scripts/data_preprocess/sample.py +++ /dev/null @@ -1,79 +0,0 @@ -#!/usr/bin/env python -# coding=utf-8 -# Copyright 2023 Statistics and Machine Learning Research Group at HKUST. All rights reserved. -""" -Samples a certain ratio of instances from a dataset. -""" -from __future__ import absolute_import - -import argparse -import json -import random -import sys -import textwrap - -def parse_argument(sys_argv): - """Parses arguments from command line. - Args: - sys_argv: the list of arguments (strings) from command line. - Returns: - A struct whose member corresponds to the required (optional) variable. - For example, - ``` - args = parse_argument(['main.py' '--input', 'a.txt', '--num', '10']) - args.input # 'a.txt' - args.num # 10 - ``` - """ - parser = argparse.ArgumentParser( - formatter_class=argparse.RawTextHelpFormatter) - - # Training parameters - parser.add_argument( - "--dataset_path", type=str, - default=None, - help="input dataset path, reads from stdin by default" - ) - parser.add_argument( - "--output_path", type=str, - default=None, - help="output dataset path, writes to stdout by default" - ) - parser.add_argument( - "--ratio", type=float, required=True, - help="sample ratio, will be floored if number of samples is not a int" - ) - parser.add_argument( - "--seed", type=int, default=42, - help="pseudorandom seed" - ) - - # Parses from commandline - args = parser.parse_args(sys_argv[1:]) - - return args - - -def main(): - args = parse_argument(sys.argv) - if args.dataset_path is not None: - with open(args.dataset_path, "r") as fin: - data_dict = json.load(fin) - else: - data_dict = json.load(sys.stdin) - - random.seed(args.seed) - num_instances = len(data_dict["instances"]) - num_sample = int(num_instances * args.ratio) - - data_dict["instances"] = random.sample(data_dict["instances"], num_sample) - - if args.output_path is not None: - with open(args.output_path, "w") as fout: - json.dump(data_dict, fout, indent=4, ensure_ascii=False) - else: - json.dump(data_dict, sys.stdout, indent=4, ensure_ascii=False) - - -if __name__ == "__main__": - main() diff --git a/scripts/data_preprocess/shuffle.py b/scripts/data_preprocess/shuffle.py deleted file mode 100644 index 7572efacd..000000000 --- a/scripts/data_preprocess/shuffle.py +++ /dev/null @@ -1,72 +0,0 @@ -#!/usr/bin/env python -# coding=utf-8 -# Copyright 2023 Statistics and Machine Learning Research Group at HKUST. All rights reserved. -""" -Samples a certain ratio of instances from a dataset. -""" -from __future__ import absolute_import - -import argparse -import json -import random -import sys -import textwrap - -def parse_argument(sys_argv): - """Parses arguments from command line. - Args: - sys_argv: the list of arguments (strings) from command line. - Returns: - A struct whose member corresponds to the required (optional) variable. - For example, - ``` - args = parse_argument(['main.py' '--input', 'a.txt', '--num', '10']) - args.input # 'a.txt' - args.num # 10 - ``` - """ - parser = argparse.ArgumentParser( - formatter_class=argparse.RawTextHelpFormatter) - - # Training parameters - parser.add_argument( - "--dataset_path", type=str, - default=None, - help="input dataset path, reads from stdin by default" - ) - parser.add_argument( - "--output_path", type=str, - default=None, - help="output dataset path, writes to stdout by default" - ) - parser.add_argument( - "--seed", type=int, default=42, - help="pseudorandom seed" - ) - - # Parses from commandline - args = parser.parse_args(sys_argv[1:]) - - return args - - -def main(): - args = parse_argument(sys.argv) - if args.dataset_path is not None: - with open(args.dataset_path, "r") as fin: - data_dict = json.load(fin) - else: - data_dict = json.load(sys.stdin) - - random.seed(args.seed) - random.shuffle(data_dict["instances"]) - - if args.output_path is not None: - with open(args.output_path, "w") as fout: - json.dump(data_dict, fout, indent=4, ensure_ascii=False) - else: - json.dump(data_dict, sys.stdout, indent=4, ensure_ascii=False) - - -if __name__ == "__main__": - main() diff --git a/scripts/run_dpov2_align.sh b/scripts/run_dpov2_align.sh deleted file mode 100644 index d9430abff..000000000 --- a/scripts/run_dpov2_align.sh +++ /dev/null @@ -1,57 +0,0 @@ -#!/bin/bash -model_name_or_path=meta-llama/Meta-Llama-3-8B-Instruct -dataset_path=data/iterative-prompt/train -output_dir=output_models/dpov2_align - -# DPO related arguments -reference_model_name_or_path=meta-llama/Meta-Llama-3-8B-Instruct -eval_dataset_path=data/iterative-prompt/eval -margin_scale=1.0 -max_prompt_length=1000 -loss_type=sigmoid -sampling_paired_method=max_min -mask_prompt=True -length_penalty=0 - -# Align -exp_id=dpov2_align -project_dir=$(cd "$(dirname $0)"/..; pwd) -log_dir=${project_dir}/log/${exp_id} -mkdir -p ${output_dir} ${log_dir} - -accelerate launch --config_file configs/accelerate_fsdp_config.yaml \ - examples/dpov2_train.py \ - --model_name_or_path ${model_name_or_path} \ - --trust_remote_code 0 \ - --reference_model_name_or_path ${reference_model_name_or_path} \ - --do_train True \ - --dataset_path ${dataset_path} \ - --eval_dataset_path ${eval_dataset_path} \ - --margin_scale ${margin_scale} \ - --max_prompt_length ${max_prompt_length} \ - --loss_type ${loss_type} \ - --sampling_paired_method ${sampling_paired_method} \ - --mask_prompt ${mask_prompt} \ - --length_penalty ${length_penalty} \ - --bf16 True \ - --torch_dtype bfloat16 \ - --learning_rate 5e-7 \ - --lr_scheduler_type cosine \ - --warmup_steps 100 \ - --optim paged_adamw_32bit \ - --per_device_train_batch_size 1 \ - --per_device_eval_batch_size 1 \ - --gradient_accumulation_steps 16 \ - --gradient_checkpointing True \ - --num_train_epochs 2 \ - --logging_steps 2 \ - --save_strategy epoch \ - --save_steps 5000 \ - --evaluation_strategy steps \ - --eval_steps 100 \ - --output_dir ${output_dir} \ - --run_name ${exp_id} \ - --report_to wandb \ - --seed 42 \ - | tee ${log_dir}/train.log \ - 2> ${log_dir}/train.err \ No newline at end of file diff --git a/scripts/run_inference.sh b/scripts/run_inference.sh deleted file mode 100755 index 3e89ac3e4..000000000 --- a/scripts/run_inference.sh +++ /dev/null @@ -1,19 +0,0 @@ -#!/bin/bash -# An interactive inference script without context history, i.e. the chatbot -# won't have conversation memory. - -model=gpt2 -lora_args="" -if [ $# -ge 1 ]; then - model=$1 -fi -if [ $# -ge 2 ]; then - lora_args="--lora_model_path $2" -fi - -accelerate launch --config_file configs/accelerate_fsdp_config.yaml \ - examples/inference.py \ - --model_name_or_path ${model} \ - --max_new_tokens 256 \ - --temperature 1.0 \ - ${lora_args} diff --git a/scripts/run_raft_align.sh b/scripts/run_raft_align.sh deleted file mode 100755 index 1215d33cf..000000000 --- a/scripts/run_raft_align.sh +++ /dev/null @@ -1,49 +0,0 @@ -#!/bin/bash -# Please run this script under project directory. - -deepspeed_args="--master_port=11110" # Default argument -if [ $# -ge 1 ]; then - deepspeed_args="$1" -fi - -exp_id=raft_align -project_dir=$(cd "$(dirname $0)"/..; pwd) -output_dir=${project_dir}/output_models/${exp_id} -log_dir=${project_dir}/log/${exp_id} - -if [ ! -d data/hh_rlhf ]; then - cd data && ./download.sh hh_rlhf && cd - -fi - -mkdir -p ${output_dir} ${log_dir} - -export PYTHONPATH=. -deepspeed ${deepspeed_args} \ - examples/raft_align.py \ - --model_name_or_path gpt2 \ - --num_raft_iteration 20 \ - --learning_rate 2e-5 \ - --lr_scheduler_type "constant" \ - --bf16 \ - --deepspeed configs/archive/ds_config_zero2.json \ - --dataset_path ${project_dir}/data/hh_rlhf/rlhf_prompt \ - --output_reward_path ${project_dir}/tmp/raft_aligner/reward.txt \ - --output_dir ${output_dir} --overwrite_output_dir \ - --run_name ${exp_id} \ - --num_train_epochs 4 \ - --per_device_train_batch_size 1 \ - --per_device_eval_batch_size 1 \ - --validation_split_percentage 0 \ - --logging_steps 1 \ - --do_train \ - --ddp_timeout 72000 \ - --save_steps 7777 \ - --dataloader_num_workers 1 \ - --preprocessing_num_workers 12 \ - --inference_batch_size_per_device 1 \ - --collection_strategy "local" \ - --raft_batch_size 1024 \ - --output_min_length 96 \ - --top_reward_percentage 0.125 \ - | tee ${log_dir}/raft_align.log \ - 2> ${log_dir}/raft_align.err diff --git a/scripts/run_reward_modeling.sh b/scripts/run_reward_modeling.sh deleted file mode 100644 index 9b8c2b9d6..000000000 --- a/scripts/run_reward_modeling.sh +++ /dev/null @@ -1,88 +0,0 @@ -#!/bin/bash -# Copyright 2024 Statistics and Machine Learning Research Group. All rights reserved. -# Parses arguments -model_name_or_path=google/gemma-2b-it -train_dataset_path=data/ultrafeedback-binarized-preferences-cleaned/train -eval_dataset_path=data/ultrafeedback-binarized-preferences-cleaned/train -output_dir=output_models/reward_modeling -conversation_template=gemma - -# Safety related arguments -trust_remote_code=0 - -while [[ $# -ge 1 ]]; do - key="$1" - case ${key} in - -m|--model_name_or_path) - model_name_or_path="$2" - shift - ;; - --train_dataset_path) - train_dataset_path="$2" - shift - ;; - --eval_dataset_path) - eval_dataset_path="$2" - shift - ;; - -o|--output_model_path) - output_dir="$2" - shift - ;; - --conversation_template) - conversation_template="$2" - shift - ;; - --trust_remote_code) - trust_remote_code="$2" - shift - ;; - *) - echo "error: unknown option \"${key}\"" 1>&2 - exit 1 - esac - shift -done - -# Finetune -exp_id=reward_modeling -project_dir=$(cd "$(dirname $0)"/..; pwd) -log_dir=${project_dir}/log/${exp_id} -mkdir -p ${output_dir} ${log_dir} - -accelerate launch --config_file configs/accelerate_fsdp_config.yaml \ - examples/reward_modeling.py \ - --model_name_or_path ${model_name_or_path} \ - --arch_type "text_regression" \ - --do_train True \ - --dataset_path ${train_dataset_path} \ - --conversation_template ${conversation_template} \ - --output_dir ${output_dir} --overwrite_output_dir \ - --use_flash_attention True \ - --block_size 4096 \ - --learning_rate 1e-5 \ - --per_device_train_batch_size 1 \ - --per_device_eval_batch_size 1 \ - --num_train_epochs 0.001 \ - --weight_decay 0.001 \ - --evaluation_strategy "steps" \ - --save_strategy "steps" \ - --save_steps 999999 \ - --gradient_accumulation_steps 32 \ - --gradient_checkpointing True \ - --remove_unused_columns False \ - --bf16 True \ - --torch_dtype bfloat16 \ - --logging_strategy "steps" \ - --logging_steps 10 \ - --optim "paged_adamw_32bit" \ - --lr_scheduler_type "cosine" \ - --warmup_ratio 0.03 \ - --report_to 'wandb' \ - --run_name ${exp_id} \ - --do_eval True \ - --eval_dataset_path ${eval_dataset_path} \ - --eval_steps 999999 \ - --preprocessing_num_workers 4 \ - | tee ${log_dir}/train.log \ - 2> ${log_dir}/train.err \ No newline at end of file diff --git a/scripts/run_reward_modeling_with_lisa.sh b/scripts/run_reward_modeling_with_lisa.sh deleted file mode 100644 index f3ad3ea2f..000000000 --- a/scripts/run_reward_modeling_with_lisa.sh +++ /dev/null @@ -1,100 +0,0 @@ -#!/bin/bash -# Copyright 2024 Statistics and Machine Learning Research Group. All rights reserved. -# Parses arguments -model_name_or_path=google/gemma-2b-it -train_dataset_path=data/ultrafeedback-binarized-preferences-cleaned/train -eval_dataset_path=data/ultrafeedback-binarized-preferences-cleaned/train -output_dir=output_models/reward_modeling_lisa -conversation_template=gemma -lisa_activated_layers=1 -lisa_interval_steps=20 - -# Safety related arguments -trust_remote_code=0 - -while [[ $# -ge 1 ]]; do - key="$1" - case ${key} in - -m|--model_name_or_path) - model_name_or_path="$2" - shift - ;; - --train_dataset_path) - train_dataset_path="$2" - shift - ;; - --eval_dataset_path) - eval_dataset_path="$2" - shift - ;; - --lisa_activated_layers) - lisa_activated_layers="$2" - shift - ;; - --lisa_interval_steps) - lisa_interval_steps="$2" - shift - ;; - -o|--output_model_path) - output_dir="$2" - shift - ;; - --conversation_template) - conversation_template="$2" - shift - ;; - --trust_remote_code) - trust_remote_code="$2" - shift - ;; - *) - echo "error: unknown option \"${key}\"" 1>&2 - exit 1 - esac - shift -done - -# Finetune -exp_id=reward_modeling_lisa -project_dir=$(cd "$(dirname $0)"/..; pwd) -log_dir=${project_dir}/log/${exp_id} -mkdir -p ${output_dir} ${log_dir} - -accelerate launch --config_file configs/accelerate_fsdp_config.yaml \ - examples/reward_modeling.py \ - --model_name_or_path ${model_name_or_path} \ - --arch_type "text_regression" \ - --do_train True \ - --dataset_path ${train_dataset_path} \ - --conversation_template ${conversation_template} \ - --output_dir ${output_dir} --overwrite_output_dir \ - --use_flash_attention True \ - --block_size 4096 \ - --learning_rate 1e-5 \ - --per_device_train_batch_size 1 \ - --per_device_eval_batch_size 1 \ - --num_train_epochs 2 \ - --weight_decay 0.001 \ - --evaluation_strategy "steps" \ - --save_strategy "steps" \ - --save_steps 999999 \ - --gradient_accumulation_steps 32 \ - --gradient_checkpointing True \ - --remove_unused_columns False \ - --bf16 True \ - --torch_dtype bfloat16 \ - --logging_strategy "steps" \ - --logging_steps 10 \ - --optim "paged_adamw_32bit" \ - --lr_scheduler_type "cosine" \ - --warmup_ratio 0.03 \ - --report_to 'wandb' \ - --run_name ${exp_id} \ - --do_eval True \ - --eval_dataset_path ${eval_dataset_path} \ - --eval_steps 999999 \ - --use_lisa True \ - --lisa_activated_layers ${lisa_activated_layers} \ - --lisa_interval_steps ${lisa_interval_steps} \ - | tee ${log_dir}/train.log \ - 2> ${log_dir}/train.err \ No newline at end of file diff --git a/scripts/run_reward_modeling_with_lora.sh b/scripts/run_reward_modeling_with_lora.sh deleted file mode 100644 index f0fe44622..000000000 --- a/scripts/run_reward_modeling_with_lora.sh +++ /dev/null @@ -1,89 +0,0 @@ -#!/bin/bash -# Copyright 2024 Statistics and Machine Learning Research Group. All rights reserved. -# Parses arguments -model_name_or_path=google/gemma-2b-it -train_dataset_path=data/ultrafeedback-binarized-preferences-cleaned/train -eval_dataset_path=data/ultrafeedback-binarized-preferences-cleaned/train -output_dir=output_models/reward_modeling_lora -conversation_template=gemma - -# Safety related arguments -trust_remote_code=0 - -while [[ $# -ge 1 ]]; do - key="$1" - case ${key} in - -m|--model_name_or_path) - model_name_or_path="$2" - shift - ;; - --train_dataset_path) - train_dataset_path="$2" - shift - ;; - --eval_dataset_path) - eval_dataset_path="$2" - shift - ;; - -o|--output_model_path) - output_dir="$2" - shift - ;; - --conversation_template) - conversation_template="$2" - shift - ;; - --trust_remote_code) - trust_remote_code="$2" - shift - ;; - *) - echo "error: unknown option \"${key}\"" 1>&2 - exit 1 - esac - shift -done - -# Finetune -exp_id=reward_modeling_lora -project_dir=$(cd "$(dirname $0)"/..; pwd) -log_dir=${project_dir}/log/${exp_id} -mkdir -p ${output_dir} ${log_dir} - -accelerate launch --config_file configs/accelerate_fsdp_config.yaml \ - examples/reward_modeling.py \ - --model_name_or_path ${model_name_or_path} \ - --arch_type "text_regression" \ - --do_train True \ - --dataset_path ${train_dataset_path} \ - --conversation_template ${conversation_template} \ - --output_dir ${output_dir} --overwrite_output_dir \ - --use_flash_attention True \ - --block_size 4096 \ - --learning_rate 1e-5 \ - --per_device_train_batch_size 1 \ - --per_device_eval_batch_size 1 \ - --num_train_epochs 2 \ - --weight_decay 0.001 \ - --evaluation_strategy "steps" \ - --save_strategy "steps" \ - --save_steps 999999 \ - --gradient_accumulation_steps 32 \ - --gradient_checkpointing True \ - --remove_unused_columns False \ - --bf16 True \ - --torch_dtype bfloat16 \ - --logging_strategy "steps" \ - --logging_steps 10 \ - --optim "paged_adamw_32bit" \ - --lr_scheduler_type "cosine" \ - --warmup_ratio 0.03 \ - --report_to 'wandb' \ - --run_name ${exp_id} \ - --do_eval True \ - --eval_dataset_path ${eval_dataset_path} \ - --eval_steps 999999 \ - --use_lora True \ - --lora_r 8 \ - | tee ${log_dir}/train.log \ - 2> ${log_dir}/train.err \ No newline at end of file diff --git a/scripts/speculative_decoding/README.md b/scripts/speculative_decoding/README.md deleted file mode 100644 index ccf112b1a..000000000 --- a/scripts/speculative_decoding/README.md +++ /dev/null @@ -1,69 +0,0 @@ -# Speculative Decoding -## Introduction -[Speculative Decoding (Ref: arXiv:2211.17192v2)](https://arxiv.org/abs/2211.17192) is now available for playing via: -```bash -python ./examples/speculative_inference.py \ - --model # your_model_name_or_path - --draft_model # your_draft_model_name_or_path - --temperature # your_temperature - --gamma # your_gamma - --max_new_tokens # your_max_new_tokens - --gpu # your_gpu_id -``` -For example, -```bash -python ./examples/speculative_inference.py \ - --model gpt2-xl - --draft_model gpt2 - --temperature 0.3 - --gamma 5 - --max_new_tokens 512 - --gpu 0 -``` -Another example, -```bash -python ./examples/speculative_inference.py \ - --model /home/eric/Documents/models/gpt2-xl - --draft_model /home/eric/Documents/models/gpt2 - --temperature 0 - --gamma 3 - --max_new_tokens 1024 - --gpu 7 -``` -## Parameter Instruction -`model`, `draft_model` -- Huggingface model name or locally cached model path. -- Currently only supports huggingface decoder only models. -- `model` refers to the target model (i.e., the large model you want to accelerate) in the paper. -- `draft_model` refers to the draft model in the paper. - -`temperature` -- Temperature for sampling. When temperature <= 1e-6, will use argmax sampling. - -`gamma` -- Number of tokens that the draft model will generate at each step. See the paper for more details. - -`max_new_tokens` -- Maximum number of tokens that the speculative inference will generate. -- TODO: currently the speculative decoding will always generate `max_new_tokens` tokens. We will add a `stop_token` in the future. - -`gpu` -- gpu id, currently speculative inference only support single gpu. - -## Experiments -We tested the speculative inference using the first 100 inputs from alpaca test dataset as prompts. When `model=gpt2-xl`, `draft_model=gpt2`, `temperature=0.`, `max_new_tokens=512`, we observed the following acceleration: - -|gamma|speedup (inference time)|speed up (num of forwards) -|--|--|--| -|1|1.75x|1.96x| -|2|2.29x|2.89x| -|3|2.71x|3.77x| -|4|3.06x|4.63x| -|5|3.35x|5.44x| -|6|3.65x|6.23x| -|7|3.82x|6.94x| -|8|3.96x|7.64x| -|9|4.05x|8.33x| -|10|4.14x|9.00x| - -Note that the speedup may be overestimated. When `temperature=0`, `gpt2-xl` and `gpt2` tend to generate duplicated tokens as the number of tokens generated increases, thus making the target model more likely to accept the draft model's output. \ No newline at end of file diff --git a/scripts/tools/print_model_architecture.py b/scripts/tools/print_model_architecture.py deleted file mode 100644 index 094f65032..000000000 --- a/scripts/tools/print_model_architecture.py +++ /dev/null @@ -1,22 +0,0 @@ -#!/usr/bin/env python -#coding=utf-8 -import argparse -import sys -from transformers import AutoModel - -def parse_argument(sys_argv): - parser = argparse.ArgumentParser(formatter_class=argparse.RawTextHelpFormatter) - parser.add_argument("--model_name_or_path", type=str, default='gpt2') - args = parser.parse_args(sys_argv[1:]) - return args - -def main(): - args = parse_argument(sys.argv) - model_name = args.model_name_or_path - model = AutoModel.from_pretrained(model_name) - - print(model.config) - print(model) - -if __name__ == "__main__": - main() diff --git a/scripts/vocab_extension/README.md b/scripts/vocab_extension/README.md deleted file mode 100644 index 5582d7d16..000000000 --- a/scripts/vocab_extension/README.md +++ /dev/null @@ -1,23 +0,0 @@ -# Vocab Extension -## Train & Merge Tokenizer -To automatically convert data, train a SentencePiece tokenizer, and merge the tokenizer, you can run the following script: -``` -bash scripts/vocab_extension/train_merge_tokenizer.sh -``` -Alternatively, you can run each of the three steps separately: - -## Convert JSON Data to TXT -To convert JSON data to TXT for sentencepiece tokenizer training, run: -``` -bash scripts/vocab_extension/convert_json_to_txt.sh -``` -## Train SentencePiece Tokenizer -To train a SentencePiece tokenizer, run: -``` -bash scripts/vocab_extension/train_tokenizer.sh -``` -## Merge New Tokenizer with the Origin One -To merge a new tokenizer with the original one, run: -``` -bash scripts/vocab_extension/merge_tokenizer.sh -``` \ No newline at end of file diff --git a/scripts/vocab_extension/convert_json_to_txt.sh b/scripts/vocab_extension/convert_json_to_txt.sh deleted file mode 100644 index 5d2a57e95..000000000 --- a/scripts/vocab_extension/convert_json_to_txt.sh +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/bash - -cd data && bash download.sh wiki_zh_eval && cd - - -python utils/convert_json_to_txt.py --dataset_path ./data/wiki_zh_eval \ - --output_path ./data/wiki_zh_eval/converted_data.txt \ - --overwrite True \ No newline at end of file diff --git a/scripts/vocab_extension/merge_tokenizer.sh b/scripts/vocab_extension/merge_tokenizer.sh deleted file mode 100644 index 0cd1722c0..000000000 --- a/scripts/vocab_extension/merge_tokenizer.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/bash -mkdir -p ./output_models/new_tokenizer -python utils/merge_tokenizer.py --tokenizer_dir openlm-research/open_llama_3b \ - --chinese_sp_model_file ./output_models/new_tokenizer/example.model \ - --output_dir ./output_models/merged_tokenizer \ \ No newline at end of file diff --git a/scripts/vocab_extension/train_merge_tokenizer.sh b/scripts/vocab_extension/train_merge_tokenizer.sh deleted file mode 100644 index 2e63e84b6..000000000 --- a/scripts/vocab_extension/train_merge_tokenizer.sh +++ /dev/null @@ -1,24 +0,0 @@ -#!/bin/bash - -# download data -cd data && bash download.sh wiki_zh_eval && cd - - -# convert json to txt for sentencepiece -python utils/convert_json_to_txt.py --dataset_path ./data/wiki_zh_eval \ - --output_path ./data/wiki_zh_eval/converted_data.txt \ - --overwrite True - -# train a new tokenizer -mkdir -p ./output_models/new_tokenizer -python utils/train_tokenizer.py --dataset_path ./data/wiki_zh_eval/converted_data.txt \ - --model_type bpe \ - --output_dir ./output_models/new_tokenizer \ - --user_defined_symbols 0,1,2,3,4,5,6,7,8,9,% \ - --vocab_size 20000 \ - --max_sentencepiece_length 4 - -# merge the new tokenizer with the old one -mkdir -p ./output_models/merged_tokenizer -python utils/merge_tokenizer.py --chinese_sp_model_file ./output_models/new_tokenizer/example.model \ - --tokenizer_dir openlm-research/open_llama_3b \ - --output_dir ./output_models/merged_tokenizer \ No newline at end of file diff --git a/scripts/vocab_extension/train_tokenizer.sh b/scripts/vocab_extension/train_tokenizer.sh deleted file mode 100644 index d61275499..000000000 --- a/scripts/vocab_extension/train_tokenizer.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/bash -mkdir -p ./output_models/merged_tokenizer -python utils/train_tokenizer.py --dataset_path ./data/wiki_zh_eval/converted_data.txt \ - --model_type bpe \ - --output_dir ./output_models/new_tokenizer \ - --user_defined_symbols 0,1,2,3,4,5,6,7,8,9,% \ - --vocab_size 20000 \ - --max_sentencepiece_length 4 \ No newline at end of file diff --git a/service/app.py b/service/app.py deleted file mode 100644 index 29b92daa9..000000000 --- a/service/app.py +++ /dev/null @@ -1,149 +0,0 @@ -from dataclasses import dataclass, field -import json -import os -from typing import Optional - -from accelerate import Accelerator -import torch -from transformers import HfArgumentParser - -from lmflow.args import ModelArguments -from lmflow.models.auto_model import AutoModel -from lmflow.utils.versioning import is_flask_available - -if is_flask_available(): - from flask import Flask, request, stream_with_context - from flask import render_template - from flask_cors import CORS -else: - raise ImportError("Flask is not available. Please install flask and flask_cors.") - -WINDOW_LENGTH = 512 - -@dataclass -class AppArguments: - end_string: Optional[str] = field( - default="##", - metadata={ - "help": "end string mark of the chatbot's output" - }, - ) - max_new_tokens: Optional[int] = field( - default=200, - metadata={ - "help": "maximum number of generated tokens" - }, - ) - -parser = HfArgumentParser(( - ModelArguments, - AppArguments, -)) - -model_args, app_args = ( - parser.parse_args_into_dataclasses() - ) - -app = Flask(__name__) -CORS(app) -ds_config_path = "./examples/ds_config.json" -with open (ds_config_path, "r") as f: - ds_config = json.load(f) - - -local_rank = int(os.getenv("LOCAL_RANK", "0")) -world_size = int(os.getenv("WORLD_SIZE", "1")) -torch.cuda.set_device(local_rank) -model = AutoModel.get_model(model_args, do_train=False, ds_config=ds_config) -accelerator = Accelerator() - -def stream_generate(inputs,context_len = 1024, max_new_tokens=128, end_string="##"): - - - max_src_len = context_len - max_new_tokens - len(end_string) - input_ids = model.tokenizer(inputs).input_ids - input_echo_len = len(input_ids) - output_ids = list(input_ids) - input_ids = input_ids[-max_src_len:] - - past_key_values = out = None - flag_stop = False - for i in range(0, max_new_tokens): - with accelerator.autocast(): - if i == 0: - with torch.no_grad(): - out = model.backend_model(torch.as_tensor([input_ids], device=local_rank), use_cache=True) - logits = out.logits - past_key_values = out.past_key_values - else: - with torch.no_grad(): - out = model.backend_model( - input_ids=torch.as_tensor([[token]], device=local_rank), - use_cache=True, - past_key_values=past_key_values, - ) - logits = out.logits - past_key_values = out.past_key_values - - last_token_logits = logits[0, -1, :] - token = int(torch.argmax(last_token_logits)) - output_ids.append(token) - - tmp_output_ids = output_ids[input_echo_len:] - - output = model.tokenizer.decode( - tmp_output_ids, - skip_special_tokens=True, - spaces_between_special_tokens=False, - ) - - if end_string in output: - index = output.index(end_string) - output = output[:index] - flag_stop = True - yield output.replace("\ufffd","") - - if flag_stop == True: - break - -@app.route('/predict',methods = ['POST']) -def predict(): - if(request.method == "POST"): - try: - user_input = request.get_json()["Input"] - conversation = request.get_json()["History"] - - history_input = "" - if(len(conversation) >= 2): - if(len(conversation) == 2): - history_input ="###Human: " + user_input +" " - else: - for i in range(0, len(conversation)-1): - if(i % 2 == 0): - history_input = history_input + "###Human: " + conversation[i+1]["content"] + " " - elif(i % 2 == 1): - history_input = history_input + "###Assistant:" + conversation[i+1]["content"] - history_input = history_input + "###Assistant:" - - if len(model.encode(history_input))> WINDOW_LENGTH: - inputs = model.encode(history_input) - inputs = inputs[-WINDOW_LENGTH:] - history_input = model.decode(inputs) - - return app.response_class(stream_with_context(stream_generate(history_input, - max_new_tokens=app_args.max_new_tokens, - end_string=app_args.end_string))) - except Exception as ex: - print(ex) - text_out = ex - else: - text_out = "Not POST Method" - return text_out - -@app.route('/',methods = ['GET']) -def login(): - - return render_template('index.html') - - -app.run(port = 5000, debug = False) diff --git a/service/static/assets/background.png b/service/static/assets/background.png deleted file mode 100644 index cb656f70a352586c571d63183e8d9828dca17a7e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 244372 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

ZMc#-p^64lM_20%$O;^Q_xp zE&A`h8nh$0I;|S?7ibVv-4WRaF+p83=vw?|&IkV|vD=jf0qLuC4{8BMP$E?Ov){^I zQcaf&~ zfQ6v}$W|K}iR0(XEq=8Fp}8z{OZTh+Lcf&YVG?UEeLQsm^*-823};*vVfuMC8JkDj zBYXU;BDuU%@23Q9k2ot%gPfuEpE3{7W!BHPmkQz@r6Sbg`6eu3WT7T)doFod&THz( zYb+95Tj`TRL=7?G1KurjyZxA`M;xQ#&yx21n1iZseh~V@jFAf5 zSFCEeXw@EO5BYt_?V^8}IK1>X@A*w@gkC5~{9mK{!cXF6R>Nq@Sw=VCf@1~2 z@gu}j!pm3dZ;~}0^LY|D?1}**6K=8t3?Gm0|Bbfz(riB^x?w8Sl=eVrY)-kFM;aFv zl*Q&tDx3`#0rcIgwkLVEUaUHNV5FVEf#S@4hivW0NsMvQ9JdyMg*lMJN2U2i^T^}d zEy>Opwj|wqzk}SoBeGt>(=#F64$JL@s(_!r1%26C3a{RNNsWjCJl8RbP2OZSjK3uy z5<&swO>B_j>~Dpi#%d7eP|U0o$={`a`%`e&-ytx51O`mZrw>86dwMKd)!*(%0Alu; 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