[train] Harden KTransformers MoE LoRA SFT integration (#10738)

This commit is contained in:
yyj
2026-08-13 20:43:15 +08:00
committed by GitHub
parent 199b8873d7
commit bc4b42cefc
17 changed files with 573 additions and 101 deletions

View File

@@ -18,6 +18,7 @@
import json
import os
import sys
from dataclasses import dataclass, field
from pathlib import Path
from typing import Any, Optional
@@ -48,6 +49,14 @@ logger = logging.get_logger(__name__)
check_dependencies()
@dataclass
class _KTransformersRuntimeArguments:
kt_config: dict[str, Any] | None = field(
default=None,
metadata={"help": "Advanced KTransformers settings used during inference or evaluation."},
)
_TRAIN_ARGS = [
ModelArguments,
DataArguments,
@@ -56,9 +65,9 @@ _TRAIN_ARGS = [
GeneratingArguments,
]
_TRAIN_CLS = tuple[ModelArguments, DataArguments, TrainingArguments, FinetuningArguments, GeneratingArguments]
_INFER_ARGS = [ModelArguments, DataArguments, FinetuningArguments, GeneratingArguments]
_INFER_ARGS = [ModelArguments, DataArguments, FinetuningArguments, GeneratingArguments, _KTransformersRuntimeArguments]
_INFER_CLS = tuple[ModelArguments, DataArguments, FinetuningArguments, GeneratingArguments]
_EVAL_ARGS = [ModelArguments, DataArguments, EvaluationArguments, FinetuningArguments]
_EVAL_ARGS = [ModelArguments, DataArguments, EvaluationArguments, FinetuningArguments, _KTransformersRuntimeArguments]
_EVAL_CLS = tuple[ModelArguments, DataArguments, EvaluationArguments, FinetuningArguments]
if is_mcore_adapter_available() and is_env_enabled("USE_MCA"):
@@ -117,6 +126,26 @@ def read_args(args: dict[str, Any] | list[str] | None = None) -> dict[str, Any]
return sys.argv[1:]
def _get_kt_runtime_capacity(
data_args: "DataArguments",
training_args: "TrainingArguments",
finetuning_args: "FinetuningArguments",
) -> int:
r"""Return the largest local token batch submitted to a KT expert."""
tokens_per_sample = data_args.cutoff_len
if finetuning_args.stage == "sft" and data_args.packing:
tokens_per_sample += 1
if finetuning_args.stage == "sft" and training_args.do_train:
tokens_per_sample = ((tokens_per_sample + 7) // 8) * 8
local_batch_sizes = [1]
if training_args.do_train:
local_batch_sizes.append(training_args.per_device_train_batch_size)
if training_args.do_eval or training_args.do_predict:
local_batch_sizes.append(training_args.per_device_eval_batch_size)
return tokens_per_sample * max(local_batch_sizes)
def _parse_args(
parser: "HfArgumentParser", args: dict[str, Any] | list[str] | None = None, allow_extra_keys: bool = False
) -> tuple[Any]:
@@ -340,13 +369,21 @@ def _configure_mbridge_training_args(training_args, data_args, finetuning_args)
def _parse_infer_args(args: dict[str, Any] | list[str] | None = None) -> _INFER_CLS:
parser = HfArgumentParser(_INFER_ARGS)
allow_extra_keys = is_env_enabled("ALLOW_EXTRA_ARGS")
return _parse_args(parser, args, allow_extra_keys=allow_extra_keys)
model_args, data_args, finetuning_args, generating_args, kt_args = _parse_args(
parser, args, allow_extra_keys=allow_extra_keys
)
model_args._kt_inference_config = kt_args.kt_config
return model_args, data_args, finetuning_args, generating_args
def _parse_eval_args(args: dict[str, Any] | list[str] | None = None) -> _EVAL_CLS:
parser = HfArgumentParser(_EVAL_ARGS)
allow_extra_keys = is_env_enabled("ALLOW_EXTRA_ARGS")
return _parse_args(parser, args, allow_extra_keys=allow_extra_keys)
model_args, data_args, eval_args, finetuning_args, kt_args = _parse_args(
parser, args, allow_extra_keys=allow_extra_keys
)
model_args._kt_inference_config = kt_args.kt_config
return model_args, data_args, eval_args, finetuning_args
def get_ray_args(args: dict[str, Any] | list[str] | None = None) -> RayArguments:
@@ -605,10 +642,10 @@ def get_train_args(args: dict[str, Any] | list[str] | None = None) -> _TRAIN_CLS
elif training_args.fp16:
model_args.compute_dtype = torch.float16
data_args.packing = data_args.packing if data_args.packing is not None else finetuning_args.stage == "pt"
model_args.device_map = {"": get_current_device()}
model_args.model_max_length = data_args.cutoff_len
model_args.block_diag_attn = data_args.neat_packing
data_args.packing = data_args.packing if data_args.packing is not None else finetuning_args.stage == "pt"
# Log on each process the small summary
logger.info(
@@ -620,7 +657,11 @@ def get_train_args(args: dict[str, Any] | list[str] | None = None) -> _TRAIN_CLS
transformers.set_seed(training_args.seed)
if model_args.use_kt:
model_args.apply_kt_config(finetuning_args, training_args, model_args.model_max_length)
model_args.apply_kt_config(
finetuning_args,
training_args,
_get_kt_runtime_capacity(data_args, training_args, finetuning_args),
)
return model_args, data_args, training_args, finetuning_args, generating_args
@@ -657,6 +698,8 @@ def get_infer_args(args: dict[str, Any] | list[str] | None = None) -> _INFER_CLS
else:
model_args.device_map = "auto"
model_args.configure_kt_loading(finetuning_args, data_args.cutoff_len)
return model_args, data_args, finetuning_args, generating_args
@@ -675,6 +718,7 @@ def get_eval_args(args: dict[str, Any] | list[str] | None = None) -> _EVAL_CLS:
_check_extra_dependencies(model_args, finetuning_args)
model_args.device_map = "auto"
model_args.configure_kt_loading(finetuning_args, data_args.cutoff_len)
transformers.set_seed(eval_args.seed)