Safetensors
valley
custom_code
Hyggge commited on
Commit
93b1113
·
1 Parent(s): f10d2e1

feat: update modeling code for Valley3

Browse files
Files changed (1) hide show
  1. modeling_valley.py +643 -3
modeling_valley.py CHANGED
@@ -1,3 +1,643 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:cf1b9862bfbdbfca512ab83ca5bf16bbdbdb1b6c125a99751603c50ee15cab96
3
- size 35176
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
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
+ import torch
16
+ import numpy as np
17
+ from torch import nn
18
+ from torch.nn import CrossEntropyLoss
19
+ from abc import ABC, abstractmethod
20
+ from typing import List, Optional, Tuple, Union, Dict, Any
21
+ from transformers.modeling_outputs import CausalLMOutputWithPast
22
+ from transformers import AutoConfig, AutoModelForCausalLM, Qwen3Config, Qwen3ForCausalLM, Qwen3Model
23
+
24
+ from .modeling_vision_tower import build_vision_tower
25
+ from .modeling_projector import build_vision_projector
26
+ from .utils import get_anyres_image_grid_shape, unpad_image, IGNORE_INDEX, IMAGE_TOKEN_INDEX, IMAGE_INDICATOR_IDS, IMAGE_ATOM_ID, pad_truncate_sequence
27
+
28
+
29
+ class ValleyConfig(Qwen3Config):
30
+ model_type = "valley"
31
+
32
+ class ValleyMetaModel:
33
+ def __init__(self, config):
34
+ super(ValleyMetaModel, self).__init__(config)
35
+ # Build vision tower
36
+ if hasattr(config, "mm_vision_tower"):
37
+ if getattr(config, "eagle_vision_tower", None) is not None:
38
+ self.vision_tower, self.qwen2vl_vision_tower = build_vision_tower(config, delay_load=False)
39
+ else:
40
+ self.vision_tower = build_vision_tower(config, delay_load=False)
41
+ # Build Projector
42
+ if hasattr(config, "mm_projector_type") and not getattr(config, "only_navit", False):
43
+ self.mm_projector = build_vision_projector(config)
44
+
45
+ def get_vision_tower(self):
46
+ vision_tower = getattr(self, "vision_tower", None)
47
+ if getattr(self.config, "eagle_vision_tower", None) is not None:
48
+ qwen2vl_vision_tower = getattr(self, "qwen2vl_vision_tower", None)
49
+ return vision_tower, qwen2vl_vision_tower
50
+ else:
51
+ return vision_tower
52
+
53
+ class ValleyMetaForCausalLM(ABC):
54
+ @abstractmethod
55
+ def get_model(self):
56
+ pass
57
+
58
+ def get_vision_tower(self):
59
+ return self.get_model().get_vision_tower()
60
+
61
+ def split_by_instance(self, original_list, split_sizes):
62
+ start = 0
63
+ sub_lists = []
64
+ for size in split_sizes:
65
+ end = start + size
66
+ sub_list = original_list[start:end]
67
+ sub_lists.append([x.to(self.device) for x in sub_list])
68
+ start = end
69
+ return sub_lists
70
+
71
+ def encode_images_qwen2vl(self, pixel_values = None, grid_thw = None, split_sizes=None):
72
+ _, qwen2vl_vision_tower = self.get_model().get_vision_tower()
73
+ qwen2vl_image_features = qwen2vl_vision_tower(pixel_values, grid_thw)
74
+ qwen2vl_image_split_sizes = torch.prod(grid_thw[:, 1:3]//2, dim=1)
75
+ qwen2vl_image_features = torch.split(qwen2vl_image_features, qwen2vl_image_split_sizes.tolist(), dim=0)
76
+ qwen2vl_image_features = self.split_by_instance(qwen2vl_image_features, split_sizes)
77
+ return qwen2vl_image_features
78
+
79
+ def encode_images(self, images = None, split_sizes = None):
80
+ """
81
+ images: (if not anyres) images.shape = [n,3,336,336] , n = number of images + (number of video) * 8
82
+ images: (if anyres) images.shape = [n,3,336,336] , n = number of tiles * number of images
83
+ """
84
+ if getattr(self.config, "eagle_vision_tower", None) is not None:
85
+ siglip_vision_tower, _ = self.get_model().get_vision_tower()
86
+ image_features = siglip_vision_tower(images)
87
+ image_features = self.get_model().mm_projector(image_features)
88
+ else:
89
+ image_features = self.get_model().get_vision_tower()(images)
90
+ image_features = self.get_model().mm_projector(image_features)
91
+
92
+ if getattr(self.config,'anyres', False) and getattr(self.config, 'max_vision_token', None) is not None:
93
+ assert split_sizes is not None
94
+ image_features = list(torch.split(image_features, split_sizes, dim=0))
95
+ for i, image_feature in enumerate(image_features):
96
+ hidden_dim = image_feature.shape[-1]
97
+ image_tokens = image_feature.shape[0]*image_feature.shape[1]
98
+ if getattr(self.config, "eagle_vision_tower", None) is not None:
99
+ pass # the max_vision_token will be processed in the unpad image token part
100
+ else:
101
+ if image_tokens > self.config.max_vision_token:
102
+ intput_shape = int((image_feature.shape[1])**0.5)
103
+ output_shape = int((self.config.max_vision_token/image_feature.shape[0])**0.5)
104
+ image_feature = image_feature.view(image_feature.shape[0],intput_shape, intput_shape, -1).permute(0,3,1,2)
105
+ m = nn.AdaptiveAvgPool2d(output_shape) # different from roi pooling, but in square image, it seems the same
106
+ pooling_feature = m(image_feature).permute(0,2,3,1)
107
+ image_features[i] = pooling_feature.view(image_feature.shape[0], -1, hidden_dim)
108
+ split_sizes = None # have already split, set the flag
109
+
110
+ if getattr(self.config, 'mm_use_im_start_end', False):
111
+ raise ValueError('mm_use_im_start is not support')
112
+ if split_sizes is not None:
113
+ image_features = torch.split(image_features, split_sizes, dim=0)
114
+
115
+ return image_features
116
+
117
+ def get_padding_method(self):
118
+ right_padding = getattr(self, 'right_padding', None)
119
+ # if right_padding flag is setted, ignore training flag.
120
+ if right_padding is not None:
121
+ method = 'right' if right_padding else 'left'
122
+ # in the other way, use training flag to determine the padding method.
123
+ method = 'right' if self.training else 'left'
124
+
125
+ return method
126
+
127
+ def prepare_inputs_labels_for_multimodal(
128
+ self, input_ids, position_ids, attention_mask, past_key_values, labels, images,
129
+ image_sizes, pixel_values, pixel_values_videos, image_grid_thw, video_grid_thw):
130
+
131
+ vision_tower = self.get_vision_tower()
132
+ if vision_tower is None or images is None or input_ids.shape[1] == 1:
133
+ if past_key_values is not None and vision_tower is not None and images is not None and input_ids.shape[1] == 1:
134
+ target_shape = past_key_values[-1][-1].shape[-2] + 1
135
+ attention_mask = torch.cat((attention_mask, torch.ones(
136
+ (attention_mask.shape[0], target_shape - attention_mask.shape[1]),
137
+ dtype=attention_mask.dtype,
138
+ device=attention_mask.device
139
+ )), dim=1)
140
+ return input_ids, position_ids, attention_mask, past_key_values, None, labels
141
+
142
+ # Step1: Get image embedings
143
+ if type(images) is list or images.ndim == 5:
144
+ # Without slicing the image
145
+ if not getattr(self.config,'anyres', False) and self.config.mm_projector_type != "ovis2_adapter":
146
+ concat_images = torch.cat([image for image in images], dim=0) # to do batch compute
147
+ split_sizes = [image.shape[0] for image in images]
148
+
149
+ # Get vision tower feature, check whether only use navit firstly
150
+ if getattr(self.config, 'eagle_vision_tower', None) is not None and getattr(self.config, 'only_navit', False):
151
+ image_features = None
152
+ else:
153
+ image_features = self.encode_images(concat_images, split_sizes)
154
+ image_features = [x.to(self.device) for x in image_features]
155
+
156
+ # Get Eagle features
157
+ if getattr(self.config, 'eagle_vision_tower', None) is not None:
158
+ if pixel_values is not None:
159
+ qwen2vl_image_features = self.encode_images_qwen2vl(pixel_values, image_grid_thw, split_sizes)
160
+ elif pixel_values_videos is not None:
161
+ qwen2vl_image_features = self.encode_images_qwen2vl(pixel_values_videos, video_grid_thw, split_sizes)
162
+ else:
163
+ qwen2vl_image_features = None
164
+
165
+ # Slicing the image, each image contains some sub_images:
166
+ # images = [
167
+ # [image1_tiles(n1,3,336,336), image2_tiles(n2,3,336,336), ...],
168
+ # [image1_tiles(n1,3,336,336), image2_tiles(n2,3,336,336), ...], ...
169
+ # ]
170
+ else:
171
+ split_sizes = [len(image) for image in images]
172
+ # Get Eagle features
173
+ if getattr(self.config, "eagle_vision_tower", None) is not None:
174
+ if pixel_values is not None:
175
+ qwen2vl_image_features = self.encode_images_qwen2vl(pixel_values, image_grid_thw, split_sizes)
176
+ elif pixel_values_videos is not None:
177
+ qwen2vl_image_features = self.encode_images_qwen2vl(pixel_values_videos, video_grid_thw, split_sizes)
178
+ else:
179
+ qwen2vl_image_features = None
180
+
181
+ # Get vision tower feature, check whether only use navit firstly
182
+ if getattr(self.config, 'eagle_vision_tower', None) is not None and getattr(self.config, 'only_navit', False):
183
+ image_features = None
184
+ else:
185
+ image_features = []
186
+ all_concat_images = []
187
+ all_split_sizes = []
188
+ for batch_images in images:
189
+ concat_images = torch.cat([image for image in batch_images], dim=0) # to do batch compute
190
+ split_sizes = [image.shape[0] for image in batch_images]
191
+ all_concat_images.append(concat_images)
192
+ all_split_sizes.append(split_sizes)
193
+ all_image_features = self.encode_images(images=torch.cat(all_concat_images, dim=0), split_sizes=sum(all_split_sizes, []))
194
+
195
+ idx = 0
196
+ for split_sizes in all_split_sizes:
197
+ batch_image_features = all_image_features[idx:idx+len(split_sizes)]
198
+ idx += len(split_sizes)
199
+ if type(batch_image_features[0]) is list:
200
+ batch_image_features = [torch.cat(x).to(self.device) for x in batch_image_features]
201
+ else:
202
+ batch_image_features = [x.view(-1,x.shape[-1]).to(self.device) for x in batch_image_features] # tiles feature need to flatten in token dimention, [n_tiles, T, d] -> [n_tiles * T, d]
203
+ image_features.append(batch_image_features)
204
+
205
+ if getattr(self.config, "eagle_vision_tower", None) is not None and getattr(self.config, 'only_navit', False) == False:
206
+ # unpad image tokens
207
+ height = width = self.config.num_patches_per_side
208
+ new_image_features = []
209
+ for batch_image_features, batch_image_sizes in zip(image_features, image_sizes):
210
+ batch_image_features_list = []
211
+ for cur_image_feature, cur_image_size in zip(batch_image_features, batch_image_sizes):
212
+ base_image_feature = cur_image_feature[:width*height, :]
213
+ image_feature = cur_image_feature[width*height:, :]
214
+ if image_feature.shape[0] != 0:
215
+ num_patch_width, num_patch_height = get_anyres_image_grid_shape(
216
+ cur_image_size,
217
+ self.config.grid_pinpoints,
218
+ self.config.vit_crop_size
219
+ )
220
+ image_feature = image_feature.view(num_patch_height, num_patch_width, height, width, -1) # (num_patch_H, num_patch_W, H, W, C)
221
+ image_feature = image_feature.permute(4, 0, 2, 1, 3).contiguous() # (C, num_patch_H, H, num_patch_W, W)
222
+ image_feature = image_feature.flatten(1, 2).flatten(2, 3) # (C, num_token_H, num_token_W)
223
+ image_feature = unpad_image(image_feature, cur_image_size) # (C, num_token_H_unpad, num_token_W_unpad)
224
+ input_shape = (image_feature.shape[-2], image_feature.shape[-1])
225
+ subimage_tokens = np.prod(input_shape)
226
+
227
+ # adaptive avg 2d pool for reducing token num
228
+ max_subimage_tokens = self.config.max_vision_token-width*height
229
+ if subimage_tokens > max_subimage_tokens:
230
+ aspect_ratio = input_shape[0] / input_shape[1]
231
+ output_shape = (
232
+ int((max_subimage_tokens/aspect_ratio)**0.5*aspect_ratio),
233
+ int((max_subimage_tokens/aspect_ratio)**0.5)
234
+ )
235
+ m = nn.AdaptiveAvgPool2d(output_shape)
236
+ image_feature = m(image_feature)
237
+ image_feature = image_feature.flatten(1, 2).transpose(0, 1)
238
+ image_feature = torch.cat((base_image_feature, image_feature), dim=0)
239
+ else:
240
+ image_feature = cur_image_feature
241
+ batch_image_features_list.append(image_feature)
242
+ new_image_features.append(batch_image_features_list)
243
+
244
+ image_features = new_image_features
245
+
246
+ else:
247
+ image_features = self.encode_images(images).to(self.device)
248
+
249
+
250
+ # Step2: Iterate through each sample in the batch, insert image embedings into input_embeds
251
+ # and filling labels, attention mask at the same time. Finally, get `new_input_embed`,
252
+ # `new_labels`, new_attention_mask`.
253
+ _labels = labels
254
+ _position_ids = position_ids
255
+ _attention_mask = attention_mask
256
+ if attention_mask is None:
257
+ attention_mask = torch.ones_like(input_ids, dtype=torch.bool)
258
+ if position_ids is None:
259
+ position_ids = torch.arange(0, input_ids.shape[1], dtype=torch.long, device=input_ids.device)
260
+ if labels is None:
261
+ labels = torch.full_like(input_ids, IGNORE_INDEX)
262
+
263
+ input_ids = [cur_input_ids[cur_attention_mask] for cur_input_ids, cur_attention_mask in zip(input_ids, attention_mask.bool())]
264
+ labels = [cur_labels[cur_attention_mask] for cur_labels, cur_attention_mask in zip(labels, attention_mask.bool())]
265
+ attention_mask = [cur_attention_mask[cur_attention_mask.bool()] for cur_attention_mask in attention_mask]
266
+
267
+ if self.config.mm_projector_type == "ovis2_adapter": # for ovis2
268
+ # prepare embedding
269
+ visual_vocab_size = self.config.mlp_hidden_dim
270
+ assert visual_vocab_size == 65536
271
+ text_embedding = self.model.get_input_embeddings()
272
+ visual_indicator_embedding = self.model.mm_projector.embedding(
273
+ torch.tensor(
274
+ list(range(visual_vocab_size - 5, visual_vocab_size)),
275
+ dtype=torch.long,
276
+ device=input_ids[0].device
277
+ )
278
+ ).to(device=input_ids[0].device)
279
+
280
+ new_attention_masks = []
281
+ new_input_embeds = []
282
+ new_labels = []
283
+ for i, cur_image_features in enumerate(image_features):
284
+ input_id = input_ids[i]
285
+ text_label = labels[i]
286
+
287
+
288
+ ovis_image_features = []
289
+ for feature in cur_image_features:
290
+ ovis_image_features.append(feature)
291
+ ovis_image_features = torch.cat(ovis_image_features, dim=0)
292
+
293
+ placeholder_token_mask = torch.lt(input_id, 0)
294
+ text_embed = text_embedding(torch.masked_fill(input_id, placeholder_token_mask, 0))
295
+
296
+
297
+ for j, indicator_id in enumerate(IMAGE_INDICATOR_IDS):
298
+ text_embed[input_id == indicator_id] = visual_indicator_embedding[j]
299
+ image_atom_positions = torch.where(torch.eq(input_id, IMAGE_ATOM_ID))[0].tolist()
300
+
301
+ input_embed_parts = []
302
+ attention_mask_parts = []
303
+ label_parts = []
304
+ prev_image_atom_position = -1
305
+ # assert ovis_image_features.shape[0] == 256*len(image_atom_positions)
306
+ image_token_len = ovis_image_features.shape[0] // len(image_atom_positions)
307
+ # print("image_token_len: ", image_token_len)
308
+ assert image_token_len in [256, 64]
309
+ if len(image_atom_positions) > 0:
310
+ for index, image_atom_positions in enumerate(image_atom_positions):
311
+ input_embed_parts.append(text_embed[prev_image_atom_position + 1:image_atom_positions, :])
312
+ input_embed_parts.append(ovis_image_features[index*image_token_len:index*image_token_len+image_token_len]) # replace 256
313
+ label_parts.append(text_label[prev_image_atom_position + 1:image_atom_positions])
314
+ label_parts.append(torch.full((image_token_len,), IGNORE_INDEX, dtype=torch.long, device=input_id.device)) # remain hypothesis
315
+ attention_mask_parts.append(
316
+ torch.ones_like(text_label[prev_image_atom_position + 1:image_atom_positions], dtype=torch.bool, device=input_id.device))
317
+ attention_mask_parts.append(
318
+ torch.ones(image_token_len, dtype=torch.bool))
319
+
320
+ prev_image_atom_position = image_atom_positions
321
+ if prev_image_atom_position + 1 < input_id.shape[0]:
322
+ input_embed_parts.append(text_embed[prev_image_atom_position + 1:, :])
323
+ label_parts.append(text_label[prev_image_atom_position + 1:])
324
+ attention_mask_parts.append(
325
+ torch.ones_like(text_label[prev_image_atom_position + 1:], dtype=torch.bool))
326
+
327
+ input_embed = torch.cat([part.to(input_id.device) for part in input_embed_parts], dim=0)
328
+ attention_mask = torch.cat([part.to(input_id.device) for part in attention_mask_parts], dim=0)
329
+ label = torch.cat([part.to(input_id.device) for part in label_parts], dim=0)
330
+
331
+ new_input_embeds.append(input_embed)
332
+ new_attention_masks.append(attention_mask)
333
+ new_labels.append(label)
334
+ else:
335
+ raise ValueError(
336
+ "No image token found in the input. Please check the input_ids and image_features.")
337
+ multimodal_max_length = 0
338
+ left_padding = True
339
+ new_input_embeds = pad_truncate_sequence(multimodal_max_length, new_input_embeds, batch_first=True, padding_value=0.0, left_padding=left_padding)
340
+ new_attention_masks = pad_truncate_sequence(multimodal_max_length, new_attention_masks, batch_first=True, padding_value=False, left_padding=left_padding)
341
+ new_labels = pad_truncate_sequence(multimodal_max_length, new_labels, batch_first=True, padding_value=IGNORE_INDEX, left_padding=left_padding)
342
+ return None, None, new_attention_masks, None, new_input_embeds, new_labels
343
+
344
+ else:
345
+ new_input_embeds = []
346
+ new_labels = []
347
+ new_attention_mask = []
348
+
349
+ for batch_idx, cur_input_ids in enumerate(input_ids):
350
+ cur_batch_image_idx = 0
351
+ num_images = (cur_input_ids == IMAGE_TOKEN_INDEX).sum()
352
+
353
+ # Step2-1: If this piece of data is pure text, then concat a dummy image to ensure the whole compute graph is same on all device
354
+ if num_images == 0:
355
+ if getattr(self.config, "eagle_vision_tower", None) is not None:
356
+ if getattr(self.config, 'only_navit', False):
357
+ cur_image_features = qwen2vl_image_features[batch_idx][cur_batch_image_idx]
358
+ else:
359
+ siglip_feat = image_features[batch_idx][cur_batch_image_idx]
360
+ try:
361
+ qwen2vl_feat = qwen2vl_image_features[batch_idx][cur_batch_image_idx]
362
+ cur_image_features = torch.cat((siglip_feat, qwen2vl_feat), dim=0)
363
+ except Exception as e:
364
+ print(e)
365
+ print("only siglip feature:", siglip_feat.shape)
366
+ cur_image_features = siglip_feat
367
+ else:
368
+ cur_image_features = image_features[batch_idx][cur_batch_image_idx]
369
+ cur_input_embeds_1 = self.get_model().embed_tokens(cur_input_ids)
370
+ cur_input_embeds = torch.cat([cur_input_embeds_1, cur_image_features.squeeze(0)[0:0]], dim=0)
371
+ new_input_embeds.append(cur_input_embeds)
372
+ new_labels.append(labels[batch_idx])
373
+ new_attention_mask.append(attention_mask[batch_idx])
374
+ cur_batch_image_idx += 1
375
+ continue
376
+
377
+ # Step2-2: Split input_ids, labels, attention_mask by IMAGE_TOKEN_INDEX
378
+ cur_input_ids_noim, cur_labels_noim, cur_attention_mask_noim = [], [], []
379
+ cur_labels = labels[batch_idx]
380
+ cur_attention_mask = attention_mask[batch_idx]
381
+ cur_img_attention_mask = [
382
+ attention_mask[batch_idx][i].item()
383
+ for i in torch.where(cur_input_ids == IMAGE_TOKEN_INDEX)[0].tolist()
384
+ ]
385
+ image_token_indices = [-1] + torch.where(cur_input_ids == IMAGE_TOKEN_INDEX)[0].tolist() + [cur_input_ids.shape[0]]
386
+ for i in range(len(image_token_indices) - 1):
387
+ cur_input_ids_noim.append(cur_input_ids[image_token_indices[i]+1:image_token_indices[i+1]])
388
+ cur_labels_noim.append(cur_labels[image_token_indices[i]+1:image_token_indices[i+1]])
389
+ cur_attention_mask_noim.append(cur_attention_mask[image_token_indices[i]+1:image_token_indices[i+1]])
390
+ split_sizes = [x.shape[0] for x in cur_labels_noim]
391
+ cur_input_embeds = self.get_model().embed_tokens(torch.cat(cur_input_ids_noim))
392
+ cur_input_embeds_no_im = list(torch.split(cur_input_embeds, split_sizes, dim=0))# get text features
393
+
394
+ # Step2-3: Insert image embedings
395
+ cur_new_input_embeds, cur_new_labels, cur_new_attention_mask = [], [], []
396
+ for i in range(num_images + 1): # to add multimodal feature internal the text feature
397
+ cur_new_input_embeds.append(cur_input_embeds_no_im[i])
398
+ cur_new_labels.append(cur_labels_noim[i])
399
+ cur_new_attention_mask.append(cur_attention_mask_noim[i])
400
+ if i < num_images:
401
+ if getattr(self.config, "eagle_vision_tower", None) is not None:
402
+ if getattr(self.config, 'only_navit', False):
403
+ cur_image_features = qwen2vl_image_features[batch_idx][cur_batch_image_idx]
404
+ else:
405
+ siglip_feat = image_features[batch_idx][cur_batch_image_idx]
406
+ try:
407
+ qwen2vl_feat = qwen2vl_image_features[batch_idx][cur_batch_image_idx]
408
+ cur_image_features = torch.cat((siglip_feat, qwen2vl_feat), dim=0)
409
+ except Exception as e:
410
+ print(e)
411
+ print("only siglip feature:", siglip_feat.shape)
412
+ cur_image_features = siglip_feat
413
+ else:
414
+ cur_image_features = image_features[batch_idx][cur_batch_image_idx]
415
+ cur_batch_image_idx += 1
416
+ cur_new_input_embeds.append(cur_image_features)
417
+ cur_new_labels.append(torch.full((cur_image_features.shape[0],), IGNORE_INDEX, device=cur_labels.device, dtype=cur_labels.dtype))
418
+ cur_new_attention_mask.append(torch.full((cur_image_features.shape[0],), True, device=cur_attention_mask.device, dtype=cur_attention_mask.dtype))
419
+
420
+ # Step2-4: Concat image embedings and text embedings
421
+ cur_new_input_embeds = torch.cat(cur_new_input_embeds)
422
+ cur_new_labels = torch.cat(cur_new_labels)
423
+ cur_new_attention_mask = torch.cat(cur_new_attention_mask)
424
+ new_input_embeds.append(cur_new_input_embeds)
425
+ new_labels.append(cur_new_labels)
426
+ new_attention_mask.append(cur_new_attention_mask)
427
+
428
+ # Step3: Truncate sequences to max length as image embeddings can make the sequence longer
429
+ tokenizer_model_max_length = getattr(self.config, 'tokenizer_model_max_length', None)
430
+ if tokenizer_model_max_length is not None:
431
+ new_input_embeds = [x[:tokenizer_model_max_length] for x in new_input_embeds]
432
+ new_labels = [x[:tokenizer_model_max_length] for x in new_labels]
433
+ new_attention_mask = [x[:tokenizer_model_max_length] for x in new_attention_mask]
434
+
435
+ # Step4: Pad and stack input_embeds, labels, attention_mask
436
+ max_len = max(x.shape[0] for x in new_input_embeds)
437
+ batch_size = len(new_input_embeds)
438
+ new_input_embeds_padded = []
439
+ new_labels_padded = torch.full((batch_size, max_len), IGNORE_INDEX, dtype=new_labels[0].dtype, device=new_labels[0].device)
440
+ new_attention_mask_padded = torch.zeros((batch_size, max_len), dtype=new_attention_mask[0].dtype, device=new_attention_mask[0].device)
441
+ position_ids = torch.zeros((batch_size, max_len), dtype=position_ids.dtype, device=position_ids.device)
442
+
443
+ for i, (cur_new_embed, cur_new_labels, cur_attention_mask) in enumerate(zip(new_input_embeds, new_labels, new_attention_mask)):
444
+ cur_len = cur_new_embed.shape[0]
445
+ if self.get_padding_method() == 'left':
446
+ new_input_embeds_padded.append(torch.cat((
447
+ torch.zeros((max_len - cur_len, cur_new_embed.shape[1]), dtype=cur_new_embed.dtype, device=cur_new_embed.device),
448
+ cur_new_embed
449
+ ), dim=0))
450
+ if cur_len > 0:
451
+ new_labels_padded[i, -cur_len:] = cur_new_labels
452
+ new_attention_mask_padded[i, -cur_len:] = cur_attention_mask
453
+ position_ids[i, -cur_len:] = torch.arange(0, cur_len, dtype=position_ids.dtype, device=position_ids.device)
454
+
455
+ else:
456
+ new_input_embeds_padded.append(torch.cat((
457
+ cur_new_embed,
458
+ torch.zeros((max_len - cur_len, cur_new_embed.shape[1]), dtype=cur_new_embed.dtype, device=cur_new_embed.device)
459
+ ), dim=0))
460
+ if cur_len > 0:
461
+ new_labels_padded[i, :cur_len] = cur_new_labels
462
+ new_attention_mask_padded[i, :cur_len] = cur_attention_mask
463
+ position_ids[i, :cur_len] = torch.arange(0, cur_len, dtype=position_ids.dtype, device=position_ids.device)
464
+
465
+ new_input_embeds = torch.stack(new_input_embeds_padded, dim=0)
466
+ new_labels = new_labels_padded if _labels is not None else None
467
+ new_attention_mask = new_attention_mask_padded if _attention_mask is not None else None
468
+ if _position_ids is None:
469
+ position_ids = None
470
+
471
+ return None, position_ids, new_attention_mask, past_key_values, new_input_embeds, new_labels
472
+
473
+
474
+ class ValleyQwen3Model(ValleyMetaModel, Qwen3Model):
475
+ config_class = ValleyConfig
476
+ def __init__(self, config: Qwen3Config):
477
+ super(ValleyQwen3Model, self).__init__(config)
478
+
479
+
480
+ class ValleyQwen3ForCausalLM(Qwen3ForCausalLM, ValleyMetaForCausalLM):
481
+ config_class = ValleyConfig
482
+
483
+ def __init__(self, config):
484
+ super(Qwen3ForCausalLM, self).__init__(config)
485
+ self.model = ValleyQwen3Model(config)
486
+ self.lm_head = nn.Linear(config.hidden_size, config.vocab_size, bias=False)
487
+ self.post_init()
488
+
489
+ def get_model(self):
490
+ return self.model
491
+
492
+ def _update_model_kwargs_for_generation(
493
+ self,
494
+ outputs: CausalLMOutputWithPast,
495
+ model_kwargs: Dict[str, Any],
496
+ is_encoder_decoder: bool = False,
497
+ num_new_tokens: int = 1,
498
+ ) -> Dict[str, Any]:
499
+ new_model_kwargs = super()._update_model_kwargs_for_generation(
500
+ outputs,
501
+ model_kwargs,
502
+ is_encoder_decoder,
503
+ num_new_tokens
504
+ )
505
+ """
506
+ Set model_kwargs["attention_mask"] to the expanded `attention_mask` in
507
+ the `prepare_inputs_labels_for_multimodal` function to ensure the
508
+ correctness of the generate behavior when `use_cache` is enabled.
509
+ """
510
+ if not is_encoder_decoder:
511
+ if "attention_mask" in new_model_kwargs:
512
+ attention_mask = outputs.attention_mask
513
+ new_model_kwargs["attention_mask"] = torch.cat(
514
+ [attention_mask, attention_mask.new_ones((attention_mask.shape[0], 1))], dim=-1
515
+ )
516
+ return new_model_kwargs
517
+
518
+
519
+ def forward(
520
+ self,
521
+ input_ids: torch.LongTensor = None,
522
+ attention_mask: Optional[torch.Tensor] = None,
523
+ position_ids: Optional[torch.LongTensor] = None,
524
+ past_key_values: Optional[List[torch.FloatTensor]] = None,
525
+ inputs_embeds: Optional[torch.FloatTensor] = None,
526
+ labels: Optional[torch.LongTensor] = None,
527
+ use_cache: Optional[bool] = None,
528
+ output_attentions: Optional[bool] = None,
529
+ output_hidden_states: Optional[bool] = None,
530
+ images: Optional[torch.FloatTensor] = None,
531
+ return_dict: Optional[bool] = None,
532
+ image_sizes: Optional[List[List[int]]] = None,
533
+ pixel_values: Optional[torch.Tensor] = None,
534
+ pixel_values_videos: Optional[torch.FloatTensor] = None,
535
+ image_grid_thw: Optional[torch.LongTensor] = None,
536
+ video_grid_thw: Optional[torch.LongTensor] = None,
537
+ ) -> Union[Tuple, CausalLMOutputWithPast]:
538
+ output_attentions = output_attentions if output_attentions is not None else self.config.output_attentions
539
+ output_hidden_states = (
540
+ output_hidden_states if output_hidden_states is not None else self.config.output_hidden_states
541
+ )
542
+ return_dict = return_dict if return_dict is not None else self.config.use_return_dict
543
+
544
+ if inputs_embeds is None:
545
+ (
546
+ input_ids,
547
+ position_ids,
548
+ attention_mask,
549
+ past_key_values,
550
+ inputs_embeds,
551
+ labels
552
+ ) = self.prepare_inputs_labels_for_multimodal(
553
+ input_ids,
554
+ position_ids,
555
+ attention_mask,
556
+ past_key_values,
557
+ labels,
558
+ images,
559
+ image_sizes,
560
+ pixel_values,
561
+ pixel_values_videos,
562
+ image_grid_thw,
563
+ video_grid_thw,
564
+ )
565
+
566
+ # decoder outputs consists of (dec_features, layer_state, dec_hidden, dec_attn)
567
+ outputs = self.model(
568
+ input_ids=input_ids,
569
+ attention_mask=attention_mask,
570
+ position_ids=position_ids,
571
+ past_key_values=past_key_values,
572
+ inputs_embeds=inputs_embeds,
573
+ use_cache=use_cache,
574
+ output_attentions=output_attentions,
575
+ output_hidden_states=output_hidden_states,
576
+ return_dict=return_dict,
577
+ )
578
+
579
+ hidden_states = outputs[0]
580
+ logits = self.lm_head(hidden_states)
581
+
582
+ loss = None
583
+ if labels is not None:
584
+ # Shift so that tokens < n predict n
585
+ shift_logits = logits[..., :-1, :].contiguous()
586
+ shift_labels = labels[..., 1:].contiguous()
587
+ loss_fct = CrossEntropyLoss(reduction='mean')
588
+ bs = shift_labels.shape[0]
589
+ shift_labels = shift_labels.to(shift_logits.device)
590
+ loss = torch.stack([loss_fct(shift_logits[i], shift_labels[i]) for i in range(bs)])
591
+
592
+ if not return_dict:
593
+ output = (logits,) + outputs[1:]
594
+ return (loss,) + output if loss is not None else output
595
+
596
+ res = CausalLMOutputWithPast(
597
+ loss=loss,
598
+ logits=logits,
599
+ past_key_values=outputs.past_key_values,
600
+ hidden_states=outputs.hidden_states,
601
+ attentions=outputs.attentions,
602
+ )
603
+
604
+ res.attention_mask = attention_mask
605
+ return res
606
+
607
+ def prepare_inputs_for_generation(
608
+ self, input_ids, past_key_values=None, attention_mask=None, inputs_embeds=None, **kwargs
609
+ ):
610
+ if past_key_values:
611
+ input_ids = input_ids[:, -1:]
612
+
613
+ # if `inputs_embeds` are passed, we only want to use them in the 1st generation step
614
+ if inputs_embeds is not None and past_key_values is None:
615
+ model_inputs = {"inputs_embeds": inputs_embeds}
616
+ else:
617
+ model_inputs = {"input_ids": input_ids}
618
+
619
+ # For cases where only navit (e.g., Valley3) is used, the input `images` may be None.
620
+ # To ensure compatibility with the Valley2 codebase, we need to supplement a dummy image.
621
+ image_sizes = kwargs.get("image_sizes", None)
622
+ if kwargs.get("images", None) is not None:
623
+ images = kwargs.get("images")
624
+ else:
625
+ images = [torch.zeros((len(image_sizes_per_sample), 3, 10, 10)) for image_sizes_per_sample in image_sizes]
626
+
627
+ model_inputs.update(
628
+ {
629
+ "past_key_values": past_key_values,
630
+ "use_cache": kwargs.get("use_cache"),
631
+ "attention_mask": attention_mask,
632
+ "images": images,
633
+ "image_sizes": kwargs.get("image_sizes", None),
634
+ "pixel_values": kwargs.get("pixel_values", None),
635
+ "pixel_values_videos": kwargs.get("pixel_values_videos", None),
636
+ "image_grid_thw": kwargs.get("image_grid_thw", None),
637
+ "video_grid_thw": kwargs.get("video_grid_thw", None),
638
+ }
639
+ )
640
+ return model_inputs
641
+
642
+ AutoConfig.register("valley", ValleyConfig)
643
+ AutoModelForCausalLM.register(ValleyConfig, ValleyQwen3ForCausalLM)