misc.py 3.44 KB
Newer Older
chenych's avatar
chenych committed
1
# Copyright 2025 the LlamaFactory team.
chenych's avatar
chenych committed
2
3
4
5
6
7
8
9
10
11
12
13
14
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

chenych's avatar
chenych committed
15
from typing import TYPE_CHECKING
chenych's avatar
chenych committed
16

luopl's avatar
luopl committed
17
from ...extras import logging
luopl's avatar
luopl committed
18
from .visual import COMPOSITE_MODELS
chenych's avatar
chenych committed
19
20
21
22
23
24


if TYPE_CHECKING:
    from transformers import PretrainedConfig, PreTrainedModel, PreTrainedTokenizer


luopl's avatar
luopl committed
25
logger = logging.get_logger(__name__)
chenych's avatar
chenych committed
26
27


chenych's avatar
chenych committed
28
29
def find_all_linear_modules(model: "PreTrainedModel", freeze_vision_tower: bool) -> list[str]:
    r"""Find all available modules to apply LoRA, GaLore or APOLLO."""
luopl's avatar
luopl committed
30
    model_type = getattr(model.config, "model_type", None)
chenych's avatar
chenych committed
31
    forbidden_modules = {"lm_head"}
luopl's avatar
luopl committed
32
    if model_type == "chatglm":
chenych's avatar
chenych committed
33
        forbidden_modules.add("output_layer")
luopl's avatar
luopl committed
34
    elif model_type == "internlm2":
chenych's avatar
chenych committed
35
        forbidden_modules.add("output")
luopl's avatar
luopl committed
36
37
38
39
40
41

    if model_type in COMPOSITE_MODELS:
        forbidden_modules.add(COMPOSITE_MODELS[model_type].projector_key)

    if freeze_vision_tower and model_type in COMPOSITE_MODELS:
        forbidden_modules.update(COMPOSITE_MODELS[model_type].vision_model_keys)
chenych's avatar
chenych committed
42
43
44
45
46
47
48
49
50

    module_names = set()
    for name, module in model.named_modules():
        if any(forbidden_module in name for forbidden_module in forbidden_modules):
            continue

        if "Linear" in module.__class__.__name__ and "Embedding" not in module.__class__.__name__:
            module_names.add(name.split(".")[-1])

luopl's avatar
luopl committed
51
    logger.info_rank0("Found linear modules: {}".format(",".join(module_names)))
chenych's avatar
chenych committed
52
53
54
    return list(module_names)


chenych's avatar
chenych committed
55
56
def find_expanded_modules(model: "PreTrainedModel", target_modules: list[str], num_layer_trainable: int) -> list[str]:
    r"""Find the modules in the expanded blocks to apply lora."""
chenych's avatar
chenych committed
57
58
59
60
61
62
    num_layers = getattr(model.config, "num_hidden_layers", None)
    if not num_layers:
        raise ValueError("Model was not supported.")

    if num_layers % num_layer_trainable != 0:
        raise ValueError(
luopl's avatar
luopl committed
63
            f"`num_layers` {num_layers} should be divisible by `num_layer_trainable` {num_layer_trainable}."
chenych's avatar
chenych committed
64
65
66
67
        )

    stride = num_layers // num_layer_trainable
    trainable_layer_ids = range(stride - 1, num_layers + stride - 1, stride)
luopl's avatar
luopl committed
68
    trainable_layers = [f".{idx:d}." for idx in trainable_layer_ids]
chenych's avatar
chenych committed
69
70
71
72
73
74
75
    module_names = []
    for name, _ in model.named_modules():
        if any(target_module in name for target_module in target_modules) and any(
            trainable_layer in name for trainable_layer in trainable_layers
        ):
            module_names.append(name)

chenych's avatar
chenych committed
76
    logger.info_rank0("Apply lora to layers: {}.".format(",".join(map(str, trainable_layer_ids))))
chenych's avatar
chenych committed
77
78
79
80
81
82
83
84
85
86
    return module_names


def register_autoclass(config: "PretrainedConfig", model: "PreTrainedModel", tokenizer: "PreTrainedTokenizer"):
    if "AutoConfig" in getattr(config, "auto_map", {}):
        config.__class__.register_for_auto_class()
    if "AutoModelForCausalLM" in getattr(config, "auto_map", {}):
        model.__class__.register_for_auto_class()
    if "AutoTokenizer" in tokenizer.init_kwargs.get("auto_map", {}):
        tokenizer.__class__.register_for_auto_class()