Fix Transformers 4.x/5.x compatibility and isolate multi-image vision attention

#102
by Bvicii - opened
Files changed (1) hide show
  1. modeling_paddleocr_vl.py +182 -43
modeling_paddleocr_vl.py CHANGED
@@ -12,9 +12,11 @@
12
  # See the License for the specific language governing permissions and
13
  # limitations under the License.
14
 
 
15
  import math
16
  import warnings
17
  from dataclasses import dataclass
 
18
  from typing import Any, Callable, Dict, List, Optional, Tuple, Union
19
 
20
  import numpy as np
@@ -28,9 +30,9 @@ from transformers.cache_utils import (
28
  Cache,
29
  DynamicCache,
30
  )
 
31
  from transformers.generation import GenerationMixin
32
  from transformers.integrations import use_kernel_forward_from_hub
33
- from transformers.masking_utils import create_causal_mask
34
  from transformers.modeling_attn_mask_utils import AttentionMaskConverter
35
  from transformers.modeling_layers import GradientCheckpointingLayer
36
  from transformers.modeling_outputs import (
@@ -66,6 +68,87 @@ else:
66
  from .configuration_paddleocr_vl import PaddleOCRVisionConfig, PaddleOCRVLConfig
67
 
68
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
69
  class RotaryEmbedding(nn.Module):
70
  def __init__(self, config: PaddleOCRVLConfig, device=None):
71
  super().__init__()
@@ -92,12 +175,25 @@ class RotaryEmbedding(nn.Module):
92
  self.original_max_seq_len = config.max_position_embeddings
93
 
94
  self.config = config
95
- self.rope_init_fn = ROPE_INIT_FUNCTIONS[self.rope_type]
 
 
 
96
 
97
  inv_freq, self.attention_scaling = self.rope_init_fn(self.config, device)
98
  self.register_buffer("inv_freq", inv_freq, persistent=False)
99
  self.original_inv_freq = self.inv_freq
100
 
 
 
 
 
 
 
 
 
 
 
101
  def _dynamic_frequency_update(self, position_ids, device):
102
  """
103
  dynamic RoPE layers should recompute `inv_freq` in the following situations:
@@ -539,6 +635,12 @@ class Ernie4_5PreTrainedModel(PreTrainedModel):
539
  }
540
 
541
 
 
 
 
 
 
 
542
  @auto_docstring
543
  class Ernie4_5Model(Ernie4_5PreTrainedModel):
544
  def __init__(self, config: PaddleOCRVLConfig):
@@ -603,13 +705,8 @@ class Ernie4_5Model(Ernie4_5PreTrainedModel):
603
  elif position_ids.dim() == 2:
604
  position_ids = position_ids[None, ...].expand(3, position_ids.shape[0], -1)
605
 
606
- causal_mask = create_causal_mask(
607
- config=self.config,
608
- inputs_embeds=inputs_embeds,
609
- attention_mask=attention_mask,
610
- past_key_values=past_key_values,
611
- position_ids=position_ids,
612
- cache_position=cache_position,
613
  )
614
 
615
  hidden_states = inputs_embeds
@@ -634,7 +731,7 @@ class Ernie4_5Model(Ernie4_5PreTrainedModel):
634
 
635
 
636
  class Ernie4_5ForCausalLM(Ernie4_5PreTrainedModel, GenerationMixin):
637
- _tied_weights_keys = ["lm_head.weight"]
638
  _tp_plan = {"lm_head": "colwise_rep"}
639
  _pp_plan = {"lm_head": (["hidden_states"], ["logits"])}
640
 
@@ -711,6 +808,7 @@ class Ernie4_5ForCausalLM(Ernie4_5PreTrainedModel, GenerationMixin):
711
  )
712
 
713
 
 
714
  def _trunc_normal_(tensor, mean, std, a, b):
715
  # Cut & paste from PyTorch official master until it's in a few official releases - RW
716
  # Method based on https://people.sc.fsu.edu/~jburkardt/presentations/truncated_normal.pdf
@@ -747,6 +845,7 @@ def _trunc_normal_(tensor, mean, std, a, b):
747
  tensor.clamp_(min=a, max=b)
748
 
749
 
 
750
  def trunc_normal_tf_(
751
  tensor: torch.Tensor,
752
  mean: float = 0.0,
@@ -777,6 +876,7 @@ def trunc_normal_tf_(
777
  tensor.mul_(std).add_(mean)
778
 
779
 
 
780
  def variance_scaling_(tensor, scale=1.0, mode="fan_in", distribution="normal"):
781
  fan_in, fan_out = _calculate_fan_in_and_fan_out(tensor)
782
  if mode == "fan_in":
@@ -1134,16 +1234,39 @@ class PaddleOCRAttention(nn.Module):
1134
  elif self.config._attn_implementation == "sdpa":
1135
  attention_interface = sdpa_attention_forward
1136
 
1137
- attn_output, attn_weights = attention_interface(
1138
- self,
1139
- queries,
1140
- keys,
1141
- values,
1142
- attention_mask,
1143
- is_causal=self.is_causal,
1144
- scaling=self.scale,
1145
- dropout=0.0 if not self.training else self.dropout,
1146
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1147
  attn_output = attn_output.reshape(
1148
  batch_size, seq_length, embed_dim
1149
  ).contiguous()
@@ -1263,45 +1386,47 @@ class PaddleOCRPreTrainedModel(PreTrainedModel):
1263
  "PaddleOCRVisionEmbeddings",
1264
  "PaddleOCRMultiheadAttentionPoolingHead",
1265
  ]
1266
- _supports_flash_attn_2 = True
 
1267
  _supports_sdpa = True
1268
 
1269
  def _init_weights(self, module):
1270
- """Initialize the weights"""
 
1271
  if isinstance(module, PaddleOCRVisionEmbeddings):
1272
  width = (
1273
  self.config.vision_config.hidden_size
1274
  if isinstance(self.config, PaddleOCRVLConfig)
1275
  else self.config.hidden_size
1276
  )
1277
- nn.init.normal_(module.position_embedding.weight, std=1 / np.sqrt(width))
1278
  elif isinstance(module, nn.Embedding):
1279
  default_flax_embed_init(module.weight)
1280
  elif isinstance(module, PaddleOCRAttention):
1281
- nn.init.xavier_uniform_(module.q_proj.weight)
1282
- nn.init.xavier_uniform_(module.k_proj.weight)
1283
- nn.init.xavier_uniform_(module.v_proj.weight)
1284
- nn.init.xavier_uniform_(module.out_proj.weight)
1285
- nn.init.zeros_(module.q_proj.bias)
1286
- nn.init.zeros_(module.k_proj.bias)
1287
- nn.init.zeros_(module.v_proj.bias)
1288
- nn.init.zeros_(module.out_proj.bias)
1289
  elif isinstance(module, PaddleOCRMLP):
1290
- nn.init.xavier_uniform_(module.fc1.weight)
1291
- nn.init.xavier_uniform_(module.fc2.weight)
1292
- nn.init.normal_(module.fc1.bias, std=1e-6)
1293
- nn.init.normal_(module.fc2.bias, std=1e-6)
1294
  elif isinstance(module, PaddleOCRMultiheadAttentionPoolingHead):
1295
- nn.init.xavier_uniform_(module.probe.data)
1296
- nn.init.xavier_uniform_(module.attention.in_proj_weight.data)
1297
- nn.init.zeros_(module.attention.in_proj_bias.data)
1298
  elif isinstance(module, (nn.Linear, nn.Conv2d)):
1299
  lecun_normal_(module.weight)
1300
  if module.bias is not None:
1301
- nn.init.zeros_(module.bias)
1302
  elif isinstance(module, nn.LayerNorm):
1303
- module.bias.data.zero_()
1304
- module.weight.data.fill_(1.0)
1305
 
1306
 
1307
  # Copied from transformers.models.altclip.modeling_altclip.AltCLIPEncoder with AltCLIP->PaddleOCR
@@ -1866,7 +1991,7 @@ class PaddleOCRVLCausalLMOutputWithPast(ModelOutput):
1866
 
1867
 
1868
  class PaddleOCRVLForConditionalGeneration(Ernie4_5PreTrainedModel, GenerationMixin):
1869
- _tied_weights_keys = ["lm_head.weight"]
1870
  config_class = PaddleOCRVLConfig
1871
  _no_split_modules = ["Ernie4_5_DecoderLayer", "PaddleOCREncoderLayer"]
1872
 
@@ -2342,7 +2467,21 @@ class PaddleOCRVLForConditionalGeneration(Ernie4_5PreTrainedModel, GenerationMix
2342
 
2343
  model_inputs["position_ids"] = None
2344
 
2345
- if cache_position[0] != 0:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2346
  model_inputs["pixel_values"] = None
2347
  model_inputs["pixel_values_videos"] = None
2348
 
 
12
  # See the License for the specific language governing permissions and
13
  # limitations under the License.
14
 
15
+ import inspect
16
  import math
17
  import warnings
18
  from dataclasses import dataclass
19
+ from functools import wraps
20
  from typing import Any, Callable, Dict, List, Optional, Tuple, Union
21
 
22
  import numpy as np
 
30
  Cache,
31
  DynamicCache,
32
  )
33
+ from transformers.masking_utils import create_causal_mask as _hf_create_causal_mask
34
  from transformers.generation import GenerationMixin
35
  from transformers.integrations import use_kernel_forward_from_hub
 
36
  from transformers.modeling_attn_mask_utils import AttentionMaskConverter
37
  from transformers.modeling_layers import GradientCheckpointingLayer
38
  from transformers.modeling_outputs import (
 
68
  from .configuration_paddleocr_vl import PaddleOCRVisionConfig, PaddleOCRVLConfig
69
 
70
 
71
+ # Resolve optional framework interfaces once, outside the forward path.
72
+ try:
73
+ from transformers import initialization as _hf_initialization
74
+ except ImportError:
75
+ _hf_initialization = None
76
+
77
+ # create_causal_mask exists in every release this file can import on (>= 4.54),
78
+ # but its signature changed: `input_embeds` -> `inputs_embeds`, and
79
+ # `cache_position` was later removed in favor of reading offsets from the cache.
80
+ _HF_MASK_PARAMETERS = frozenset(inspect.signature(_hf_create_causal_mask).parameters)
81
+ _HF_MASK_INPUT_NAME = "inputs_embeds" if "inputs_embeds" in _HF_MASK_PARAMETERS else "input_embeds"
82
+
83
+
84
+ def _guard_initializer(function):
85
+ @wraps(function)
86
+ def initialize(tensor, *args, **kwargs):
87
+ if getattr(tensor, "_is_hf_initialized", False):
88
+ return tensor
89
+ with torch.no_grad():
90
+ return function(tensor, *args, **kwargs)
91
+ return initialize
92
+
93
+
94
+ @_guard_initializer
95
+ def _init_tensor(tensor, operation, *args, **kwargs):
96
+ # Standard primitives use the framework's protected implementation when
97
+ # present. Keep model-specific TF/LeCun sampling formulas below unchanged.
98
+ function = getattr(_hf_initialization, operation, None)
99
+ if function is not None:
100
+ return function(tensor, *args, **kwargs)
101
+ if operation == "copy_":
102
+ return tensor.copy_(*args, **kwargs)
103
+ return getattr(nn.init, operation)(tensor, *args, **kwargs)
104
+
105
+
106
+ def _create_causal_mask(config, inputs_embeds, attention_mask, past_key_values, cache_position):
107
+ # Only dense tensors need conversion; flex BlockMask is passed through to the native function.
108
+ if isinstance(attention_mask, torch.Tensor) and attention_mask.ndim == 4:
109
+ mask = attention_mask.to(device=inputs_embeds.device)
110
+ if mask.dtype == torch.bool:
111
+ additive = torch.zeros(mask.shape, device=mask.device, dtype=inputs_embeds.dtype)
112
+ return additive.masked_fill(~mask, torch.finfo(inputs_embeds.dtype).min)
113
+ return mask.to(dtype=inputs_embeds.dtype)
114
+
115
+ mask_kwargs = {
116
+ "config": config,
117
+ _HF_MASK_INPUT_NAME: inputs_embeds,
118
+ "attention_mask": attention_mask,
119
+ "past_key_values": past_key_values,
120
+ }
121
+ if "cache_position" in _HF_MASK_PARAMETERS:
122
+ mask_kwargs["cache_position"] = cache_position
123
+ if "position_ids" in _HF_MASK_PARAMETERS:
124
+ # 3D M-RoPE coordinates are not packed text-sequence positions.
125
+ mask_kwargs["position_ids"] = None
126
+ return _hf_create_causal_mask(**mask_kwargs)
127
+
128
+
129
+ def _init_derived_buffers(module):
130
+ # v5 materializes non-persistent buffers from meta storage; they are not
131
+ # loaded from the checkpoint and must be initialized explicitly.
132
+ if isinstance(module, RotaryEmbedding):
133
+ inv_freq, module.attention_scaling = module.rope_init_fn(
134
+ module.config, device=module.inv_freq.device
135
+ )
136
+ _init_tensor(module.inv_freq, "copy_", inv_freq)
137
+ module.original_inv_freq = module.inv_freq
138
+ elif isinstance(module, SigLIPRotaryEmbedding):
139
+ inv_freq = 1.0 / (
140
+ module.theta ** (
141
+ torch.arange(0, module.dim, 2, dtype=torch.float32, device=module.inv_freq.device)
142
+ / module.dim
143
+ )
144
+ )
145
+ _init_tensor(module.inv_freq, "copy_", inv_freq)
146
+ elif isinstance(module, PaddleOCRVisionEmbeddings):
147
+ _init_tensor(module.position_ids, "copy_",
148
+ torch.arange(module.num_positions, device=module.position_ids.device).expand(1, -1)
149
+ )
150
+
151
+
152
  class RotaryEmbedding(nn.Module):
153
  def __init__(self, config: PaddleOCRVLConfig, device=None):
154
  super().__init__()
 
175
  self.original_max_seq_len = config.max_position_embeddings
176
 
177
  self.config = config
178
+ if self.rope_type == "default":
179
+ self.rope_init_fn = self.compute_default_rope_parameters
180
+ else:
181
+ self.rope_init_fn = ROPE_INIT_FUNCTIONS[self.rope_type]
182
 
183
  inv_freq, self.attention_scaling = self.rope_init_fn(self.config, device)
184
  self.register_buffer("inv_freq", inv_freq, persistent=False)
185
  self.original_inv_freq = self.inv_freq
186
 
187
+ @staticmethod
188
+ def compute_default_rope_parameters(config, device=None, seq_len=None):
189
+ # Default RoPE is no longer part of ROPE_INIT_FUNCTIONS in v5.
190
+ head_dim = getattr(config, "head_dim", None) or config.hidden_size // config.num_attention_heads
191
+ dim = int(head_dim * getattr(config, "partial_rotary_factor", 1.0))
192
+ inv_freq = 1.0 / (
193
+ config.rope_theta ** (torch.arange(0, dim, 2, dtype=torch.float32, device=device) / dim)
194
+ )
195
+ return inv_freq, 1.0
196
+
197
  def _dynamic_frequency_update(self, position_ids, device):
198
  """
199
  dynamic RoPE layers should recompute `inv_freq` in the following situations:
 
635
  }
636
 
637
 
638
+ @torch.no_grad()
639
+ def _init_weights(self, module):
640
+ super()._init_weights(module)
641
+ _init_derived_buffers(module)
642
+
643
+
644
  @auto_docstring
645
  class Ernie4_5Model(Ernie4_5PreTrainedModel):
646
  def __init__(self, config: PaddleOCRVLConfig):
 
705
  elif position_ids.dim() == 2:
706
  position_ids = position_ids[None, ...].expand(3, position_ids.shape[0], -1)
707
 
708
+ causal_mask = _create_causal_mask(
709
+ self.config, inputs_embeds, attention_mask, past_key_values, cache_position
 
 
 
 
 
710
  )
711
 
712
  hidden_states = inputs_embeds
 
731
 
732
 
733
  class Ernie4_5ForCausalLM(Ernie4_5PreTrainedModel, GenerationMixin):
734
+ _tied_weights_keys = {"lm_head.weight": "model.embed_tokens.weight"}
735
  _tp_plan = {"lm_head": "colwise_rep"}
736
  _pp_plan = {"lm_head": (["hidden_states"], ["logits"])}
737
 
 
808
  )
809
 
810
 
811
+ @_guard_initializer
812
  def _trunc_normal_(tensor, mean, std, a, b):
813
  # Cut & paste from PyTorch official master until it's in a few official releases - RW
814
  # Method based on https://people.sc.fsu.edu/~jburkardt/presentations/truncated_normal.pdf
 
845
  tensor.clamp_(min=a, max=b)
846
 
847
 
848
+ @_guard_initializer
849
  def trunc_normal_tf_(
850
  tensor: torch.Tensor,
851
  mean: float = 0.0,
 
876
  tensor.mul_(std).add_(mean)
877
 
878
 
879
+ @_guard_initializer
880
  def variance_scaling_(tensor, scale=1.0, mode="fan_in", distribution="normal"):
881
  fan_in, fan_out = _calculate_fan_in_and_fan_out(tensor)
882
  if mode == "fan_in":
 
1234
  elif self.config._attn_implementation == "sdpa":
1235
  attention_interface = sdpa_attention_forward
1236
 
1237
+ if cu_seqlens is not None and cu_seqlens.numel() > 2:
1238
+ boundaries = cu_seqlens.tolist()
1239
+ outputs = []
1240
+ attn_weights = (
1241
+ queries.new_zeros(batch_size, self.num_heads, seq_length, seq_length)
1242
+ if output_attentions else None
1243
+ )
1244
+ for start, end in zip(boundaries[:-1], boundaries[1:]):
1245
+ local_mask = None
1246
+ if attention_mask is not None:
1247
+ # Keep size-1 broadcast dims, e.g. a [B, 1, 1, L] padding mask.
1248
+ span = slice(start, end)
1249
+ local_mask = attention_mask[
1250
+ ...,
1251
+ span if attention_mask.shape[-2] > 1 else slice(None),
1252
+ span if attention_mask.shape[-1] > 1 else slice(None),
1253
+ ]
1254
+ output, weights = attention_interface(
1255
+ self, queries[:, :, start:end], keys[:, :, start:end],
1256
+ values[:, :, start:end], local_mask,
1257
+ is_causal=False, scaling=self.scale,
1258
+ dropout=0.0 if not self.training else self.dropout,
1259
+ )
1260
+ outputs.append(output)
1261
+ if attn_weights is not None and weights is not None:
1262
+ attn_weights[..., start:end, start:end] = weights
1263
+ attn_output = torch.cat(outputs, dim=1)
1264
+ else:
1265
+ attn_output, attn_weights = attention_interface(
1266
+ self, queries, keys, values, attention_mask,
1267
+ is_causal=self.is_causal, scaling=self.scale,
1268
+ dropout=0.0 if not self.training else self.dropout,
1269
+ )
1270
  attn_output = attn_output.reshape(
1271
  batch_size, seq_length, embed_dim
1272
  ).contiguous()
 
1386
  "PaddleOCRVisionEmbeddings",
1387
  "PaddleOCRMultiheadAttentionPoolingHead",
1388
  ]
1389
+ # v5 only reads `_supports_flash_attn`; 4.x accepts both names.
1390
+ _supports_flash_attn = True
1391
  _supports_sdpa = True
1392
 
1393
  def _init_weights(self, module):
1394
+ """Initialize the weights and derived non-persistent buffers."""
1395
+ _init_derived_buffers(module)
1396
  if isinstance(module, PaddleOCRVisionEmbeddings):
1397
  width = (
1398
  self.config.vision_config.hidden_size
1399
  if isinstance(self.config, PaddleOCRVLConfig)
1400
  else self.config.hidden_size
1401
  )
1402
+ _init_tensor(module.position_embedding.weight, 'normal_', std=1 / np.sqrt(width))
1403
  elif isinstance(module, nn.Embedding):
1404
  default_flax_embed_init(module.weight)
1405
  elif isinstance(module, PaddleOCRAttention):
1406
+ _init_tensor(module.q_proj.weight, 'xavier_uniform_')
1407
+ _init_tensor(module.k_proj.weight, 'xavier_uniform_')
1408
+ _init_tensor(module.v_proj.weight, 'xavier_uniform_')
1409
+ _init_tensor(module.out_proj.weight, 'xavier_uniform_')
1410
+ _init_tensor(module.q_proj.bias, 'zeros_')
1411
+ _init_tensor(module.k_proj.bias, 'zeros_')
1412
+ _init_tensor(module.v_proj.bias, 'zeros_')
1413
+ _init_tensor(module.out_proj.bias, 'zeros_')
1414
  elif isinstance(module, PaddleOCRMLP):
1415
+ _init_tensor(module.fc1.weight, 'xavier_uniform_')
1416
+ _init_tensor(module.fc2.weight, 'xavier_uniform_')
1417
+ _init_tensor(module.fc1.bias, 'normal_', std=1e-6)
1418
+ _init_tensor(module.fc2.bias, 'normal_', std=1e-6)
1419
  elif isinstance(module, PaddleOCRMultiheadAttentionPoolingHead):
1420
+ _init_tensor(module.probe, 'xavier_uniform_')
1421
+ _init_tensor(module.attention.in_proj_weight, 'xavier_uniform_')
1422
+ _init_tensor(module.attention.in_proj_bias, 'zeros_')
1423
  elif isinstance(module, (nn.Linear, nn.Conv2d)):
1424
  lecun_normal_(module.weight)
1425
  if module.bias is not None:
1426
+ _init_tensor(module.bias, 'zeros_')
1427
  elif isinstance(module, nn.LayerNorm):
1428
+ _init_tensor(module.bias, 'zeros_')
1429
+ _init_tensor(module.weight, 'ones_')
1430
 
1431
 
1432
  # Copied from transformers.models.altclip.modeling_altclip.AltCLIPEncoder with AltCLIP->PaddleOCR
 
1991
 
1992
 
1993
  class PaddleOCRVLForConditionalGeneration(Ernie4_5PreTrainedModel, GenerationMixin):
1994
+ _tied_weights_keys = {"lm_head.weight": "model.embed_tokens.weight"}
1995
  config_class = PaddleOCRVLConfig
1996
  _no_split_modules = ["Ernie4_5_DecoderLayer", "PaddleOCREncoderLayer"]
1997
 
 
2467
 
2468
  model_inputs["position_ids"] = None
2469
 
2470
+ # v5 creates cache_position inside the parent method, rather than
2471
+ # passing it to this override. Read the prepared value back first.
2472
+ cache_position = model_inputs.get("cache_position", cache_position)
2473
+ if cache_position is None:
2474
+ past_seen_tokens = past_key_values.get_seq_length() if past_key_values is not None else 0
2475
+ prepared = model_inputs.get("inputs_embeds")
2476
+ if prepared is None:
2477
+ prepared = model_inputs["input_ids"]
2478
+ cache_position = torch.arange(
2479
+ past_seen_tokens, past_seen_tokens + prepared.shape[1], device=prepared.device
2480
+ )
2481
+ model_inputs["cache_position"] = cache_position
2482
+
2483
+ # Without KV caching, every forward still consumes the image tokens.
2484
+ if use_cache and past_key_values is not None and past_key_values.get_seq_length() > 0:
2485
  model_inputs["pixel_values"] = None
2486
  model_inputs["pixel_values_videos"] = None
2487