| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| from __future__ import annotations |
|
|
| import importlib |
| import os |
| from typing import Optional |
|
|
| from transformers import ( |
| AutoModel, |
| AutoModelForCausalLM, |
| AutoModelForQuestionAnswering, |
| AutoModelForSeq2SeqLM, |
| AutoModelForSequenceClassification, |
| AutoModelForTokenClassification, |
| AutoTokenizer, |
| ) |
|
|
| from .config import PeftConfig |
| from .peft_model import ( |
| PeftModel, |
| PeftModelForCausalLM, |
| PeftModelForFeatureExtraction, |
| PeftModelForQuestionAnswering, |
| PeftModelForSeq2SeqLM, |
| PeftModelForSequenceClassification, |
| PeftModelForTokenClassification, |
| ) |
| from .utils.constants import TOKENIZER_CONFIG_NAME |
| from .utils.other import check_file_exists_on_hf_hub |
|
|
|
|
| MODEL_TYPE_TO_PEFT_MODEL_MAPPING: dict[str, type[PeftModel]] = { |
| "SEQ_CLS": PeftModelForSequenceClassification, |
| "SEQ_2_SEQ_LM": PeftModelForSeq2SeqLM, |
| "CAUSAL_LM": PeftModelForCausalLM, |
| "TOKEN_CLS": PeftModelForTokenClassification, |
| "QUESTION_ANS": PeftModelForQuestionAnswering, |
| "FEATURE_EXTRACTION": PeftModelForFeatureExtraction, |
| } |
|
|
|
|
| class _BaseAutoPeftModel: |
| _target_class = None |
| _target_peft_class = None |
|
|
| def __init__(self, *args, **kwargs): |
| |
| raise EnvironmentError( |
| f"{self.__class__.__name__} is designed to be instantiated " |
| f"using the `{self.__class__.__name__}.from_pretrained(pretrained_model_name_or_path)` or " |
| f"`{self.__class__.__name__}.from_config(config)` methods." |
| ) |
|
|
| @classmethod |
| def from_pretrained( |
| cls, |
| pretrained_model_name_or_path, |
| adapter_name: str = "default", |
| is_trainable: bool = False, |
| config: Optional[PeftConfig] = None, |
| revision: Optional[str] = None, |
| **kwargs, |
| ): |
| r""" |
| A wrapper around all the preprocessing steps a user needs to perform in order to load a PEFT model. The kwargs |
| are passed along to `PeftConfig` that automatically takes care of filtering the kwargs of the Hub methods and |
| the config object init. |
| """ |
| peft_config = PeftConfig.from_pretrained(pretrained_model_name_or_path, revision=revision, **kwargs) |
| base_model_path = peft_config.base_model_name_or_path |
| base_model_revision = peft_config.revision |
|
|
| task_type = getattr(peft_config, "task_type", None) |
|
|
| if cls._target_class is not None: |
| target_class = cls._target_class |
| elif cls._target_class is None and task_type is not None: |
| |
| raise ValueError( |
| "Cannot use `AutoPeftModel` with a task type, please use a specific class for your task type. (e.g. `AutoPeftModelForCausalLM` for `task_type='CAUSAL_LM'`)" |
| ) |
|
|
| if task_type is not None: |
| expected_target_class = MODEL_TYPE_TO_PEFT_MODEL_MAPPING[task_type] |
| if cls._target_peft_class.__name__ != expected_target_class.__name__: |
| raise ValueError( |
| f"Expected target PEFT class: {expected_target_class.__name__}, but you have asked for: {cls._target_peft_class.__name__}" |
| " make sure that you are loading the correct model for your task type." |
| ) |
| elif task_type is None and getattr(peft_config, "auto_mapping", None) is not None: |
| auto_mapping = getattr(peft_config, "auto_mapping", None) |
| base_model_class = auto_mapping["base_model_class"] |
| parent_library_name = auto_mapping["parent_library"] |
|
|
| parent_library = importlib.import_module(parent_library_name) |
| target_class = getattr(parent_library, base_model_class) |
| else: |
| raise ValueError( |
| "Cannot infer the auto class from the config, please make sure that you are loading the correct model for your task type." |
| ) |
|
|
| base_model = target_class.from_pretrained(base_model_path, revision=base_model_revision, **kwargs) |
|
|
| tokenizer_exists = False |
| if os.path.exists(os.path.join(pretrained_model_name_or_path, TOKENIZER_CONFIG_NAME)): |
| tokenizer_exists = True |
| else: |
| token = kwargs.get("token", None) |
| if token is None: |
| token = kwargs.get("use_auth_token", None) |
|
|
| tokenizer_exists = check_file_exists_on_hf_hub( |
| repo_id=pretrained_model_name_or_path, |
| filename=TOKENIZER_CONFIG_NAME, |
| revision=revision, |
| repo_type=kwargs.get("repo_type", None), |
| token=token, |
| ) |
|
|
| if tokenizer_exists and hasattr(base_model, "get_input_embeddings"): |
| tokenizer = AutoTokenizer.from_pretrained( |
| pretrained_model_name_or_path, trust_remote_code=kwargs.get("trust_remote_code", False) |
| ) |
| embedding_size = base_model.get_input_embeddings().weight.shape[0] |
| if len(tokenizer) > embedding_size: |
| |
| base_model.resize_token_embeddings(len(tokenizer)) |
|
|
| return cls._target_peft_class.from_pretrained( |
| base_model, |
| pretrained_model_name_or_path, |
| adapter_name=adapter_name, |
| is_trainable=is_trainable, |
| config=config, |
| **kwargs, |
| ) |
|
|
|
|
| class AutoPeftModel(_BaseAutoPeftModel): |
| _target_class = None |
| _target_peft_class = PeftModel |
|
|
|
|
| class AutoPeftModelForCausalLM(_BaseAutoPeftModel): |
| _target_class = AutoModelForCausalLM |
| _target_peft_class = PeftModelForCausalLM |
|
|
|
|
| class AutoPeftModelForSeq2SeqLM(_BaseAutoPeftModel): |
| _target_class = AutoModelForSeq2SeqLM |
| _target_peft_class = PeftModelForSeq2SeqLM |
|
|
|
|
| class AutoPeftModelForSequenceClassification(_BaseAutoPeftModel): |
| _target_class = AutoModelForSequenceClassification |
| _target_peft_class = PeftModelForSequenceClassification |
|
|
|
|
| class AutoPeftModelForTokenClassification(_BaseAutoPeftModel): |
| _target_class = AutoModelForTokenClassification |
| _target_peft_class = PeftModelForTokenClassification |
|
|
|
|
| class AutoPeftModelForQuestionAnswering(_BaseAutoPeftModel): |
| _target_class = AutoModelForQuestionAnswering |
| _target_peft_class = PeftModelForQuestionAnswering |
|
|
|
|
| class AutoPeftModelForFeatureExtraction(_BaseAutoPeftModel): |
| _target_class = AutoModel |
| _target_peft_class = PeftModelForFeatureExtraction |
|
|