Skip to content

Commit ed9448f

Browse files
authored
fix rotary/embedding config hf compat with older models and older hf (#2496)
* fix rotary/embedding config hf compat with older models and older hf * compat fix
1 parent c51ece2 commit ed9448f

1 file changed

Lines changed: 123 additions & 0 deletions

File tree

gptqmodel/utils/hf.py

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,122 @@
2626

2727
log = setup_logger()
2828

29+
30+
# Older remote model files sometimes store `_tied_weights_keys` as a plain list
31+
# like `["lm_head.weight"]`. transformers 5.x now expects `{target: source}`,
32+
# and otherwise later save/load helpers fail with `'list' object has no attribute 'keys'`.
33+
def _resolve_legacy_tied_weights_mapping(model: PreTrainedModel, tied_mapping) -> dict[str, str]:
34+
if not isinstance(tied_mapping, (list, tuple, set)):
35+
return {}
36+
37+
if not getattr(model.config, "tie_word_embeddings", False):
38+
return {}
39+
40+
input_embeddings = model.get_input_embeddings()
41+
input_weight = getattr(input_embeddings, "weight", None)
42+
if input_weight is None:
43+
return {}
44+
45+
source_name = None
46+
for name, param in model.named_parameters(remove_duplicate=False):
47+
if param is input_weight:
48+
source_name = name
49+
break
50+
51+
if source_name is None:
52+
return {}
53+
54+
return {
55+
# Legacy list entries only name the tied target, so resolve them back
56+
# to the input embedding weight name expected by transformers 5.x.
57+
target_name: source_name
58+
for target_name in tied_mapping
59+
if isinstance(target_name, str) and target_name != source_name
60+
}
61+
62+
63+
# Rewrite legacy list-based `_tied_weights_keys` in-place so transformers 5.x
64+
# save/load code stops crashing on older trust_remote_code models that still use
65+
# the pre-5.x list format.
66+
def _normalize_legacy_tied_weights_keys(model: PreTrainedModel) -> None:
67+
for _name, submodule in model.named_modules(remove_duplicate=False):
68+
tied_mapping = getattr(submodule, "_tied_weights_keys", None)
69+
if not isinstance(tied_mapping, (list, tuple, set)):
70+
continue
71+
72+
if isinstance(submodule, PreTrainedModel):
73+
submodule._tied_weights_keys = _resolve_legacy_tied_weights_mapping(submodule, tied_mapping)
74+
else:
75+
submodule._tied_weights_keys = {}
76+
77+
78+
# Bridge a few transformers 5.x API changes so older trust_remote_code model
79+
# files still import and initialize without editing the cached remote source.
80+
def _patch_transformers_remote_code_compat() -> None:
81+
try:
82+
from transformers.utils import import_utils
83+
except Exception:
84+
return
85+
86+
if not hasattr(import_utils, "is_torch_fx_available"):
87+
# transformers 5.x removed `import_utils.is_torch_fx_available`, but
88+
# older remote model files still import it during module import.
89+
def is_torch_fx_available() -> bool:
90+
return hasattr(torch, "fx")
91+
92+
import_utils.is_torch_fx_available = is_torch_fx_available
93+
94+
if not getattr(PreTrainedModel, "_gptqmodel_legacy_tied_weights_patch", False):
95+
original_get_expanded_tied_weights_keys = PreTrainedModel.get_expanded_tied_weights_keys
96+
97+
def get_expanded_tied_weights_keys(self, all_submodels: bool = False) -> dict:
98+
# transformers 5.x expects `_tied_weights_keys` to be a dict, while
99+
# older trust_remote_code models still declare `["lm_head.weight"]`.
100+
# Handle the legacy form here so HF tied-weight expansion still works.
101+
tied_mapping = getattr(self, "_tied_weights_keys", None)
102+
if not isinstance(tied_mapping, (list, tuple, set)):
103+
return original_get_expanded_tied_weights_keys(self, all_submodels=all_submodels)
104+
105+
if all_submodels:
106+
expanded_tied_weights = {}
107+
for prefix, submodule in self.named_modules(remove_duplicate=False):
108+
if isinstance(submodule, PreTrainedModel):
109+
submodel_tied_weights = submodule.get_expanded_tied_weights_keys(all_submodels=False)
110+
if prefix != "":
111+
submodel_tied_weights = {
112+
f"{prefix}.{k}": f"{prefix}.{v}" for k, v in submodel_tied_weights.items()
113+
}
114+
expanded_tied_weights.update(submodel_tied_weights)
115+
return expanded_tied_weights
116+
117+
if not getattr(self.config, "tie_word_embeddings", False):
118+
return {}
119+
120+
return _resolve_legacy_tied_weights_mapping(self, tied_mapping)
121+
122+
PreTrainedModel.get_expanded_tied_weights_keys = get_expanded_tied_weights_keys
123+
PreTrainedModel._gptqmodel_legacy_tied_weights_patch = True
124+
125+
126+
# Restore the pre-transformers-5 RoPE config shape expected by older MiniCPM
127+
# remote code before HF instantiates the architecture from config.
128+
def _normalize_remote_code_config_compat(config: Any) -> None:
129+
# transformers 5.x normalizes RoPE config to `rope_type`, but older
130+
# MiniCPM remote code still reads `rope_scaling["type"]` or expects `None`.
131+
rope_scaling = getattr(config, "rope_scaling", None)
132+
if not isinstance(rope_scaling, dict) or "type" in rope_scaling:
133+
return
134+
135+
rope_type = rope_scaling.get("rope_type")
136+
factor = rope_scaling.get("factor")
137+
138+
if rope_type in (None, "default") and factor is None:
139+
config.rope_scaling = None
140+
return
141+
142+
config.rope_scaling = dict(rope_scaling)
143+
config.rope_scaling["type"] = rope_type
144+
29145
def _sanitize_generation_config(cfg: GenerationConfig, *, drop_sampling_fields: bool = False) -> bool:
30146
changed = False
31147
if cfg is None:
@@ -154,6 +270,10 @@ def build_shell_model(
154270
del init_kwargs["_fast_init"]
155271
# All nn.Parameters and buffers are created
156272

273+
if trust_remote_code:
274+
_patch_transformers_remote_code_compat()
275+
_normalize_remote_code_config_compat(config)
276+
157277
# All nn.Parameters and buffers are created on 'meta' and initializers are skipped.
158278
pb = log.spinner(title="Model loading...", interval=0.1)
159279
try:
@@ -167,4 +287,7 @@ def build_shell_model(
167287
finally:
168288
pb.close()
169289

290+
if trust_remote_code and isinstance(shell, PreTrainedModel):
291+
_normalize_legacy_tied_weights_keys(shell)
292+
170293
return shell

0 commit comments

Comments
 (0)