-
Notifications
You must be signed in to change notification settings - Fork 185
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add DoRA pass #1579
base: main
Are you sure you want to change the base?
Add DoRA pass #1579
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -369,7 +369,9 @@ def init_lora_adapters( | |
task: str, | ||
config: ConfigBase, | ||
target_modules: Optional[List[str]] = None, | ||
ephemeral_gpu_offload: Optional[bool] = False, | ||
use_loftq: Optional[bool] = False, | ||
use_dora: Optional[bool] = False, | ||
) -> "PeftModel": | ||
"""Initialize LoRA adapters. | ||
|
||
|
@@ -378,9 +380,10 @@ def init_lora_adapters( | |
:param config: The config for the pass run. | ||
:param target_modules: List of modules to target for LoRA fine-tuning. | ||
:param use_loftq: Whether to use LoftQ to initialize weights. | ||
:param use_dora: Whether to use Dora for optimization. | ||
:return: The LoRA model. | ||
""" | ||
from peft import LoraConfig, get_peft_model | ||
from peft import LoraConfig, LoraRuntimeConfig, get_peft_model | ||
|
||
lora_config_kwargs = {} | ||
if use_loftq: | ||
|
@@ -391,6 +394,11 @@ def init_lora_adapters( | |
"loftq_config": LoftQConfig(loftq_bits=4, loftq_iter=config.loftq_iter), | ||
} | ||
|
||
if use_dora: | ||
lora_config_kwargs = { | ||
"use_dora": True, | ||
} | ||
|
||
peft_task_type = get_peft_task_type_from_task(task, fail_on_not_found=True) | ||
lora_config = LoraConfig( | ||
r=config.lora_r, | ||
|
@@ -400,6 +408,7 @@ def init_lora_adapters( | |
bias="none", | ||
task_type=peft_task_type, | ||
modules_to_save=config.modules_to_save, | ||
runtime_config=LoraRuntimeConfig(ephemeral_gpu_offload=ephemeral_gpu_offload), | ||
**lora_config_kwargs, | ||
) | ||
|
||
|
@@ -412,6 +421,8 @@ def enable_lora( | |
config: ConfigBase, | ||
adapter_path: Optional[str] = None, | ||
target_modules: Optional[List[str]] = None, | ||
use_dora: Optional[bool] = False, | ||
ephemeral_gpu_offload: Optional[bool] = False, | ||
) -> "PeftModel": | ||
"""Enable LoRA fine-tuning on a Hugging Face PyTorch model. | ||
|
||
|
@@ -425,6 +436,8 @@ def enable_lora( | |
:param config: The config for the pass run. | ||
:param adapter_path: Path to the adapter weights. If None, will initialize new adapters. | ||
:param target_modules: List of modules to target for LoRA fine-tuning. Only used if adapter_path is None. | ||
:param use_dora: Whether to use Dora for optimization. | ||
:param ephemeral_gpu_offload: Whether to use ephemeral GPU offload. | ||
:return: The LoRA model. | ||
""" | ||
from peft import PeftModel | ||
|
@@ -450,10 +463,19 @@ def enable_lora( | |
) | ||
if not adapter_path: | ||
logger.debug("Initializing LoRA adapters from config") | ||
lora_model = self.init_lora_adapters(model, task, config, target_modules=target_modules) | ||
lora_model = self.init_lora_adapters( | ||
model, | ||
task, | ||
config, | ||
target_modules=target_modules, | ||
use_dora=use_dora, | ||
ephemeral_gpu_offload=ephemeral_gpu_offload, | ||
) | ||
else: | ||
logger.debug("Loading LoRA adapters from %s", adapter_path) | ||
lora_model = PeftModel.from_pretrained(model, adapter_path, is_trainable=True) | ||
lora_model = PeftModel.from_pretrained( | ||
model, adapter_path, is_trainable=True, ephemeral_gpu_offload=ephemeral_gpu_offload | ||
) | ||
logger.debug( | ||
"The number of trainable parameters in the LoRA model: %s", self.count_trainable_parameters(lora_model) | ||
) | ||
|
@@ -641,6 +663,42 @@ def _run_for_config(self, model: HfModelHandler, config: Dict[str, Any], output_ | |
) | ||
|
||
|
||
class DoRA(LoRABase): | ||
"""Run DoRA fine-tuning on a Hugging Face PyTorch model.""" | ||
|
||
@classmethod | ||
def _default_config(cls, accelerator_spec: AcceleratorSpec) -> Dict[str, PassConfigParam]: | ||
config = { | ||
"ephemeral_gpu_offload": PassConfigParam( | ||
type_=bool, default_value=False, description="Ephemeral GPU offload" | ||
), | ||
} | ||
config.update(super()._default_config(accelerator_spec)) | ||
return config | ||
|
||
def _run_for_config(self, model: HfModelHandler, config: Dict[str, Any], output_model_path: str) -> HfModelHandler: | ||
# convert config to pass config class | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is identical as LoRA pass except the use_dora flag on enable_lora(). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That's true. I'm working on LoHa and LoKr also. Let me revisit this when adding those 2. |
||
# this will validate the config and convert to the correct types | ||
config = self._config_class(**config) | ||
|
||
# check dependencies | ||
self.check_dependencies(config) | ||
|
||
# use default training args if not provided | ||
config.training_args = config.training_args or HFTrainingArguments() | ||
|
||
# get new model | ||
pytorch_model = self.load_base_pytorch_model(model, config) | ||
|
||
# add lora modules | ||
pytorch_model = self.enable_lora(pytorch_model, model.task, config, use_dora=True) | ||
|
||
# train and return new model | ||
return self.train_and_save_new_model( | ||
pytorch_model, model.get_hf_tokenizer(), config, deepcopy(model), output_model_path | ||
) | ||
|
||
|
||
class QLoRABase(LoRABase): | ||
"""Base class for QLoRA and LoftQ fine-tuning passes.""" | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can this be used with LoRA also?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure, but from Huggingface documentation, this option is only used for Dora, so I didn't add this for Lora.