From 0717f6bd34ae9a582ece0ba6183f49a83f35a2a3 Mon Sep 17 00:00:00 2001 From: "yuze.zyz" Date: Mon, 17 Feb 2025 15:35:27 +0800 Subject: [PATCH 1/7] support swanlab --- swift/llm/argument/train_args.py | 20 +++++++++ swift/llm/train/callback.py | 4 ++ swift/ui/llm_train/llm_train.py | 3 ++ swift/ui/llm_train/report_to.py | 71 ++++++++++++++++++++++++++++++++ 4 files changed, 98 insertions(+) create mode 100644 swift/ui/llm_train/report_to.py diff --git a/swift/llm/argument/train_args.py b/swift/llm/argument/train_args.py index 1d109aaa0d..e2664f007c 100644 --- a/swift/llm/argument/train_args.py +++ b/swift/llm/argument/train_args.py @@ -37,6 +37,12 @@ class Seq2SeqTrainingOverrideArguments(Seq2SeqTrainingArguments): logging_first_step: bool = True + swanlab_token: Optional[str] = None + swanlab_project: str = 'ms-swift' + swanlab_workspace: Optional[str] = None + swanlab_exp_name: Optional[str] = None + swanlab_mode: Literal['cloud', 'local'] = 'cloud' + def _init_output_dir(self): if self.output_dir is not None: return @@ -58,6 +64,18 @@ def _init_metric_for_best_model(self): self.metric_for_best_model = 'rouge-l' if self.predict_with_generate else 'loss' def __post_init__(self): + if 'swanlab' in self.report_to: + from transformers.integrations import INTEGRATION_TO_CALLBACK + import swanlab + from swanlab.integration.transformers import SwanLabCallback + if self.swanlab_token: + swanlab.login(self.swanlab_token) + INTEGRATION_TO_CALLBACK['swanlab'] = SwanLabCallback( + project=self.swanlab_project, + workspace=self.swanlab_workspace, + experiment_name=self.swanlab_exp_name, + mode=self.swanlab_mode, + ) self._init_output_dir() self._init_metric_for_best_model() if self.greater_is_better is None and self.metric_for_best_model is not None: @@ -129,6 +147,8 @@ class TrainArguments(TorchAccArguments, TunerArguments, Seq2SeqTrainingOverrideA max_new_tokens: int = 64 temperature: float = 0. + use_swanlab: bool = False + def __post_init__(self) -> None: if self.resume_from_checkpoint: self.resume_from_checkpoint = to_abspath(self.resume_from_checkpoint, True) diff --git a/swift/llm/train/callback.py b/swift/llm/train/callback.py index 2c466519b9..5e6b787c79 100644 --- a/swift/llm/train/callback.py +++ b/swift/llm/train/callback.py @@ -78,3 +78,7 @@ def switch_active_layers(self): for idx in self.active_layers_indices: for param in layers[idx].parameters(): param.requires_grad = True + + +class SwanLabCallback(TrainerCallback): + diff --git a/swift/ui/llm_train/llm_train.py b/swift/ui/llm_train/llm_train.py index be04e2b204..14d934029f 100644 --- a/swift/ui/llm_train/llm_train.py +++ b/swift/ui/llm_train/llm_train.py @@ -25,6 +25,7 @@ from swift.ui.llm_train.lora import LoRA from swift.ui.llm_train.model import Model from swift.ui.llm_train.quantization import Quantization +from swift.ui.llm_train.report_to import ReportTo from swift.ui.llm_train.rlhf import RLHF from swift.ui.llm_train.runtime import Runtime from swift.ui.llm_train.save import Save @@ -51,6 +52,7 @@ class LLMTrain(BaseUI): Lisa, Galore, LlamaPro, + ReportTo, ] locale_dict: Dict[str, Dict] = { @@ -245,6 +247,7 @@ def do_build_ui(cls, base_tab: Type['BaseUI']): LlamaPro.build_ui(base_tab) SelfCog.build_ui(base_tab) Save.build_ui(base_tab) + ReportTo.build_ui(base_tab) Advanced.build_ui(base_tab) cls.element('train_type').change( diff --git a/swift/ui/llm_train/report_to.py b/swift/ui/llm_train/report_to.py new file mode 100644 index 0000000000..30fe57f086 --- /dev/null +++ b/swift/ui/llm_train/report_to.py @@ -0,0 +1,71 @@ +# Copyright (c) Alibaba, Inc. and its affiliates. +from typing import Type + +import gradio as gr + +from swift.ui.base import BaseUI + + +class ReportTo(BaseUI): + + group = 'llm_train' + + locale_dict = { + 'reporter': { + 'label': { + 'zh': '训练记录', + 'en': 'Training report' + }, + }, + 'report_to': { + 'label': { + 'zh': '训练记录方式', + 'en': 'Report to' + }, + }, + 'swanlab_token': { + 'label': { + 'zh': 'swanlab登录token', + 'en': 'The login token of swanlab' + }, + }, + 'swanlab_project': { + 'label': { + 'zh': 'swanlab项目名称', + 'en': 'Project of swanlab' + }, + }, + 'swanlab_workspace': { + 'label': { + 'zh': 'swanlab工作空间', + 'en': 'Workspace of swanlab' + }, + }, + 'swanlab_exp_name': { + 'label': { + 'zh': 'swanlab实验名称', + 'en': 'Experiment of swanlab' + }, + }, + 'swanlab_mode': { + 'label': { + 'zh': 'swanlab工作模式', + 'en': 'Work mode of swanlab' + }, + }, + } + + @classmethod + def do_build_ui(cls, base_tab: Type['BaseUI']): + with gr.Accordion(elem_id='reporter', open=False): + with gr.Blocks(): + with gr.Row(): + gr.Dropdown(elem_id='report_to', multiselect=True, + is_list=True, choices=['tensorboard', 'wandb', 'swanlab'], + allow_custom_value=True, scale=20) + gr.Textbox(elem_id='swanlab_token', lines=1, scale=20) + gr.Textbox(elem_id='swanlab_project', lines=1, scale=20) + with gr.Row(): + gr.Textbox(elem_id='swanlab_workspace', lines=1, scale=20) + gr.Textbox(elem_id='swanlab_exp_name', lines=1, scale=20) + gr.Dropdown(elem_id='swanlab_mode', scale=20) From dd773b652baa6ce0903d9850f25655ed2a1e885c Mon Sep 17 00:00:00 2001 From: "yuze.zyz" Date: Mon, 17 Feb 2025 15:42:58 +0800 Subject: [PATCH 2/7] add install notice --- swift/llm/argument/train_args.py | 5 ++++- swift/utils/__init__.py | 2 +- swift/utils/import_utils.py | 4 ++++ 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/swift/llm/argument/train_args.py b/swift/llm/argument/train_args.py index e2664f007c..979b32f16c 100644 --- a/swift/llm/argument/train_args.py +++ b/swift/llm/argument/train_args.py @@ -11,7 +11,7 @@ from swift.plugin import LOSS_MAPPING from swift.trainers import TrainerFactory from swift.utils import (add_version_to_work_dir, get_device_count, get_logger, get_pai_tensorboard_dir, - is_liger_available, is_local_master, is_mp, is_pai_training_job, use_torchacc) + is_liger_available, is_swanlab_available, is_local_master, is_mp, is_pai_training_job, use_torchacc) from .base_args import BaseArguments, to_abspath from .tuner_args import TunerArguments @@ -65,6 +65,9 @@ def _init_metric_for_best_model(self): def __post_init__(self): if 'swanlab' in self.report_to: + if not is_swanlab_available(): + raise ValueError(f'You are using swanlab as `report_to`, please install swanlab by ' + f'`pip install swanlab`') from transformers.integrations import INTEGRATION_TO_CALLBACK import swanlab from swanlab.integration.transformers import SwanLabCallback diff --git a/swift/utils/__init__.py b/swift/utils/__init__.py index 39d5f71a07..3183d914b7 100644 --- a/swift/utils/__init__.py +++ b/swift/utils/__init__.py @@ -3,7 +3,7 @@ from .env import (get_dist_setting, get_pai_tensorboard_dir, is_deepspeed_enabled, is_dist, is_dist_ta, is_local_master, is_master, is_mp, is_mp_ddp, is_pai_training_job, torchacc_trim_graph, use_hf_hub, use_torchacc) from .import_utils import (is_liger_available, is_lmdeploy_available, is_megatron_available, is_unsloth_available, - is_vllm_available, is_wandb_available, is_xtuner_available) + is_vllm_available, is_wandb_available, is_xtuner_available, is_swanlab_available) from .io_utils import JsonlWriter, append_to_jsonl, download_ms_file, get_file_mm_type, read_from_jsonl, write_to_jsonl from .logger import get_logger from .np_utils import get_seed, stat_array, transform_jsonl_to_df diff --git a/swift/utils/import_utils.py b/swift/utils/import_utils.py index bda2383ced..983229f23c 100644 --- a/swift/utils/import_utils.py +++ b/swift/utils/import_utils.py @@ -24,6 +24,10 @@ def is_liger_available(): return importlib.util.find_spec('liger_kernel') is not None +def is_swanlab_available(): + return importlib.util.find_spec('swanlab') is not None + + def is_xtuner_available(): return importlib.util.find_spec('xtuner') is not None From 7e2d22f7d9f04a0f7c77034562a6a91d9643aa93 Mon Sep 17 00:00:00 2001 From: tastelikefeet Date: Mon, 17 Feb 2025 19:18:23 +0800 Subject: [PATCH 3/7] fix --- swift/llm/argument/train_args.py | 42 ++++++++++++++++++------------- swift/llm/train/callback.py | 4 --- swift/ui/base.py | 8 +++--- swift/ui/llm_eval/llm_eval.py | 8 +++++- swift/ui/llm_export/llm_export.py | 8 +++++- swift/ui/llm_infer/llm_infer.py | 8 +++++- swift/ui/llm_train/llm_train.py | 33 +++++++++++++++++++----- 7 files changed, 75 insertions(+), 36 deletions(-) diff --git a/swift/llm/argument/train_args.py b/swift/llm/argument/train_args.py index 979b32f16c..2664fe12d5 100644 --- a/swift/llm/argument/train_args.py +++ b/swift/llm/argument/train_args.py @@ -38,7 +38,7 @@ class Seq2SeqTrainingOverrideArguments(Seq2SeqTrainingArguments): logging_first_step: bool = True swanlab_token: Optional[str] = None - swanlab_project: str = 'ms-swift' + swanlab_project: Optional[str] = None swanlab_workspace: Optional[str] = None swanlab_exp_name: Optional[str] = None swanlab_mode: Literal['cloud', 'local'] = 'cloud' @@ -64,21 +64,6 @@ def _init_metric_for_best_model(self): self.metric_for_best_model = 'rouge-l' if self.predict_with_generate else 'loss' def __post_init__(self): - if 'swanlab' in self.report_to: - if not is_swanlab_available(): - raise ValueError(f'You are using swanlab as `report_to`, please install swanlab by ' - f'`pip install swanlab`') - from transformers.integrations import INTEGRATION_TO_CALLBACK - import swanlab - from swanlab.integration.transformers import SwanLabCallback - if self.swanlab_token: - swanlab.login(self.swanlab_token) - INTEGRATION_TO_CALLBACK['swanlab'] = SwanLabCallback( - project=self.swanlab_project, - workspace=self.swanlab_workspace, - experiment_name=self.swanlab_exp_name, - mode=self.swanlab_mode, - ) self._init_output_dir() self._init_metric_for_best_model() if self.greater_is_better is None and self.metric_for_best_model is not None: @@ -94,6 +79,26 @@ def __post_init__(self): if getattr(self, 'gradient_checkpointing_kwargs', None): self.gradient_checkpointing_kwargs = self.parse_to_dict(self.gradient_checkpointing_kwargs) self._init_eval_strategy() + + def _init_swanlab(self): + if not is_swanlab_available(): + raise ValueError(f'You are using swanlab as `report_to`, please install swanlab by ' + f'`pip install swanlab`') + if not self.swanlab_project: + raise ValueError(f'Please specify a project existed in your swanlab page(https://swanlab.cn/space/~)') + if not self.swanlab_exp_name: + self.swanlab_exp_name = self.output_dir + from transformers.integrations import INTEGRATION_TO_CALLBACK + import swanlab + from swanlab.integration.transformers import SwanLabCallback + if self.swanlab_token: + swanlab.login(self.swanlab_token) + INTEGRATION_TO_CALLBACK['swanlab'] = SwanLabCallback( + project=self.swanlab_project, + workspace=self.swanlab_workspace, + experiment_name=self.swanlab_exp_name, + mode=self.swanlab_mode, + ) @dataclass @@ -150,8 +155,6 @@ class TrainArguments(TorchAccArguments, TunerArguments, Seq2SeqTrainingOverrideA max_new_tokens: int = 64 temperature: float = 0. - use_swanlab: bool = False - def __post_init__(self) -> None: if self.resume_from_checkpoint: self.resume_from_checkpoint = to_abspath(self.resume_from_checkpoint, True) @@ -194,6 +197,9 @@ def __post_init__(self) -> None: self._add_version() self.import_plugin() + if 'swanlab' in self.report_to: + self._init_swanlab() + def import_plugin(self): if not self.external_plugins: return diff --git a/swift/llm/train/callback.py b/swift/llm/train/callback.py index 5e6b787c79..2c466519b9 100644 --- a/swift/llm/train/callback.py +++ b/swift/llm/train/callback.py @@ -78,7 +78,3 @@ def switch_active_layers(self): for idx in self.active_layers_indices: for param in layers[idx].parameters(): param.requires_grad = True - - -class SwanLabCallback(TrainerCallback): - diff --git a/swift/ui/base.py b/swift/ui/base.py index 6e1c847137..ecca8a45ab 100644 --- a/swift/ui/base.py +++ b/swift/ui/base.py @@ -292,6 +292,8 @@ def get_argument_names(dataclass): @classmethod def update_input_model(cls, model, allow_keys=None, has_record=True, arg_cls=BaseArguments, is_ref_model=False): keys = cls.valid_element_keys() + if allow_keys: + keys = [key for key in keys if key in allow_keys] if not model: ret = [gr.update()] * (len(keys) + int(has_record)) @@ -320,8 +322,6 @@ def update_input_model(cls, model, allow_keys=None, has_record=True, arg_cls=Bas return [gr.update()] * (len(keys) + int(has_record)) values = [] for key in keys: - if allow_keys is not None and key not in allow_keys: - continue arg_value = getattr(args, key, None) if arg_value and key != 'model': if key in ('torch_dtype', 'bnb_4bit_compute_dtype'): @@ -342,8 +342,6 @@ def update_input_model(cls, model, allow_keys=None, has_record=True, arg_cls=Bas else: values = [] for key in keys: - if allow_keys is not None and key not in allow_keys: - continue if key not in ('template', 'model_type', 'ref_model_type', 'system'): values.append(gr.update()) elif key in ('template', 'model_type', 'ref_model_type'): @@ -370,7 +368,7 @@ def update_all_settings(cls, model, train_record, base_tab): return [gr.update()] * len(cls.elements()) cache = cls.load_cache(model, train_record) updates = [] - for key, value in cls.valid_elements().items(): + for key, value in base_tab.valid_elements().items(): if key in cache: updates.append(gr.update(value=cache[key])) else: diff --git a/swift/ui/llm_eval/llm_eval.py b/swift/ui/llm_eval/llm_eval.py index aa87607634..b542dbfbc1 100644 --- a/swift/ui/llm_eval/llm_eval.py +++ b/swift/ui/llm_eval/llm_eval.py @@ -14,6 +14,7 @@ from swift.llm import EvalArguments from swift.ui.base import BaseUI +from transformers.utils import is_torch_cuda_available, is_torch_npu_available from swift.ui.llm_eval.eval import Eval from swift.ui.llm_eval.model import Model from swift.ui.llm_eval.runtime import EvalRuntime @@ -157,7 +158,12 @@ def eval(cls, *args): gpus = ','.join(devices) cuda_param = '' if gpus != 'cpu': - cuda_param = f'CUDA_VISIBLE_DEVICES={gpus}' + if is_torch_npu_available(): + cuda_param = f'ASCEND_RT_VISIBLE_DEVICES={gpus}' + elif is_torch_cuda_available(): + cuda_param = f'CUDA_VISIBLE_DEVICES={gpus}' + else: + cuda_param = '' now = datetime.now() time_str = f'{now.year}{now.month}{now.day}{now.hour}{now.minute}{now.second}' file_path = f'output/{eval_args.model_type}-{time_str}' diff --git a/swift/ui/llm_export/llm_export.py b/swift/ui/llm_export/llm_export.py index 898ed67763..2883b2ce52 100644 --- a/swift/ui/llm_export/llm_export.py +++ b/swift/ui/llm_export/llm_export.py @@ -14,6 +14,7 @@ from swift.llm import ExportArguments from swift.ui.base import BaseUI +from transformers.utils import is_torch_cuda_available, is_torch_npu_available from swift.ui.llm_export.export import Export from swift.ui.llm_export.model import Model from swift.ui.llm_export.runtime import ExportRuntime @@ -154,7 +155,12 @@ def export(cls, *args): gpus = ','.join(devices) cuda_param = '' if gpus != 'cpu': - cuda_param = f'CUDA_VISIBLE_DEVICES={gpus}' + if is_torch_npu_available(): + cuda_param = f'ASCEND_RT_VISIBLE_DEVICES={gpus}' + elif is_torch_cuda_available(): + cuda_param = f'CUDA_VISIBLE_DEVICES={gpus}' + else: + cuda_param = '' now = datetime.now() time_str = f'{now.year}{now.month}{now.day}{now.hour}{now.minute}{now.second}' file_path = f'output/{export_args.model_type}-{time_str}' diff --git a/swift/ui/llm_infer/llm_infer.py b/swift/ui/llm_infer/llm_infer.py index 8a268ee518..98685d412f 100644 --- a/swift/ui/llm_infer/llm_infer.py +++ b/swift/ui/llm_infer/llm_infer.py @@ -16,6 +16,7 @@ from swift.llm import DeployArguments, InferArguments, InferClient, InferRequest, RequestConfig from swift.ui.base import BaseUI +from transformers.utils import is_torch_cuda_available, is_torch_npu_available from swift.ui.llm_infer.model import Model from swift.ui.llm_infer.runtime import Runtime from swift.utils import get_device_count, get_logger @@ -249,7 +250,12 @@ def deploy(cls, *args): gpus = ','.join(devices) cuda_param = '' if gpus != 'cpu': - cuda_param = f'CUDA_VISIBLE_DEVICES={gpus}' + if is_torch_npu_available(): + cuda_param = f'ASCEND_RT_VISIBLE_DEVICES={gpus}' + elif is_torch_cuda_available(): + cuda_param = f'CUDA_VISIBLE_DEVICES={gpus}' + else: + cuda_param = '' now = datetime.now() time_str = f'{now.year}{now.month}{now.day}{now.hour}{now.minute}{now.second}' file_path = f'output/{deploy_args.model_type}-{time_str}' diff --git a/swift/ui/llm_train/llm_train.py b/swift/ui/llm_train/llm_train.py index 14d934029f..1d999b9178 100644 --- a/swift/ui/llm_train/llm_train.py +++ b/swift/ui/llm_train/llm_train.py @@ -31,6 +31,7 @@ from swift.ui.llm_train.save import Save from swift.ui.llm_train.self_cog import SelfCog from swift.utils import get_device_count, get_logger +from transformers.utils import is_torch_cuda_available, is_torch_npu_available logger = get_logger() @@ -143,6 +144,12 @@ class LLMTrain(BaseUI): 'en': 'Select the training precision' } }, + 'envs': { + 'label': { + 'zh': '环境变量', + 'en': 'Extra env vars' + }, + }, 'use_ddp': { 'label': { 'zh': '使用DDP', @@ -236,6 +243,7 @@ def do_build_ui(cls, base_tab: Type['BaseUI']): choices=[str(i) for i in range(device_count)] + ['cpu'], value=default_device, scale=8) + gr.Textbox(elem_id='envs', scale=8) gr.Checkbox(elem_id='dry_run', value=False, scale=4) submit = gr.Button(elem_id='submit', scale=4, variant='primary') @@ -279,7 +287,7 @@ def update_runtime(cls): @classmethod def train(cls, *args): - ignore_elements = ('logging_dir', 'more_params', 'train_stage') + ignore_elements = ('logging_dir', 'more_params', 'train_stage', 'envs') default_args = cls.get_default_value_from_dataclass(RLHFArguments) kwargs = {} kwargs_is_list = {} @@ -342,6 +350,8 @@ def train(cls, *args): f'--logging_dir {sft_args.logging_dir} --ignore_args_error True' ddp_param = '' devices = other_kwargs['gpu_id'] + envs = other_kwargs['envs'] or '' + envs = envs.strip() devices = [d for d in devices if d] if other_kwargs['use_ddp']: assert int(other_kwargs['ddp_num']) > 0 @@ -350,22 +360,33 @@ def train(cls, *args): gpus = ','.join(devices) cuda_param = '' if gpus != 'cpu': - cuda_param = f'CUDA_VISIBLE_DEVICES={gpus}' - + if is_torch_npu_available(): + cuda_param = f'ASCEND_RT_VISIBLE_DEVICES={gpus}' + elif is_torch_cuda_available(): + cuda_param = f'CUDA_VISIBLE_DEVICES={gpus}' + else: + cuda_param = '' + log_file = os.path.join(sft_args.logging_dir, 'run.log') if sys.platform == 'win32': if cuda_param: cuda_param = f'set {cuda_param} && ' if ddp_param: ddp_param = f'set {ddp_param} && ' - run_command = f'{cuda_param}{ddp_param}start /b swift sft {params} > {log_file} 2>&1' + if envs: + envs = [env.strip() for env in envs.split(' ') if env.strip()] + _envs = '' + for env in envs: + _envs += f'set {env} && ' + envs = _envs + run_command = f'{cuda_param}{ddp_param}{envs}start /b swift sft {params} > {log_file} 2>&1' else: - run_command = f'{cuda_param} {ddp_param} nohup swift {cmd} {params} > {log_file} 2>&1 &' + run_command = f'{cuda_param} {ddp_param} {envs} nohup swift {cmd} {params} > {log_file} 2>&1 &' logger.info(f'Run training: {run_command}') if model: record = {} for key, value in zip(keys, args): - if key in default_args or key in ('more_params', 'train_stage', 'use_ddp', 'ddp_num', 'gpu_id'): + if key in default_args or key in ('more_params', 'train_stage', 'use_ddp', 'ddp_num', 'gpu_id', 'envs'): record[key] = value or None cls.save_cache(model, record) return run_command, sft_args, other_kwargs From 3abbf0509a59ecb1ef99c4b513a5aaaca1efab36 Mon Sep 17 00:00:00 2001 From: "yuze.zyz" Date: Mon, 17 Feb 2025 19:32:30 +0800 Subject: [PATCH 4/7] wip --- ...5\344\273\244\350\241\214\345\217\202\346\225\260.md" | 8 ++++++++ docs/source_en/Instruction/Command-line-parameters.md | 9 +++++++++ requirements/swanlab.txt | 1 + setup.py | 2 ++ 4 files changed, 20 insertions(+) create mode 100644 requirements/swanlab.txt diff --git "a/docs/source/Instruction/\345\221\275\344\273\244\350\241\214\345\217\202\346\225\260.md" "b/docs/source/Instruction/\345\221\275\344\273\244\350\241\214\345\217\202\346\225\260.md" index c04339f93e..de98ac7062 100644 --- "a/docs/source/Instruction/\345\221\275\344\273\244\350\241\214\345\217\202\346\225\260.md" +++ "b/docs/source/Instruction/\345\221\275\344\273\244\350\241\214\345\217\202\346\225\260.md" @@ -394,6 +394,14 @@ repetition 奖励参数 - repetition_n_grams:用于检测重复的 n-gram 大小。默认值为3 - repetition_max_penalty:最大惩罚值,用于控制惩罚的强度。默认值为-1.0 +#### SWANLAB + +- swanlab_token: SwanLab的api-key +- swanlab_project: swanlab的project,需要在页面中预先创建好:[https://swanlab.cn/space/~](https://swanlab.cn/space/~) +- swanlab_workspace: 默认为None,会使用api-key对应的username +- swanlab_exp_name: 实验名,可以为空,为空时默认传入--output_dir的值 +- swanlab_mode: 可选cloud和local,云模式或者本地模式 + ### 推理参数 推理参数除包含[基本参数](#基本参数)、[合并参数](#合并参数)、[vLLM参数](#vllm参数)、[LMDeploy参数](#LMDeploy参数)外,还包含下面的部分: diff --git a/docs/source_en/Instruction/Command-line-parameters.md b/docs/source_en/Instruction/Command-line-parameters.md index 9281331f5a..90e8f77b75 100644 --- a/docs/source_en/Instruction/Command-line-parameters.md +++ b/docs/source_en/Instruction/Command-line-parameters.md @@ -406,6 +406,15 @@ repetition penalty function arguments - `repetition_n_grams` (default: 3): Size of the n-gram used to detect repetition. - `repetition_max_penalty` (default: -1.0): Maximum penalty value, which controls the intensity of the penalty. +#### SWANLAB + +- **swanlab_token**: SwanLab's API key +- **swanlab_project**: SwanLab's project, which needs to be created in advance on the page: [https://swanlab.cn/space/~](https://swanlab.cn/space/~) +- **swanlab_workspace**: Defaults to `None`, will use the username associated with the API key +- **swanlab_exp_name**: Experiment name, can be left empty. If empty, the value of `--output_dir` will be used by default +- **swanlab_mode**: Optional values are `cloud` and `local`, representing cloud mode or local mode + + ### Inference Arguments Inference arguments include the [base arguments](#base-arguments), [merge arguments](#merge-arguments), [vLLM arguments](#vllm-arguments), [LMDeploy arguments](#LMDeploy-arguments), and also contain the following: diff --git a/requirements/swanlab.txt b/requirements/swanlab.txt new file mode 100644 index 0000000000..85381455c6 --- /dev/null +++ b/requirements/swanlab.txt @@ -0,0 +1 @@ +swanlab diff --git a/setup.py b/setup.py index 846cb31f5e..7d67fc729e 100644 --- a/setup.py +++ b/setup.py @@ -120,10 +120,12 @@ def gen_packages_items(): extra_requires = {} all_requires = [] extra_requires['eval'], _ = parse_requirements('requirements/eval.txt') + extra_requires['swanlab'], _ = parse_requirements('requirements/swanlab.txt') extra_requires['seq_parallel'], _ = parse_requirements('requirements/seq_parallel.txt') all_requires.extend(install_requires) all_requires.extend(extra_requires['eval']) all_requires.extend(extra_requires['seq_parallel']) + all_requires.extend(extra_requires['swanlab']) extra_requires['all'] = all_requires setup( From 1705740f8272ea8b18e49b66f4d4a0566eddb335 Mon Sep 17 00:00:00 2001 From: "yuze.zyz" Date: Mon, 17 Feb 2025 19:40:30 +0800 Subject: [PATCH 5/7] fix and lint --- README.md | 1 + README_CN.md | 1 + swift/llm/argument/train_args.py | 12 ++++++------ swift/ui/llm_eval/llm_eval.py | 2 +- swift/ui/llm_export/llm_export.py | 2 +- swift/ui/llm_infer/llm_infer.py | 2 +- swift/ui/llm_train/llm_train.py | 4 ++-- swift/ui/llm_train/report_to.py | 10 +++++++--- swift/utils/__init__.py | 4 ++-- 9 files changed, 22 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index cc70e81830..55873f8d9a 100644 --- a/README.md +++ b/README.md @@ -78,6 +78,7 @@ You can contact us and communicate with us by adding our group: ## 🎉 News +- 🎁 2025.02.17: Support SwanLab, just add [a few of arguments](docs/source_en/Instruction/Command-line-parameters.md#swanlab) you can use swanlab to analysis your training results - 🎁 2025.02.16: Support LMDeploy in GRPO, use `--use_lmdeploy true`. Please check [this script](examples/train/grpo/full_lmdeploy.sh) - 🔥 2025.02.12: Support for GRPO(Group Relative Policy Optimization) algorithm for llm and mllm, document can be found in [here](docs/source_en/Instruction/GRPO.md) - 🎁 2025.02.10: SWIFT support the fine-tuning of embedding models,please check the [training script](examples/train/embedding/train.sh)。 diff --git a/README_CN.md b/README_CN.md index 3c9966109a..637b295b1c 100644 --- a/README_CN.md +++ b/README_CN.md @@ -74,6 +74,7 @@ - **模型量化**:支持AWQ、GPTQ和BNB的量化导出,导出的模型支持使用vLLM/LmDeploy推理加速,并支持继续训练。 ## 🎉 新闻 +- 🎁 2025.02.17: 支持SwanLab, 仅需添加[几个新的参数](docs/source/Instruction/命令行参数.md#swanlab)就可以在swanlab上验证你的训练效果 - 🎁 2025.02.16: 在GRPO算法中支持LMDeploy, 请查看`--use_lmdeploy true`. 具体参考[这个脚本](examples/train/grpo/full_lmdeploy.sh) - 🔥 2025.02.12: 支持GRPO(Group Relative Policy Optimization) 训练算法,训练脚本可以在[这里](docs/source/Instruction/GRPO.md)找到 - 🎁 2025.02.10: SWIFT支持了embedding模型的微调,请查看[训练脚本](examples/train/embedding/train.sh)。 diff --git a/swift/llm/argument/train_args.py b/swift/llm/argument/train_args.py index 2664fe12d5..1566f394aa 100644 --- a/swift/llm/argument/train_args.py +++ b/swift/llm/argument/train_args.py @@ -11,7 +11,8 @@ from swift.plugin import LOSS_MAPPING from swift.trainers import TrainerFactory from swift.utils import (add_version_to_work_dir, get_device_count, get_logger, get_pai_tensorboard_dir, - is_liger_available, is_swanlab_available, is_local_master, is_mp, is_pai_training_job, use_torchacc) + is_liger_available, is_local_master, is_mp, is_pai_training_job, is_swanlab_available, + use_torchacc) from .base_args import BaseArguments, to_abspath from .tuner_args import TunerArguments @@ -79,13 +80,12 @@ def __post_init__(self): if getattr(self, 'gradient_checkpointing_kwargs', None): self.gradient_checkpointing_kwargs = self.parse_to_dict(self.gradient_checkpointing_kwargs) self._init_eval_strategy() - - def _init_swanlab(self): + + def _init_swanlab(self): if not is_swanlab_available(): - raise ValueError(f'You are using swanlab as `report_to`, please install swanlab by ' - f'`pip install swanlab`') + raise ValueError('You are using swanlab as `report_to`, please install swanlab by ' '`pip install swanlab`') if not self.swanlab_project: - raise ValueError(f'Please specify a project existed in your swanlab page(https://swanlab.cn/space/~)') + raise ValueError('Please specify a project existed in your swanlab page(https://swanlab.cn/space/~)') if not self.swanlab_exp_name: self.swanlab_exp_name = self.output_dir from transformers.integrations import INTEGRATION_TO_CALLBACK diff --git a/swift/ui/llm_eval/llm_eval.py b/swift/ui/llm_eval/llm_eval.py index b542dbfbc1..05824f1904 100644 --- a/swift/ui/llm_eval/llm_eval.py +++ b/swift/ui/llm_eval/llm_eval.py @@ -11,10 +11,10 @@ import json import torch from json import JSONDecodeError +from transformers.utils import is_torch_cuda_available, is_torch_npu_available from swift.llm import EvalArguments from swift.ui.base import BaseUI -from transformers.utils import is_torch_cuda_available, is_torch_npu_available from swift.ui.llm_eval.eval import Eval from swift.ui.llm_eval.model import Model from swift.ui.llm_eval.runtime import EvalRuntime diff --git a/swift/ui/llm_export/llm_export.py b/swift/ui/llm_export/llm_export.py index 2883b2ce52..c992369165 100644 --- a/swift/ui/llm_export/llm_export.py +++ b/swift/ui/llm_export/llm_export.py @@ -11,10 +11,10 @@ import json import torch from json import JSONDecodeError +from transformers.utils import is_torch_cuda_available, is_torch_npu_available from swift.llm import ExportArguments from swift.ui.base import BaseUI -from transformers.utils import is_torch_cuda_available, is_torch_npu_available from swift.ui.llm_export.export import Export from swift.ui.llm_export.model import Model from swift.ui.llm_export.runtime import ExportRuntime diff --git a/swift/ui/llm_infer/llm_infer.py b/swift/ui/llm_infer/llm_infer.py index 98685d412f..be525a743c 100644 --- a/swift/ui/llm_infer/llm_infer.py +++ b/swift/ui/llm_infer/llm_infer.py @@ -13,10 +13,10 @@ import json import torch from json import JSONDecodeError +from transformers.utils import is_torch_cuda_available, is_torch_npu_available from swift.llm import DeployArguments, InferArguments, InferClient, InferRequest, RequestConfig from swift.ui.base import BaseUI -from transformers.utils import is_torch_cuda_available, is_torch_npu_available from swift.ui.llm_infer.model import Model from swift.ui.llm_infer.runtime import Runtime from swift.utils import get_device_count, get_logger diff --git a/swift/ui/llm_train/llm_train.py b/swift/ui/llm_train/llm_train.py index 1d999b9178..2f2c58b04f 100644 --- a/swift/ui/llm_train/llm_train.py +++ b/swift/ui/llm_train/llm_train.py @@ -12,6 +12,7 @@ import json import torch from json import JSONDecodeError +from transformers.utils import is_torch_cuda_available, is_torch_npu_available from swift.llm import RLHFArguments from swift.llm.argument.base_args.base_args import get_supported_tuners @@ -31,7 +32,6 @@ from swift.ui.llm_train.save import Save from swift.ui.llm_train.self_cog import SelfCog from swift.utils import get_device_count, get_logger -from transformers.utils import is_torch_cuda_available, is_torch_npu_available logger = get_logger() @@ -366,7 +366,7 @@ def train(cls, *args): cuda_param = f'CUDA_VISIBLE_DEVICES={gpus}' else: cuda_param = '' - + log_file = os.path.join(sft_args.logging_dir, 'run.log') if sys.platform == 'win32': if cuda_param: diff --git a/swift/ui/llm_train/report_to.py b/swift/ui/llm_train/report_to.py index 30fe57f086..fa77c08737 100644 --- a/swift/ui/llm_train/report_to.py +++ b/swift/ui/llm_train/report_to.py @@ -60,9 +60,13 @@ def do_build_ui(cls, base_tab: Type['BaseUI']): with gr.Accordion(elem_id='reporter', open=False): with gr.Blocks(): with gr.Row(): - gr.Dropdown(elem_id='report_to', multiselect=True, - is_list=True, choices=['tensorboard', 'wandb', 'swanlab'], - allow_custom_value=True, scale=20) + gr.Dropdown( + elem_id='report_to', + multiselect=True, + is_list=True, + choices=['tensorboard', 'wandb', 'swanlab'], + allow_custom_value=True, + scale=20) gr.Textbox(elem_id='swanlab_token', lines=1, scale=20) gr.Textbox(elem_id='swanlab_project', lines=1, scale=20) with gr.Row(): diff --git a/swift/utils/__init__.py b/swift/utils/__init__.py index 3183d914b7..1d6d7ffb67 100644 --- a/swift/utils/__init__.py +++ b/swift/utils/__init__.py @@ -2,8 +2,8 @@ from .env import (get_dist_setting, get_pai_tensorboard_dir, is_deepspeed_enabled, is_dist, is_dist_ta, is_local_master, is_master, is_mp, is_mp_ddp, is_pai_training_job, torchacc_trim_graph, use_hf_hub, use_torchacc) -from .import_utils import (is_liger_available, is_lmdeploy_available, is_megatron_available, is_unsloth_available, - is_vllm_available, is_wandb_available, is_xtuner_available, is_swanlab_available) +from .import_utils import (is_liger_available, is_lmdeploy_available, is_megatron_available, is_swanlab_available, + is_unsloth_available, is_vllm_available, is_wandb_available, is_xtuner_available) from .io_utils import JsonlWriter, append_to_jsonl, download_ms_file, get_file_mm_type, read_from_jsonl, write_to_jsonl from .logger import get_logger from .np_utils import get_seed, stat_array, transform_jsonl_to_df From d677c9b510b109fcc1bf9cacaa45f089c694a8ed Mon Sep 17 00:00:00 2001 From: "yuze.zyz" Date: Mon, 17 Feb 2025 19:51:52 +0800 Subject: [PATCH 6/7] fix --- swift/llm/argument/train_args.py | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/swift/llm/argument/train_args.py b/swift/llm/argument/train_args.py index 1566f394aa..7ab68285c9 100644 --- a/swift/llm/argument/train_args.py +++ b/swift/llm/argument/train_args.py @@ -38,12 +38,6 @@ class Seq2SeqTrainingOverrideArguments(Seq2SeqTrainingArguments): logging_first_step: bool = True - swanlab_token: Optional[str] = None - swanlab_project: Optional[str] = None - swanlab_workspace: Optional[str] = None - swanlab_exp_name: Optional[str] = None - swanlab_mode: Literal['cloud', 'local'] = 'cloud' - def _init_output_dir(self): if self.output_dir is not None: return @@ -81,6 +75,16 @@ def __post_init__(self): self.gradient_checkpointing_kwargs = self.parse_to_dict(self.gradient_checkpointing_kwargs) self._init_eval_strategy() + +@dataclass +class SwanlabArguments: + + swanlab_token: Optional[str] = None + swanlab_project: Optional[str] = None + swanlab_workspace: Optional[str] = None + swanlab_exp_name: Optional[str] = None + swanlab_mode: Literal['cloud', 'local'] = 'cloud' + def _init_swanlab(self): if not is_swanlab_available(): raise ValueError('You are using swanlab as `report_to`, please install swanlab by ' '`pip install swanlab`') @@ -117,7 +121,8 @@ def __post_init__(self): @dataclass -class TrainArguments(TorchAccArguments, TunerArguments, Seq2SeqTrainingOverrideArguments, BaseArguments): +class TrainArguments(SwanlabArguments, TorchAccArguments, TunerArguments, Seq2SeqTrainingOverrideArguments, + BaseArguments): """ TrainArguments class is a dataclass that inherits from multiple argument classes: TorchAccArguments, TunerArguments, Seq2SeqTrainingOverrideArguments, and BaseArguments. From 4c4bca0366afebebf363ec039339dbc85c8b0576 Mon Sep 17 00:00:00 2001 From: "yuze.zyz" Date: Mon, 17 Feb 2025 20:33:05 +0800 Subject: [PATCH 7/7] change lmdeploy branch --- examples/train/grpo/full_lmdeploy.sh | 6 +++--- swift/trainers/rlhf_trainer/grpo_trainer.py | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/examples/train/grpo/full_lmdeploy.sh b/examples/train/grpo/full_lmdeploy.sh index c3f0993966..3ece39d79a 100644 --- a/examples/train/grpo/full_lmdeploy.sh +++ b/examples/train/grpo/full_lmdeploy.sh @@ -1,8 +1,8 @@ # pip install lmdeploy==0.6.4 # Replace three files: -# 1. https://github.com/tastelikefeet/lmdeploy/blob/feat/reload_state_dict/lmdeploy/messages.py -# 2. https://github.com/tastelikefeet/lmdeploy/blob/feat/reload_state_dict/lmdeploy/turbomind/turbomind.py -# 3. https://github.com/tastelikefeet/lmdeploy/blob/feat/reload_state_dict/lmdeploy/turbomind/deploy/loader.py +# 1. https://github.com/tastelikefeet/lmdeploy/blob/feat/reload_state_dict_064/lmdeploy/messages.py +# 2. https://github.com/tastelikefeet/lmdeploy/blob/feat/reload_state_dict_064/lmdeploy/turbomind/turbomind.py +# 3. https://github.com/tastelikefeet/lmdeploy/blob/feat/reload_state_dict_064/lmdeploy/turbomind/deploy/loader.py CUDA_VISIBLE_DEVICES=0,1,2,3 \ NPROC_PER_NODE=3 \ diff --git a/swift/trainers/rlhf_trainer/grpo_trainer.py b/swift/trainers/rlhf_trainer/grpo_trainer.py index a1921cc99e..ba55f06bee 100644 --- a/swift/trainers/rlhf_trainer/grpo_trainer.py +++ b/swift/trainers/rlhf_trainer/grpo_trainer.py @@ -151,17 +151,17 @@ def __init__(self, self.llm = namedtuple('LLM', ['llm_engine'])(self.engine.engine.engine) self.engine.default_template = self.template elif use_lmdeploy: - # https://github.com/tastelikefeet/lmdeploy.git@feat/reload_state_dict + # https://github.com/tastelikefeet/lmdeploy.git@feat/reload_state_dict_064 # Compile:https://github.com/tastelikefeet/lmdeploy/blob/main/docs/en/get_started/installation.md if not is_lmdeploy_available(): raise ImportError('Please install `pip install lmdeploy==0.6.4`' ' and replace three files with:\n' '1. https://github.com/tastelikefeet/lmdeploy/blob/feat/' - 'reload_state_dict/lmdeploy/messages.py\n' + 'reload_state_dict_064/lmdeploy/messages.py\n' '2. https://github.com/tastelikefeet/lmdeploy/blob/feat/' - 'reload_state_dict/lmdeploy/turbomind/turbomind.py\n' + 'reload_state_dict_064/lmdeploy/turbomind/turbomind.py\n' '3. https://github.com/tastelikefeet/lmdeploy/blob/feat/' - 'reload_state_dict/lmdeploy/turbomind/deploy/loader.py\n') + 'reload_state_dict_064/lmdeploy/turbomind/deploy/loader.py\n') from swift.llm import LmdeployEngine from swift.tuners import Swift with Swift.grpo_context(model, self.template.processor):