Skip to content

Commit 9328199

Browse files
authored
Merge branch 'develop' into feat/add-granite-model
2 parents 3276dae + ab92762 commit 9328199

22 files changed

Lines changed: 4843 additions & 0 deletions

File tree

paddleformers/cli/utils/llm_utils.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -440,6 +440,17 @@ def get_lora_target_modules(model):
440440
"model.visual.blocks.*mlp.up_proj.*",
441441
"model.visual.blocks.*mlp.down_proj.*",
442442
]
443+
elif model.config.model_type == "internlm2":
444+
# Covers both InternLM2 2.0 and 2.5: both route through the unified
445+
# `intern/` proxy with `model_type = "internlm2"` and share the same
446+
# weight key names (wqkv/wo/w1/w2/w3).
447+
target_modules = [
448+
".*wqkv.*",
449+
".*wo.*",
450+
".*w1.*",
451+
".*w2.*",
452+
".*w3.*",
453+
]
443454
else:
444455
raise ValueError(f"Unknown base_model_prefix: {model.config.model_type}.")
445456
return target_modules

paddleformers/datasets/template/template.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1004,6 +1004,16 @@ def _get_gpt_oss_prefix():
10041004
chat_sep="<|assistant|>\n",
10051005
mm_plugin=get_mm_plugin(name="glm_ocr", image_token="<|image|>"),
10061006
)
1007+
register_template(
1008+
name="internlm2_5",
1009+
format_user=StringFormatter(slots=["<|im_start|>user\n{{content}}<|im_end|>\n<|im_start|>assistant\n"]),
1010+
format_assistant=StringFormatter(slots=["{{content}}<|im_end|>\n"]),
1011+
format_system=StringFormatter(slots=["<|im_start|>system\n{{content}}<|im_end|>\n"]),
1012+
format_prefix=EmptyFormatter(slots=["<s>"]),
1013+
chat_sep="<|im_end|>\n",
1014+
suffix=["<|im_end|>\n"],
1015+
enable_thinking=None,
1016+
)
10071017

10081018

10091019
register_template(

paddleformers/transformers/__init__.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -352,6 +352,27 @@
352352
],
353353
"glm_ocr.processor": ["Glm46VProcessor"],
354354
"glm_ocr.image_processor": ["Glm46VImageProcessor"],
355+
"intern_lm2_5.configuration": ["InternLM25Config"],
356+
"intern_lm2_5.modeling": [
357+
"InternLM25DecoderLayer",
358+
"InternLM25Model",
359+
"InternLM25ForCausalLM",
360+
"InternLM25PretrainedModel",
361+
"InternLM25ForSequenceClassification",
362+
"InternLM25ForQuestionAnswering",
363+
"InternLM25ForTokenClassification",
364+
],
365+
"intern_lm2_5.tokenizer": ["InternLM25Tokenizer"],
366+
"intern.configuration": ["InternLM2Config"],
367+
"intern.modeling": [
368+
"InternLM2PretrainedModel",
369+
"InternLM2Model",
370+
"InternLM2ForCausalLM",
371+
"InternLM2ForSequenceClassification",
372+
"InternLM2ForQuestionAnswering",
373+
"InternLM2ForTokenClassification",
374+
],
375+
"intern_lm2.tokenizer": ["InternLM2Tokenizer"],
355376
"gemma4_moe.configuration": ["Gemma4MoeConfig"],
356377
"gemma4_moe.modeling": ["Gemma4MoeForCausalLM"],
357378
"gemma4_moe": [],
@@ -438,6 +459,9 @@
438459
from .phi3 import *
439460
from .gemma3_text import *
440461
from .glm_ocr import *
462+
from .intern_lm2_5 import *
463+
from .intern import *
464+
from .intern_lm2 import InternLM2Tokenizer
441465
from .gemma4_moe import *
442466
from .phi4 import *
443467
else:

paddleformers/transformers/auto/configuration.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@
6666
("glm_ocr", "GlmOcrConfig"),
6767
("qwen3_5", "Qwen3_5Config"),
6868
("qwen3_5_moe", "Qwen3_5MoEConfig"),
69+
("internlm2", "InternLM2Config"),
6970
# TODO(VL): When Gemma4 VL is implemented, "gemma4" should point to Gemma4Config (VL wrapper)
7071
("gemma4_text", "Gemma4MoeConfig"),
7172
("gemma4", "Gemma4MoeConfig"), # Temporary: no standalone text ckpt, extract text_config in from_dict
@@ -102,6 +103,7 @@
102103
("minicpm", "MiniCPM"),
103104
("qwen3_5_moe", "Qwen3_5MoEForConditionalGeneration"),
104105
("qwen3_5", "Qwen3_5ForConditionalGeneration"),
106+
("internlm2", "InternLM2"),
105107
("gemma4_moe", "Gemma4MoeForCausalLM"),
106108
("gemma4_text", "Gemma4MoeForCausalLM"),
107109
("gemma4", "Gemma4MoeForCausalLM"),
@@ -121,6 +123,7 @@
121123
("qwen3_vl_text", "qwen3_vl"),
122124
("qwen3_vl_moe_text", "qwen3_vl_moe"),
123125
("granitemoehybrid", "granite"),
126+
("internlm2", "intern"),
124127
# TODO(VL): Remove these when Gemma4 VL module (gemma4/) is created
125128
("gemma4_text", "gemma4_moe"),
126129
("gemma4", "gemma4_moe"),

paddleformers/transformers/auto/modeling.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@
8585
("Gemma4Moe", "gemma4_moe"),
8686
("Glm4vMoe", "glm4v_moe"),
8787
("GlmOcr", "glm_ocr"),
88+
("InternLM2", "intern"),
8889
]
8990
)
9091

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
# Copyright (c) 2026 PaddlePaddle Authors. All Rights Reserved.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
"""
16+
InternLM2 Common Module
17+
18+
This module provides unified access to both InternLM2 2.0 and 2.5 models.
19+
It automatically routes to the correct implementation based on the model configuration.
20+
"""
21+
22+
from .configuration import InternLM2Config
23+
from .modeling import (
24+
InternLM2ForCausalLM,
25+
InternLM2ForQuestionAnswering,
26+
InternLM2ForSequenceClassification,
27+
InternLM2ForTokenClassification,
28+
InternLM2Model,
29+
InternLM2PretrainedModel,
30+
)
31+
32+
# Alias for auto system compatibility
33+
InternLM2 = InternLM2Model
34+
35+
__all__ = [
36+
"InternLM2Config",
37+
"InternLM2Model",
38+
"InternLM2",
39+
"InternLM2PretrainedModel",
40+
"InternLM2ForCausalLM",
41+
"InternLM2ForSequenceClassification",
42+
"InternLM2ForQuestionAnswering",
43+
"InternLM2ForTokenClassification",
44+
]
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
# Copyright (c) 2026 PaddlePaddle Authors. All Rights Reserved.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
"""
16+
InternLM2 Common Configuration
17+
18+
This module provides a unified configuration for both InternLM2 2.0 and 2.5 models.
19+
It detects the version based on the configuration fields and routes accordingly.
20+
"""
21+
22+
from paddleformers.transformers.configuration_utils import PretrainedConfig
23+
24+
25+
class InternLM2Config(PretrainedConfig):
26+
"""
27+
InternLM2 configuration. This is a unified config that handles both 2.0 and 2.5 versions.
28+
29+
When loading from HuggingFace, the `model_type` will be "internlm2" (not "internlm2_5").
30+
This config detects the actual version and routes to the appropriate implementation.
31+
"""
32+
33+
model_type = "internlm2" # Important: must match HuggingFace config
34+
_auto_class = "AutoConfig"
35+
keys_to_ignore_at_inference = ["past_key_values"]
36+
37+
def __init__(
38+
self,
39+
vocab_size=92550,
40+
hidden_size=4096,
41+
intermediate_size=11008,
42+
num_hidden_layers=32,
43+
num_attention_heads=32,
44+
num_key_value_heads=None,
45+
hidden_act="silu",
46+
max_position_embeddings=2048,
47+
initializer_range=0.02,
48+
rms_norm_eps=1e-6,
49+
use_cache=True,
50+
pad_token_id=0,
51+
bos_token_id=1,
52+
eos_token_id=2,
53+
pretraining_tp=1,
54+
tie_word_embeddings=False,
55+
bias=True,
56+
rope_theta=10000,
57+
rope_scaling=None,
58+
attn_implementation=None,
59+
dtype="bfloat16",
60+
**kwargs,
61+
):
62+
self.vocab_size = vocab_size
63+
self.max_position_embeddings = max_position_embeddings
64+
self.hidden_size = hidden_size
65+
self.intermediate_size = intermediate_size
66+
self.num_hidden_layers = num_hidden_layers
67+
self.num_attention_heads = num_attention_heads
68+
self.bias = bias
69+
70+
import paddle
71+
72+
if isinstance(dtype, str):
73+
dtype_map = {
74+
"float32": paddle.float32,
75+
"float16": paddle.float16,
76+
"bfloat16": paddle.bfloat16,
77+
}
78+
self.dtype = dtype_map.get(dtype.lower(), paddle.float32)
79+
else:
80+
self.dtype = dtype
81+
82+
if num_key_value_heads is None:
83+
num_key_value_heads = num_attention_heads
84+
self.num_key_value_heads = num_key_value_heads
85+
86+
self.hidden_act = hidden_act
87+
self.initializer_range = initializer_range
88+
self.rms_norm_eps = rms_norm_eps
89+
self.pretraining_tp = pretraining_tp
90+
self.use_cache = use_cache
91+
self.rope_theta = rope_theta
92+
self.rope_scaling = rope_scaling
93+
self._rope_scaling_validation()
94+
self.attn_implementation = attn_implementation
95+
if self.attn_implementation is None:
96+
self.attn_implementation = "eager"
97+
98+
super().__init__(
99+
pad_token_id=pad_token_id,
100+
bos_token_id=bos_token_id,
101+
eos_token_id=eos_token_id,
102+
tie_word_embeddings=tie_word_embeddings,
103+
**kwargs,
104+
)
105+
106+
def _rope_scaling_validation(self):
107+
if self.rope_scaling is None:
108+
return
109+
110+
if not isinstance(self.rope_scaling, dict):
111+
raise ValueError(f"`rope_scaling` must be a dictionary, got {self.rope_scaling}")
112+
rope_scaling_type = self.rope_scaling.get("type", None)
113+
rope_scaling_factor = self.rope_scaling.get("factor", None)
114+
if rope_scaling_type is None or rope_scaling_factor is None:
115+
raise ValueError("`rope_scaling` must contain 'type' and 'factor' keys, " f"got {self.rope_scaling}")
116+
if rope_scaling_type not in ["linear", "dynamic"]:
117+
raise ValueError(f"`rope_scaling` type must be 'linear' or 'dynamic', got '{rope_scaling_type}'")
118+
if not isinstance(rope_scaling_factor, (int, float)) or rope_scaling_factor < 1.0:
119+
raise ValueError(f"`rope_scaling` factor must be a number >= 1, got {rope_scaling_factor}")
120+
121+
@property
122+
def is_version_2_5(self):
123+
if hasattr(self, "auto_map") and self.auto_map is not None:
124+
if "AutoModelForSequenceClassification" in self.auto_map:
125+
return True
126+
return False
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
# Copyright (c) 2026 PaddlePaddle Authors. All Rights Reserved.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
"""
16+
InternLM2 Common Modeling
17+
18+
Factory-routing entry point. The classes here are never instantiated as
19+
themselves: `__new__` (direct construction) and `from_pretrained` (loading)
20+
both return a real implementation-class instance from `intern_lm2` (2.0) or
21+
`intern_lm2_5` (2.5), selected via `config.is_version_2_5`.
22+
23+
"""
24+
25+
from paddleformers.transformers.model_utils import PretrainedModel
26+
from paddleformers.utils.log import logger
27+
28+
from .configuration import InternLM2Config
29+
30+
31+
def _select_impl_cls(cls_name, config):
32+
"""Pick the real implementation class by version. Returns the class object."""
33+
if config.is_version_2_5:
34+
logger.info("Detected InternLM2 2.5, loading 2.5 implementation")
35+
from ..intern_lm2_5 import modeling as _impl_module
36+
else:
37+
logger.info("Detected InternLM2 2.0, loading 2.0 implementation")
38+
from ..intern_lm2 import modeling as _impl_module
39+
40+
impl_cls = getattr(_impl_module, cls_name, None)
41+
if impl_cls is None:
42+
raise NotImplementedError(
43+
f"{cls_name} is not implemented for InternLM2 "
44+
f"{'2.5' if config.is_version_2_5 else '2.0'} in PaddleFormers."
45+
)
46+
return impl_cls
47+
48+
49+
class InternLM2PretrainedModel(PretrainedModel):
50+
config_class = InternLM2Config
51+
base_model_prefix = "model"
52+
supports_gradient_checkpointing = True
53+
_no_split_modules = ["InternLM2DecoderLayer", "InternLM25DecoderLayer"]
54+
_skip_keys_device_placement = ["past_key_values"]
55+
transpose_weight_keys = ["wqkv", "wo", "w1", "w2", "w3", "output"]
56+
_supports_flash_attn_2 = True
57+
_supports_sdpa = True
58+
_supports_cache_class = True
59+
_supports_quantized_cache = True
60+
_supports_static_cache = True
61+
62+
def __new__(cls, config, *args, **kwargs):
63+
impl_cls = _select_impl_cls(cls.__name__, config)
64+
return impl_cls(config, *args, **kwargs)
65+
66+
@classmethod
67+
def from_pretrained(cls, pretrained_model_name_or_path, *args, **kwargs):
68+
# Read config first (without instantiating) to decide the version,
69+
# then delegate to the real implementation class's from_pretrained.
70+
cfg_kwargs = {}
71+
for k in ("download_hub", "cache_dir", "subfolder", "trust_remote_code"):
72+
if k in kwargs:
73+
cfg_kwargs[k] = kwargs[k]
74+
config = InternLM2Config.from_pretrained(pretrained_model_name_or_path, **cfg_kwargs)
75+
impl_cls = _select_impl_cls(cls.__name__, config)
76+
return impl_cls.from_pretrained(pretrained_model_name_or_path, *args, **kwargs)
77+
78+
@classmethod
79+
def _gen_aoa_config(cls, config):
80+
impl_cls = _select_impl_cls(cls.__name__, config)
81+
return impl_cls._gen_aoa_config(config)
82+
83+
@classmethod
84+
def _gen_inv_aoa_config(cls, config):
85+
impl_cls = _select_impl_cls(cls.__name__, config)
86+
return impl_cls._gen_inv_aoa_config(config)
87+
88+
89+
class InternLM2Model(InternLM2PretrainedModel):
90+
_auto_class = "AutoModel"
91+
92+
93+
class InternLM2ForCausalLM(InternLM2PretrainedModel):
94+
_auto_class = "AutoModelForCausalLM"
95+
_tied_weights_keys = ["output.weight"]
96+
97+
98+
class InternLM2ForSequenceClassification(InternLM2PretrainedModel):
99+
_auto_class = "AutoModelForSequenceClassification"
100+
101+
102+
class InternLM2ForQuestionAnswering(InternLM2PretrainedModel):
103+
_auto_class = "AutoModelForQuestionAnswering"
104+
105+
106+
class InternLM2ForTokenClassification(InternLM2PretrainedModel):
107+
_auto_class = "AutoModelForTokenClassification"

0 commit comments

Comments
 (0)