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 +186 -44
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 (
@@ -54,7 +56,10 @@ from transformers.utils import (
54
  is_flash_attn_2_available,
55
  torch_int,
56
  )
57
- from transformers.utils.generic import check_model_inputs
 
 
 
58
 
59
  if is_flash_attn_2_available():
60
  from flash_attn import flash_attn_varlen_func
@@ -66,6 +71,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 +178,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 +638,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 +708,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 +734,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 +811,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 +848,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 +879,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 +1237,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 +1389,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 +1994,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 +2470,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 (
 
56
  is_flash_attn_2_available,
57
  torch_int,
58
  )
59
+ try:
60
+ from transformers.utils.generic import merge_with_config_defaults as check_model_inputs
61
+ except ImportError: # Transformers < 5.2
62
+ from transformers.utils.generic import check_model_inputs
63
 
64
  if is_flash_attn_2_available():
65
  from flash_attn import flash_attn_varlen_func
 
71
  from .configuration_paddleocr_vl import PaddleOCRVisionConfig, PaddleOCRVLConfig
72
 
73
 
74
+ # Resolve optional framework interfaces once, outside the forward path.
75
+ try:
76
+ from transformers import initialization as _hf_initialization
77
+ except ImportError:
78
+ _hf_initialization = None
79
+
80
+ # create_causal_mask exists in every release this file can import on (>= 4.54),
81
+ # but its signature changed: `input_embeds` -> `inputs_embeds`, and
82
+ # `cache_position` was later removed in favor of reading offsets from the cache.
83
+ _HF_MASK_PARAMETERS = frozenset(inspect.signature(_hf_create_causal_mask).parameters)
84
+ _HF_MASK_INPUT_NAME = "inputs_embeds" if "inputs_embeds" in _HF_MASK_PARAMETERS else "input_embeds"
85
+
86
+
87
+ def _guard_initializer(function):
88
+ @wraps(function)
89
+ def initialize(tensor, *args, **kwargs):
90
+ if getattr(tensor, "_is_hf_initialized", False):
91
+ return tensor
92
+ with torch.no_grad():
93
+ return function(tensor, *args, **kwargs)
94
+ return initialize
95
+
96
+
97
+ @_guard_initializer
98
+ def _init_tensor(tensor, operation, *args, **kwargs):
99
+ # Standard primitives use the framework's protected implementation when
100
+ # present. Keep model-specific TF/LeCun sampling formulas below unchanged.
101
+ function = getattr(_hf_initialization, operation, None)
102
+ if function is not None:
103
+ return function(tensor, *args, **kwargs)
104
+ if operation == "copy_":
105
+ return tensor.copy_(*args, **kwargs)
106
+ return getattr(nn.init, operation)(tensor, *args, **kwargs)
107
+
108
+
109
+ def _create_causal_mask(config, inputs_embeds, attention_mask, past_key_values, cache_position):
110
+ # Only dense tensors need conversion; flex BlockMask is passed through to the native function.
111
+ if isinstance(attention_mask, torch.Tensor) and attention_mask.ndim == 4:
112
+ mask = attention_mask.to(device=inputs_embeds.device)
113
+ if mask.dtype == torch.bool:
114
+ additive = torch.zeros(mask.shape, device=mask.device, dtype=inputs_embeds.dtype)
115
+ return additive.masked_fill(~mask, torch.finfo(inputs_embeds.dtype).min)
116
+ return mask.to(dtype=inputs_embeds.dtype)
117
+
118
+ mask_kwargs = {
119
+ "config": config,
120
+ _HF_MASK_INPUT_NAME: inputs_embeds,
121
+ "attention_mask": attention_mask,
122
+ "past_key_values": past_key_values,
123
+ }
124
+ if "cache_position" in _HF_MASK_PARAMETERS:
125
+ mask_kwargs["cache_position"] = cache_position
126
+ if "position_ids" in _HF_MASK_PARAMETERS:
127
+ # 3D M-RoPE coordinates are not packed text-sequence positions.
128
+ mask_kwargs["position_ids"] = None
129
+ return _hf_create_causal_mask(**mask_kwargs)
130
+
131
+
132
+ def _init_derived_buffers(module):
133
+ # v5 materializes non-persistent buffers from meta storage; they are not
134
+ # loaded from the checkpoint and must be initialized explicitly.
135
+ if isinstance(module, RotaryEmbedding):
136
+ inv_freq, module.attention_scaling = module.rope_init_fn(
137
+ module.config, device=module.inv_freq.device
138
+ )
139
+ _init_tensor(module.inv_freq, "copy_", inv_freq)
140
+ module.original_inv_freq = module.inv_freq
141
+ elif isinstance(module, SigLIPRotaryEmbedding):
142
+ inv_freq = 1.0 / (
143
+ module.theta ** (
144
+ torch.arange(0, module.dim, 2, dtype=torch.float32, device=module.inv_freq.device)
145
+ / module.dim
146
+ )
147
+ )
148
+ _init_tensor(module.inv_freq, "copy_", inv_freq)
149
+ elif isinstance(module, PaddleOCRVisionEmbeddings):
150
+ _init_tensor(module.position_ids, "copy_",
151
+ torch.arange(module.num_positions, device=module.position_ids.device).expand(1, -1)
152
+ )
153
+
154
+
155
  class RotaryEmbedding(nn.Module):
156
  def __init__(self, config: PaddleOCRVLConfig, device=None):
157
  super().__init__()
 
178
  self.original_max_seq_len = config.max_position_embeddings
179
 
180
  self.config = config
181
+ if self.rope_type == "default":
182
+ self.rope_init_fn = self.compute_default_rope_parameters
183
+ else:
184
+ self.rope_init_fn = ROPE_INIT_FUNCTIONS[self.rope_type]
185
 
186
  inv_freq, self.attention_scaling = self.rope_init_fn(self.config, device)
187
  self.register_buffer("inv_freq", inv_freq, persistent=False)
188
  self.original_inv_freq = self.inv_freq
189
 
190
+ @staticmethod
191
+ def compute_default_rope_parameters(config, device=None, seq_len=None):
192
+ # Default RoPE is no longer part of ROPE_INIT_FUNCTIONS in v5.
193
+ head_dim = getattr(config, "head_dim", None) or config.hidden_size // config.num_attention_heads
194
+ dim = int(head_dim * getattr(config, "partial_rotary_factor", 1.0))
195
+ inv_freq = 1.0 / (
196
+ config.rope_theta ** (torch.arange(0, dim, 2, dtype=torch.float32, device=device) / dim)
197
+ )
198
+ return inv_freq, 1.0
199
+
200
  def _dynamic_frequency_update(self, position_ids, device):
201
  """
202
  dynamic RoPE layers should recompute `inv_freq` in the following situations:
 
638
  }
639
 
640
 
641
+ @torch.no_grad()
642
+ def _init_weights(self, module):
643
+ super()._init_weights(module)
644
+ _init_derived_buffers(module)
645
+
646
+
647
  @auto_docstring
648
  class Ernie4_5Model(Ernie4_5PreTrainedModel):
649
  def __init__(self, config: PaddleOCRVLConfig):
 
708
  elif position_ids.dim() == 2:
709
  position_ids = position_ids[None, ...].expand(3, position_ids.shape[0], -1)
710
 
711
+ causal_mask = _create_causal_mask(
712
+ self.config, inputs_embeds, attention_mask, past_key_values, cache_position
 
 
 
 
 
713
  )
714
 
715
  hidden_states = inputs_embeds
 
734
 
735
 
736
  class Ernie4_5ForCausalLM(Ernie4_5PreTrainedModel, GenerationMixin):
737
+ _tied_weights_keys = {"lm_head.weight": "model.embed_tokens.weight"}
738
  _tp_plan = {"lm_head": "colwise_rep"}
739
  _pp_plan = {"lm_head": (["hidden_states"], ["logits"])}
740
 
 
811
  )
812
 
813
 
814
+ @_guard_initializer
815
  def _trunc_normal_(tensor, mean, std, a, b):
816
  # Cut & paste from PyTorch official master until it's in a few official releases - RW
817
  # Method based on https://people.sc.fsu.edu/~jburkardt/presentations/truncated_normal.pdf
 
848
  tensor.clamp_(min=a, max=b)
849
 
850
 
851
+ @_guard_initializer
852
  def trunc_normal_tf_(
853
  tensor: torch.Tensor,
854
  mean: float = 0.0,
 
879
  tensor.mul_(std).add_(mean)
880
 
881
 
882
+ @_guard_initializer
883
  def variance_scaling_(tensor, scale=1.0, mode="fan_in", distribution="normal"):
884
  fan_in, fan_out = _calculate_fan_in_and_fan_out(tensor)
885
  if mode == "fan_in":
 
1237
  elif self.config._attn_implementation == "sdpa":
1238
  attention_interface = sdpa_attention_forward
1239
 
1240
+ if cu_seqlens is not None and cu_seqlens.numel() > 2:
1241
+ boundaries = cu_seqlens.tolist()
1242
+ outputs = []
1243
+ attn_weights = (
1244
+ queries.new_zeros(batch_size, self.num_heads, seq_length, seq_length)
1245
+ if output_attentions else None
1246
+ )
1247
+ for start, end in zip(boundaries[:-1], boundaries[1:]):
1248
+ local_mask = None
1249
+ if attention_mask is not None:
1250
+ # Keep size-1 broadcast dims, e.g. a [B, 1, 1, L] padding mask.
1251
+ span = slice(start, end)
1252
+ local_mask = attention_mask[
1253
+ ...,
1254
+ span if attention_mask.shape[-2] > 1 else slice(None),
1255
+ span if attention_mask.shape[-1] > 1 else slice(None),
1256
+ ]
1257
+ output, weights = attention_interface(
1258
+ self, queries[:, :, start:end], keys[:, :, start:end],
1259
+ values[:, :, start:end], local_mask,
1260
+ is_causal=False, scaling=self.scale,
1261
+ dropout=0.0 if not self.training else self.dropout,
1262
+ )
1263
+ outputs.append(output)
1264
+ if attn_weights is not None and weights is not None:
1265
+ attn_weights[..., start:end, start:end] = weights
1266
+ attn_output = torch.cat(outputs, dim=1)
1267
+ else:
1268
+ attn_output, attn_weights = attention_interface(
1269
+ self, queries, keys, values, attention_mask,
1270
+ is_causal=self.is_causal, scaling=self.scale,
1271
+ dropout=0.0 if not self.training else self.dropout,
1272
+ )
1273
  attn_output = attn_output.reshape(
1274
  batch_size, seq_length, embed_dim
1275
  ).contiguous()
 
1389
  "PaddleOCRVisionEmbeddings",
1390
  "PaddleOCRMultiheadAttentionPoolingHead",
1391
  ]
1392
+ # v5 only reads `_supports_flash_attn`; 4.x accepts both names.
1393
+ _supports_flash_attn = True
1394
  _supports_sdpa = True
1395
 
1396
  def _init_weights(self, module):
1397
+ """Initialize the weights and derived non-persistent buffers."""
1398
+ _init_derived_buffers(module)
1399
  if isinstance(module, PaddleOCRVisionEmbeddings):
1400
  width = (
1401
  self.config.vision_config.hidden_size
1402
  if isinstance(self.config, PaddleOCRVLConfig)
1403
  else self.config.hidden_size
1404
  )
1405
+ _init_tensor(module.position_embedding.weight, 'normal_', std=1 / np.sqrt(width))
1406
  elif isinstance(module, nn.Embedding):
1407
  default_flax_embed_init(module.weight)
1408
  elif isinstance(module, PaddleOCRAttention):
1409
+ _init_tensor(module.q_proj.weight, 'xavier_uniform_')
1410
+ _init_tensor(module.k_proj.weight, 'xavier_uniform_')
1411
+ _init_tensor(module.v_proj.weight, 'xavier_uniform_')
1412
+ _init_tensor(module.out_proj.weight, 'xavier_uniform_')
1413
+ _init_tensor(module.q_proj.bias, 'zeros_')
1414
+ _init_tensor(module.k_proj.bias, 'zeros_')
1415
+ _init_tensor(module.v_proj.bias, 'zeros_')
1416
+ _init_tensor(module.out_proj.bias, 'zeros_')
1417
  elif isinstance(module, PaddleOCRMLP):
1418
+ _init_tensor(module.fc1.weight, 'xavier_uniform_')
1419
+ _init_tensor(module.fc2.weight, 'xavier_uniform_')
1420
+ _init_tensor(module.fc1.bias, 'normal_', std=1e-6)
1421
+ _init_tensor(module.fc2.bias, 'normal_', std=1e-6)
1422
  elif isinstance(module, PaddleOCRMultiheadAttentionPoolingHead):
1423
+ _init_tensor(module.probe, 'xavier_uniform_')
1424
+ _init_tensor(module.attention.in_proj_weight, 'xavier_uniform_')
1425
+ _init_tensor(module.attention.in_proj_bias, 'zeros_')
1426
  elif isinstance(module, (nn.Linear, nn.Conv2d)):
1427
  lecun_normal_(module.weight)
1428
  if module.bias is not None:
1429
+ _init_tensor(module.bias, 'zeros_')
1430
  elif isinstance(module, nn.LayerNorm):
1431
+ _init_tensor(module.bias, 'zeros_')
1432
+ _init_tensor(module.weight, 'ones_')
1433
 
1434
 
1435
  # Copied from transformers.models.altclip.modeling_altclip.AltCLIPEncoder with AltCLIP->PaddleOCR
 
1994
 
1995
 
1996
  class PaddleOCRVLForConditionalGeneration(Ernie4_5PreTrainedModel, GenerationMixin):
1997
+ _tied_weights_keys = {"lm_head.weight": "model.embed_tokens.weight"}
1998
  config_class = PaddleOCRVLConfig
1999
  _no_split_modules = ["Ernie4_5_DecoderLayer", "PaddleOCREncoderLayer"]
2000
 
 
2470
 
2471
  model_inputs["position_ids"] = None
2472
 
2473
+ # v5 creates cache_position inside the parent method, rather than
2474
+ # passing it to this override. Read the prepared value back first.
2475
+ cache_position = model_inputs.get("cache_position", cache_position)
2476
+ if cache_position is None:
2477
+ past_seen_tokens = past_key_values.get_seq_length() if past_key_values is not None else 0
2478
+ prepared = model_inputs.get("inputs_embeds")
2479
+ if prepared is None:
2480
+ prepared = model_inputs["input_ids"]
2481
+ cache_position = torch.arange(
2482
+ past_seen_tokens, past_seen_tokens + prepared.shape[1], device=prepared.device
2483
+ )
2484
+ model_inputs["cache_position"] = cache_position
2485
+
2486
+ # Without KV caching, every forward still consumes the image tokens.
2487
+ if use_cache and past_key_values is not None and past_key_values.get_seq_length() > 0:
2488
  model_inputs["pixel_values"] = None
2489
  model_inputs["pixel_values_videos"] = None
2490