Rohit56negi commited on
Commit
0a5ac05
·
verified ·
1 Parent(s): 3038e70

Upload 46 files

Browse files
Files changed (46) hide show
  1. GOT-OCR-2.0-master/GOT/__init__.py +0 -0
  2. GOT-OCR-2.0-master/GOT/data/__init__.py +68 -0
  3. GOT-OCR-2.0-master/GOT/data/base_dataset.py +70 -0
  4. GOT-OCR-2.0-master/GOT/data/conversation_dataset_qwen.py +279 -0
  5. GOT-OCR-2.0-master/GOT/demo/process_results.py +34 -0
  6. GOT-OCR-2.0-master/GOT/demo/run_ocr_2.0.py +245 -0
  7. GOT-OCR-2.0-master/GOT/demo/run_ocr_2.0_crop.py +251 -0
  8. GOT-OCR-2.0-master/GOT/eval/eval_GOT_ocr.py +323 -0
  9. GOT-OCR-2.0-master/GOT/eval/evaluate_GOT.py +52 -0
  10. GOT-OCR-2.0-master/GOT/eval/multi_hardware_eval_GOT.py +47 -0
  11. GOT-OCR-2.0-master/GOT/eval/pyevaltools/__init__.py +1 -0
  12. GOT-OCR-2.0-master/GOT/eval/pyevaltools/eval_ocr.py +220 -0
  13. GOT-OCR-2.0-master/GOT/eval/pyevaltools/eval_ocr_format.py +220 -0
  14. GOT-OCR-2.0-master/GOT/eval/pyevaltools/eval_ocr_scene.py +87 -0
  15. GOT-OCR-2.0-master/GOT/eval/pyevaltools/merge_results.py +21 -0
  16. GOT-OCR-2.0-master/GOT/model/GOT_ocr_2_0.py +391 -0
  17. GOT-OCR-2.0-master/GOT/model/__init__.py +3 -0
  18. GOT-OCR-2.0-master/GOT/model/plug/blip_process.py +504 -0
  19. GOT-OCR-2.0-master/GOT/model/vision_encoder/__init__.py +1 -0
  20. GOT-OCR-2.0-master/GOT/model/vision_encoder/vary_b.py +547 -0
  21. GOT-OCR-2.0-master/GOT/train/train.py +194 -0
  22. GOT-OCR-2.0-master/GOT/train/train_GOT.py +147 -0
  23. GOT-OCR-2.0-master/GOT/train/train_flash_attn.py +13 -0
  24. GOT-OCR-2.0-master/GOT/train/train_lora.py +216 -0
  25. GOT-OCR-2.0-master/GOT/train/train_lora_flash_attn.py +14 -0
  26. GOT-OCR-2.0-master/GOT/train/trainer.py +66 -0
  27. GOT-OCR-2.0-master/GOT/train/trainer_llm_llrd.py +392 -0
  28. GOT-OCR-2.0-master/GOT/train/trainer_vit_fixlr.py +110 -0
  29. GOT-OCR-2.0-master/GOT/train/trainer_vit_llrd.py +389 -0
  30. GOT-OCR-2.0-master/GOT/utils/arguments.py +53 -0
  31. GOT-OCR-2.0-master/GOT/utils/constants.py +39 -0
  32. GOT-OCR-2.0-master/GOT/utils/conversation.py +455 -0
  33. GOT-OCR-2.0-master/GOT/utils/utils.py +235 -0
  34. GOT-OCR-2.0-master/pyproject.toml +37 -0
  35. GOT-OCR-2.0-master/pyvenv.cfg +8 -0
  36. GOT-OCR-2.0-master/render_tools/content-mmd-to-html.html +39 -0
  37. GOT-OCR-2.0-master/render_tools/tikz.html +17 -0
  38. GOT-OCR-2.0-master/results/demo.html +56 -0
  39. GOT-OCR-2.0-master/zero_config/zero2.json +13 -0
  40. GOT-OCR-2.0-master/zero_config/zero3.json +28 -0
  41. assets/got_logo.png +0 -0
  42. assets/got_support.jpg +0 -0
  43. assets/train_sample.jpg +0 -0
  44. assets/wechat.jpg +0 -0
  45. assets/wechat3.jpg +0 -0
  46. assets/weichat2.jpg +0 -0
GOT-OCR-2.0-master/GOT/__init__.py ADDED
File without changes
GOT-OCR-2.0-master/GOT/data/__init__.py ADDED
@@ -0,0 +1,68 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ import torch
3
+ import transformers
4
+ from dataclasses import dataclass, field
5
+
6
+ from GOT.utils.constants import *
7
+
8
+
9
+ @dataclass
10
+ class DataCollatorForSupervisedDataset(object):
11
+ tokenizer: transformers.PreTrainedTokenizer
12
+
13
+ def __call__(self, instances):
14
+ # print(instances)
15
+ # exit()
16
+ input_ids, labels = tuple([instance[key] for instance in instances] for key in ("input_ids", "labels"))
17
+ images = [torch.stack(instance['image']) for instance in instances]
18
+
19
+ # if 'flattened_patches' in instances[0]['image_high'][0].keys():
20
+ # images_high = [torch.stack([instance['image_high'][0]['flattened_patches']]) for instance in instances]
21
+ # else:
22
+ images_high = [torch.stack(instance['image_high']) for instance in instances]
23
+
24
+ images = list(zip(images, images_high))
25
+
26
+
27
+ input_ids = torch.nn.utils.rnn.pad_sequence(
28
+ input_ids,
29
+ batch_first=True,
30
+ padding_value=self.tokenizer.pad_token_id)
31
+
32
+ labels = torch.nn.utils.rnn.pad_sequence(
33
+ labels,
34
+ batch_first=True,
35
+ padding_value=IGNORE_INDEX)
36
+
37
+ batch = dict(
38
+ input_ids=input_ids,
39
+ labels=labels,
40
+ attention_mask=input_ids.ne(self.tokenizer.pad_token_id),
41
+ images=images,
42
+ )
43
+ return batch
44
+
45
+
46
+ def make_supervised_data_module(interleave, with_box, tokenizer, data_args):
47
+
48
+ if data_args.conversation_version == 'mpt':
49
+ from GOT.data.conversation_dataset_qwen import ConversationDataset
50
+ dataset_cls = ConversationDataset
51
+
52
+ train_dataset = dataset_cls(
53
+ tokenizer=tokenizer,
54
+ datasets=data_args.datasets,
55
+ multimodal_cfg=dict(
56
+ sep_image_conv_front=data_args.sep_image_conv_front,
57
+ image_token_len=data_args.image_token_len,
58
+ image_aspect_ratio=data_args.image_aspect_ratio,
59
+ use_im_start_end=data_args.use_im_start_end,
60
+ image_processor=data_args.image_processor,
61
+ image_processor_high = data_args.image_processor_high,
62
+ box_limit=data_args.box_limit,
63
+ )
64
+ )
65
+ data_collator = DataCollatorForSupervisedDataset(tokenizer=tokenizer)
66
+ return dict(train_dataset=train_dataset,
67
+ eval_dataset=None,
68
+ data_collator=data_collator)
GOT-OCR-2.0-master/GOT/data/base_dataset.py ADDED
@@ -0,0 +1,70 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import io
2
+ import os
3
+ import copy
4
+ import json
5
+ import logging
6
+ import torch
7
+ import transformers
8
+ import boto3
9
+ from typing import List, Optional, Tuple, Union, Dict, Sequence
10
+ from torch.utils.data import Dataset
11
+ from PIL import Image, ImageFile
12
+ ImageFile.LOAD_TRUNCATED_IMAGES = True
13
+ from GOT.utils.constants import *
14
+
15
+
16
+
17
+ class BaseDataset(Dataset):
18
+ def __init__(
19
+ self,
20
+ datasets: str,
21
+ tokenizer: transformers.PreTrainedTokenizer,
22
+ multimodal_cfg: dict
23
+ ):
24
+ super(BaseDataset, self).__init__()
25
+ self.tokenizer = tokenizer
26
+ self.multimodal_cfg = multimodal_cfg
27
+
28
+ logging.warning(f"Using {multimodal_cfg['image_token_len']} tokens for representing image")
29
+
30
+ def image_processor(self, image):
31
+ # processor = self.multimodal_cfg['image_processor'] # the first processor, usually is the clip pretrained model (vit)
32
+ processor_high = self.multimodal_cfg['image_processor_high'] # the second processor, usually is the designed image encoder (sam/swin/cnn)
33
+ image_high = image.copy()
34
+
35
+ # Vary old codes
36
+
37
+ # # TODO the 'keep', 'padding' only used for the first processor
38
+ # if self.multimodal_cfg['image_aspect_ratio'] == 'keep':
39
+ # max_hw, min_hw = max(image.size), min(image.size)
40
+ # aspect_ratio = max_hw / min_hw
41
+ # max_len, min_len = 448, 224
42
+ # shortest_edge = int(min(max_len / aspect_ratio, min_len))
43
+ # image = processor.preprocess(image, return_tensors='pt', do_center_crop=False, size={"shortest_edge": shortest_edge})['pixel_values'][0]
44
+ # elif self.multimodal_cfg['image_aspect_ratio'] == 'pad':
45
+ # def expand2square(pil_img, background_color):
46
+ # width, height = pil_img.size
47
+ # if width == height:
48
+ # return pil_img
49
+ # elif width > height:
50
+ # result = Image.new(pil_img.mode, (width, width), background_color)
51
+ # result.paste(pil_img) # for simpler box processing
52
+ # return result
53
+ # else:
54
+ # result = Image.new(pil_img.mode, (height, height), background_color)
55
+ # result.paste(pil_img) # for simpler box processing
56
+ # return result
57
+ # image = expand2square(image, tuple(int(x*255) for x in processor.image_mean))
58
+ # image = processor.preprocess(image, return_tensors='pt', do_center_crop=False, size={"shortest_edge": 224})['pixel_values'][0]
59
+ # else:
60
+ # image = processor.preprocess(image, return_tensors='pt')['pixel_values'][0]
61
+
62
+ image_high = processor_high(image_high)
63
+
64
+ return image_high
65
+
66
+ def __len__(self):
67
+ return len(self.list_data_dict)
68
+
69
+ def __getitem__(self, i) -> Dict[str, torch.Tensor]:
70
+ pass
GOT-OCR-2.0-master/GOT/data/conversation_dataset_qwen.py ADDED
@@ -0,0 +1,279 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ import io
3
+ import os
4
+ import copy
5
+ import json
6
+ import logging
7
+ import torch
8
+ import random
9
+
10
+ from typing import List, Optional, Tuple, Union, Dict, Sequence
11
+ from PIL import Image, ImageFile
12
+ ImageFile.LOAD_TRUNCATED_IMAGES = True
13
+
14
+ from GOT.data.base_dataset import BaseDataset
15
+ from GOT.utils.constants import *
16
+ from GOT.utils import conversation as conversation_lib
17
+ import boto3
18
+ import smart_open
19
+ from megfile import smart_glob
20
+ from natsort import natsorted
21
+
22
+
23
+ class ConversationDataset(BaseDataset):
24
+ """Conversation format dataset stage2 fine-tuning."""
25
+
26
+ def __init__(self, datasets, tokenizer, multimodal_cfg):
27
+ super(ConversationDataset, self).__init__(datasets, tokenizer, multimodal_cfg)
28
+ # v0 version format conversation
29
+ conversation_lib.default_conversation = conversation_lib.conv_templates["mpt"]
30
+ logging.warning("Formatting inputs into conversation type: mpt-fixed")
31
+ logging.warning("Loading data...")
32
+
33
+ list_data_dict = []
34
+ list_image_path = []
35
+
36
+ # TODO add your data [data1, data2, data3, .....]
37
+ got_data_dict = {
38
+ "pdf-ocr": ["data1", "data2"],
39
+ 'scene-ocr': ["data3", "data4"]
40
+ # ......
41
+ }
42
+ for name_all in datasets.split("+"):
43
+ for name in got_data_dict[name_all]:
44
+ dataset = CONVERSATION_DATA[name]
45
+
46
+ data_path = dataset['annotations']
47
+ data = json.load(open(data_path, "r"))
48
+
49
+ list_data_dict.extend(data)
50
+
51
+ image_path = dataset['images']
52
+
53
+ list_image_path.extend([image_path] * len(data))
54
+
55
+ logging.warning(f"Data from {data_path} provide {len(data)} conversations.")
56
+
57
+ assert len(list_data_dict) == len(list_image_path)
58
+ logging.warning(f"{len(list_data_dict)} conversations in total.")
59
+ a_new_list = list(zip(list_data_dict, list_image_path))
60
+ random.shuffle(a_new_list)
61
+ list_data_dict_new, list_image_path_new = zip(*a_new_list)
62
+ self.list_data_dict = list_data_dict_new
63
+ self.list_image_path = list_image_path_new
64
+
65
+ self.im_patch_token = 151859
66
+
67
+ self.im_start_token = 151857
68
+
69
+ self.im_end_token = 151858
70
+
71
+ def multimodal_processor(self, sources, flag_num_patches):
72
+ for source in sources:
73
+ if self.multimodal_cfg['sep_image_conv_front']:
74
+ assert DEFAULT_IMAGE_TOKEN in source[0]['value']
75
+ source[0]['value'] = source[0]['value'].replace(DEFAULT_IMAGE_TOKEN, '').strip()
76
+ source[0]['value'] = DEFAULT_IMAGE_TOKEN + conversation_lib.default_conversation.sep + conversation_lib.default_conversation.roles[0] + ": " + source[0]['value']
77
+
78
+ for sentence in source:
79
+ replace_token = DEFAULT_IMAGE_PATCH_TOKEN * self.multimodal_cfg['image_token_len']*flag_num_patches
80
+ replace_token = DEFAULT_IM_START_TOKEN + replace_token + DEFAULT_IM_END_TOKEN
81
+ # sentence["value"] = str(sentence["value"]).replace('\qquad', '\quad')
82
+ sentence["value"] = str(sentence["value"]).replace(DEFAULT_IMAGE_TOKEN, replace_token)
83
+ return sources
84
+
85
+ def _tokenize_fn(self, strings):
86
+ """Tokenize a list of strings."""
87
+ tokenized_list = [
88
+ self.tokenizer(
89
+ text,
90
+ return_tensors="pt",
91
+ padding="longest",
92
+ max_length=self.tokenizer.model_max_length,
93
+ truncation=True,
94
+ ) for text in strings
95
+ ]
96
+ input_ids = labels = [
97
+ tokenized.input_ids[0] for tokenized in tokenized_list
98
+ ]
99
+ input_ids_lens = labels_lens = [
100
+ tokenized.input_ids.ne(self.tokenizer.pad_token_id).sum().item()
101
+ for tokenized in tokenized_list
102
+ ]
103
+ return dict(
104
+ input_ids=input_ids,
105
+ labels=labels,
106
+ input_ids_lens=input_ids_lens,
107
+ labels_lens=labels_lens,
108
+ )
109
+
110
+ def _mask_targets(self, target, tokenized_lens, speakers):
111
+ # cur_idx = 0
112
+ cur_idx = tokenized_lens[0]
113
+ tokenized_lens = tokenized_lens[1:]
114
+ target[:cur_idx] = IGNORE_INDEX
115
+ for tokenized_len, speaker in zip(tokenized_lens, speakers):
116
+ if speaker.lower() == "human":
117
+ target[cur_idx+2:cur_idx + tokenized_len] = IGNORE_INDEX
118
+ cur_idx += tokenized_len
119
+
120
+ def token_processor(self, sources, image_name):
121
+ conv = conversation_lib.default_conversation.copy()
122
+ roles = {"human": conv.roles[0], "gpt": conv.roles[1]}
123
+
124
+ # Apply prompt templates
125
+ conversations = []
126
+ for i, source in enumerate(sources):
127
+ if roles[source[0]["from"]] != conv.roles[0]:
128
+ # Skip the first one if it is not from human
129
+ source = source[1:]
130
+
131
+ conv.messages = []
132
+ for j, sentence in enumerate(source):
133
+ role = roles[sentence["from"]]
134
+ assert role == conv.roles[j % 2], f"{i}"
135
+ conv.append_message(role, sentence["value"])
136
+ conversations.append(conv.get_prompt())
137
+
138
+ # Tokenize conversations
139
+
140
+
141
+ input_ids = self.tokenizer(
142
+ conversations,
143
+ return_tensors="pt",
144
+ padding="longest",
145
+ max_length=self.tokenizer.model_max_length,
146
+ truncation=True,
147
+ ).input_ids
148
+
149
+ # input_ids = torch.stack([tokenizer_image_token(prompt, tokenizer, return_tensors='pt') for prompt in conversations], dim=0)
150
+ targets = input_ids.clone()
151
+ assert conv.sep_style == conversation_lib.SeparatorStyle.MPT
152
+
153
+ # Mask targets
154
+ sep = conv.sep + conv.roles[1]
155
+ for conversation, target in zip(conversations, targets):
156
+ total_len = int(target.ne(self.tokenizer.pad_token_id).sum())
157
+
158
+ rounds = conversation.split(conv.sep)
159
+ re_rounds = [conv.sep.join(rounds[:3])] # system + user + gpt
160
+ for conv_idx in range(3, len(rounds), 2):
161
+ re_rounds.append(conv.sep.join(rounds[conv_idx:conv_idx+2])) # user + gpt
162
+ cur_len = 0
163
+ target[:cur_len] = IGNORE_INDEX
164
+ for i, rou in enumerate(re_rounds):
165
+ if rou == "":
166
+ break
167
+
168
+ parts = rou.split(sep)
169
+ if len(parts) != 2:
170
+ break
171
+ parts[0] += sep
172
+ round_len = len(self.tokenizer(rou).input_ids) + len(self.tokenizer(conv.sep).input_ids)
173
+ # round_len = len(tokenizer_image_token(rou, self.tokenizer)) + len(tokenizer_image_token(conv.sep, self.tokenizer))
174
+ # instruction_len = len(tokenizer_image_token(parts[0], tokenizer))
175
+ instruction_len = len(self.tokenizer(parts[0]).input_ids)
176
+ target[cur_len : cur_len + instruction_len] = IGNORE_INDEX
177
+
178
+ cur_len += round_len
179
+ target[cur_len:] = IGNORE_INDEX
180
+
181
+ if cur_len < self.tokenizer.model_max_length:
182
+ if cur_len != total_len:
183
+ target[:] = IGNORE_INDEX
184
+ print(
185
+ f"WARNING: tokenization mismatch: {cur_len} vs. {total_len}."
186
+ f" (ignored)"
187
+ )
188
+ print(image_name)
189
+
190
+ return dict(
191
+ input_ids=input_ids,
192
+ labels=targets,
193
+ )
194
+
195
+ def __getitem__(self, i) -> Dict[str, torch.Tensor]:
196
+ # data = self.list_data_dict[i]
197
+ data = copy.deepcopy(self.list_data_dict[i])
198
+
199
+ if isinstance(data, dict):
200
+ image_list = []
201
+ image_high_list = []
202
+ flag_num_patches = 1
203
+ if 'image' in data:
204
+ image_path = self.list_image_path[i]
205
+ image_file = data['image']
206
+
207
+ # multi-crop or multi page, only support .png files
208
+ if ('.jpg' not in image_file and '.png' not in image_file and '.jpeg' not in image_file) and ('.jpg' not in image_path and '.png' not in image_path and '.jpeg' not in image_path):
209
+ if image_file[0] == '/':
210
+ patch_dir = image_path[:-1] + image_file
211
+ patches = smart_glob(patch_dir + '*.png')
212
+ else:
213
+ patch_dir = image_path + image_file
214
+ patches = smart_glob(patch_dir + '*.png')
215
+
216
+ # print(patches)
217
+ if not patches:
218
+ print(f'cannot glob the dir {patch_dir}.')
219
+ return self.__getitem__(0)
220
+
221
+ # sort multi images by name
222
+ patches = natsorted(patches)
223
+ flag_num_patches = len(patches)
224
+
225
+ for patch in patches:
226
+ try:
227
+ image = Image.open(patch).convert('RGB')
228
+ except:
229
+ print(f'cannot identify image file {patch}.')
230
+ return self.__getitem__(0)
231
+
232
+ try:
233
+ img = self.image_processor(image)
234
+ image_list.append(img)
235
+ image_high_list.append(img)
236
+ except:
237
+ print(f'image {image_path + image_file + patch} are broken or grayscale! we thus select 0-th sample instead!')
238
+ return self.__getitem__(0)
239
+
240
+ else:
241
+ flag_num_patches = 1
242
+ try:
243
+ image = Image.open(image_path + image_file).convert('RGB')
244
+ except:
245
+ print(f'cannot identify image file {image_file}.')
246
+ return self.__getitem__(0)
247
+
248
+ try:
249
+ image = self.image_processor(image)
250
+ except:
251
+ print(f'image {image_file} are broken or grayscale! we thus select 0-th sample instead!')
252
+ return self.__getitem__(0)
253
+
254
+ conversations = self.multimodal_processor([data["conversations"]], flag_num_patches)
255
+ # print(conversations)
256
+ # exit()
257
+ else:
258
+ conversations = [data]
259
+
260
+ # align with fastchat & llava here, put the conversation into a list for tokenization
261
+ image_name = image_path + image_file
262
+ data_dict = self.token_processor(conversations, image_name)
263
+ data_dict = dict(input_ids=data_dict["input_ids"][0], labels=data_dict["labels"][0])
264
+
265
+ if isinstance(data, dict) and 'image' in data:
266
+ if image_list and image_high_list:
267
+ data_dict['image'] = image_list
268
+ data_dict['image_high'] = image_high_list
269
+ else:
270
+ data_dict['image'] = [image]
271
+ data_dict['image_high'] = [image]
272
+ else:
273
+ # crop_size = self.multimodal_cfg['image_processor'].crop_size
274
+ # data_dict['image'] = [torch.zeros(3, crop_size['height'], crop_size['width'])]
275
+ # Vary for two image, GOT does not use the data_dict['image]
276
+ data_dict['image'] = [torch.zeros(3, 1024, 1024)]
277
+ data_dict['image_high'] = [torch.zeros(3, 1024, 1024)]
278
+ return data_dict
279
+
GOT-OCR-2.0-master/GOT/demo/process_results.py ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import string
2
+
3
+ punctuation_dict = {
4
+ ",": ",",
5
+ "。": ".",
6
+
7
+ }
8
+
9
+
10
+ # import os
11
+
12
+ def svg_to_html(svg_content, output_filename):
13
+
14
+ html_content = f"""
15
+ <!DOCTYPE html>
16
+ <html lang="en">
17
+ <head>
18
+ <meta charset="UTF-8">
19
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
20
+ <title>SVG Embedded in HTML</title>
21
+ </head>
22
+ <body>
23
+ <svg width="2100" height="15000" xmlns="http://www.w3.org/2000/svg">
24
+ {svg_content}
25
+ </svg>
26
+ </body>
27
+ </html>
28
+ """
29
+
30
+ with open(output_filename, 'w') as file:
31
+ file.write(html_content)
32
+
33
+
34
+
GOT-OCR-2.0-master/GOT/demo/run_ocr_2.0.py ADDED
@@ -0,0 +1,245 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import argparse
2
+ from transformers import AutoTokenizer, AutoModelForCausalLM
3
+ import torch
4
+ import os
5
+ from GOT.utils.conversation import conv_templates, SeparatorStyle
6
+ from GOT.utils.utils import disable_torch_init
7
+ from transformers import CLIPVisionModel, CLIPImageProcessor, StoppingCriteria
8
+ from GOT.model import *
9
+ from GOT.utils.utils import KeywordsStoppingCriteria
10
+
11
+ from PIL import Image
12
+
13
+ import os
14
+ import requests
15
+ from PIL import Image
16
+ from io import BytesIO
17
+ from GOT.model.plug.blip_process import BlipImageEvalProcessor
18
+
19
+ from transformers import TextStreamer
20
+ import re
21
+ from GOT.demo.process_results import punctuation_dict, svg_to_html
22
+ import string
23
+
24
+ DEFAULT_IMAGE_TOKEN = "<image>"
25
+ DEFAULT_IMAGE_PATCH_TOKEN = '<imgpad>'
26
+
27
+ DEFAULT_IM_START_TOKEN = '<img>'
28
+ DEFAULT_IM_END_TOKEN = '</img>'
29
+
30
+
31
+
32
+ translation_table = str.maketrans(punctuation_dict)
33
+
34
+
35
+ def load_image(image_file):
36
+ if image_file.startswith('http') or image_file.startswith('https'):
37
+ response = requests.get(image_file)
38
+ image = Image.open(BytesIO(response.content)).convert('RGB')
39
+ else:
40
+ image = Image.open(image_file).convert('RGB')
41
+ return image
42
+
43
+
44
+ def eval_model(args):
45
+ # Model
46
+ disable_torch_init()
47
+ model_name = os.path.expanduser(args.model_name)
48
+
49
+ tokenizer = AutoTokenizer.from_pretrained(model_name, trust_remote_code=True)
50
+
51
+
52
+ model = GOTQwenForCausalLM.from_pretrained(model_name, low_cpu_mem_usage=True, device_map='cuda', use_safetensors=True, pad_token_id=151643).eval()
53
+
54
+
55
+
56
+ model.to(device='cuda', dtype=torch.bfloat16)
57
+
58
+
59
+ # TODO vary old codes, NEED del
60
+ image_processor = BlipImageEvalProcessor(image_size=1024)
61
+
62
+ image_processor_high = BlipImageEvalProcessor(image_size=1024)
63
+
64
+ use_im_start_end = True
65
+
66
+ image_token_len = 256
67
+
68
+ image = load_image(args.image_file)
69
+
70
+ w, h = image.size
71
+ # print(image.size)
72
+
73
+ if args.type == 'format':
74
+ qs = 'OCR with format: '
75
+ else:
76
+ qs = 'OCR: '
77
+
78
+ if args.box:
79
+ bbox = eval(args.box)
80
+ if len(bbox) == 2:
81
+ bbox[0] = int(bbox[0]/w*1000)
82
+ bbox[1] = int(bbox[1]/h*1000)
83
+ if len(bbox) == 4:
84
+ bbox[0] = int(bbox[0]/w*1000)
85
+ bbox[1] = int(bbox[1]/h*1000)
86
+ bbox[2] = int(bbox[2]/w*1000)
87
+ bbox[3] = int(bbox[3]/h*1000)
88
+ if args.type == 'format':
89
+ qs = str(bbox) + ' ' + 'OCR with format: '
90
+ else:
91
+ qs = str(bbox) + ' ' + 'OCR: '
92
+
93
+ if args.color:
94
+ if args.type == 'format':
95
+ qs = '[' + args.color + ']' + ' ' + 'OCR with format: '
96
+ else:
97
+ qs = '[' + args.color + ']' + ' ' + 'OCR: '
98
+
99
+ if use_im_start_end:
100
+ qs = DEFAULT_IM_START_TOKEN + DEFAULT_IMAGE_PATCH_TOKEN*image_token_len + DEFAULT_IM_END_TOKEN + '\n' + qs
101
+ else:
102
+ qs = DEFAULT_IMAGE_TOKEN + '\n' + qs
103
+
104
+
105
+
106
+ conv_mode = "mpt"
107
+ args.conv_mode = conv_mode
108
+
109
+ conv = conv_templates[args.conv_mode].copy()
110
+ conv.append_message(conv.roles[0], qs)
111
+ conv.append_message(conv.roles[1], None)
112
+ prompt = conv.get_prompt()
113
+
114
+ print(prompt)
115
+
116
+
117
+ inputs = tokenizer([prompt])
118
+
119
+
120
+ # vary old codes, no use
121
+ image_1 = image.copy()
122
+ image_tensor = image_processor(image)
123
+
124
+
125
+ image_tensor_1 = image_processor_high(image_1)
126
+
127
+
128
+ input_ids = torch.as_tensor(inputs.input_ids).cuda()
129
+
130
+ stop_str = conv.sep if conv.sep_style != SeparatorStyle.TWO else conv.sep2
131
+ keywords = [stop_str]
132
+ stopping_criteria = KeywordsStoppingCriteria(keywords, tokenizer, input_ids)
133
+ streamer = TextStreamer(tokenizer, skip_prompt=True, skip_special_tokens=True)
134
+
135
+
136
+ with torch.autocast("cuda", dtype=torch.bfloat16):
137
+ output_ids = model.generate(
138
+ input_ids,
139
+ images=[(image_tensor.unsqueeze(0).half().cuda(), image_tensor_1.unsqueeze(0).half().cuda())],
140
+ do_sample=False,
141
+ num_beams = 1,
142
+ no_repeat_ngram_size = 20,
143
+ streamer=streamer,
144
+ max_new_tokens=4096,
145
+ stopping_criteria=[stopping_criteria]
146
+ )
147
+
148
+
149
+ if args.render:
150
+ print('==============rendering===============')
151
+
152
+ outputs = tokenizer.decode(output_ids[0, input_ids.shape[1]:]).strip()
153
+
154
+ if outputs.endswith(stop_str):
155
+ outputs = outputs[:-len(stop_str)]
156
+ outputs = outputs.strip()
157
+
158
+ if '**kern' in outputs:
159
+ import verovio
160
+ from cairosvg import svg2png
161
+ import cv2
162
+ import numpy as np
163
+ tk = verovio.toolkit()
164
+ tk.loadData(outputs)
165
+ tk.setOptions({"pageWidth": 2100, "footer": 'none',
166
+ 'barLineWidth': 0.5, 'beamMaxSlope': 15,
167
+ 'staffLineWidth': 0.2, 'spacingStaff': 6})
168
+ tk.getPageCount()
169
+ svg = tk.renderToSVG()
170
+ svg = svg.replace("overflow=\"inherit\"", "overflow=\"visible\"")
171
+
172
+ svg_to_html(svg, "./results/demo.html")
173
+
174
+ if args.type == 'format' and '**kern' not in outputs:
175
+
176
+
177
+ if '\\begin{tikzpicture}' not in outputs:
178
+ html_path = "./render_tools/" + "/content-mmd-to-html.html"
179
+ html_path_2 = "./results/demo.html"
180
+ right_num = outputs.count('\\right')
181
+ left_num = outputs.count('\left')
182
+
183
+ if right_num != left_num:
184
+ outputs = outputs.replace('\left(', '(').replace('\\right)', ')').replace('\left[', '[').replace('\\right]', ']').replace('\left{', '{').replace('\\right}', '}').replace('\left|', '|').replace('\\right|', '|').replace('\left.', '.').replace('\\right.', '.')
185
+
186
+
187
+ outputs = outputs.replace('"', '``').replace('$', '')
188
+
189
+ outputs_list = outputs.split('\n')
190
+ gt= ''
191
+ for out in outputs_list:
192
+ gt += '"' + out.replace('\\', '\\\\') + r'\n' + '"' + '+' + '\n'
193
+
194
+ gt = gt[:-2]
195
+
196
+ with open(html_path, 'r') as web_f:
197
+ lines = web_f.read()
198
+ lines = lines.split("const text =")
199
+ new_web = lines[0] + 'const text =' + gt + lines[1]
200
+ else:
201
+ html_path = "./render_tools/" + "/tikz.html"
202
+ html_path_2 = "./results/demo.html"
203
+ outputs = outputs.translate(translation_table)
204
+ outputs_list = outputs.split('\n')
205
+ gt= ''
206
+ for out in outputs_list:
207
+ if out:
208
+ if '\\begin{tikzpicture}' not in out and '\\end{tikzpicture}' not in out:
209
+ while out[-1] == ' ':
210
+ out = out[:-1]
211
+ if out is None:
212
+ break
213
+
214
+ if out:
215
+ if out[-1] != ';':
216
+ gt += out[:-1] + ';\n'
217
+ else:
218
+ gt += out + '\n'
219
+ else:
220
+ gt += out + '\n'
221
+
222
+
223
+ with open(html_path, 'r') as web_f:
224
+ lines = web_f.read()
225
+ lines = lines.split("const text =")
226
+ new_web = lines[0] + gt + lines[1]
227
+
228
+ with open(html_path_2, 'w') as web_f_new:
229
+ web_f_new.write(new_web)
230
+
231
+
232
+
233
+
234
+
235
+ if __name__ == "__main__":
236
+ parser = argparse.ArgumentParser()
237
+ parser.add_argument("--model-name", type=str, default="facebook/opt-350m")
238
+ parser.add_argument("--image-file", type=str, required=True)
239
+ parser.add_argument("--type", type=str, required=True)
240
+ parser.add_argument("--box", type=str, default= '')
241
+ parser.add_argument("--color", type=str, default= '')
242
+ parser.add_argument("--render", action='store_true')
243
+ args = parser.parse_args()
244
+
245
+ eval_model(args)
GOT-OCR-2.0-master/GOT/demo/run_ocr_2.0_crop.py ADDED
@@ -0,0 +1,251 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import argparse
2
+ from transformers import AutoTokenizer, AutoModelForCausalLM
3
+ import torch
4
+ import os
5
+ from GOT.utils.conversation import conv_templates, SeparatorStyle
6
+ from GOT.utils.utils import disable_torch_init
7
+ from transformers import CLIPVisionModel, CLIPImageProcessor, StoppingCriteria
8
+ from GOT.model import *
9
+ from GOT.utils.utils import KeywordsStoppingCriteria
10
+
11
+ from PIL import Image
12
+
13
+ import os
14
+ import requests
15
+ from PIL import Image
16
+ from io import BytesIO
17
+ from GOT.model.plug.blip_process import BlipImageEvalProcessor
18
+ from transformers import TextStreamer
19
+ from natsort import natsorted
20
+ import glob
21
+
22
+
23
+
24
+
25
+ DEFAULT_IMAGE_TOKEN = "<image>"
26
+ DEFAULT_IMAGE_PATCH_TOKEN = '<imgpad>'
27
+ DEFAULT_IM_START_TOKEN = '<img>'
28
+ DEFAULT_IM_END_TOKEN = '</img>'
29
+
30
+
31
+
32
+ def load_image(image_file):
33
+ if image_file.startswith('http') or image_file.startswith('https'):
34
+ response = requests.get(image_file)
35
+ image = Image.open(BytesIO(response.content)).convert('RGB')
36
+ else:
37
+ image = Image.open(image_file).convert('RGB')
38
+ return image
39
+
40
+ def find_closest_aspect_ratio(aspect_ratio, target_ratios, width, height, image_size):
41
+ best_ratio_diff = float('inf')
42
+ best_ratio = (1, 1)
43
+ area = width * height
44
+ for ratio in target_ratios:
45
+ target_aspect_ratio = ratio[0] / ratio[1]
46
+ ratio_diff = abs(aspect_ratio - target_aspect_ratio)
47
+ if ratio_diff < best_ratio_diff:
48
+ best_ratio_diff = ratio_diff
49
+ best_ratio = ratio
50
+ elif ratio_diff == best_ratio_diff:
51
+ if area > 0.5 * image_size * image_size * ratio[0] * ratio[1]:
52
+ best_ratio = ratio
53
+ # print(f'width: {width}, height: {height}, best_ratio: {best_ratio}')
54
+ return best_ratio
55
+
56
+
57
+ def dynamic_preprocess(image, min_num=1, max_num=6, image_size=1024, use_thumbnail=True):
58
+ orig_width, orig_height = image.size
59
+ aspect_ratio = orig_width / orig_height
60
+
61
+ # calculate the existing image aspect ratio
62
+ target_ratios = set(
63
+ (i, j) for n in range(min_num, max_num + 1) for i in range(1, n + 1) for j in range(1, n + 1) if
64
+ i * j <= max_num and i * j >= min_num)
65
+ # print(target_ratios)
66
+ target_ratios = sorted(target_ratios, key=lambda x: x[0] * x[1])
67
+
68
+ # find the closest aspect ratio to the target
69
+ target_aspect_ratio = find_closest_aspect_ratio(
70
+ aspect_ratio, target_ratios, orig_width, orig_height, image_size)
71
+
72
+ # print(target_aspect_ratio)
73
+ # calculate the target width and height
74
+ target_width = image_size * target_aspect_ratio[0]
75
+ target_height = image_size * target_aspect_ratio[1]
76
+ blocks = target_aspect_ratio[0] * target_aspect_ratio[1]
77
+
78
+ # resize the image
79
+ resized_img = image.resize((target_width, target_height))
80
+ processed_images = []
81
+ for i in range(blocks):
82
+ box = (
83
+ (i % (target_width // image_size)) * image_size,
84
+ (i // (target_width // image_size)) * image_size,
85
+ ((i % (target_width // image_size)) + 1) * image_size,
86
+ ((i // (target_width // image_size)) + 1) * image_size
87
+ )
88
+ # split the image
89
+ split_img = resized_img.crop(box)
90
+ processed_images.append(split_img)
91
+ assert len(processed_images) == blocks
92
+ if use_thumbnail and len(processed_images) != 1:
93
+ thumbnail_img = image.resize((image_size, image_size))
94
+ processed_images.append(thumbnail_img)
95
+ return processed_images
96
+
97
+
98
+
99
+ def eval_model(args):
100
+ # Model
101
+ disable_torch_init()
102
+ model_name = os.path.expanduser(args.model_name)
103
+
104
+ tokenizer = AutoTokenizer.from_pretrained(model_name, trust_remote_code=True)
105
+
106
+
107
+ model = GOTQwenForCausalLM.from_pretrained(model_name, low_cpu_mem_usage=True, device_map='cuda', use_safetensors=True, pad_token_id=151643).eval()
108
+
109
+
110
+
111
+ model.to(device='cuda', dtype=torch.bfloat16)
112
+
113
+
114
+ # vary old codes, no use
115
+ image_processor = BlipImageEvalProcessor(image_size=1024)
116
+
117
+ image_processor_high = BlipImageEvalProcessor(image_size=1024)
118
+
119
+ use_im_start_end = True
120
+
121
+
122
+ image_token_len = 256
123
+
124
+
125
+
126
+
127
+ image_list = []
128
+
129
+ if args.multi_page:
130
+ qs = 'OCR with format across multi pages: '
131
+ # only for png files
132
+ patches = glob.glob(args.image_file + '/*png')
133
+ patches = natsorted(patches)
134
+ sub_images = []
135
+ for sub_image in patches:
136
+ sub_images.append(load_image(sub_image))
137
+
138
+ ll = len(patches)
139
+
140
+ else:
141
+ qs = 'OCR with format upon the patch reference: '
142
+ img = load_image(args.image_file)
143
+ sub_images = dynamic_preprocess(img)
144
+ ll = len(sub_images)
145
+
146
+ for p in sub_images:
147
+
148
+ image = p
149
+ image_1 = image.copy()
150
+ # no use, vary old codes
151
+ image_tensor = image_processor(image)
152
+
153
+
154
+ image_tensor_1 = image_processor_high(image_1)
155
+
156
+ image_list.append(image_tensor_1)
157
+
158
+
159
+ image_list = torch.stack(image_list)
160
+
161
+ print('====new images batch size======: ',image_list.shape)
162
+
163
+
164
+
165
+
166
+
167
+ # qs = args.query
168
+ if use_im_start_end:
169
+ qs = DEFAULT_IM_START_TOKEN + DEFAULT_IMAGE_PATCH_TOKEN*image_token_len*ll + DEFAULT_IM_END_TOKEN + '\n' + qs
170
+ else:
171
+ qs = DEFAULT_IMAGE_TOKEN + '\n' + qs
172
+
173
+
174
+
175
+
176
+ conv_mode = "mpt"
177
+ args.conv_mode = conv_mode
178
+
179
+ conv = conv_templates[args.conv_mode].copy()
180
+ conv.append_message(conv.roles[0], qs)
181
+ conv.append_message(conv.roles[1], None)
182
+ prompt = conv.get_prompt()
183
+
184
+
185
+ inputs = tokenizer([prompt])
186
+
187
+ input_ids = torch.as_tensor(inputs.input_ids).cuda()
188
+
189
+ stop_str = conv.sep if conv.sep_style != SeparatorStyle.TWO else conv.sep2
190
+ keywords = [stop_str]
191
+ stopping_criteria = KeywordsStoppingCriteria(keywords, tokenizer, input_ids)
192
+ streamer = TextStreamer(tokenizer, skip_prompt=True, skip_special_tokens=True)
193
+
194
+
195
+ with torch.autocast("cuda", dtype=torch.bfloat16):
196
+ output_ids = model.generate(
197
+ input_ids,
198
+ images=[(image_list.half().cuda(), image_list.half().cuda())],
199
+ do_sample=False,
200
+ num_beams = 1,
201
+ # no_repeat_ngram_size = 20,
202
+ streamer=streamer,
203
+ max_new_tokens=4096,
204
+ stopping_criteria=[stopping_criteria]
205
+ )
206
+
207
+ if args.render:
208
+ print('==============rendering===============')
209
+ outputs = tokenizer.decode(output_ids[0, input_ids.shape[1]:]).strip()
210
+
211
+ if outputs.endswith(stop_str):
212
+ outputs = outputs[:-len(stop_str)]
213
+ outputs = outputs.strip()
214
+
215
+ html_path = "./render_tools/" + "/content-mmd-to-html.html"
216
+ html_path_2 = "./results/demo.html"
217
+ right_num = outputs.count('\\right')
218
+ left_num = outputs.count('\left')
219
+
220
+ if right_num != left_num:
221
+ outputs = outputs.replace('\left(', '(').replace('\\right)', ')').replace('\left[', '[').replace('\\right]', ']').replace('\left{', '{').replace('\\right}', '}').replace('\left|', '|').replace('\\right|', '|').replace('\left.', '.').replace('\\right.', '.')
222
+
223
+
224
+ outputs = outputs.replace('"', '``').replace('$', '')
225
+
226
+ outputs_list = outputs.split('\n')
227
+ gt= ''
228
+ for out in outputs_list:
229
+ gt += '"' + out.replace('\\', '\\\\') + r'\n' + '"' + '+' + '\n'
230
+
231
+ gt = gt[:-2]
232
+
233
+ with open(html_path, 'r') as web_f:
234
+ lines = web_f.read()
235
+ lines = lines.split("const text =")
236
+ new_web = lines[0] + 'const text =' + gt + lines[1]
237
+
238
+ with open(html_path_2, 'w') as web_f_new:
239
+ web_f_new.write(new_web)
240
+
241
+
242
+ if __name__ == "__main__":
243
+ parser = argparse.ArgumentParser()
244
+ parser.add_argument("--model-name", type=str, default="facebook/opt-350m")
245
+ parser.add_argument("--image-file", type=str, required=True)
246
+ parser.add_argument("--conv-mode", type=str, default=None)
247
+ parser.add_argument("--multi-page", action='store_true')
248
+ parser.add_argument("--render", action='store_true')
249
+ args = parser.parse_args()
250
+
251
+ eval_model(args)
GOT-OCR-2.0-master/GOT/eval/eval_GOT_ocr.py ADDED
@@ -0,0 +1,323 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import argparse
2
+ from transformers import AutoTokenizer, AutoModelForCausalLM
3
+ import torch
4
+ import os
5
+
6
+ from tqdm import tqdm
7
+ from PIL import Image
8
+ import json
9
+ import os
10
+ import requests
11
+ from PIL import Image
12
+ from io import BytesIO
13
+ import math
14
+
15
+ import argparse
16
+ from transformers import AutoTokenizer, AutoModelForCausalLM
17
+ import torch
18
+ import os
19
+ from GOT.utils.conversation import conv_templates, SeparatorStyle
20
+ from GOT.utils.utils import disable_torch_init
21
+ from transformers import CLIPVisionModel, CLIPImageProcessor, StoppingCriteria
22
+ from GOT.model import *
23
+ from GOT.utils.utils import KeywordsStoppingCriteria
24
+
25
+ from PIL import Image
26
+
27
+ import os
28
+ import requests
29
+ from PIL import Image
30
+ from io import BytesIO
31
+ from GOT.model.plug.blip_process import BlipImageEvalProcessor
32
+
33
+ from transformers import TextStreamer
34
+ from GOT.model.plug.transforms import train_transform, test_transform
35
+ import re
36
+ from GOT.demo.process_results import punctuation_dict, svg_to_html
37
+
38
+ DEFAULT_IMAGE_TOKEN = "<image>"
39
+ DEFAULT_IMAGE_PATCH_TOKEN = '<imgpad>'
40
+ DEFAULT_IM_START_TOKEN = '<img>'
41
+ DEFAULT_IM_END_TOKEN = '</img>'
42
+
43
+
44
+ import string
45
+
46
+ translation_table = str.maketrans(punctuation_dict)
47
+
48
+
49
+ def load_image(image_file):
50
+ if image_file.startswith('http') or image_file.startswith('https'):
51
+ response = requests.get(image_file)
52
+ image = Image.open(BytesIO(response.content)).convert('RGB')
53
+ else:
54
+ image = Image.open(image_file).convert('RGB')
55
+ return image
56
+
57
+
58
+ def find_closest_aspect_ratio(aspect_ratio, target_ratios, width, height, image_size):
59
+ best_ratio_diff = float('inf')
60
+ best_ratio = (1, 1)
61
+ area = width * height
62
+ for ratio in target_ratios:
63
+ target_aspect_ratio = ratio[0] / ratio[1]
64
+ ratio_diff = abs(aspect_ratio - target_aspect_ratio)
65
+ if ratio_diff < best_ratio_diff:
66
+ best_ratio_diff = ratio_diff
67
+ best_ratio = ratio
68
+ elif ratio_diff == best_ratio_diff:
69
+ if area > 0.5 * image_size * image_size * ratio[0] * ratio[1]:
70
+ best_ratio = ratio
71
+ # print(f'width: {width}, height: {height}, best_ratio: {best_ratio}')
72
+ return best_ratio
73
+
74
+
75
+ def dynamic_preprocess(image, min_num=1, max_num=6, image_size=1024, use_thumbnail=True):
76
+ orig_width, orig_height = image.size
77
+ aspect_ratio = orig_width / orig_height
78
+
79
+ # calculate the existing image aspect ratio
80
+ target_ratios = set(
81
+ (i, j) for n in range(min_num, max_num + 1) for i in range(1, n + 1) for j in range(1, n + 1) if
82
+ i * j <= max_num and i * j >= min_num)
83
+ # print(target_ratios)
84
+ target_ratios = sorted(target_ratios, key=lambda x: x[0] * x[1])
85
+
86
+ # find the closest aspect ratio to the target
87
+ target_aspect_ratio = find_closest_aspect_ratio(
88
+ aspect_ratio, target_ratios, orig_width, orig_height, image_size)
89
+
90
+ # print(target_aspect_ratio)
91
+ # calculate the target width and height
92
+ target_width = image_size * target_aspect_ratio[0]
93
+ target_height = image_size * target_aspect_ratio[1]
94
+ blocks = target_aspect_ratio[0] * target_aspect_ratio[1]
95
+
96
+ # print(blocks)
97
+
98
+ # resize the image
99
+ resized_img = image.resize((target_width, target_height))
100
+ processed_images = []
101
+ for i in range(blocks):
102
+ box = (
103
+ (i % (target_width // image_size)) * image_size,
104
+ (i // (target_width // image_size)) * image_size,
105
+ ((i % (target_width // image_size)) + 1) * image_size,
106
+ ((i // (target_width // image_size)) + 1) * image_size
107
+ )
108
+ # split the image
109
+ split_img = resized_img.crop(box)
110
+ processed_images.append(split_img)
111
+ assert len(processed_images) == blocks
112
+ if use_thumbnail and len(processed_images) != 1:
113
+ thumbnail_img = image.resize((image_size, image_size))
114
+ processed_images.append(thumbnail_img)
115
+ return processed_images
116
+
117
+
118
+
119
+ def split_list(lst, n):
120
+ """Split a list into n (roughly) equal-sized chunks"""
121
+ chunk_size = math.ceil(len(lst) / n) # integer division
122
+ return [lst[i:i+chunk_size] for i in range(0, len(lst), chunk_size)]
123
+
124
+
125
+ def get_chunk(lst, n, k):
126
+ chunks = split_list(lst, n)
127
+ return chunks[k]
128
+
129
+
130
+
131
+ output_list = []
132
+
133
+ def eval_model(args):
134
+ # Model
135
+ disable_torch_init()
136
+ model_name = os.path.expanduser(args.model_name)
137
+ tokenizer = AutoTokenizer.from_pretrained(model_name, trust_remote_code=True)
138
+
139
+
140
+ model = GOTQwenForCausalLM.from_pretrained(model_name, low_cpu_mem_usage=True, device_map='cuda', use_safetensors=True, pad_token_id=151643).eval()
141
+
142
+
143
+ # vary old codes, no use
144
+ image_processor = BlipImageEvalProcessor(image_size=1024)
145
+
146
+
147
+ # image_processor_high = BlipImageEvalProcessor(image_size=1280)
148
+ image_processor_high = BlipImageEvalProcessor(image_size=1024)
149
+ use_im_start_end = True
150
+
151
+
152
+
153
+ # image_token_len = 400
154
+ image_token_len = 256
155
+ gts_path = args.gtfile_path
156
+ gts = json.load(open(gts_path))
157
+
158
+ # gts = gts[0]
159
+
160
+
161
+ print("Generate Results......")
162
+
163
+
164
+ if "OCR" in args.datatype:
165
+ gts = get_chunk(gts, args.num_chunks, args.chunk_idx)
166
+
167
+
168
+ for ann in tqdm(gts):
169
+ output_json = {}
170
+
171
+ if "OCR" in args.datatype:
172
+ qs = ann["conversations"][0]["value"]
173
+ else:
174
+ qs = ann["question"]
175
+ # ans = ann["answers"][0]
176
+
177
+ qs2 = qs
178
+ image_file = ann["image"]
179
+ if 'Text' in args.datatype:
180
+ image_file = image_file + '.jpg'
181
+ if "VQAv2" in args.datatype:
182
+ image_file = 'COCO_' + 'val2014' + '_'+ str(image_file).zfill(12) + '.jpg'
183
+ if "Cap" in args.datatype:
184
+ image_file = 'COCO_' + 'val2014' + '_'+ str(image_file).zfill(12) + '.jpg'
185
+
186
+ image_file_path = os.path.join(args.image_path, image_file)
187
+ # print(image_file_path)
188
+ # exit()
189
+
190
+ # qs = args.query
191
+ # if mm_use_im_start_end:
192
+
193
+
194
+
195
+ multi_crop = False
196
+ if multi_crop:
197
+ image_list = []
198
+ # qs = DEFAULT_IM_START_TOKEN + DEFAULT_IMAGE_PATCH_TOKEN * image_token_len + DEFAULT_IM_END_TOKEN + '\n' + 'OCR with format upon the patch reference: '
199
+ img = load_image(image_file_path)
200
+ sub_images = dynamic_preprocess(img)
201
+ ll = len(sub_images)
202
+ for p in sub_images:
203
+ image = p
204
+ image_1 = image.copy()
205
+ # vary old code, NO USE
206
+ image_tensor = image_processor_high(image_1)
207
+
208
+ # image_tensor_1 = image_processor_high.preprocess(image_1, return_tensors='pt')['pixel_values'][0]
209
+
210
+ image_tensor_1 = image_processor_high(image_1)
211
+
212
+ image_list.append(image_tensor_1)
213
+
214
+ # print(image_tensor_1.shape)
215
+
216
+ image_list = torch.stack(image_list)
217
+
218
+ else:
219
+ ll = 1
220
+ image = load_image(image_file_path)
221
+ image_1 = image.copy()
222
+ # image_1 = image_1.resize((1024, 1024))
223
+
224
+ # vary old code, NO USE
225
+ image_tensor = image_processor_high(image_1)
226
+
227
+ image_tensor_1 = image_processor_high(image_1)
228
+ # image_tensor_1 = torch.zeros(3, 1024, 1024)
229
+
230
+
231
+ qs = DEFAULT_IM_START_TOKEN + DEFAULT_IMAGE_PATCH_TOKEN * image_token_len*ll + DEFAULT_IM_END_TOKEN + '\n' + 'OCR with format: '
232
+
233
+
234
+
235
+ conv_mode = "mpt"
236
+
237
+ if args.conv_mode is not None and conv_mode != args.conv_mode:
238
+ print('[WARNING] the auto inferred conversation mode is {}, while `--conv-mode` is {}, using {}'.format(conv_mode, args.conv_mode, args.conv_mode))
239
+ else:
240
+ args.conv_mode = conv_mode
241
+
242
+ conv = conv_templates[args.conv_mode].copy()
243
+ conv.append_message(conv.roles[0], qs)
244
+ conv.append_message(conv.roles[1], None)
245
+ prompt = conv.get_prompt()
246
+ inputs = tokenizer([prompt])
247
+
248
+ input_ids = torch.as_tensor(inputs.input_ids).cuda()
249
+
250
+ stop_str = conv.sep if conv.sep_style != SeparatorStyle.TWO else conv.sep2
251
+ keywords = [stop_str]
252
+ stopping_criteria = KeywordsStoppingCriteria(keywords, tokenizer, input_ids)
253
+
254
+ if multi_crop:
255
+ with torch.autocast("cuda", dtype=torch.bfloat16):
256
+ output_ids = model.generate(
257
+ input_ids,
258
+ images=[(image_list.half().cuda(), image_list.half().cuda())],
259
+ do_sample=False,
260
+ num_beams = 1,
261
+ # temperature=0.2,
262
+ # no_repeat_ngram_size = 20,
263
+ # streamer=streamer,
264
+ max_new_tokens=4096,
265
+ stopping_criteria=[stopping_criteria]
266
+ )
267
+ else:
268
+ with torch.autocast("cuda", dtype=torch.bfloat16):
269
+ output_ids = model.generate(
270
+ input_ids,
271
+ images=[(image_tensor.unsqueeze(0).half().cuda(), image_tensor_1.unsqueeze(0).half().cuda())],
272
+ do_sample=False,
273
+ num_beams = 1,
274
+ # temperature=0.2,
275
+ no_repeat_ngram_size = 20,
276
+ # encoder_repetition_penalty = 1.2,
277
+ # penalty_alpha=0.2,
278
+ # top_k=3,
279
+ max_new_tokens=4096,
280
+ stopping_criteria=[stopping_criteria]
281
+ )
282
+
283
+ outputs = tokenizer.decode(output_ids[0, input_ids.shape[1]:]).strip()
284
+
285
+ if outputs.endswith(stop_str):
286
+ outputs = outputs[:-len(stop_str)]
287
+ outputs = outputs.strip()
288
+ # outputs = outputs.strip()[:-1]
289
+ if "Cap" in args.datatype:
290
+ # output_json['image'] = ann["image"]
291
+ output_json['image_id'] = ann["id"]
292
+ output_json["caption"] = outputs
293
+ else:
294
+ # output_json['questionId'] = qs_id
295
+ # output_json['question_id'] = qs_id
296
+ output_json['image'] = ann["image"]
297
+ output_json['question'] = qs
298
+ output_json['label'] = ann["conversations"][1]["value"]
299
+ output_json['answer'] = outputs
300
+ output_list.append(output_json)
301
+
302
+ filename = args.out_path + "/results_" + str(args.chunk_idx) + ".json"
303
+ with open(filename, 'w', encoding="utf-8") as file_obj:
304
+ json.dump(output_list, file_obj, ensure_ascii=False, indent=1)
305
+ # print(outputs)
306
+ # print("Evaluate Results... ")
307
+ # doc_text_eval(gts_path, filename, args.datatype)
308
+
309
+ if __name__ == "__main__":
310
+ parser = argparse.ArgumentParser()
311
+ parser.add_argument("--model-name", type=str, default="facebook/opt-350m")
312
+ parser.add_argument("--gtfile_path", type=str, required=True)
313
+ parser.add_argument("--image_path", type=str, required=True)
314
+ parser.add_argument("--out_path", type=str, required=True)
315
+ parser.add_argument("--datatype", type=str, required=True) # Text or Doc
316
+ parser.add_argument("--num-chunks", type=int, default=1)
317
+ parser.add_argument("--chunk-idx", type=int, default=0)
318
+ # parser.add_argument("--query", type=str, required=True)
319
+ parser.add_argument("--conv-mode", type=str, default=None)
320
+ parser.add_argument("--temperature", type=float, default=0.2)
321
+ args = parser.parse_args()
322
+ print(args)
323
+ eval_model(args)
GOT-OCR-2.0-master/GOT/eval/evaluate_GOT.py ADDED
@@ -0,0 +1,52 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import argparse
3
+
4
+ parser = argparse.ArgumentParser()
5
+ parser.add_argument("--model-name", type=str, default="facebook/opt-350m")
6
+ parser.add_argument("--gtfile_path", type=str, required=True)
7
+ parser.add_argument("--image_path", type=str, required=True)
8
+ parser.add_argument("--out_path", type=str, required=True)
9
+ parser.add_argument("--num-chunks", type=int, default=1)
10
+ parser.add_argument("--temperature", type=float, default=0.2)
11
+ parser.add_argument("--datatype", type=str, required=True) # Text\Doc\VQAv2\Cap
12
+ # parser.add_argument("--eval", type=str, required=True)
13
+ args = parser.parse_args()
14
+
15
+ os.system("python3 -m GOT.eval.multi_hardware_eval_GOT" + " "
16
+ + "--model-name" + " " + args.model_name + " "
17
+ + "--gtfile_path" + " " + args.gtfile_path + " "
18
+ + "--image_path" + " " + args.image_path + " "
19
+ + "--out_path" + " " + args.out_path + " "
20
+ + "--num-chunks" + " " + str(args.num_chunks) + " "
21
+ + "--temperature" + " " + str(args.temperature) + " "
22
+ + "--datatype" + " " + args.datatype
23
+ )
24
+
25
+ print("Evaluating.....")
26
+ os.system("python3 -m GOT.eval.pyevaltools.merge_results" + " "
27
+ + "--out_path" + " " + args.out_path)
28
+
29
+
30
+ # if args.datatype == "OCR":
31
+
32
+
33
+ a_type = 'plain' # 'palin'; 'format'; 'scene'
34
+
35
+ if a_type == 'plain':
36
+ os.system("python3 -m GOT.eval.pyevaltools.eval_ocr" + " "
37
+ + "--out_path" + " " + args.out_path + " "
38
+ + "--gt_path" + " " + args.gtfile_path + " "
39
+ + "--datatype" + " " + args.datatype
40
+ )
41
+ if a_type == 'format':
42
+ os.system("python3 -m GOT.eval.pyevaltools.eval_ocr_format" + " "
43
+ + "--out_path" + " " + args.out_path + " "
44
+ + "--gt_path" + " " + args.gtfile_path + " "
45
+ + "--datatype" + " " + args.datatype
46
+ )
47
+ if a_type == 'scene':
48
+ os.system("python3 -m GOT.eval.pyevaltools.eval_ocr_scene" + " "
49
+ + "--out_path" + " " + args.out_path + " "
50
+ + "--gt_path" + " " + args.gtfile_path + " "
51
+ + "--datatype" + " " + args.datatype
52
+ )
GOT-OCR-2.0-master/GOT/eval/multi_hardware_eval_GOT.py ADDED
@@ -0,0 +1,47 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import argparse
3
+ from multiprocessing import Pool
4
+ # from GOT.eval.merge_results import merge_outputs
5
+ # from GOT.eval.doctextVQA import doc_text_eval
6
+
7
+
8
+ def run_eval(chunk_id, model_name, gtfile_path, image_path, out_path, num_chunks, datatype, temperature):
9
+ os.system("CUDA_VISIBLE_DEVICES=" + str(chunk_id) + " "
10
+ + "python3 -m GOT.eval.eval_GOT_ocr" + " "
11
+ + "--model-name" + " " + model_name + " "
12
+ + "--gtfile_path" + " " + gtfile_path + " "
13
+ + "--image_path" + " " + image_path + " "
14
+ + "--out_path" + " " + out_path + " "
15
+ + "--num-chunks" + " " + str(num_chunks) + " "
16
+ + "--chunk-idx" + " " + str(chunk_id) + " "
17
+ + "--temperature" + " " + str(temperature) + " "
18
+ + "--datatype" + " " + datatype
19
+ )
20
+
21
+
22
+ if __name__ == "__main__":
23
+ parser = argparse.ArgumentParser()
24
+ parser.add_argument("--model-name", type=str, default="facebook/opt-350m")
25
+ parser.add_argument("--gtfile_path", type=str, required=True)
26
+ parser.add_argument("--image_path", type=str, required=True)
27
+ parser.add_argument("--out_path", type=str, required=True)
28
+ parser.add_argument("--num-chunks", type=int, default=1)
29
+ parser.add_argument("--temperature", type=float, default=0.2)
30
+ parser.add_argument("--datatype", type=str, required=True) # Text or Doc
31
+ # parser.add_argument("--eval", type=str, required=True)
32
+ args = parser.parse_args()
33
+
34
+ num_chunks = args.num_chunks
35
+
36
+ if os.path.exists(args.out_path) == False:
37
+ os.makedirs(args.out_path)
38
+
39
+
40
+ with Pool(num_chunks) as p:
41
+ for i in range(num_chunks):
42
+ chunk_id = i
43
+ p.apply_async(run_eval, (chunk_id, args.model_name, args.gtfile_path,
44
+ args.image_path, args.out_path, num_chunks, args.datatype, args.temperature))
45
+ p.close()
46
+ p.join()
47
+
GOT-OCR-2.0-master/GOT/eval/pyevaltools/__init__.py ADDED
@@ -0,0 +1 @@
 
 
1
+ author='aagrawal'
GOT-OCR-2.0-master/GOT/eval/pyevaltools/eval_ocr.py ADDED
@@ -0,0 +1,220 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import json
2
+ # from doctextVQAeval import VQAEval
3
+
4
+ import argparse
5
+ # import fitz as pymupdf
6
+ import nltk
7
+ from nltk.metrics import precision, recall, f_measure
8
+ import numpy as np
9
+ import jieba
10
+ # import megfile as mf
11
+ import pickle
12
+ import pandas as pd
13
+ import re
14
+ # from loguru import logger
15
+ # nltk.download('wordnet')
16
+ from nltk.translate import meteor_score
17
+
18
+ # from marker_scoring import score_text
19
+ # from utils import contain_chinese_string
20
+ parser = argparse.ArgumentParser()
21
+
22
+ parser.add_argument("--out_path", type=str, required=True)
23
+ parser.add_argument("--gt_path", type=str, required=True)
24
+ parser.add_argument("--datatype", type=str, required=True)
25
+ args = parser.parse_args()
26
+
27
+ def preprocess(text, predict_root_):
28
+ if 'InternVL' in predict_root_:
29
+ text = text.split("All words in the image:\n")[1]
30
+ text = text.split("[UNUSED_TOKEN_145]")[0]
31
+ return text
32
+
33
+ def contain_chinese_string(text):
34
+ # 使用正则表达式匹配中文字符
35
+ chinese_pattern = re.compile(r'[\u4e00-\u9fa5]')
36
+ return bool(chinese_pattern.search(text))
37
+
38
+
39
+ inline_reg = re.compile(r"\\\((.*?)(?<!\\)\\\)")
40
+ display_reg = re.compile(r"\\\[(.+?)(?<!\\)\\\]")
41
+ table_reg = re.compile(r"\\begin\{tabular\}(.+?)(?:\\end\{tabular\}|$)", re.S)
42
+
43
+ def split_text(pages, a_type):
44
+ """
45
+ Split a list of pages into text, inline math, display math, and table blocks.
46
+
47
+ Args:
48
+ pages: The pages to split.
49
+ """
50
+ text, math, table = [], [], []
51
+ for page in pages:
52
+ for i, reg in enumerate([inline_reg, display_reg, table_reg]):
53
+ matches = "\n".join(reg.findall(page[a_type]))
54
+ if i == 2:
55
+ table.append(matches)
56
+ elif i == 1:
57
+ math[-1] += matches
58
+ else:
59
+ math.append(matches)
60
+ page_str = page[a_type]
61
+ text.append(page_str.strip())
62
+ return text, math, table
63
+
64
+ def nougat_per_metrics(predict_root_, pred, gt, minlen=1, heavy_mode: int = 2):
65
+ """
66
+ Args:
67
+ - heavy_mode:
68
+ 0 is clean mode, only similar, bleu, f1
69
+ 1 is normal, do not include edit_dist
70
+ 2 is heavy, total
71
+ """
72
+ metrics = {}
73
+
74
+ # pred = preprocess(pred, predict_root_)
75
+
76
+ if len(pred) < minlen or len(gt) < minlen:
77
+ return metrics
78
+
79
+ # metrics["similar"] = score_text(pred, gt)
80
+ if contain_chinese_string(gt) or contain_chinese_string(pred):
81
+ reference = jieba.lcut(gt)
82
+ hypothesis = jieba.lcut(pred)
83
+ else:
84
+ reference = gt.split()
85
+ hypothesis = pred.split()
86
+
87
+ metrics["bleu"] = nltk.translate.bleu([reference], hypothesis)
88
+ if heavy_mode >= 1:
89
+ # try:
90
+ metrics["meteor"] = meteor_score.meteor_score([reference], hypothesis)
91
+ # except LookupError:
92
+ # metrics["meteor"] = np.nan
93
+
94
+ reference = set(reference)
95
+ hypothesis = set(hypothesis)
96
+ metrics["f_measure"] = f_measure(reference, hypothesis)
97
+
98
+ if heavy_mode >= 1:
99
+ metrics["precision"] = precision(reference, hypothesis)
100
+ metrics["recall"] = recall(reference, hypothesis)
101
+ if heavy_mode == 2:
102
+ # 速度太慢
103
+ metrics["edit_dist"] = nltk.edit_distance(pred, gt) / max(len(pred), len(gt))
104
+ return metrics
105
+
106
+ def doc_formated_text_eval(gt_root_, predict_root_, datatype):
107
+
108
+ predicts = json.load(open(predict_root_, encoding='utf-8'))
109
+
110
+ # print(predicts)
111
+
112
+ gt_text_split, gt_math_split, gt_table_split= split_text(predicts, 'label')
113
+ pre_text_split, pre_math_split, pre_table_split = split_text(predicts, 'answer')
114
+ text_results = []
115
+ math_results = []
116
+ table_results = []
117
+
118
+ for gt0, pre0, gt1, pre1, gt2, pre2 in zip(gt_text_split, pre_text_split, gt_math_split, pre_math_split, gt_table_split, pre_table_split):
119
+ # try:
120
+ # text, math, table
121
+ text_gts, text_pres = gt0, pre0
122
+ math_gts, math_pres = gt1, pre1
123
+ table_gts, table_pres = gt2, pre2
124
+
125
+ # for text_gt, text_pre in zip(text_gts, text_pres):
126
+ ans = nougat_per_metrics(predict_root_, text_gts, text_pres)
127
+ # if len(ans) == 0:
128
+ # continue
129
+ if ans:
130
+ text_results.append(ans)
131
+ # for math_gt, math_pre in zip(math_gts, math_pres):
132
+ ans = nougat_per_metrics(predict_root_, math_gts, math_pres)
133
+ # if len(ans) == 0:
134
+ # continue
135
+ if ans:
136
+ math_results.append(ans)
137
+
138
+ # for table_gt, table_pre in zip(table_gts, table_pres):
139
+ ans = nougat_per_metrics(predict_root_, table_gts, table_pres)
140
+ # if len(ans) == 0:
141
+ # continue
142
+ if ans:
143
+ table_results.append(ans)
144
+
145
+ mean_dict = {}
146
+ # print((result))
147
+ # print(len(result))
148
+ mean_dict["eval question num"] = len(text_results)
149
+ mean_dict['text'] = {}
150
+ mean_dict['math'] = {}
151
+ mean_dict['table'] = {}
152
+
153
+ for k, v in text_results[0].items():
154
+ mean_dict['text'][k] = 0
155
+ mean_dict['math'][k] = 0
156
+ mean_dict['table'][k] = 0
157
+
158
+ for each in text_results:
159
+ for k, v in each.items():
160
+ mean_dict['text'][k] += v
161
+
162
+ for each in math_results:
163
+ for k, v in each.items():
164
+ mean_dict['math'][k] += v
165
+
166
+ for each in table_results:
167
+ for k, v in each.items():
168
+ mean_dict['table'][k] += v
169
+
170
+ for k, v in mean_dict['text'].items():
171
+ mean_dict['text'][k] /= len(text_results)
172
+
173
+ for k, v in mean_dict['math'].items():
174
+ mean_dict['math'][k] /= len(math_results)
175
+
176
+
177
+ for k, v in mean_dict['table'].items():
178
+ mean_dict['table'][k] /= len(table_results)
179
+
180
+ print(json.dumps(mean_dict, indent=4))
181
+
182
+ def doc_text_eval(gt_root_, predict_root_, datatype):
183
+
184
+
185
+ predicts = json.load(open(predict_root_, encoding='utf-8'))
186
+
187
+ # print(predicts)
188
+ result = []
189
+ for ann in predicts:
190
+ try:
191
+ ans = nougat_per_metrics(predict_root_, ann["label"], ann["answer"])
192
+ if len(ans) == 0:
193
+ continue
194
+ result.append(ans)
195
+ except:
196
+ assert False, print("ERROR!!! Check yout output!!!")
197
+
198
+ mean_dict = {}
199
+ # print((result))
200
+ # print(len(result))
201
+ mean_dict["eval question num"] = len(result)
202
+ for k, v in result[0].items():
203
+ mean_dict[k] = 0
204
+
205
+ for each in result:
206
+ for k, v in each.items():
207
+ mean_dict[k] += v
208
+
209
+ for k, v in mean_dict.items():
210
+ if k == "eval question num":
211
+ continue
212
+ mean_dict[k] /= len(result)
213
+ print(json.dumps(mean_dict, indent=4))
214
+
215
+ # doc_text_eval("/data/data/DocVQA/val/val_v1.0.json", "/data/codes/GOT_docshot-main/results_cc595k-freeze-docvqa-unfreeze-224/results_final.json", "Doc")
216
+
217
+
218
+ # doc_formated_text_eval(args.gt_path, args.out_path + "/results_final.json", args.datatype)
219
+
220
+ doc_text_eval(args.gt_path, args.out_path + "/results_final.json", args.datatype)
GOT-OCR-2.0-master/GOT/eval/pyevaltools/eval_ocr_format.py ADDED
@@ -0,0 +1,220 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import json
2
+ # from doctextVQAeval import VQAEval
3
+
4
+ import argparse
5
+ # import fitz as pymupdf
6
+ import nltk
7
+ from nltk.metrics import precision, recall, f_measure
8
+ import numpy as np
9
+ import jieba
10
+ # import megfile as mf
11
+ import pickle
12
+ import pandas as pd
13
+ import re
14
+ # from loguru import logger
15
+ # nltk.download('wordnet')
16
+ from nltk.translate import meteor_score
17
+
18
+ # from marker_scoring import score_text
19
+ # from utils import contain_chinese_string
20
+ parser = argparse.ArgumentParser()
21
+
22
+ parser.add_argument("--out_path", type=str, required=True)
23
+ parser.add_argument("--gt_path", type=str, required=True)
24
+ parser.add_argument("--datatype", type=str, required=True)
25
+ args = parser.parse_args()
26
+
27
+ def preprocess(text, predict_root_):
28
+ if 'InternVL' in predict_root_:
29
+ text = text.split("All words in the image:\n")[1]
30
+ text = text.split("[UNUSED_TOKEN_145]")[0]
31
+ return text
32
+
33
+ def contain_chinese_string(text):
34
+ # 使用正则表达式匹配中文字符
35
+ chinese_pattern = re.compile(r'[\u4e00-\u9fa5]')
36
+ return bool(chinese_pattern.search(text))
37
+
38
+
39
+ inline_reg = re.compile(r"\\\((.*?)(?<!\\)\\\)")
40
+ display_reg = re.compile(r"\\\[(.+?)(?<!\\)\\\]")
41
+ table_reg = re.compile(r"\\begin\{tabular\}(.+?)(?:\\end\{tabular\}|$)", re.S)
42
+
43
+ def split_text(pages, a_type):
44
+ """
45
+ Split a list of pages into text, inline math, display math, and table blocks.
46
+
47
+ Args:
48
+ pages: The pages to split.
49
+ """
50
+ text, math, table = [], [], []
51
+ for page in pages:
52
+ for i, reg in enumerate([inline_reg, display_reg, table_reg]):
53
+ matches = "\n".join(reg.findall(page[a_type]))
54
+ if i == 2:
55
+ table.append(matches)
56
+ elif i == 1:
57
+ math[-1] += matches
58
+ else:
59
+ math.append(matches)
60
+ page_str = page[a_type]
61
+ text.append(page_str.strip())
62
+ return text, math, table
63
+
64
+ def nougat_per_metrics(predict_root_, pred, gt, minlen=1, heavy_mode: int = 2):
65
+ """
66
+ Args:
67
+ - heavy_mode:
68
+ 0 is clean mode, only similar, bleu, f1
69
+ 1 is normal, do not include edit_dist
70
+ 2 is heavy, total
71
+ """
72
+ metrics = {}
73
+
74
+ # pred = preprocess(pred, predict_root_)
75
+
76
+ if len(pred) < minlen or len(gt) < minlen:
77
+ return metrics
78
+
79
+ # metrics["similar"] = score_text(pred, gt)
80
+ if contain_chinese_string(gt) or contain_chinese_string(pred):
81
+ reference = jieba.lcut(gt)
82
+ hypothesis = jieba.lcut(pred)
83
+ else:
84
+ reference = gt.split()
85
+ hypothesis = pred.split()
86
+
87
+ metrics["bleu"] = nltk.translate.bleu([reference], hypothesis)
88
+ if heavy_mode >= 1:
89
+ # try:
90
+ metrics["meteor"] = meteor_score.meteor_score([reference], hypothesis)
91
+ # except LookupError:
92
+ # metrics["meteor"] = np.nan
93
+
94
+ reference = set(reference)
95
+ hypothesis = set(hypothesis)
96
+ metrics["f_measure"] = f_measure(reference, hypothesis)
97
+
98
+ if heavy_mode >= 1:
99
+ metrics["precision"] = precision(reference, hypothesis)
100
+ metrics["recall"] = recall(reference, hypothesis)
101
+ if heavy_mode == 2:
102
+ # 速度太慢
103
+ metrics["edit_dist"] = nltk.edit_distance(pred, gt) / max(len(pred), len(gt))
104
+ return metrics
105
+
106
+ def doc_formated_text_eval(gt_root_, predict_root_, datatype):
107
+
108
+ predicts = json.load(open(predict_root_, encoding='utf-8'))
109
+
110
+ # print(predicts)
111
+
112
+ gt_text_split, gt_math_split, gt_table_split= split_text(predicts, 'label')
113
+ pre_text_split, pre_math_split, pre_table_split = split_text(predicts, 'answer')
114
+ text_results = []
115
+ math_results = []
116
+ table_results = []
117
+
118
+ for gt0, pre0, gt1, pre1, gt2, pre2 in zip(gt_text_split, pre_text_split, gt_math_split, pre_math_split, gt_table_split, pre_table_split):
119
+ # try:
120
+ # text, math, table
121
+ text_gts, text_pres = gt0, pre0
122
+ math_gts, math_pres = gt1, pre1
123
+ table_gts, table_pres = gt2, pre2
124
+
125
+ # for text_gt, text_pre in zip(text_gts, text_pres):
126
+ ans = nougat_per_metrics(predict_root_, text_gts, text_pres)
127
+ # if len(ans) == 0:
128
+ # continue
129
+ if ans:
130
+ text_results.append(ans)
131
+ # for math_gt, math_pre in zip(math_gts, math_pres):
132
+ ans = nougat_per_metrics(predict_root_, math_gts, math_pres)
133
+ # if len(ans) == 0:
134
+ # continue
135
+ if ans:
136
+ math_results.append(ans)
137
+
138
+ # for table_gt, table_pre in zip(table_gts, table_pres):
139
+ ans = nougat_per_metrics(predict_root_, table_gts, table_pres)
140
+ # if len(ans) == 0:
141
+ # continue
142
+ if ans:
143
+ table_results.append(ans)
144
+
145
+ mean_dict = {}
146
+ # print((result))
147
+ # print(len(result))
148
+ mean_dict["eval question num"] = len(text_results)
149
+ mean_dict['text'] = {}
150
+ mean_dict['math'] = {}
151
+ mean_dict['table'] = {}
152
+
153
+ for k, v in text_results[0].items():
154
+ mean_dict['text'][k] = 0
155
+ mean_dict['math'][k] = 0
156
+ mean_dict['table'][k] = 0
157
+
158
+ for each in text_results:
159
+ for k, v in each.items():
160
+ mean_dict['text'][k] += v
161
+
162
+ for each in math_results:
163
+ for k, v in each.items():
164
+ mean_dict['math'][k] += v
165
+
166
+ for each in table_results:
167
+ for k, v in each.items():
168
+ mean_dict['table'][k] += v
169
+
170
+ for k, v in mean_dict['text'].items():
171
+ mean_dict['text'][k] /= len(text_results)
172
+
173
+ for k, v in mean_dict['math'].items():
174
+ mean_dict['math'][k] /= len(math_results)
175
+
176
+
177
+ for k, v in mean_dict['table'].items():
178
+ mean_dict['table'][k] /= len(table_results)
179
+
180
+ print(json.dumps(mean_dict, indent=4))
181
+
182
+ def doc_text_eval(gt_root_, predict_root_, datatype):
183
+
184
+
185
+ predicts = json.load(open(predict_root_, encoding='utf-8'))
186
+
187
+ # print(predicts)
188
+ result = []
189
+ for ann in predicts:
190
+ try:
191
+ ans = nougat_per_metrics(predict_root_, ann["label"], ann["answer"])
192
+ if len(ans) == 0:
193
+ continue
194
+ result.append(ans)
195
+ except:
196
+ assert False, print("ERROR!!! Check yout output!!!")
197
+
198
+ mean_dict = {}
199
+ # print((result))
200
+ # print(len(result))
201
+ mean_dict["eval question num"] = len(result)
202
+ for k, v in result[0].items():
203
+ mean_dict[k] = 0
204
+
205
+ for each in result:
206
+ for k, v in each.items():
207
+ mean_dict[k] += v
208
+
209
+ for k, v in mean_dict.items():
210
+ if k == "eval question num":
211
+ continue
212
+ mean_dict[k] /= len(result)
213
+ print(json.dumps(mean_dict, indent=4))
214
+
215
+ # doc_text_eval("/data/data/DocVQA/val/val_v1.0.json", "/data/codes/GOT_docshot-main/results_cc595k-freeze-docvqa-unfreeze-224/results_final.json", "Doc")
216
+
217
+
218
+ doc_formated_text_eval(args.gt_path, args.out_path + "/results_final.json", args.datatype)
219
+
220
+ # doc_text_eval(args.gt_path, args.out_path + "/results_final.json", args.datatype)
GOT-OCR-2.0-master/GOT/eval/pyevaltools/eval_ocr_scene.py ADDED
@@ -0,0 +1,87 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import json
2
+ import argparse
3
+ import nltk
4
+ from nltk.metrics import precision, recall, f_measure
5
+ import numpy as np
6
+ import jieba
7
+ # import megfile as mf
8
+ import pickle
9
+ import pandas as pd
10
+ import re
11
+ from nltk.translate import meteor_score
12
+
13
+ parser = argparse.ArgumentParser()
14
+
15
+ parser.add_argument("--out_path", type=str, required=True)
16
+ parser.add_argument("--gt_path", type=str, required=True)
17
+ parser.add_argument("--datatype", type=str, required=True)
18
+ args = parser.parse_args()
19
+
20
+ def preprocess(text, predict_root_):
21
+ if 'InternVL' in predict_root_:
22
+ text = text.split("All words in the image:\n")[1]
23
+ text = text.split("[UNUSED_TOKEN_145]")[0]
24
+ return text
25
+
26
+ def contain_chinese_string(text):
27
+ chinese_pattern = re.compile(r'[\u4e00-\u9fa5]')
28
+ return bool(chinese_pattern.search(text))
29
+
30
+ def nougat_per_metrics(predict_root_, pred, gt, minlen=1):
31
+
32
+ metrics = {}
33
+
34
+ if len(pred) < minlen or len(gt) < minlen:
35
+ return metrics
36
+
37
+
38
+ reference = list(gt)
39
+ hypothesis = list(pred)
40
+
41
+ metrics["bleu"] = nltk.translate.bleu([reference], hypothesis)
42
+
43
+ metrics["meteor"] = meteor_score.meteor_score([reference], hypothesis)
44
+
45
+ reference = set(reference)
46
+ hypothesis = set(hypothesis)
47
+ metrics["f_measure"] = f_measure(reference, hypothesis)
48
+ metrics["precision"] = precision(reference, hypothesis)
49
+ metrics["recall"] = recall(reference, hypothesis)
50
+ metrics["edit_dist"] = nltk.edit_distance(pred, gt) / max(len(pred), len(gt))
51
+
52
+ return metrics
53
+
54
+ def doc_text_eval(gt_root_, predict_root_, datatype):
55
+
56
+
57
+
58
+ predicts = json.load(open(predict_root_, encoding='utf-8'))
59
+
60
+ result = []
61
+ for ann in predicts:
62
+ try:
63
+ ans = nougat_per_metrics(predict_root_, ann["label"], ann["answer"])
64
+ if len(ans) == 0:
65
+ continue
66
+ result.append(ans)
67
+ except:
68
+ assert False, print("ERROR!!! Check yout output!!!")
69
+
70
+ mean_dict = {}
71
+
72
+ mean_dict["eval question num"] = len(result)
73
+ for k, v in result[0].items():
74
+ mean_dict[k] = 0
75
+
76
+ for each in result:
77
+ for k, v in each.items():
78
+ mean_dict[k] += v
79
+
80
+ for k, v in mean_dict.items():
81
+ if k == "eval question num":
82
+ continue
83
+ mean_dict[k] /= len(result)
84
+ print(json.dumps(mean_dict, indent=4))
85
+
86
+
87
+ doc_text_eval(args.gt_path, args.out_path + "/results_final.json", args.datatype)
GOT-OCR-2.0-master/GOT/eval/pyevaltools/merge_results.py ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import json
3
+ import argparse
4
+
5
+ def merge_outputs(out_path):
6
+ files = os.listdir(out_path)
7
+ # print(files)
8
+ alist = []
9
+ for file in files:
10
+ alist += json.load(open(os.path.join(out_path, file), encoding='utf-8'))
11
+ # print(len(alist))
12
+
13
+ filename = out_path + "/results_final" + ".json"
14
+ with open(filename, 'w', encoding="utf-8") as file_obj:
15
+ json.dump(alist, file_obj, ensure_ascii=False, indent=1)
16
+
17
+ parser = argparse.ArgumentParser()
18
+ parser.add_argument("--out_path", type=str, required=True)
19
+ args = parser.parse_args()
20
+
21
+ merge_outputs(args.out_path)
GOT-OCR-2.0-master/GOT/model/GOT_ocr_2_0.py ADDED
@@ -0,0 +1,391 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from transformers import AutoConfig, AutoModelForCausalLM, \
2
+ Qwen2Config, Qwen2Model, Qwen2ForCausalLM, \
3
+ CLIPVisionModel, CLIPImageProcessor
4
+ from transformers.modeling_outputs import BaseModelOutputWithPast, CausalLMOutputWithPast
5
+ from typing import List, Optional, Tuple, Union
6
+ from transformers.cache_utils import Cache, DynamicCache
7
+ import torch
8
+ import torch.nn as nn
9
+ import torch.nn.functional as F
10
+ from torch.nn import CrossEntropyLoss
11
+ from GOT.utils.constants import *
12
+ from GOT.model.vision_encoder.vary_b import build_vary_vit_b
13
+ from GOT.model.plug.blip_process import BlipImageEvalProcessor
14
+
15
+ class GOTConfig(Qwen2Config):
16
+ model_type = "GOT"
17
+
18
+
19
+ class GOTQwenModel(Qwen2Model):
20
+ config_class = GOTConfig
21
+
22
+ def __init__(self, config: Qwen2Config):
23
+ super(GOTQwenModel, self).__init__(config)
24
+
25
+ self.vision_tower_high = build_vary_vit_b()
26
+
27
+ self.mm_projector_vary = nn.Linear(1024, 1024)
28
+
29
+
30
+ def initialize_vision_modules(
31
+ self,
32
+ vision_tower,
33
+ pretrained_stage1_model=None,
34
+ freeze_vision_tower=False,
35
+ use_im_start_end=False,
36
+ vision_select_layer=-1,
37
+ dtype=torch.float16,
38
+ device="cuda"
39
+ ):
40
+
41
+ # Vary old codes, not use in GOT
42
+ image_processor = BlipImageEvalProcessor(image_size=1024)
43
+ # 1024*1024
44
+
45
+ image_processor_high = BlipImageEvalProcessor(image_size=1024)
46
+
47
+
48
+
49
+ self.vision_tower_high = self.vision_tower_high.to(dtype=dtype, device=device)
50
+
51
+ self.mm_projector_vary = self.mm_projector_vary.to(dtype=dtype, device=device)
52
+
53
+
54
+ image_token_len = 256
55
+
56
+ self.config.vision_tower = vision_tower
57
+ self.config.image_token_len = image_token_len
58
+ # self.config.use_im_start_end = use_im_start_end
59
+ self.config.use_im_start_end = True
60
+
61
+ self.config.vision_select_layer = vision_select_layer
62
+ self.config.freeze_vision_tower = freeze_vision_tower
63
+
64
+ return dict(
65
+ image_processor=image_processor,
66
+ image_processor_high=image_processor_high,
67
+ image_token_len=image_token_len,
68
+ )
69
+
70
+ # def get_input_embeddings(self, x):
71
+ # return self.wte(x)
72
+
73
+ def forward(
74
+ self,
75
+ input_ids: torch.LongTensor = None,
76
+ attention_mask: Optional[torch.Tensor] = None,
77
+ position_ids: Optional[torch.LongTensor] = None,
78
+ past_key_values: Optional[List[torch.FloatTensor]] = None,
79
+ inputs_embeds: Optional[torch.FloatTensor] = None,
80
+ use_cache: Optional[bool] = None,
81
+ output_attentions: Optional[bool] = None,
82
+ output_hidden_states: Optional[bool] = None,
83
+ images: Optional[torch.FloatTensor] = None,
84
+ return_dict: Optional[bool] = None,
85
+ ) -> Union[Tuple, BaseModelOutputWithPast]:
86
+
87
+ # HACK: replace back original embeddings for LLaVA pretraining
88
+ orig_embeds_params = getattr(self, 'orig_embeds_params', None)
89
+ if orig_embeds_params is not None:
90
+ with torch.no_grad():
91
+ self.get_input_embeddings().weight[:-self.num_new_tokens] = orig_embeds_params[:-self.num_new_tokens].data
92
+
93
+ if inputs_embeds is None:
94
+ inputs_embeds = self.embed_tokens(input_ids)
95
+
96
+
97
+ vision_tower_high = getattr(self, 'vision_tower_high', None)
98
+
99
+
100
+ if vision_tower_high is not None and (input_ids.shape[1] != 1 or self.training) and images is not None:
101
+ # if True:
102
+ # assert type(images) is list, ValueError("To fit both interleave and conversation, images must be list of batches of images")
103
+ # print(im)
104
+ use_im_start_end = getattr(self.config, "use_im_start_end", -1)
105
+
106
+ vision_select_layer = getattr(self.config, "vision_select_layer", -1)
107
+ im_patch_token = getattr(self.config, "im_patch_token", -1)
108
+ im_start_token = getattr(self.config, "im_start_token", -1)
109
+ im_end_token = getattr(self.config, "im_end_token", -1)
110
+ freeze_vision_tower = getattr(self.config, "freeze_vision_tower", False)
111
+
112
+ im_patch_token = 151859
113
+
114
+ im_start_token = 151857
115
+
116
+ im_end_token = 151858
117
+
118
+
119
+
120
+ image_features = []
121
+
122
+
123
+ for image in images:
124
+ P, C, H, W = image[1].shape
125
+ # with torch.set_grad_enabled(True):
126
+ # # print(image[1].shape)
127
+ # cnn_feature = vision_tower_high(image[1])
128
+ # cnn_feature = cnn_feature.flatten(2).permute(0, 2, 1) # 256 1024
129
+ # # image_features.append(cnn_feature)
130
+ # image_features_2.append(cnn_feature)
131
+ if P == 1:
132
+ with torch.set_grad_enabled(False):
133
+ # print(image[1].shape)
134
+ cnn_feature = vision_tower_high(image[1])
135
+ cnn_feature = cnn_feature.flatten(2).permute(0, 2, 1) # 256*1024
136
+ # image_features.append(cnn_feature)
137
+ # image_features_2.append(cnn_feature)
138
+ image_feature = self.mm_projector_vary(cnn_feature)
139
+ image_features.append(image_feature)
140
+
141
+ else:
142
+ image_patches = torch.unbind(image[1])
143
+ image_patches_features = []
144
+ for image_patch in image_patches:
145
+ image_p = torch.stack([image_patch])
146
+ with torch.set_grad_enabled(False):
147
+ cnn_feature_p = vision_tower_high(image_p)
148
+ cnn_feature_p = cnn_feature_p.flatten(2).permute(0, 2, 1)
149
+ image_feature_p = self.mm_projector_vary(cnn_feature_p)
150
+ image_patches_features.append(image_feature_p)
151
+ image_feature = torch.cat(image_patches_features, dim=1)
152
+ # print(P)
153
+ # print(image_feature.shape)
154
+ # exit()
155
+ image_features.append(image_feature)
156
+
157
+
158
+
159
+ dummy_image_features_2 = torch.zeros(256, 1024, device=inputs_embeds.device, dtype=inputs_embeds.dtype)
160
+ # dummy_image_features_2 = self.mm_projector_vary(dummy_image_features_2)
161
+ dummy_image_features = dummy_image_features_2
162
+ use_im_start_end = True
163
+ new_input_embeds = []
164
+ for cur_input_ids, cur_input_embeds, cur_image_features in zip(input_ids, inputs_embeds, image_features):
165
+ if (cur_input_ids == im_patch_token).sum() == 0:
166
+ # multimodal LLM, but the current sample is not multimodal
167
+ cur_input_embeds = cur_input_embeds + (0. * dummy_image_features).sum()
168
+ new_input_embeds.append(cur_input_embeds)
169
+ continue
170
+
171
+ if use_im_start_end:
172
+ if (cur_input_ids == im_start_token).sum() != (cur_input_ids == im_end_token).sum():
173
+ raise ValueError("The number of image start tokens and image end tokens should be the same.")
174
+
175
+ image_start_tokens = torch.where(cur_input_ids == im_start_token)[0]
176
+ for image_start_token_pos, per_cur_image_features in zip(image_start_tokens, cur_image_features):
177
+ per_cur_image_features = per_cur_image_features.to(device=cur_input_embeds.device)
178
+ num_patches = per_cur_image_features.shape[0]
179
+
180
+ if cur_input_ids[image_start_token_pos + num_patches + 1] != im_end_token:
181
+ raise ValueError("The image end token should follow the image start token.")
182
+
183
+ cur_input_embeds = torch.cat(
184
+ (
185
+ cur_input_embeds[:image_start_token_pos+1],
186
+ per_cur_image_features,
187
+ cur_input_embeds[image_start_token_pos + num_patches + 1:]
188
+ ),
189
+ dim=0
190
+ )
191
+
192
+
193
+ new_input_embeds.append(cur_input_embeds)
194
+ else:
195
+ raise NotImplementedError
196
+
197
+ inputs_embeds = torch.stack(new_input_embeds, dim=0)
198
+
199
+ return super(GOTQwenModel, self).forward(
200
+ input_ids=None, attention_mask=attention_mask, past_key_values=past_key_values,
201
+ inputs_embeds=inputs_embeds, use_cache=use_cache, position_ids = position_ids,
202
+ output_attentions=output_attentions, output_hidden_states=output_hidden_states,
203
+ return_dict=return_dict
204
+ )
205
+
206
+
207
+
208
+ class GOTQwenForCausalLM(Qwen2ForCausalLM):
209
+ config_class = GOTConfig
210
+ # supports_gradient_checkpointing = True
211
+
212
+ def __init__(self, config):
213
+ super(Qwen2ForCausalLM, self).__init__(config)
214
+ self.model = GOTQwenModel(config)
215
+
216
+ self.vocab_size = config.vocab_size
217
+ self.lm_head = nn.Linear(config.hidden_size, config.vocab_size, bias=False)
218
+
219
+ # Initialize weights and apply final processing
220
+ self.post_init()
221
+
222
+ def get_model(self):
223
+ return self.model
224
+
225
+ # def _set_gradient_checkpointing(self, module, value=False):
226
+ # if isinstance(module, GOTQwenModel):
227
+ # module.gradient_checkpointing = value
228
+ # @add_start_docstrings_to_model_forward(QWEN2_INPUTS_DOCSTRING)
229
+ # @replace_return_docstrings(output_type=CausalLMOutputWithPast, config_class=_CONFIG_FOR_DOC)
230
+ def forward(
231
+ self,
232
+ input_ids: torch.LongTensor = None,
233
+ attention_mask: Optional[torch.Tensor] = None,
234
+ position_ids: Optional[torch.LongTensor] = None,
235
+ past_key_values: Optional[List[torch.FloatTensor]] = None,
236
+ inputs_embeds: Optional[torch.FloatTensor] = None,
237
+ labels: Optional[torch.LongTensor] = None,
238
+ use_cache: Optional[bool] = None,
239
+ output_attentions: Optional[bool] = None,
240
+ output_hidden_states: Optional[bool] = None,
241
+ images: Optional[torch.FloatTensor] = None,
242
+ return_dict: Optional[bool] = None,
243
+
244
+ ) -> Union[Tuple, CausalLMOutputWithPast]:
245
+ output_attentions = output_attentions if output_attentions is not None else self.config.output_attentions
246
+ output_hidden_states = (
247
+ output_hidden_states if output_hidden_states is not None else self.config.output_hidden_states
248
+ )
249
+ return_dict = return_dict if return_dict is not None else self.config.use_return_dict
250
+
251
+ # decoder outputs consists of (dec_features, layer_state, dec_hidden, dec_attn)
252
+ # print(input_ids)
253
+ # print(len(images))
254
+
255
+ # print(inputs_embeds)
256
+
257
+ outputs = self.model(
258
+ input_ids=input_ids,
259
+ past_key_values=past_key_values,
260
+ attention_mask=attention_mask,
261
+ position_ids=position_ids,
262
+ inputs_embeds=inputs_embeds,
263
+ use_cache=use_cache,
264
+ output_attentions=output_attentions,
265
+ output_hidden_states=output_hidden_states,
266
+ images=images,
267
+ return_dict=return_dict
268
+
269
+ )
270
+
271
+
272
+ hidden_states = outputs[0]
273
+ logits = self.lm_head(hidden_states)
274
+ logits = logits.float()
275
+
276
+ # logits
277
+
278
+ loss = None
279
+ if labels is not None:
280
+ # Shift so that tokens < n predict n
281
+ shift_logits = logits[..., :-1, :].contiguous()
282
+ shift_labels = labels[..., 1:].contiguous()
283
+ # Flatten the tokens
284
+ loss_fct = CrossEntropyLoss()
285
+ shift_logits = shift_logits.view(-1, self.config.vocab_size)
286
+ shift_labels = shift_labels.view(-1)
287
+ # Enable model parallelism
288
+ shift_labels = shift_labels.to(shift_logits.device)
289
+ loss = loss_fct(shift_logits, shift_labels)
290
+
291
+ if not return_dict:
292
+ output = (logits,) + outputs[1:]
293
+ return (loss,) + output if loss is not None else output
294
+
295
+ return CausalLMOutputWithPast(
296
+ loss=loss,
297
+ logits=logits,
298
+ past_key_values=outputs.past_key_values,
299
+ hidden_states=outputs.hidden_states,
300
+ attentions=outputs.attentions,
301
+ )
302
+
303
+
304
+ def prepare_inputs_for_generation(
305
+ self, input_ids, past_key_values=None, attention_mask=None, inputs_embeds=None, **kwargs
306
+ ):
307
+ # Omit tokens covered by past_key_values
308
+ if past_key_values is not None:
309
+ if isinstance(past_key_values, Cache):
310
+ cache_length = past_key_values.get_seq_length()
311
+ past_length = past_key_values.seen_tokens
312
+ max_cache_length = past_key_values.get_max_length()
313
+ else:
314
+ cache_length = past_length = past_key_values[0][0].shape[2]
315
+ max_cache_length = None
316
+
317
+ # Keep only the unprocessed tokens:
318
+ # 1 - If the length of the attention_mask exceeds the length of input_ids, then we are in a setting where
319
+ # some of the inputs are exclusively passed as part of the cache (e.g. when passing input_embeds as
320
+ # input)
321
+ if attention_mask is not None and attention_mask.shape[1] > input_ids.shape[1]:
322
+ input_ids = input_ids[:, -(attention_mask.shape[1] - past_length) :]
323
+ # 2 - If the past_length is smaller than input_ids', then input_ids holds all input tokens. We can discard
324
+ # input_ids based on the past_length.
325
+ elif past_length < input_ids.shape[1]:
326
+ input_ids = input_ids[:, past_length:]
327
+ # 3 - Otherwise (past_length >= input_ids.shape[1]), let's assume input_ids only has unprocessed tokens.
328
+
329
+ # If we are about to go beyond the maximum cache length, we need to crop the input attention mask.
330
+ if (
331
+ max_cache_length is not None
332
+ and attention_mask is not None
333
+ and cache_length + input_ids.shape[1] > max_cache_length
334
+ ):
335
+ attention_mask = attention_mask[:, -max_cache_length:]
336
+
337
+ position_ids = kwargs.get("position_ids", None)
338
+ if attention_mask is not None and position_ids is None:
339
+ # create position_ids on the fly for batch generation
340
+ position_ids = attention_mask.long().cumsum(-1) - 1
341
+ position_ids.masked_fill_(attention_mask == 0, 1)
342
+ if past_key_values:
343
+ position_ids = position_ids[:, -input_ids.shape[1] :]
344
+
345
+ # if `inputs_embeds` are passed, we only want to use them in the 1st generation step
346
+ if inputs_embeds is not None and past_key_values is None:
347
+ model_inputs = {"inputs_embeds": inputs_embeds}
348
+ else:
349
+ model_inputs = {"input_ids": input_ids}
350
+
351
+ model_inputs.update(
352
+ {
353
+ "position_ids": position_ids,
354
+ "past_key_values": past_key_values,
355
+ "use_cache": kwargs.get("use_cache"),
356
+ "attention_mask": attention_mask,
357
+ "images": kwargs.get("images", None),
358
+ }
359
+ )
360
+ return model_inputs
361
+
362
+ def initialize_vision_tokenizer(
363
+ self,
364
+ tokenizer,
365
+ freeze_lm_model=False,
366
+ pretrained_stage1_model=None,
367
+ device="cuda"
368
+ ):
369
+ config = self.get_model().config
370
+
371
+ # add image patch token <image>
372
+ # tokenizer.add_tokens([DEFAULT_IMAGE_PATCH_TOKEN], special_tokens=True)
373
+ self.resize_token_embeddings(len(tokenizer))
374
+ # config.im_patch_token = tokenizer.convert_tokens_to_ids([DEFAULT_IMAGE_PATCH_TOKEN])[0]
375
+
376
+ config.im_patch_token = 151859
377
+
378
+ config.use_im_start_end = True
379
+
380
+ # add image start token <im_start> and end token <im_end>
381
+ if config.use_im_start_end:
382
+ # num_new_tokens = tokenizer.add_tokens([DEFAULT_IM_START_TOKEN, DEFAULT_IM_END_TOKEN], special_tokens=True)
383
+ self.resize_token_embeddings(len(tokenizer))
384
+ # config.im_start_token, config.im_end_token = tokenizer.convert_tokens_to_ids([DEFAULT_IM_START_TOKEN, DEFAULT_IM_END_TOKEN])
385
+
386
+ config.im_start_token, config.im_end_token = 151857, 151858
387
+
388
+
389
+ AutoConfig.register("GOT", GOTConfig)
390
+ AutoModelForCausalLM.register(GOTConfig, GOTQwenForCausalLM)
391
+
GOT-OCR-2.0-master/GOT/model/__init__.py ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+
2
+ from .GOT_ocr_2_0 import GOTQwenModel, GOTQwenForCausalLM, GOTConfig
3
+
GOT-OCR-2.0-master/GOT/model/plug/blip_process.py ADDED
@@ -0,0 +1,504 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Copyright (c) 2022, salesforce.com, inc.
3
+ All rights reserved.
4
+ SPDX-License-Identifier: BSD-3-Clause
5
+ For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/BSD-3-Clause
6
+ """
7
+
8
+ import cv2
9
+ import numpy as np
10
+
11
+ import torch
12
+
13
+ # from omegaconf import OmegaConf
14
+ from torchvision import transforms
15
+ from torchvision.transforms.functional import InterpolationMode
16
+ from PIL import Image
17
+
18
+ class BaseProcessor:
19
+ def __init__(self):
20
+ self.transform = lambda x: x
21
+ return
22
+
23
+ def __call__(self, item):
24
+ return self.transform(item)
25
+
26
+ # @classmethod
27
+ # def from_config(cls, cfg=None):
28
+ # return cls()
29
+
30
+ # def build(self, **kwargs):
31
+ # cfg = OmegaConf.create(kwargs)
32
+
33
+ # return self.from_config(cfg)
34
+
35
+ class BlipImageBaseProcessor(BaseProcessor):
36
+ def __init__(self, mean=None, std=None):
37
+ if mean is None:
38
+ mean = (0.48145466, 0.4578275, 0.40821073)
39
+ if std is None:
40
+ std = (0.26862954, 0.26130258, 0.27577711)
41
+ # mean = (0.0, 0.0, 0.0)
42
+ # std = (1.0, 1.0, 1.0)
43
+
44
+ self.normalize = transforms.Normalize(mean, std)
45
+
46
+
47
+ ## aug functions
48
+ def identity_func(img):
49
+ return img
50
+
51
+
52
+ def autocontrast_func(img, cutoff=0):
53
+ """
54
+ same output as PIL.ImageOps.autocontrast
55
+ """
56
+ n_bins = 256
57
+
58
+ def tune_channel(ch):
59
+ n = ch.size
60
+ cut = cutoff * n // 100
61
+ if cut == 0:
62
+ high, low = ch.max(), ch.min()
63
+ else:
64
+ hist = cv2.calcHist([ch], [0], None, [n_bins], [0, n_bins])
65
+ low = np.argwhere(np.cumsum(hist) > cut)
66
+ low = 0 if low.shape[0] == 0 else low[0]
67
+ high = np.argwhere(np.cumsum(hist[::-1]) > cut)
68
+ high = n_bins - 1 if high.shape[0] == 0 else n_bins - 1 - high[0]
69
+ if high <= low:
70
+ table = np.arange(n_bins)
71
+ else:
72
+ scale = (n_bins - 1) / (high - low)
73
+ offset = -low * scale
74
+ table = np.arange(n_bins) * scale + offset
75
+ table[table < 0] = 0
76
+ table[table > n_bins - 1] = n_bins - 1
77
+ table = table.clip(0, 255).astype(np.uint8)
78
+ return table[ch]
79
+
80
+ channels = [tune_channel(ch) for ch in cv2.split(img)]
81
+ out = cv2.merge(channels)
82
+ return out
83
+
84
+
85
+ def equalize_func(img):
86
+ """
87
+ same output as PIL.ImageOps.equalize
88
+ PIL's implementation is different from cv2.equalize
89
+ """
90
+ n_bins = 256
91
+
92
+ def tune_channel(ch):
93
+ hist = cv2.calcHist([ch], [0], None, [n_bins], [0, n_bins])
94
+ non_zero_hist = hist[hist != 0].reshape(-1)
95
+ step = np.sum(non_zero_hist[:-1]) // (n_bins - 1)
96
+ if step == 0:
97
+ return ch
98
+ n = np.empty_like(hist)
99
+ n[0] = step // 2
100
+ n[1:] = hist[:-1]
101
+ table = (np.cumsum(n) // step).clip(0, 255).astype(np.uint8)
102
+ return table[ch]
103
+
104
+ channels = [tune_channel(ch) for ch in cv2.split(img)]
105
+ out = cv2.merge(channels)
106
+ return out
107
+
108
+
109
+ def rotate_func(img, degree, fill=(0, 0, 0)):
110
+ """
111
+ like PIL, rotate by degree, not radians
112
+ """
113
+ H, W = img.shape[0], img.shape[1]
114
+ center = W / 2, H / 2
115
+ M = cv2.getRotationMatrix2D(center, degree, 1)
116
+ out = cv2.warpAffine(img, M, (W, H), borderValue=fill)
117
+ return out
118
+
119
+
120
+ def solarize_func(img, thresh=128):
121
+ """
122
+ same output as PIL.ImageOps.posterize
123
+ """
124
+ table = np.array([el if el < thresh else 255 - el for el in range(256)])
125
+ table = table.clip(0, 255).astype(np.uint8)
126
+ out = table[img]
127
+ return out
128
+
129
+
130
+ def color_func(img, factor):
131
+ """
132
+ same output as PIL.ImageEnhance.Color
133
+ """
134
+ ## implementation according to PIL definition, quite slow
135
+ # degenerate = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)[:, :, np.newaxis]
136
+ # out = blend(degenerate, img, factor)
137
+ # M = (
138
+ # np.eye(3) * factor
139
+ # + np.float32([0.114, 0.587, 0.299]).reshape(3, 1) * (1. - factor)
140
+ # )[np.newaxis, np.newaxis, :]
141
+ M = np.float32(
142
+ [[0.886, -0.114, -0.114], [-0.587, 0.413, -0.587], [-0.299, -0.299, 0.701]]
143
+ ) * factor + np.float32([[0.114], [0.587], [0.299]])
144
+ out = np.matmul(img, M).clip(0, 255).astype(np.uint8)
145
+ return out
146
+
147
+
148
+ def contrast_func(img, factor):
149
+ """
150
+ same output as PIL.ImageEnhance.Contrast
151
+ """
152
+ mean = np.sum(np.mean(img, axis=(0, 1)) * np.array([0.114, 0.587, 0.299]))
153
+ table = (
154
+ np.array([(el - mean) * factor + mean for el in range(256)])
155
+ .clip(0, 255)
156
+ .astype(np.uint8)
157
+ )
158
+ out = table[img]
159
+ return out
160
+
161
+
162
+ def brightness_func(img, factor):
163
+ """
164
+ same output as PIL.ImageEnhance.Contrast
165
+ """
166
+ table = (np.arange(256, dtype=np.float32) * factor).clip(0, 255).astype(np.uint8)
167
+ out = table[img]
168
+ return out
169
+
170
+
171
+ def sharpness_func(img, factor):
172
+ """
173
+ The differences the this result and PIL are all on the 4 boundaries, the center
174
+ areas are same
175
+ """
176
+ kernel = np.ones((3, 3), dtype=np.float32)
177
+ kernel[1][1] = 5
178
+ kernel /= 13
179
+ degenerate = cv2.filter2D(img, -1, kernel)
180
+ if factor == 0.0:
181
+ out = degenerate
182
+ elif factor == 1.0:
183
+ out = img
184
+ else:
185
+ out = img.astype(np.float32)
186
+ degenerate = degenerate.astype(np.float32)[1:-1, 1:-1, :]
187
+ out[1:-1, 1:-1, :] = degenerate + factor * (out[1:-1, 1:-1, :] - degenerate)
188
+ out = out.astype(np.uint8)
189
+ return out
190
+
191
+
192
+ def shear_x_func(img, factor, fill=(0, 0, 0)):
193
+ H, W = img.shape[0], img.shape[1]
194
+ M = np.float32([[1, factor, 0], [0, 1, 0]])
195
+ out = cv2.warpAffine(
196
+ img, M, (W, H), borderValue=fill, flags=cv2.INTER_LINEAR
197
+ ).astype(np.uint8)
198
+ return out
199
+
200
+
201
+ def translate_x_func(img, offset, fill=(0, 0, 0)):
202
+ """
203
+ same output as PIL.Image.transform
204
+ """
205
+ H, W = img.shape[0], img.shape[1]
206
+ M = np.float32([[1, 0, -offset], [0, 1, 0]])
207
+ out = cv2.warpAffine(
208
+ img, M, (W, H), borderValue=fill, flags=cv2.INTER_LINEAR
209
+ ).astype(np.uint8)
210
+ return out
211
+
212
+
213
+ def translate_y_func(img, offset, fill=(0, 0, 0)):
214
+ """
215
+ same output as PIL.Image.transform
216
+ """
217
+ H, W = img.shape[0], img.shape[1]
218
+ M = np.float32([[1, 0, 0], [0, 1, -offset]])
219
+ out = cv2.warpAffine(
220
+ img, M, (W, H), borderValue=fill, flags=cv2.INTER_LINEAR
221
+ ).astype(np.uint8)
222
+ return out
223
+
224
+
225
+ def posterize_func(img, bits):
226
+ """
227
+ same output as PIL.ImageOps.posterize
228
+ """
229
+ out = np.bitwise_and(img, np.uint8(255 << (8 - bits)))
230
+ return out
231
+
232
+
233
+ def shear_y_func(img, factor, fill=(0, 0, 0)):
234
+ H, W = img.shape[0], img.shape[1]
235
+ M = np.float32([[1, 0, 0], [factor, 1, 0]])
236
+ out = cv2.warpAffine(
237
+ img, M, (W, H), borderValue=fill, flags=cv2.INTER_LINEAR
238
+ ).astype(np.uint8)
239
+ return out
240
+
241
+
242
+ def cutout_func(img, pad_size, replace=(0, 0, 0)):
243
+ replace = np.array(replace, dtype=np.uint8)
244
+ H, W = img.shape[0], img.shape[1]
245
+ rh, rw = np.random.random(2)
246
+ pad_size = pad_size // 2
247
+ ch, cw = int(rh * H), int(rw * W)
248
+ x1, x2 = max(ch - pad_size, 0), min(ch + pad_size, H)
249
+ y1, y2 = max(cw - pad_size, 0), min(cw + pad_size, W)
250
+ out = img.copy()
251
+ out[x1:x2, y1:y2, :] = replace
252
+ return out
253
+
254
+
255
+ ### level to args
256
+ def enhance_level_to_args(MAX_LEVEL):
257
+ def level_to_args(level):
258
+ return ((level / MAX_LEVEL) * 1.8 + 0.1,)
259
+
260
+ return level_to_args
261
+
262
+
263
+ def shear_level_to_args(MAX_LEVEL, replace_value):
264
+ def level_to_args(level):
265
+ level = (level / MAX_LEVEL) * 0.3
266
+ if np.random.random() > 0.5:
267
+ level = -level
268
+ return (level, replace_value)
269
+
270
+ return level_to_args
271
+
272
+
273
+ def translate_level_to_args(translate_const, MAX_LEVEL, replace_value):
274
+ def level_to_args(level):
275
+ level = (level / MAX_LEVEL) * float(translate_const)
276
+ if np.random.random() > 0.5:
277
+ level = -level
278
+ return (level, replace_value)
279
+
280
+ return level_to_args
281
+
282
+
283
+ def cutout_level_to_args(cutout_const, MAX_LEVEL, replace_value):
284
+ def level_to_args(level):
285
+ level = int((level / MAX_LEVEL) * cutout_const)
286
+ return (level, replace_value)
287
+
288
+ return level_to_args
289
+
290
+
291
+ def solarize_level_to_args(MAX_LEVEL):
292
+ def level_to_args(level):
293
+ level = int((level / MAX_LEVEL) * 256)
294
+ return (level,)
295
+
296
+ return level_to_args
297
+
298
+
299
+ def none_level_to_args(level):
300
+ return ()
301
+
302
+
303
+ def posterize_level_to_args(MAX_LEVEL):
304
+ def level_to_args(level):
305
+ level = int((level / MAX_LEVEL) * 4)
306
+ return (level,)
307
+
308
+ return level_to_args
309
+
310
+
311
+ def rotate_level_to_args(MAX_LEVEL, replace_value):
312
+ def level_to_args(level):
313
+ level = (level / MAX_LEVEL) * 30
314
+ if np.random.random() < 0.5:
315
+ level = -level
316
+ return (level, replace_value)
317
+
318
+ return level_to_args
319
+
320
+
321
+ func_dict = {
322
+ "Identity": identity_func,
323
+ "AutoContrast": autocontrast_func,
324
+ "Equalize": equalize_func,
325
+ "Rotate": rotate_func,
326
+ "Solarize": solarize_func,
327
+ "Color": color_func,
328
+ "Contrast": contrast_func,
329
+ "Brightness": brightness_func,
330
+ "Sharpness": sharpness_func,
331
+ "ShearX": shear_x_func,
332
+ "TranslateX": translate_x_func,
333
+ "TranslateY": translate_y_func,
334
+ "Posterize": posterize_func,
335
+ "ShearY": shear_y_func,
336
+ }
337
+
338
+ translate_const = 10
339
+ MAX_LEVEL = 10
340
+ replace_value = (128, 128, 128)
341
+ arg_dict = {
342
+ "Identity": none_level_to_args,
343
+ "AutoContrast": none_level_to_args,
344
+ "Equalize": none_level_to_args,
345
+ "Rotate": rotate_level_to_args(MAX_LEVEL, replace_value),
346
+ "Solarize": solarize_level_to_args(MAX_LEVEL),
347
+ "Color": enhance_level_to_args(MAX_LEVEL),
348
+ "Contrast": enhance_level_to_args(MAX_LEVEL),
349
+ "Brightness": enhance_level_to_args(MAX_LEVEL),
350
+ "Sharpness": enhance_level_to_args(MAX_LEVEL),
351
+ "ShearX": shear_level_to_args(MAX_LEVEL, replace_value),
352
+ "TranslateX": translate_level_to_args(translate_const, MAX_LEVEL, replace_value),
353
+ "TranslateY": translate_level_to_args(translate_const, MAX_LEVEL, replace_value),
354
+ "Posterize": posterize_level_to_args(MAX_LEVEL),
355
+ "ShearY": shear_level_to_args(MAX_LEVEL, replace_value),
356
+ }
357
+
358
+
359
+ class RandomAugment(object):
360
+ def __init__(self, N=2, M=10, isPIL=False, augs=[]):
361
+ self.N = N
362
+ self.M = M
363
+ self.isPIL = isPIL
364
+ if augs:
365
+ self.augs = augs
366
+ else:
367
+ self.augs = list(arg_dict.keys())
368
+
369
+ def get_random_ops(self):
370
+ sampled_ops = np.random.choice(self.augs, self.N)
371
+ return [(op, 0.5, self.M) for op in sampled_ops]
372
+
373
+ def __call__(self, img):
374
+ if self.isPIL:
375
+ img = np.array(img)
376
+ ops = self.get_random_ops()
377
+ for name, prob, level in ops:
378
+ if np.random.random() > prob:
379
+ continue
380
+ args = arg_dict[name](level)
381
+ img = func_dict[name](img, *args)
382
+ return img
383
+
384
+
385
+ class VideoRandomAugment(object):
386
+ def __init__(self, N=2, M=10, p=0.0, tensor_in_tensor_out=True, augs=[]):
387
+ self.N = N
388
+ self.M = M
389
+ self.p = p
390
+ self.tensor_in_tensor_out = tensor_in_tensor_out
391
+ if augs:
392
+ self.augs = augs
393
+ else:
394
+ self.augs = list(arg_dict.keys())
395
+
396
+ def get_random_ops(self):
397
+ sampled_ops = np.random.choice(self.augs, self.N, replace=False)
398
+ return [(op, self.M) for op in sampled_ops]
399
+
400
+ def __call__(self, frames):
401
+ assert (
402
+ frames.shape[-1] == 3
403
+ ), "Expecting last dimension for 3-channels RGB (b, h, w, c)."
404
+
405
+ if self.tensor_in_tensor_out:
406
+ frames = frames.numpy().astype(np.uint8)
407
+
408
+ num_frames = frames.shape[0]
409
+
410
+ ops = num_frames * [self.get_random_ops()]
411
+ apply_or_not = num_frames * [np.random.random(size=self.N) > self.p]
412
+
413
+ frames = torch.stack(
414
+ list(map(self._aug, frames, ops, apply_or_not)), dim=0
415
+ ).float()
416
+
417
+ return frames
418
+
419
+ def _aug(self, img, ops, apply_or_not):
420
+ for i, (name, level) in enumerate(ops):
421
+ if not apply_or_not[i]:
422
+ continue
423
+ args = arg_dict[name](level)
424
+ img = func_dict[name](img, *args)
425
+ return torch.from_numpy(img)
426
+
427
+
428
+ # if __name__ == "__main__":
429
+ # a = RandomAugment()
430
+ # img = np.random.randn(32, 32, 3)
431
+ # a(img)
432
+
433
+
434
+
435
+
436
+
437
+
438
+ class BlipImageTrainProcessor(BlipImageBaseProcessor):
439
+ def __init__(
440
+ self, image_size=384, mean=None, std=None, min_scale=0.5, max_scale=1.0
441
+ ):
442
+ super().__init__(mean=mean, std=std)
443
+
444
+ self.transform = transforms.Compose(
445
+ [
446
+ transforms.RandomResizedCrop(
447
+ image_size,
448
+ scale=(min_scale, max_scale),
449
+ interpolation=InterpolationMode.BICUBIC,
450
+ ),
451
+ # transforms.RandomHorizontalFlip(),
452
+ RandomAugment(
453
+ 2,
454
+ 5,
455
+ isPIL=True,
456
+ augs=[
457
+ "Identity",
458
+ # "AutoContrast",
459
+ "Brightness",
460
+ "Sharpness",
461
+ "Equalize",
462
+ # "ShearX",
463
+ # "ShearY",
464
+ # "TranslateX",
465
+ # "TranslateY",
466
+ # "Rotate",
467
+ ],
468
+ ),
469
+ transforms.ToTensor(),
470
+ self.normalize,
471
+ ]
472
+ )
473
+
474
+ def __call__(self, item):
475
+ return self.transform(item)
476
+
477
+
478
+ class BlipImageEvalProcessor(BlipImageBaseProcessor):
479
+ def __init__(self, image_size=384, mean=None, std=None):
480
+ super().__init__(mean=mean, std=std)
481
+
482
+ self.transform = transforms.Compose(
483
+ [
484
+ transforms.Resize(
485
+ (image_size, image_size), interpolation=InterpolationMode.BICUBIC
486
+ ),
487
+ transforms.ToTensor(),
488
+ self.normalize,
489
+ ]
490
+ )
491
+
492
+ def __call__(self, item):
493
+ return self.transform(item)
494
+
495
+
496
+ # if __name__ == "__main__":
497
+ # a = BlipImageTrainProcessor(image_size=1024)
498
+ # # img = np.random.randn(1024, 1024, 3)
499
+ # # x = torch.zeros(1024, 1024, 3)
500
+ # x = Image.open("/data/codes/GOT-main/log/serve_images/2023-05-23/a2a783d89ede819cdeae943a2199ad3d.jpg").convert("RGB")
501
+ # print(x.size)
502
+ # y = a(x)
503
+
504
+ # print(y.size())
GOT-OCR-2.0-master/GOT/model/vision_encoder/__init__.py ADDED
@@ -0,0 +1 @@
 
 
1
+
GOT-OCR-2.0-master/GOT/model/vision_encoder/vary_b.py ADDED
@@ -0,0 +1,547 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (c) Meta Platforms, Inc. and affiliates.
2
+ # All rights reserved.
3
+
4
+ # This source code is licensed under the license found in the
5
+ # LICENSE file in the root directory of this source tree.
6
+
7
+ import torch
8
+ import torch.nn as nn
9
+ import torch.nn.functional as F
10
+
11
+ from typing import Optional, Tuple, Type
12
+
13
+ from functools import partial
14
+
15
+ import torch
16
+ import torch.nn as nn
17
+
18
+ from typing import Type
19
+
20
+ # from GOT.model.vision_encoder.vitg_qwen import Resampler
21
+ import math
22
+
23
+
24
+ class Projector(nn.Module):
25
+ def __init__(
26
+ self,
27
+ width: 256,
28
+ n_queries: int = 256,
29
+ output_dim: int = 4096,
30
+ **kwargs
31
+ ):
32
+ super().__init__()
33
+
34
+ norm_layer = partial(nn.LayerNorm, eps=1e-6)
35
+ self.attn_pool = Resampler(
36
+ grid_size=int(math.sqrt(n_queries)),
37
+ embed_dim=output_dim,
38
+ num_heads=output_dim // 128,
39
+ kv_dim=width,
40
+ norm_layer=norm_layer,
41
+ )
42
+ self.ln_post = norm_layer(output_dim)
43
+ self.proj = nn.Parameter((output_dim** -0.5) * torch.randn(output_dim, output_dim))
44
+
45
+ def forward(self, x: torch.Tensor):
46
+ x = self.attn_pool(x)
47
+ x = self.ln_post(x)
48
+ x = x @ self.proj
49
+
50
+ return x
51
+
52
+
53
+ class MLPBlock(nn.Module):
54
+ def __init__(
55
+ self,
56
+ embedding_dim: int,
57
+ mlp_dim: int,
58
+ act: Type[nn.Module] = nn.GELU,
59
+ ) -> None:
60
+ super().__init__()
61
+ self.lin1 = nn.Linear(embedding_dim, mlp_dim)
62
+ self.lin2 = nn.Linear(mlp_dim, embedding_dim)
63
+ self.act = act()
64
+
65
+ def forward(self, x: torch.Tensor) -> torch.Tensor:
66
+ return self.lin2(self.act(self.lin1(x)))
67
+
68
+
69
+ # From https://github.com/facebookresearch/detectron2/blob/main/detectron2/layers/batch_norm.py # noqa
70
+ # Itself from https://github.com/facebookresearch/ConvNeXt/blob/d1fa8f6fef0a165b27399986cc2bdacc92777e40/models/convnext.py#L119 # noqa
71
+ class LayerNorm2d(nn.Module):
72
+ def __init__(self, num_channels: int, eps: float = 1e-6) -> None:
73
+ super().__init__()
74
+ self.weight = nn.Parameter(torch.ones(num_channels))
75
+ self.bias = nn.Parameter(torch.zeros(num_channels))
76
+ self.eps = eps
77
+
78
+ def forward(self, x: torch.Tensor) -> torch.Tensor:
79
+ u = x.mean(1, keepdim=True)
80
+ s = (x - u).pow(2).mean(1, keepdim=True)
81
+ x = (x - u) / torch.sqrt(s + self.eps)
82
+ x = self.weight[:, None, None] * x + self.bias[:, None, None]
83
+ return x
84
+
85
+
86
+ # This class and its supporting functions below lightly adapted from the ViTDet backbone available at: https://github.com/facebookresearch/detectron2/blob/main/detectron2/modeling/backbone/vit.py # noqa
87
+ class ImageEncoderViT(nn.Module):
88
+ def __init__(
89
+ self,
90
+ img_size: int = 1024,
91
+ patch_size: int = 16,
92
+ in_chans: int = 3,
93
+ embed_dim: int = 768,
94
+ depth: int = 12,
95
+ num_heads: int = 12,
96
+ mlp_ratio: float = 4.0,
97
+ out_chans: int = 256,
98
+ qkv_bias: bool = True,
99
+ norm_layer: Type[nn.Module] = nn.LayerNorm,
100
+ act_layer: Type[nn.Module] = nn.GELU,
101
+ use_abs_pos: bool = True,
102
+ use_rel_pos: bool = False,
103
+ rel_pos_zero_init: bool = True,
104
+ window_size: int = 0,
105
+ global_attn_indexes: Tuple[int, ...] = (),
106
+ ) -> None:
107
+ """
108
+ Args:
109
+ img_size (int): Input image size.
110
+ patch_size (int): Patch size.
111
+ in_chans (int): Number of input image channels.
112
+ embed_dim (int): Patch embedding dimension.
113
+ depth (int): Depth of ViT.
114
+ num_heads (int): Number of attention heads in each ViT block.
115
+ mlp_ratio (float): Ratio of mlp hidden dim to embedding dim.
116
+ qkv_bias (bool): If True, add a learnable bias to query, key, value.
117
+ norm_layer (nn.Module): Normalization layer.
118
+ act_layer (nn.Module): Activation layer.
119
+ use_abs_pos (bool): If True, use absolute positional embeddings.
120
+ use_rel_pos (bool): If True, add relative positional embeddings to the attention map.
121
+ rel_pos_zero_init (bool): If True, zero initialize relative positional parameters.
122
+ window_size (int): Window size for window attention blocks.
123
+ global_attn_indexes (list): Indexes for blocks using global attention.
124
+ """
125
+ super().__init__()
126
+ self.img_size = img_size
127
+
128
+ self.patch_embed = PatchEmbed(
129
+ kernel_size=(patch_size, patch_size),
130
+ stride=(patch_size, patch_size),
131
+ in_chans=in_chans,
132
+ embed_dim=embed_dim,
133
+ )
134
+
135
+ self.pos_embed: Optional[nn.Parameter] = None
136
+ if use_abs_pos:
137
+ # Initialize absolute positional embedding with pretrain image size.
138
+ self.pos_embed = nn.Parameter(
139
+ torch.zeros(1, img_size // patch_size, img_size // patch_size, embed_dim)
140
+ )
141
+
142
+ self.blocks = nn.ModuleList()
143
+ for i in range(depth):
144
+ block = Block(
145
+ dim=embed_dim,
146
+ num_heads=num_heads,
147
+ mlp_ratio=mlp_ratio,
148
+ qkv_bias=qkv_bias,
149
+ norm_layer=norm_layer,
150
+ act_layer=act_layer,
151
+ use_rel_pos=use_rel_pos,
152
+ rel_pos_zero_init=rel_pos_zero_init,
153
+ window_size=window_size if i not in global_attn_indexes else 0,
154
+ input_size=(img_size // patch_size, img_size // patch_size),
155
+ )
156
+ self.blocks.append(block)
157
+
158
+ self.neck = nn.Sequential(
159
+ nn.Conv2d(
160
+ embed_dim,
161
+ out_chans,
162
+ kernel_size=1,
163
+ bias=False,
164
+ ),
165
+ LayerNorm2d(out_chans),
166
+ nn.Conv2d(
167
+ out_chans,
168
+ out_chans,
169
+ kernel_size=3,
170
+ padding=1,
171
+ bias=False,
172
+ ),
173
+ LayerNorm2d(out_chans),
174
+ )
175
+
176
+
177
+ self.net_2 = nn.Conv2d(256, 512, kernel_size=3, stride=2, padding=1, bias=False)
178
+ self.net_3 = nn.Conv2d(512, 1024, kernel_size=3, stride=2, padding=1, bias=False)
179
+
180
+ def forward(self, x: torch.Tensor) -> torch.Tensor:
181
+ x = self.patch_embed(x)
182
+ if self.pos_embed is not None:
183
+ x = x + self.pos_embed
184
+
185
+ for blk in self.blocks:
186
+ x = blk(x)
187
+
188
+ x = self.neck(x.permute(0, 3, 1, 2))
189
+ x = self.net_2(x)
190
+ x = self.net_3(x)
191
+
192
+
193
+ return x
194
+
195
+
196
+ class Block(nn.Module):
197
+ """Transformer blocks with support of window attention and residual propagation blocks"""
198
+
199
+ def __init__(
200
+ self,
201
+ dim: int,
202
+ num_heads: int,
203
+ mlp_ratio: float = 4.0,
204
+ qkv_bias: bool = True,
205
+ norm_layer: Type[nn.Module] = nn.LayerNorm,
206
+ act_layer: Type[nn.Module] = nn.GELU,
207
+ use_rel_pos: bool = False,
208
+ rel_pos_zero_init: bool = True,
209
+ window_size: int = 0,
210
+ input_size: Optional[Tuple[int, int]] = None,
211
+ ) -> None:
212
+ """
213
+ Args:
214
+ dim (int): Number of input channels.
215
+ num_heads (int): Number of attention heads in each ViT block.
216
+ mlp_ratio (float): Ratio of mlp hidden dim to embedding dim.
217
+ qkv_bias (bool): If True, add a learnable bias to query, key, value.
218
+ norm_layer (nn.Module): Normalization layer.
219
+ act_layer (nn.Module): Activation layer.
220
+ use_rel_pos (bool): If True, add relative positional embeddings to the attention map.
221
+ rel_pos_zero_init (bool): If True, zero initialize relative positional parameters.
222
+ window_size (int): Window size for window attention blocks. If it equals 0, then
223
+ use global attention.
224
+ input_size (tuple(int, int) or None): Input resolution for calculating the relative
225
+ positional parameter size.
226
+ """
227
+ super().__init__()
228
+ self.norm1 = norm_layer(dim)
229
+ self.attn = Attention(
230
+ dim,
231
+ num_heads=num_heads,
232
+ qkv_bias=qkv_bias,
233
+ use_rel_pos=use_rel_pos,
234
+ rel_pos_zero_init=rel_pos_zero_init,
235
+ input_size=input_size if window_size == 0 else (window_size, window_size),
236
+ )
237
+
238
+ self.norm2 = norm_layer(dim)
239
+ self.mlp = MLPBlock(embedding_dim=dim, mlp_dim=int(dim * mlp_ratio), act=act_layer)
240
+
241
+ self.window_size = window_size
242
+
243
+ def forward(self, x: torch.Tensor) -> torch.Tensor:
244
+ shortcut = x
245
+ x = self.norm1(x)
246
+ # Window partition
247
+ if self.window_size > 0:
248
+ H, W = x.shape[1], x.shape[2]
249
+ x, pad_hw = window_partition(x, self.window_size)
250
+
251
+ x = self.attn(x)
252
+ # Reverse window partition
253
+ if self.window_size > 0:
254
+ x = window_unpartition(x, self.window_size, pad_hw, (H, W))
255
+
256
+ x = shortcut + x
257
+ x = x + self.mlp(self.norm2(x))
258
+
259
+ return x
260
+
261
+
262
+ class Attention(nn.Module):
263
+ """Multi-head Attention block with relative position embeddings."""
264
+
265
+ def __init__(
266
+ self,
267
+ dim: int,
268
+ num_heads: int = 8,
269
+ qkv_bias: bool = True,
270
+ use_rel_pos: bool = False,
271
+ rel_pos_zero_init: bool = True,
272
+ input_size: Optional[Tuple[int, int]] = None,
273
+ ) -> None:
274
+ """
275
+ Args:
276
+ dim (int): Number of input channels.
277
+ num_heads (int): Number of attention heads.
278
+ qkv_bias (bool): If True, add a learnable bias to query, key, value.
279
+ rel_pos (bool): If True, add relative positional embeddings to the attention map.
280
+ rel_pos_zero_init (bool): If True, zero initialize relative positional parameters.
281
+ input_size (tuple(int, int) or None): Input resolution for calculating the relative
282
+ positional parameter size.
283
+ """
284
+ super().__init__()
285
+ self.num_heads = num_heads
286
+ head_dim = dim // num_heads
287
+ self.scale = head_dim**-0.5
288
+
289
+ self.qkv = nn.Linear(dim, dim * 3, bias=qkv_bias)
290
+ self.proj = nn.Linear(dim, dim)
291
+
292
+ self.use_rel_pos = use_rel_pos
293
+ if self.use_rel_pos:
294
+ assert (
295
+ input_size is not None
296
+ ), "Input size must be provided if using relative positional encoding."
297
+ # initialize relative positional embeddings
298
+ self.rel_pos_h = nn.Parameter(torch.zeros(2 * input_size[0] - 1, head_dim))
299
+ self.rel_pos_w = nn.Parameter(torch.zeros(2 * input_size[1] - 1, head_dim))
300
+
301
+ def forward(self, x: torch.Tensor) -> torch.Tensor:
302
+ B, H, W, _ = x.shape
303
+ # qkv with shape (3, B, nHead, H * W, C)
304
+ qkv = self.qkv(x).reshape(B, H * W, 3, self.num_heads, -1).permute(2, 0, 3, 1, 4)
305
+ # q, k, v with shape (B * nHead, H * W, C)
306
+ q, k, v = qkv.reshape(3, B * self.num_heads, H * W, -1).unbind(0)
307
+
308
+ attn = (q * self.scale) @ k.transpose(-2, -1)
309
+
310
+ if self.use_rel_pos:
311
+ attn = add_decomposed_rel_pos(attn, q, self.rel_pos_h, self.rel_pos_w, (H, W), (H, W))
312
+
313
+ attn = attn.softmax(dim=-1)
314
+ x = (attn @ v).view(B, self.num_heads, H, W, -1).permute(0, 2, 3, 1, 4).reshape(B, H, W, -1)
315
+ x = self.proj(x)
316
+
317
+ return x
318
+
319
+
320
+ def window_partition(x: torch.Tensor, window_size: int) -> Tuple[torch.Tensor, Tuple[int, int]]:
321
+ """
322
+ Partition into non-overlapping windows with padding if needed.
323
+ Args:
324
+ x (tensor): input tokens with [B, H, W, C].
325
+ window_size (int): window size.
326
+
327
+ Returns:
328
+ windows: windows after partition with [B * num_windows, window_size, window_size, C].
329
+ (Hp, Wp): padded height and width before partition
330
+ """
331
+ B, H, W, C = x.shape
332
+
333
+ pad_h = (window_size - H % window_size) % window_size
334
+ pad_w = (window_size - W % window_size) % window_size
335
+ if pad_h > 0 or pad_w > 0:
336
+ x = F.pad(x, (0, 0, 0, pad_w, 0, pad_h))
337
+ Hp, Wp = H + pad_h, W + pad_w
338
+
339
+ x = x.view(B, Hp // window_size, window_size, Wp // window_size, window_size, C)
340
+ windows = x.permute(0, 1, 3, 2, 4, 5).contiguous().view(-1, window_size, window_size, C)
341
+ return windows, (Hp, Wp)
342
+
343
+
344
+ def window_unpartition(
345
+ windows: torch.Tensor, window_size: int, pad_hw: Tuple[int, int], hw: Tuple[int, int]
346
+ ) -> torch.Tensor:
347
+ """
348
+ Window unpartition into original sequences and removing padding.
349
+ Args:
350
+ windows (tensor): input tokens with [B * num_windows, window_size, window_size, C].
351
+ window_size (int): window size.
352
+ pad_hw (Tuple): padded height and width (Hp, Wp).
353
+ hw (Tuple): original height and width (H, W) before padding.
354
+
355
+ Returns:
356
+ x: unpartitioned sequences with [B, H, W, C].
357
+ """
358
+ Hp, Wp = pad_hw
359
+ H, W = hw
360
+ B = windows.shape[0] // (Hp * Wp // window_size // window_size)
361
+ x = windows.view(B, Hp // window_size, Wp // window_size, window_size, window_size, -1)
362
+ x = x.permute(0, 1, 3, 2, 4, 5).contiguous().view(B, Hp, Wp, -1)
363
+
364
+ if Hp > H or Wp > W:
365
+ x = x[:, :H, :W, :].contiguous()
366
+ return x
367
+
368
+
369
+ def get_rel_pos(q_size: int, k_size: int, rel_pos: torch.Tensor) -> torch.Tensor:
370
+ """
371
+ Get relative positional embeddings according to the relative positions of
372
+ query and key sizes.
373
+ Args:
374
+ q_size (int): size of query q.
375
+ k_size (int): size of key k.
376
+ rel_pos (Tensor): relative position embeddings (L, C).
377
+
378
+ Returns:
379
+ Extracted positional embeddings according to relative positions.
380
+ """
381
+ max_rel_dist = int(2 * max(q_size, k_size) - 1)
382
+ # Interpolate rel pos if needed.
383
+ if rel_pos.shape[0] != max_rel_dist:
384
+ # Interpolate rel pos.
385
+ rel_pos_resized = F.interpolate(
386
+ rel_pos.reshape(1, rel_pos.shape[0], -1).permute(0, 2, 1),
387
+ size=max_rel_dist,
388
+ mode="linear",
389
+ )
390
+ rel_pos_resized = rel_pos_resized.reshape(-1, max_rel_dist).permute(1, 0)
391
+ else:
392
+ rel_pos_resized = rel_pos
393
+
394
+ # Scale the coords with short length if shapes for q and k are different.
395
+ q_coords = torch.arange(q_size)[:, None] * max(k_size / q_size, 1.0)
396
+ k_coords = torch.arange(k_size)[None, :] * max(q_size / k_size, 1.0)
397
+ relative_coords = (q_coords - k_coords) + (k_size - 1) * max(q_size / k_size, 1.0)
398
+
399
+ return rel_pos_resized[relative_coords.long()]
400
+
401
+
402
+ def add_decomposed_rel_pos(
403
+ attn: torch.Tensor,
404
+ q: torch.Tensor,
405
+ rel_pos_h: torch.Tensor,
406
+ rel_pos_w: torch.Tensor,
407
+ q_size: Tuple[int, int],
408
+ k_size: Tuple[int, int],
409
+ ) -> torch.Tensor:
410
+ """
411
+ Calculate decomposed Relative Positional Embeddings from :paper:`mvitv2`.
412
+ https://github.com/facebookresearch/mvit/blob/19786631e330df9f3622e5402b4a419a263a2c80/mvit/models/attention.py # noqa B950
413
+ Args:
414
+ attn (Tensor): attention map.
415
+ q (Tensor): query q in the attention layer with shape (B, q_h * q_w, C).
416
+ rel_pos_h (Tensor): relative position embeddings (Lh, C) for height axis.
417
+ rel_pos_w (Tensor): relative position embeddings (Lw, C) for width axis.
418
+ q_size (Tuple): spatial sequence size of query q with (q_h, q_w).
419
+ k_size (Tuple): spatial sequence size of key k with (k_h, k_w).
420
+
421
+ Returns:
422
+ attn (Tensor): attention map with added relative positional embeddings.
423
+ """
424
+ q_h, q_w = q_size
425
+ k_h, k_w = k_size
426
+ Rh = get_rel_pos(q_h, k_h, rel_pos_h)
427
+ Rw = get_rel_pos(q_w, k_w, rel_pos_w)
428
+
429
+ B, _, dim = q.shape
430
+ r_q = q.reshape(B, q_h, q_w, dim)
431
+ rel_h = torch.einsum("bhwc,hkc->bhwk", r_q, Rh)
432
+ rel_w = torch.einsum("bhwc,wkc->bhwk", r_q, Rw)
433
+
434
+ attn = (
435
+ attn.view(B, q_h, q_w, k_h, k_w) + rel_h[:, :, :, :, None] + rel_w[:, :, :, None, :]
436
+ ).view(B, q_h * q_w, k_h * k_w)
437
+
438
+ return attn
439
+
440
+
441
+ class PatchEmbed(nn.Module):
442
+ """
443
+ Image to Patch Embedding.
444
+ """
445
+
446
+ def __init__(
447
+ self,
448
+ kernel_size: Tuple[int, int] = (16, 16),
449
+ stride: Tuple[int, int] = (16, 16),
450
+ padding: Tuple[int, int] = (0, 0),
451
+ in_chans: int = 3,
452
+ embed_dim: int = 768,
453
+ ) -> None:
454
+ """
455
+ Args:
456
+ kernel_size (Tuple): kernel size of the projection layer.
457
+ stride (Tuple): stride of the projection layer.
458
+ padding (Tuple): padding size of the projection layer.
459
+ in_chans (int): Number of input image channels.
460
+ embed_dim (int): Patch embedding dimension.
461
+ """
462
+ super().__init__()
463
+
464
+ self.proj = nn.Conv2d(
465
+ in_chans, embed_dim, kernel_size=kernel_size, stride=stride, padding=padding
466
+ )
467
+
468
+ def forward(self, x: torch.Tensor) -> torch.Tensor:
469
+ x = self.proj(x)
470
+ # B C H W -> B H W C
471
+ x = x.permute(0, 2, 3, 1)
472
+ return x
473
+
474
+
475
+
476
+ def build_vary_vit_b(checkpoint=None):
477
+ return _build_vary(
478
+ encoder_embed_dim=768,
479
+ encoder_depth=12,
480
+ encoder_num_heads=12,
481
+ encoder_global_attn_indexes=[2, 5, 8, 11],
482
+ checkpoint=checkpoint,
483
+ )
484
+
485
+
486
+ def _build_vary(
487
+ encoder_embed_dim,
488
+ encoder_depth,
489
+ encoder_num_heads,
490
+ encoder_global_attn_indexes,
491
+ checkpoint=None,
492
+ ):
493
+ prompt_embed_dim = 256
494
+ image_size = 1024
495
+ vit_patch_size = 16
496
+ image_embedding_size = image_size // vit_patch_size
497
+ image_encoder=ImageEncoderViT(
498
+ depth=encoder_depth,
499
+ embed_dim=encoder_embed_dim,
500
+ img_size=image_size,
501
+ mlp_ratio=4,
502
+ norm_layer=partial(torch.nn.LayerNorm, eps=1e-6),
503
+ num_heads=encoder_num_heads,
504
+ patch_size=vit_patch_size,
505
+ qkv_bias=True,
506
+ use_rel_pos=True,
507
+ global_attn_indexes=encoder_global_attn_indexes,
508
+ window_size=14,
509
+ out_chans=prompt_embed_dim,
510
+ )
511
+
512
+ # if checkpoint is not None:
513
+ # # with open(checkpoint, "rb") as f:
514
+ # state_dict = torch.load(checkpoint)
515
+ # # print(state_dict.keys())
516
+ # # for key in state_dict:
517
+ # # image_encoder.load_state_dict({k[14:]: v for k, v in state_dict.items() if 'image_encoder' in k}, strict=False)
518
+ # # ocr-anyting
519
+ # # image_encoder.load_state_dict(state_dict, strict=True)
520
+ # # tob
521
+ # # model.vision_tower.
522
+ # image_encoder.load_state_dict({k[19:]: v for k, v in state_dict.items() if 'vision_tower' in k}, strict=True)
523
+ # print(checkpoint)
524
+ return image_encoder
525
+
526
+
527
+
528
+
529
+ if __name__ == '__main__':
530
+
531
+ x = torch.zeros(2, 3, 1024, 1024)
532
+
533
+ # x.permute(0, 3, 1, 2)
534
+
535
+ net = build_vary_vit_b(checkpoint ='/mnt/shared-storage/tenant/hypertext/xpkong/jycode/checkpoint/pytorch_model.bin')
536
+
537
+ # mlp = Projector(width=256, n_queries = 256, output_dim = 768)
538
+ y = net(x)
539
+ y = y.flatten(2).permute(0, 2, 1)
540
+ print(y.shape)
541
+ # y = mlp(y)
542
+
543
+ # y = net_2(y)
544
+ # y = net_3(y)
545
+ #
546
+
547
+ # print(y.shape)
GOT-OCR-2.0-master/GOT/train/train.py ADDED
@@ -0,0 +1,194 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Adopted from https://github.com/lm-sys/FastChat. Below is the original copyright:
2
+ # Adopted from tatsu-lab@stanford_alpaca. Below is the original copyright:
3
+ # Copyright 2023 Rohan Taori, Ishaan Gulrajani, Tianyi Zhang, Yann Dubois, Xuechen Li
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+ import logging
18
+ import pathlib
19
+ import torch
20
+ import transformers
21
+
22
+ # from GOT.train.trainer import GOTTrainer
23
+ # from GOT.train.trainer_vit_llrd import GOTTrainer
24
+ from GOT.train.trainer_vit_fixlr import GOTTrainer
25
+ from GOT.model import GOTLlamaForCausalLM
26
+ from GOT.model import *
27
+ from GOT.data import make_supervised_data_module
28
+ from GOT.utils.arguments import *
29
+ from GOT.utils.constants import *
30
+ from GOT.utils.utils import smart_tokenizer_and_embedding_resize
31
+ from GOT.model.vision_encoder.sam import build_sam_vit_b
32
+ from GOT.model.vision_encoder.swin_transformer import build_swin_transformer
33
+ def train():
34
+ parser = transformers.HfArgumentParser((ModelArguments, DataArguments, TrainingArguments))
35
+ model_args, data_args, training_args = parser.parse_args_into_dataclasses()
36
+
37
+ model = GOTLlamaForCausalLM.from_pretrained(
38
+ model_args.model_name_or_path,
39
+ cache_dir=training_args.cache_dir,
40
+ )
41
+
42
+ tokenizer = transformers.AutoTokenizer.from_pretrained(
43
+ '/data/hypertext/xpkong/newcode/checkpoints/kly-vary-1025-cc595-pretrain/',
44
+ cache_dir=training_args.cache_dir,
45
+ model_max_length=training_args.model_max_length,
46
+ padding_side="right",
47
+ use_fast=False,
48
+ )
49
+
50
+ # tokenizer = transformers.AutoTokenizer.from_pretrained(model_args.model_name_or_path, trust_remote_code=True, padding_side="right", model_max_length=training_args.model_max_length,)
51
+
52
+ # # model = AutoModelForCausalLM.from_pretrained("/data/public/ucaswei/cache/Qwen/qwen/", device_map="cuda", trust_remote_code=True).eval()
53
+
54
+ # model = GOTQwenForCausalLM.from_pretrained(model_args.model_name_or_path, low_cpu_mem_usage=True, device_map='cuda')
55
+
56
+
57
+ if data_args.conversation_version == "v0" or "models--decapoda-research--llama-7b-hf" in model_args.model_name_or_path:
58
+ if tokenizer.pad_token is None:
59
+ smart_tokenizer_and_embedding_resize(
60
+ special_tokens_dict=dict(pad_token=DEFAULT_PAD_TOKEN),
61
+ tokenizer=tokenizer,
62
+ model=model,
63
+ )
64
+ if "llama" in model_args.model_name_or_path:
65
+ tokenizer.add_special_tokens({
66
+ "eos_token": DEFAULT_EOS_TOKEN,
67
+ "bos_token": DEFAULT_BOS_TOKEN,
68
+ "unk_token": DEFAULT_UNK_TOKEN,
69
+ })
70
+ else:
71
+ tokenizer.pad_token = tokenizer.unk_token
72
+
73
+ # tokenizer.pad_token = DEFAULT_UNK_TOKEN
74
+ # tokenizer.pad_token = tokenizer.eos_token
75
+ # tokenizer.add_special_tokens({'pad_token':'<|endoftext|>'})
76
+
77
+ dtype = torch.float32
78
+ if training_args.fp16:
79
+ dtype = torch.float16
80
+ if training_args.bf16:
81
+ dtype = torch.bfloat16
82
+
83
+ vision_tower_dict = model.get_model().initialize_vision_modules(
84
+ vision_tower=model_args.vision_tower,
85
+ pretrained_stage1_model=model_args.pretrained_stage1_model,
86
+ freeze_vision_tower=model_args.freeze_vision_tower,
87
+ use_im_start_end=model_args.use_im_start_end,
88
+ vision_select_layer=model_args.vision_select_layer,
89
+ dtype=dtype,
90
+ device=training_args.device
91
+ )
92
+
93
+ model.initialize_vision_tokenizer(
94
+ tokenizer=tokenizer,
95
+ freeze_lm_model=model_args.freeze_lm_model,
96
+ pretrained_stage1_model=model_args.pretrained_stage1_model,
97
+ device=training_args.device,
98
+ )
99
+ model.get_model().vision_tower = transformers.CLIPVisionModel.from_pretrained(
100
+ '/data/public/ucaswei/pretrain/vit-large-patch14')
101
+ model.get_model().vision_tower_high = build_sam_vit_b(checkpoint='/data/hypertext/xpkong/newcode/checkpoints/kly-sam-opt-all-1023-new/pytorch_model.bin')
102
+ # model.get_model().mm_projector = create_perciever()
103
+
104
+ model.to(dtype=dtype, device=training_args.device)
105
+ # 'image_processor_high
106
+ # data_args.image_token_len = vision_tower_dict['image_token_len']
107
+ data_args.image_token_len = 256
108
+ data_args.image_processor = vision_tower_dict['image_processor']
109
+ data_args.image_processor_high = vision_tower_dict['image_processor_high']
110
+ data_args.use_im_start_end = model_args.use_im_start_end
111
+
112
+ # mixed relation, to be fixed
113
+ if model_args.freeze_lm_model:
114
+ model.requires_grad_(False)
115
+ for p in model.get_model().mm_projector.parameters():
116
+ p.requires_grad = True
117
+ # for p in model.get_model().vision_encoder.parameters():
118
+ # p.requires_grad = True
119
+ # for p in model.get_model().chatt.parameters():
120
+ # p.requires_grad = True
121
+ for p in model.get_input_embeddings().parameters():
122
+ p.requires_grad = True
123
+ # conv_final
124
+ # for p in model.get_model().conv_final.parameters():
125
+ # p.requires_grad = True
126
+
127
+
128
+ if not model_args.freeze_vision_tower:
129
+
130
+ model.get_model().vision_tower.requires_grad_(True)
131
+ # for i in range(20):
132
+ # model.get_model().vision_tower.vision_model.encoder.layers[i].requires_grad_(False)
133
+ # model.get_model().vision_tower.vision_model.encoder.layers[-1].requires_grad_(False)
134
+ # model.get_model().vision_tower.vision_model.embeddings.requires_grad_(False)
135
+ # model.get_model().vision_tower.vision_model.pre_layrnorm.requires_grad_(False)
136
+ # model.get_model().vision_tower.vision_model.post_layernorm.requires_grad_(False)
137
+
138
+ # for p in model.get_model().vision_encoder.parameters():
139
+ # p.requires_grad = True
140
+
141
+ # for n, p in model.named_parameters():
142
+ # print(n, p.requires_grad)
143
+
144
+ if model_args.freeze_vision_tower:
145
+ model.get_model().vision_tower.requires_grad_(False)
146
+
147
+ params_grad = [p.numel() for n, p in model.named_parameters() if p.requires_grad]
148
+ print(f"Number of Mapping Trainable Parameters: {sum(params_grad) / (1 << 20):.2f} M")
149
+
150
+ # params_no_grad = [n for n, p in model.named_parameters() if not p.requires_grad]
151
+ # if len(params_no_grad) > 0:
152
+ # if training_args.fsdp is not None and len(training_args.fsdp) > 0:
153
+ # if len(params_no_grad) < 10:
154
+ # print('[WARNING] Attempting to use FSDP while {} parameters do not require gradients: {}'. format(len(params_no_grad), params_no_grad))
155
+ # else:
156
+ # print('[WARNING] Attempting to use FSDP while {} parameters do not require gradients: {}...(omitted)'. format(len(params_no_grad), ', '.join(params_no_grad[:10])))
157
+ # print("[WARNING] Attempting to use FSDP with partially frozen paramters, this is experimental.")
158
+ # print("[WARNING] As of 4/30/23, this feature requires PyTorch-nightly build. See here for details: https://github.com/haotian-liu/LLaVA#experimental-use-fsdp-to-save-memory-in-pretraining")
159
+
160
+ # from torch.distributed.fsdp.fully_sharded_data_parallel import FullyShardedDataParallel as FSDP
161
+ # def patch_FSDP_use_orig_params(func):
162
+ # def wrap_func(*args, **kwargs):
163
+ # use_orig_params = kwargs.pop('use_orig_params', True)
164
+ # return func(*args, **kwargs, use_orig_params=use_orig_params)
165
+ # return wrap_func
166
+
167
+ # FSDP.__init__ = patch_FSDP_use_orig_params(FSDP.__init__)
168
+
169
+
170
+ data_module = make_supervised_data_module(
171
+ interleave=training_args.interleave,
172
+ with_box=training_args.with_box,
173
+ tokenizer=tokenizer,
174
+ data_args=data_args
175
+ )
176
+
177
+ trainer = GOTTrainer(
178
+ model=model,
179
+ tokenizer=tokenizer,
180
+ args=training_args,
181
+ **data_module)
182
+
183
+ if list(pathlib.Path(training_args.output_dir).glob("checkpoint-*")):
184
+ trainer.train(resume_from_checkpoint=True)
185
+ else:
186
+ trainer.train()
187
+ trainer.save_state()
188
+ trainer._safe_save(output_dir=training_args.output_dir)
189
+
190
+
191
+ if __name__ == "__main__":
192
+ train()
193
+
194
+
GOT-OCR-2.0-master/GOT/train/train_GOT.py ADDED
@@ -0,0 +1,147 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Adopted from https://github.com/lm-sys/FastChat. Below is the original copyright:
2
+ # Adopted from tatsu-lab@stanford_alpaca. Below is the original copyright:
3
+ # Copyright 2023 Rohan Taori, Ishaan Gulrajani, Tianyi Zhang, Yann Dubois, Xuechen Li
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+ import logging
18
+ import pathlib
19
+ import torch
20
+ # torch.set_num_threads(1)
21
+ import transformers
22
+
23
+ # from GOT.train.trainer import GOTTrainer
24
+ # from GOT.train.trainer_vit_llrd import GOTTrainer
25
+ from GOT.train.trainer_vit_fixlr import GOTTrainer
26
+ from GOT.model import *
27
+ from GOT.data import make_supervised_data_module
28
+ from GOT.utils.arguments import *
29
+ from GOT.utils.constants import *
30
+ from GOT.utils.utils import smart_tokenizer_and_embedding_resize
31
+ from GOT.model.vision_encoder.vary_b import build_vary_vit_b
32
+ import os
33
+
34
+ # os.environ['NCCL_IB_DISABLE'] = '1'
35
+ os.environ['NCCL_DEBUG'] = 'INFO'
36
+ os.environ['OSS_ENDPOINT'] = "http://oss.i.shaipower.com"
37
+
38
+ def train():
39
+ parser = transformers.HfArgumentParser((ModelArguments, DataArguments, TrainingArguments))
40
+ model_args, data_args, training_args = parser.parse_args_into_dataclasses()
41
+
42
+
43
+ tokenizer = transformers.AutoTokenizer.from_pretrained(model_args.model_name_or_path, trust_remote_code=True, padding_side="right", model_max_length=training_args.model_max_length,)
44
+
45
+
46
+ model = GOTQwenForCausalLM.from_pretrained(model_args.model_name_or_path, use_safetensors=True)
47
+
48
+
49
+
50
+ smart_tokenizer_and_embedding_resize(
51
+ special_tokens_dict=dict(pad_token='<|endoftext|>'),
52
+ tokenizer=tokenizer,
53
+ model=model,
54
+ )
55
+
56
+
57
+ dtype = torch.float32
58
+ if training_args.fp16:
59
+ dtype = torch.float16
60
+ if training_args.bf16:
61
+ dtype = torch.bfloat16
62
+
63
+ vision_tower_dict = model.get_model().initialize_vision_modules(
64
+ vision_tower=model_args.vision_tower,
65
+ pretrained_stage1_model=model_args.pretrained_stage1_model,
66
+ freeze_vision_tower=model_args.freeze_vision_tower,
67
+ use_im_start_end=model_args.use_im_start_end,
68
+ vision_select_layer=model_args.vision_select_layer,
69
+ dtype=dtype,
70
+ device=training_args.device
71
+ )
72
+
73
+ model.initialize_vision_tokenizer(
74
+ tokenizer=tokenizer,
75
+ freeze_lm_model=model_args.freeze_lm_model,
76
+ pretrained_stage1_model=model_args.pretrained_stage1_model,
77
+ device=training_args.device,
78
+ )
79
+
80
+
81
+ model.to(dtype=dtype, device=training_args.device)
82
+ # 'image_processor_high
83
+ # data_args.image_token_len = vision_tower_dict['image_token_len']
84
+ data_args.image_token_len = 256
85
+ data_args.image_processor = vision_tower_dict['image_processor']
86
+ data_args.image_processor_high = vision_tower_dict['image_processor_high']
87
+ data_args.use_im_start_end = model_args.use_im_start_end
88
+
89
+ # mixed relation, to be fixed
90
+ if model_args.freeze_lm_model:
91
+ model.requires_grad_(False)
92
+ for p in model.get_model().mm_projector.parameters():
93
+ p.requires_grad = True
94
+ for p in model.get_model().mm_projector_vary.parameters():
95
+ p.requires_grad = True
96
+ for p in model.get_input_embeddings().parameters():
97
+ p.requires_grad = True
98
+
99
+
100
+
101
+ params_grad = [p.numel() for n, p in model.named_parameters() if p.requires_grad]
102
+ print(f"Number of Mapping Trainable Parameters: {sum(params_grad) / (1 << 20):.2f} M")
103
+
104
+ # params_no_grad = [n for n, p in model.named_parameters() if not p.requires_grad]
105
+ # if len(params_no_grad) > 0:
106
+ # if training_args.fsdp is not None and len(training_args.fsdp) > 0:
107
+ # if len(params_no_grad) < 10:
108
+ # print('[WARNING] Attempting to use FSDP while {} parameters do not require gradients: {}'. format(len(params_no_grad), params_no_grad))
109
+ # else:
110
+ # print('[WARNING] Attempting to use FSDP while {} parameters do not require gradients: {}...(omitted)'. format(len(params_no_grad), ', '.join(params_no_grad[:10])))
111
+ # print("[WARNING] Attempting to use FSDP with partially frozen paramters, this is experimental.")
112
+ # print("[WARNING] As of 4/30/23, this feature requires PyTorch-nightly build. See here for details: https://github.com/haotian-liu/LLaVA#experimental-use-fsdp-to-save-memory-in-pretraining")
113
+
114
+ # from torch.distributed.fsdp.fully_sharded_data_parallel import FullyShardedDataParallel as FSDP
115
+ # def patch_FSDP_use_orig_params(func):
116
+ # def wrap_func(*args, **kwargs):
117
+ # use_orig_params = kwargs.pop('use_orig_params', True)
118
+ # return func(*args, **kwargs, use_orig_params=use_orig_params)
119
+ # return wrap_func
120
+
121
+ # FSDP.__init__ = patch_FSDP_use_orig_params(FSDP.__init__)
122
+
123
+
124
+
125
+ data_module = make_supervised_data_module(
126
+ interleave=training_args.interleave,
127
+ with_box=training_args.with_box,
128
+ tokenizer=tokenizer,
129
+ data_args=data_args
130
+ )
131
+
132
+ trainer = GOTTrainer(
133
+ model=model,
134
+ tokenizer=tokenizer,
135
+ args=training_args,
136
+ **data_module)
137
+
138
+ if list(pathlib.Path(training_args.output_dir).glob("checkpoint-*")):
139
+ trainer.train(resume_from_checkpoint=True)
140
+ else:
141
+ trainer.train()
142
+ trainer.save_state()
143
+ trainer._safe_save(output_dir=training_args.output_dir)
144
+
145
+
146
+ if __name__ == "__main__":
147
+ train()
GOT-OCR-2.0-master/GOT/train/train_flash_attn.py ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Adopted from https://github.com/lm-sys/FastChat. Below is the original copyright:
2
+ # Adopted from tatsu-lab@stanford_alpaca. Below is the original copyright:
3
+ # Make it more memory efficient by monkey patching the LLaMA model with FlashAttn.
4
+
5
+ # Need to call this before importing transformers.
6
+ from GOT.utils.llama_flash_attn_monkey_patch import replace_llama_attn_with_flash_attn
7
+
8
+ replace_llama_attn_with_flash_attn()
9
+
10
+ from GOT.train.train import train
11
+
12
+ if __name__ == "__main__":
13
+ train()
GOT-OCR-2.0-master/GOT/train/train_lora.py ADDED
@@ -0,0 +1,216 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Adopted from https://github.com/lm-sys/FastChat. Below is the original copyright:
2
+ # Adopted from tatsu-lab@stanford_alpaca. Below is the original copyright:
3
+ # Copyright 2023 Rohan Taori, Ishaan Gulrajani, Tianyi Zhang, Yann Dubois, Xuechen Li
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+ import logging
18
+ import pathlib
19
+ import torch
20
+ import transformers
21
+
22
+ # from GOT.train.trainer import GOTTrainer
23
+ # from GOT.train.trainer_vit_llrd import GOTTrainer
24
+ from GOT.train.trainer_vit_fixlr import GOTTrainer
25
+ from GOT.model import GOTLlamaForCausalLM
26
+ from GOT.data import make_supervised_data_module
27
+ from GOT.utils.arguments import *
28
+ from GOT.utils.constants import *
29
+ from GOT.utils.utils import *
30
+
31
+
32
+ # def find_all_linear_names(model):
33
+ # cls = torch.nn.Linear
34
+ # lora_module_names = set()
35
+ # for name, module in model.named_modules():
36
+ # if isinstance(module, cls):
37
+ # names = name.split('.')
38
+ # lora_module_names.add(names[0] if len(names) == 1 else names[-1])
39
+
40
+
41
+ # if 'lm_head' in lora_module_names: # needed for 16-bit
42
+ # lora_module_names.remove('lm_head')
43
+ # return list(lora_module_names)
44
+
45
+ def train():
46
+ parser = transformers.HfArgumentParser((ModelArguments, DataArguments, TrainingArguments))
47
+ model_args, data_args, training_args = parser.parse_args_into_dataclasses()
48
+
49
+ # model = GOTLlamaForCausalLM.from_pretrained(
50
+ # model_args.model_name_or_path,
51
+ # cache_dir=training_args.cache_dir,
52
+ # )
53
+
54
+ # tokenizer = transformers.AutoTokenizer.from_pretrained(
55
+ # model_args.model_name_or_path,
56
+ # cache_dir=training_args.cache_dir,
57
+ # model_max_length=training_args.model_max_length,
58
+ # padding_side="right",
59
+ # use_fast=False,
60
+ # )
61
+
62
+ tokenizer = transformers.AutoTokenizer.from_pretrained("/data/public/ucaswei/cache/Qwen/qwen-chat/", trust_remote_code=True, padding_side="right", model_max_length=training_args.model_max_length,)
63
+
64
+ # # model = AutoModelForCausalLM.from_pretrained("/data/public/ucaswei/cache/Qwen/qwen/", device_map="cuda", trust_remote_code=True).eval()
65
+
66
+ model = GOTQwenForCausalLM.from_pretrained(model_args.model_name_or_path, low_cpu_mem_usage=True, device_map='cuda')
67
+
68
+ smart_tokenizer_and_embedding_resize(
69
+ special_tokens_dict=dict(pad_token=DEFAULT_PAD_TOKEN),
70
+ tokenizer=tokenizer,
71
+ model=model,
72
+ )
73
+
74
+ # if data_args.conversation_version == "v0" or "models--decapoda-research--llama-7b-hf" in model_args.model_name_or_path:
75
+ # if tokenizer.pad_token is None:
76
+ # smart_tokenizer_and_embedding_resize(
77
+ # special_tokens_dict=dict(pad_token=DEFAULT_PAD_TOKEN),
78
+ # tokenizer=tokenizer,
79
+ # model=model,
80
+ # )
81
+ # if "llama" in model_args.model_name_or_path:
82
+ # tokenizer.add_special_tokens({
83
+ # "eos_token": DEFAULT_EOS_TOKEN,
84
+ # "bos_token": DEFAULT_BOS_TOKEN,
85
+ # "unk_token": DEFAULT_UNK_TOKEN,
86
+ # })
87
+ # else:
88
+ # tokenizer.pad_token = tokenizer.unk_token
89
+
90
+ dtype = torch.float32
91
+ if training_args.fp16:
92
+ dtype = torch.float16
93
+ if training_args.bf16:
94
+ dtype = torch.bfloat16
95
+
96
+ if training_args.lora_enable:
97
+ from peft import LoraConfig, get_peft_model
98
+ lora_config = LoraConfig(
99
+ r=training_args.lora_r,
100
+ lora_alpha=training_args.lora_alpha,
101
+ target_modules=find_all_linear_names(model),
102
+ lora_dropout=training_args.lora_dropout,
103
+ bias=training_args.lora_bias,
104
+ task_type="CAUSAL_LM",
105
+ )
106
+ logging.warning("Adding LoRA adapters...")
107
+ model = get_peft_model(model, lora_config)
108
+
109
+ vision_tower_dict = model.get_model().initialize_vision_modules(
110
+ vision_tower=model_args.vision_tower,
111
+ pretrained_stage1_model=model_args.pretrained_stage1_model,
112
+ freeze_vision_tower=model_args.freeze_vision_tower,
113
+ use_im_start_end=model_args.use_im_start_end,
114
+ vision_select_layer=model_args.vision_select_layer,
115
+ dtype=dtype,
116
+ device=training_args.device
117
+ )
118
+
119
+ model.initialize_vision_tokenizer(
120
+ tokenizer=tokenizer,
121
+ freeze_lm_model=model_args.freeze_lm_model,
122
+ pretrained_stage1_model=model_args.pretrained_stage1_model,
123
+ device=training_args.device,
124
+ )
125
+
126
+ model.get_model().vision_tower = create_clip_vit_g(448)
127
+ model.get_model().mm_projector = create_perciever()
128
+ model.to(dtype=dtype, device=training_args.device)
129
+
130
+ data_args.image_token_len = vision_tower_dict['image_token_len']
131
+ data_args.image_processor = vision_tower_dict['image_processor']
132
+ data_args.image_processor_high = vision_tower_dict['image_processor_high']
133
+ data_args.use_im_start_end = model_args.use_im_start_end
134
+
135
+ # mixed relation, to be fixed
136
+ if model_args.freeze_lm_model:
137
+ model.requires_grad_(False)
138
+ for p in model.get_model().mm_projector.parameters():
139
+ p.requires_grad = True
140
+ for p in model.get_input_embeddings().parameters():
141
+ p.requires_grad = True
142
+ for p in model.get_model().conv_final.parameters():
143
+ p.requires_grad = True
144
+ for p in model.get_model().vision_encoder.parameters():
145
+ p.requires_grad = True
146
+
147
+ if not model_args.freeze_vision_tower:
148
+ model.get_model().vision_tower.requires_grad_(True)
149
+ # for i in range(20):
150
+ # model.get_model().vision_tower.vision_model.encoder.layers[i].requires_grad_(False)
151
+ model.get_model().vision_tower.vision_model.encoder.layers[-1].requires_grad_(False)
152
+ # model.get_model().vision_tower.vision_model.embeddings.requires_grad_(False)
153
+ # model.get_model().vision_tower.vision_model.pre_layrnorm.requires_grad_(False)
154
+ model.get_model().vision_tower.vision_model.post_layernorm.requires_grad_(False)
155
+
156
+ for n, p in model.named_parameters():
157
+ print(n, p.requires_grad)
158
+
159
+ params_grad = [p.numel() for n, p in model.named_parameters() if p.requires_grad]
160
+ print(f"Number of Mapping Trainable Parameters: {sum(params_grad) / (1 << 20):.2f} M")
161
+
162
+ # params_no_grad = [n for n, p in model.named_parameters() if not p.requires_grad]
163
+ # if len(params_no_grad) > 0:
164
+ # if training_args.fsdp is not None and len(training_args.fsdp) > 0:
165
+ # if len(params_no_grad) < 10:
166
+ # print('[WARNING] Attempting to use FSDP while {} parameters do not require gradients: {}'. format(len(params_no_grad), params_no_grad))
167
+ # else:
168
+ # print('[WARNING] Attempting to use FSDP while {} parameters do not require gradients: {}...(omitted)'. format(len(params_no_grad), ', '.join(params_no_grad[:10])))
169
+ # print("[WARNING] Attempting to use FSDP with partially frozen paramters, this is experimental.")
170
+ # print("[WARNING] As of 4/30/23, this feature requires PyTorch-nightly build. See here for details: https://github.com/haotian-liu/LLaVA#experimental-use-fsdp-to-save-memory-in-pretraining")
171
+
172
+ # from torch.distributed.fsdp.fully_sharded_data_parallel import FullyShardedDataParallel as FSDP
173
+ # def patch_FSDP_use_orig_params(func):
174
+ # def wrap_func(*args, **kwargs):
175
+ # use_orig_params = kwargs.pop('use_orig_params', True)
176
+ # return func(*args, **kwargs, use_orig_params=use_orig_params)
177
+ # return wrap_func
178
+
179
+ # FSDP.__init__ = patch_FSDP_use_orig_params(FSDP.__init__)
180
+
181
+ data_module = make_supervised_data_module(
182
+ interleave=training_args.interleave,
183
+ with_box=training_args.with_box,
184
+ tokenizer=tokenizer,
185
+ data_args=data_args
186
+ )
187
+
188
+ trainer = GOTTrainer(
189
+ model=model,
190
+ tokenizer=tokenizer,
191
+ args=training_args,
192
+ **data_module)
193
+
194
+ if list(pathlib.Path(training_args.output_dir).glob("checkpoint-*")):
195
+ trainer.train(resume_from_checkpoint=True)
196
+ else:
197
+ trainer.train()
198
+ trainer.save_state()
199
+
200
+ if training_args.lora_enable:
201
+ state_dict = get_peft_state_maybe_zero_3(
202
+ model.named_parameters(), training_args.lora_bias
203
+ )
204
+ non_lora_state_dict = get_peft_state_non_lora_maybe_zero_3(
205
+ model.named_parameters()
206
+ )
207
+ if training_args.local_rank == 0 or training_args.local_rank == -1:
208
+ model.config.save_pretrained(training_args.output_dir)
209
+ model.save_pretrained(training_args.output_dir, state_dict=state_dict)
210
+ torch.save(non_lora_state_dict, os.path.join(training_args.output_dir, 'non_lora_trainables.bin'))
211
+ else:
212
+ trainer._safe_save(output_dir=training_args.output_dir)
213
+
214
+
215
+ if __name__ == "__main__":
216
+ train()
GOT-OCR-2.0-master/GOT/train/train_lora_flash_attn.py ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Adopted from https://github.com/lm-sys/FastChat. Below is the original copyright:
2
+ # Adopted from tatsu-lab@stanford_alpaca. Below is the original copyright:
3
+ # Make it more memory efficient by monkey patching the LLaMA model with FlashAttn.
4
+
5
+ # Need to call this before importing transformers.
6
+ from GOT.utils.llama_flash_attn_monkey_patch import replace_llama_attn_with_flash_attn
7
+
8
+ replace_llama_attn_with_flash_attn()
9
+
10
+ # from GOT.train.train import train
11
+ from GOT.train.train_lora import train
12
+
13
+ if __name__ == "__main__":
14
+ train()
GOT-OCR-2.0-master/GOT/train/trainer.py ADDED
@@ -0,0 +1,66 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import torch
3
+ import torch.nn as nn
4
+
5
+ from transformers import Trainer
6
+ from typing import Dict, Optional, Sequence
7
+
8
+
9
+ def unwrap_model(model: nn.Module) -> nn.Module:
10
+ """
11
+ Recursively unwraps a model from potential containers (as used in distributed training).
12
+
13
+ Args:
14
+ model (`torch.nn.Module`): The model to unwrap.
15
+ """
16
+ # since there could be multiple levels of wrapping, unwrap recursively
17
+ if hasattr(model, "module"):
18
+ return unwrap_model(model.module)
19
+ else:
20
+ return model
21
+
22
+
23
+ class GOTTrainer(Trainer):
24
+
25
+ def _safe_save(self, output_dir: str):
26
+ """Collects the state dict and dump to disk."""
27
+ if self.deepspeed:
28
+ torch.cuda.synchronize()
29
+ self.save_model(output_dir)
30
+ return
31
+
32
+ state_dict = self.model.state_dict()
33
+ if self.args.should_save:
34
+ cpu_state_dict = {
35
+ key: value.cpu()
36
+ for key, value in state_dict.items()
37
+ }
38
+ del state_dict
39
+ self._save(output_dir, state_dict=cpu_state_dict) # noqa
40
+
41
+
42
+ def _save(self, output_dir: Optional[str] = None, state_dict=None):
43
+ if getattr(self.args, 'tune_mm_mlp_adapter', False):
44
+ # Save the model
45
+ _state_dict = state_dict
46
+ if _state_dict is None:
47
+ # Only save the model itself if we are using distributed training
48
+ model_to_save = unwrap_model(self.model)
49
+ _state_dict = model_to_save.state_dict()
50
+
51
+ weight_to_save = {}
52
+ keys_to_match = ['mm_projector', 'embed_tokens', 'embed_in']
53
+ for k, v in _state_dict.items():
54
+ if any(key_match in k for key_match in keys_to_match):
55
+ weight_to_save[k] = v
56
+
57
+ current_folder = output_dir.split('/')[-1]
58
+ parent_folder = os.path.dirname(output_dir)
59
+ if current_folder.startswith('checkpoint-'):
60
+ mm_projector_folder = os.path.join(parent_folder, "mm_projector")
61
+ os.makedirs(mm_projector_folder, exist_ok=True)
62
+ torch.save(weight_to_save, os.path.join(mm_projector_folder, f'{current_folder}.bin'))
63
+ else:
64
+ torch.save(weight_to_save, os.path.join(output_dir, f'mm_projector.bin'))
65
+
66
+ super(GOTTrainer, self)._save(output_dir, state_dict)
GOT-OCR-2.0-master/GOT/train/trainer_llm_llrd.py ADDED
@@ -0,0 +1,392 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import torch
3
+ import torch.nn as nn
4
+ import time
5
+ import functools
6
+ import re
7
+
8
+ from transformers import Trainer
9
+ from transformers.trainer_pt_utils import (
10
+ get_module_class_from_name,
11
+ get_parameter_names,
12
+ )
13
+ from transformers.pytorch_utils import ALL_LAYERNORM_LAYERS
14
+ from transformers.utils import (
15
+ is_sagemaker_dp_enabled,
16
+ is_sagemaker_mp_enabled,
17
+ is_torch_neuroncore_available,
18
+ )
19
+ from transformers.trainer_utils import (
20
+ FSDPOption,
21
+ ShardedDDPOption,
22
+ )
23
+ from transformers.training_args import ParallelMode
24
+ from transformers.modeling_utils import PreTrainedModel, unwrap_model
25
+ from typing import Dict, Optional, Sequence
26
+
27
+
28
+ def lr_scale_func(key):
29
+ if "embed_tokens.weight" in key:
30
+ return 0
31
+ if "mm_projector" in key:
32
+ return 0.01
33
+ # return 1
34
+ elif "vision_tower" in key:
35
+ return 0.01
36
+ # return 1
37
+ elif "norm.weight" in key or "lm_head.weight" in key:
38
+ return 1
39
+ else:
40
+ in_pp_layer = int(re.findall(f"layers\.(\d+)\.", key)[0])
41
+ decay = 0.86 ** (32 - in_pp_layer - 1)
42
+ return decay
43
+
44
+
45
+ def get_param_groups(model, no_weight_decay_cond, scale_lr_cond):
46
+ """creates param groups based on weight decay condition (regularized vs non regularized)
47
+ and learning rate scale condition (args.lr vs lr_mult * args.lr)
48
+ scale_lr_cond is used during finetuning where head of the network requires a scaled
49
+ version of the base learning rate.
50
+ """
51
+ wd_no_scale_lr = []
52
+ wd_scale_lr = {}
53
+ no_wd_no_scale_lr = []
54
+ no_wd_scale_lr = {}
55
+ for name, param in model.named_parameters():
56
+ if not param.requires_grad:
57
+ continue
58
+
59
+ if no_weight_decay_cond is not None:
60
+ no_wd = no_weight_decay_cond(name, param)
61
+ else:
62
+ # do not regularize biases nor Norm parameters
63
+ no_wd = name.endswith(".bias") or len(param.shape) == 1
64
+
65
+ if scale_lr_cond is not None:
66
+ lr_mult = scale_lr_cond(name)
67
+ print(name, lr_mult)
68
+ scale_lr = lr_mult != 1
69
+ else:
70
+ scale_lr = False
71
+
72
+ if not no_wd and not scale_lr:
73
+ wd_no_scale_lr.append(param)
74
+ elif not no_wd and scale_lr:
75
+ if lr_mult not in wd_scale_lr:
76
+ wd_scale_lr[lr_mult] = [param]
77
+ else:
78
+ wd_scale_lr[lr_mult].append(param)
79
+ elif no_wd and not scale_lr:
80
+ no_wd_no_scale_lr.append(param)
81
+ else:
82
+ if lr_mult not in no_wd_scale_lr:
83
+ no_wd_scale_lr[lr_mult] = [param]
84
+ else:
85
+ no_wd_scale_lr[lr_mult].append(param)
86
+
87
+ param_groups = []
88
+ if len(wd_no_scale_lr):
89
+ param_groups.append({"params": wd_no_scale_lr, "wd_mult": 1.0, "lr_mult": 1.0})
90
+ if len(wd_scale_lr):
91
+ for lr_mult, params in wd_scale_lr.items():
92
+ param_groups.append({"params": params, "wd_mult": 1.0, "lr_mult": lr_mult})
93
+ if len(no_wd_no_scale_lr):
94
+ param_groups.append(
95
+ {"params": no_wd_no_scale_lr, "wd_mult": 0.0, "lr_mult": 1.0}
96
+ )
97
+ if len(no_wd_scale_lr):
98
+ for lr_mult, params in no_wd_scale_lr.items():
99
+ param_groups.append({"params": params, "wd_mult": 0.0, "lr_mult": lr_mult})
100
+
101
+ return param_groups
102
+
103
+
104
+ def unwrap_model(model: nn.Module) -> nn.Module:
105
+ """
106
+ Recursively unwraps a model from potential containers (as used in distributed training).
107
+
108
+ Args:
109
+ model (`torch.nn.Module`): The model to unwrap.
110
+ """
111
+ # since there could be multiple levels of wrapping, unwrap recursively
112
+ if hasattr(model, "module"):
113
+ return unwrap_model(model.module)
114
+ else:
115
+ return model
116
+
117
+
118
+ class GOTTrainer(Trainer):
119
+
120
+ def _safe_save(self, output_dir: str):
121
+ """Collects the state dict and dump to disk."""
122
+ state_dict = self.model.state_dict()
123
+ if self.args.should_save:
124
+ cpu_state_dict = {
125
+ key: value.cpu()
126
+ for key, value in state_dict.items()
127
+ }
128
+ del state_dict
129
+ self._save(output_dir, state_dict=cpu_state_dict) # noqa
130
+
131
+
132
+ def _save(self, output_dir: Optional[str] = None, state_dict=None):
133
+ if getattr(self.args, 'tune_mm_mlp_adapter', False):
134
+ # Save the model
135
+ _state_dict = state_dict
136
+ if _state_dict is None:
137
+ # Only save the model itself if we are using distributed training
138
+ model_to_save = unwrap_model(self.model)
139
+ _state_dict = model_to_save.state_dict()
140
+
141
+ weight_to_save = {}
142
+ keys_to_match = ['mm_projector', 'embed_tokens', 'embed_in']
143
+ for k, v in _state_dict.items():
144
+ if any(key_match in k for key_match in keys_to_match):
145
+ weight_to_save[k] = v
146
+
147
+ current_folder = output_dir.split('/')[-1]
148
+ parent_folder = os.path.dirname(output_dir)
149
+ if current_folder.startswith('checkpoint-'):
150
+ mm_projector_folder = os.path.join(parent_folder, "mm_projector")
151
+ os.makedirs(mm_projector_folder, exist_ok=True)
152
+ torch.save(weight_to_save, os.path.join(mm_projector_folder, f'{current_folder}.bin'))
153
+ else:
154
+ torch.save(weight_to_save, os.path.join(output_dir, f'mm_projector.bin'))
155
+
156
+ super(GOTTrainer, self)._save(output_dir, state_dict)
157
+
158
+ def create_optimizer(self):
159
+ """
160
+ Setup the optimizer.
161
+
162
+ We provide a reasonable default that works well. If you want to use something else, you can pass a tuple in the
163
+ Trainer's init through `optimizers`, or subclass and override this method in a subclass.
164
+ """
165
+ opt_model = self.model
166
+
167
+ if self.optimizer is None:
168
+ # decay_parameters = get_parameter_names(opt_model, ALL_LAYERNORM_LAYERS)
169
+ # decay_parameters = [name for name in decay_parameters if "bias" not in name]
170
+ # optimizer_grouped_parameters = [
171
+ # {
172
+ # "params": [
173
+ # p for n, p in opt_model.named_parameters() if (n in decay_parameters and p.requires_grad)
174
+ # ],
175
+ # "weight_decay": self.args.weight_decay,
176
+ # },
177
+ # {
178
+ # "params": [
179
+ # p for n, p in opt_model.named_parameters() if (n not in decay_parameters and p.requires_grad)
180
+ # ],
181
+ # "weight_decay": 0.0,
182
+ # },
183
+ # ]
184
+
185
+ optimizer_grouped_parameters = get_param_groups(opt_model, None, lr_scale_func)
186
+
187
+ optimizer_cls, optimizer_kwargs = Trainer.get_optimizer_cls_and_kwargs(self.args)
188
+ self.optimizer = optimizer_cls(optimizer_grouped_parameters, **optimizer_kwargs)
189
+
190
+ return self.optimizer
191
+
192
+
193
+ def _wrap_model(self, model, training=True, dataloader=None):
194
+ if self.args.use_ipex:
195
+ dtype = torch.bfloat16 if self.use_cpu_amp else torch.float32
196
+ model = self.ipex_optimize_model(model, training, dtype=dtype)
197
+
198
+ if is_sagemaker_mp_enabled():
199
+ import smdistributed.modelparallel.torch as smp
200
+ # Wrapping the base model twice in a DistributedModel will raise an error.
201
+ if isinstance(self.model_wrapped, smp.model.DistributedModel):
202
+ return self.model_wrapped
203
+ return smp.DistributedModel(model, backward_passes_per_step=self.args.gradient_accumulation_steps)
204
+ # already initialized its own DDP and AMP
205
+ if self.deepspeed:
206
+ return self.deepspeed
207
+
208
+ # train/eval could be run multiple-times - if already wrapped, don't re-wrap it again
209
+ if unwrap_model(model) is not model:
210
+ return model
211
+
212
+ # Mixed precision training with apex (torch < 1.6)
213
+ if self.use_apex and training:
214
+ from apex import amp
215
+ model, self.optimizer = amp.initialize(model, self.optimizer, opt_level=self.args.fp16_opt_level)
216
+
217
+ # Multi-gpu training (should be after apex fp16 initialization)
218
+ if self.args.n_gpu > 1:
219
+ model = nn.DataParallel(model)
220
+
221
+ if self.args.jit_mode_eval:
222
+ start_time = time.time()
223
+ model = self.torch_jit_model_eval(model, dataloader, training)
224
+ self.jit_compilation_time = round(time.time() - start_time, 4)
225
+
226
+ # Note: in torch.distributed mode, there's no point in wrapping the model
227
+ # inside a DistributedDataParallel as we'll be under `no_grad` anyways.
228
+ if not training:
229
+ return model
230
+
231
+ # Distributed training (should be after apex fp16 initialization)
232
+ if self.sharded_ddp is not None:
233
+ from fairscale.nn.data_parallel import FullyShardedDataParallel as FullyShardedDDP
234
+ from fairscale.nn.data_parallel import ShardedDataParallel as ShardedDDP
235
+ from fairscale.nn.wrap import auto_wrap
236
+ # Sharded DDP!
237
+ if self.sharded_ddp == ShardedDDPOption.SIMPLE:
238
+ model = ShardedDDP(model, self.optimizer)
239
+ else:
240
+ mixed_precision = self.args.fp16 or self.args.bf16
241
+ cpu_offload = ShardedDDPOption.OFFLOAD in self.args.sharded_ddp
242
+ zero_3 = self.sharded_ddp == ShardedDDPOption.ZERO_DP_3
243
+ # XXX: Breaking the self.model convention but I see no way around it for now.
244
+ if ShardedDDPOption.AUTO_WRAP in self.args.sharded_ddp:
245
+ model = auto_wrap(model)
246
+ self.model = model = FullyShardedDDP(
247
+ model,
248
+ mixed_precision=mixed_precision,
249
+ reshard_after_forward=zero_3,
250
+ cpu_offload=cpu_offload,
251
+ ).to(self.args.device)
252
+ # Distributed training using PyTorch FSDP
253
+ elif self.fsdp is not None:
254
+ if not self.args.fsdp_config["xla"]:
255
+ # PyTorch FSDP!
256
+ from torch.distributed.fsdp.fully_sharded_data_parallel import CPUOffload, MixedPrecision
257
+ from torch.distributed.fsdp.fully_sharded_data_parallel import FullyShardedDataParallel as FSDP
258
+ from torch.distributed.fsdp.wrap import size_based_auto_wrap_policy, transformer_auto_wrap_policy
259
+
260
+ if FSDPOption.OFFLOAD in self.args.fsdp:
261
+ cpu_offload = CPUOffload(offload_params=True)
262
+ else:
263
+ cpu_offload = CPUOffload(offload_params=False)
264
+
265
+ auto_wrap_policy = None
266
+
267
+ if FSDPOption.AUTO_WRAP in self.args.fsdp:
268
+ if self.args.fsdp_config["fsdp_min_num_params"] > 0:
269
+ auto_wrap_policy = functools.partial(
270
+ size_based_auto_wrap_policy, min_num_params=self.args.fsdp_config["fsdp_min_num_params"]
271
+ )
272
+ elif self.args.fsdp_config.get("fsdp_transformer_layer_cls_to_wrap", None) is not None:
273
+ transformer_cls_to_wrap = set()
274
+ for layer_class in self.args.fsdp_config["fsdp_transformer_layer_cls_to_wrap"]:
275
+ transformer_cls = get_module_class_from_name(model, layer_class)
276
+ if transformer_cls is None:
277
+ raise Exception("Could not find the transformer layer class to wrap in the model.")
278
+ else:
279
+ transformer_cls_to_wrap.add(transformer_cls)
280
+ auto_wrap_policy = functools.partial(
281
+ transformer_auto_wrap_policy,
282
+ # Transformer layer class to wrap
283
+ transformer_layer_cls=transformer_cls_to_wrap,
284
+ )
285
+ mixed_precision_policy = None
286
+ dtype = None
287
+ if self.args.fp16:
288
+ dtype = torch.float16
289
+ elif self.args.bf16:
290
+ dtype = torch.bfloat16
291
+ if dtype is not None:
292
+ mixed_precision_policy = MixedPrecision(param_dtype=dtype, reduce_dtype=dtype, buffer_dtype=dtype)
293
+ if type(model) != FSDP:
294
+ # XXX: Breaking the self.model convention but I see no way around it for now.
295
+ self.model = model = FSDP(
296
+ model,
297
+ sharding_strategy=self.fsdp,
298
+ cpu_offload=cpu_offload,
299
+ auto_wrap_policy=auto_wrap_policy,
300
+ mixed_precision=mixed_precision_policy,
301
+ device_id=self.args.device,
302
+ backward_prefetch=self.backward_prefetch,
303
+ forward_prefetch=self.forword_prefetch,
304
+ limit_all_gathers=self.limit_all_gathers,
305
+ use_orig_params=True,
306
+ )
307
+ else:
308
+ try:
309
+ from torch_xla.distributed.fsdp import XlaFullyShardedDataParallel as FSDP
310
+ from torch_xla.distributed.fsdp import checkpoint_module
311
+ from torch_xla.distributed.fsdp.wrap import (
312
+ size_based_auto_wrap_policy,
313
+ transformer_auto_wrap_policy,
314
+ )
315
+ except ImportError:
316
+ raise ImportError("Missing XLA FSDP related module; please make sure to use torch-xla >= 2.0.")
317
+ auto_wrap_policy = None
318
+ auto_wrapper_callable = None
319
+ if self.args.fsdp_config["fsdp_min_num_params"] > 0:
320
+ auto_wrap_policy = functools.partial(
321
+ size_based_auto_wrap_policy, min_num_params=self.args.fsdp_config["fsdp_min_num_params"]
322
+ )
323
+ elif self.args.fsdp_config.get("fsdp_transformer_layer_cls_to_wrap", None) is not None:
324
+ transformer_cls_to_wrap = set()
325
+ for layer_class in self.args.fsdp_config["fsdp_transformer_layer_cls_to_wrap"]:
326
+ transformer_cls = get_module_class_from_name(model, layer_class)
327
+ if transformer_cls is None:
328
+ raise Exception("Could not find the transformer layer class to wrap in the model.")
329
+ else:
330
+ transformer_cls_to_wrap.add(transformer_cls)
331
+ auto_wrap_policy = functools.partial(
332
+ transformer_auto_wrap_policy,
333
+ # Transformer layer class to wrap
334
+ transformer_layer_cls=transformer_cls_to_wrap,
335
+ )
336
+ fsdp_kwargs = self.args.xla_fsdp_config
337
+ if self.args.fsdp_config["xla_fsdp_grad_ckpt"]:
338
+ # Apply gradient checkpointing to auto-wrapped sub-modules if specified
339
+ def auto_wrapper_callable(m, *args, **kwargs):
340
+ return FSDP(checkpoint_module(m), *args, **kwargs)
341
+
342
+ # Wrap the base model with an outer FSDP wrapper
343
+ self.model = model = FSDP(
344
+ model,
345
+ auto_wrap_policy=auto_wrap_policy,
346
+ auto_wrapper_callable=auto_wrapper_callable,
347
+ **fsdp_kwargs,
348
+ )
349
+
350
+ import torch_xla.core.xla_model as xm
351
+ # Patch `xm.optimizer_step` should not reduce gradients in this case,
352
+ # as FSDP does not need gradient reduction over sharded parameters.
353
+ def patched_optimizer_step(optimizer, barrier=False, optimizer_args={}):
354
+ loss = optimizer.step(**optimizer_args)
355
+ if barrier:
356
+ xm.mark_step()
357
+ return loss
358
+
359
+ xm.optimizer_step = patched_optimizer_step
360
+ elif is_sagemaker_dp_enabled():
361
+ model = nn.parallel.DistributedDataParallel(
362
+ model, device_ids=[int(os.getenv("SMDATAPARALLEL_LOCAL_RANK"))]
363
+ )
364
+ elif self.args.local_rank != -1:
365
+ kwargs = {}
366
+ if self.args.ddp_find_unused_parameters is not None:
367
+ kwargs["find_unused_parameters"] = self.args.ddp_find_unused_parameters
368
+ elif isinstance(model, PreTrainedModel):
369
+ # find_unused_parameters breaks checkpointing as per
370
+ # https://github.com/huggingface/transformers/pull/4659#issuecomment-643356021
371
+ kwargs["find_unused_parameters"] = not model.is_gradient_checkpointing
372
+ else:
373
+ kwargs["find_unused_parameters"] = True
374
+
375
+ if self.args.ddp_bucket_cap_mb is not None:
376
+ kwargs["bucket_cap_mb"] = self.args.ddp_bucket_cap_mb
377
+ if is_torch_neuroncore_available():
378
+ return model
379
+ model = nn.parallel.DistributedDataParallel(
380
+ model,
381
+ device_ids=[self.args.local_rank] if self.args._n_gpu != 0 else None,
382
+ output_device=self.args.local_rank if self.args._n_gpu != 0 else None,
383
+ **kwargs,
384
+ )
385
+
386
+ # torch.compile() needs to be called after wrapping the model with FSDP or DDP
387
+ # to ensure that it accounts for the graph breaks required by those wrappers
388
+ if self.args.torch_compile:
389
+ model = torch.compile(model, backend=self.args.torch_compile_backend, mode=self.args.torch_compile_mode)
390
+
391
+ return model
392
+
GOT-OCR-2.0-master/GOT/train/trainer_vit_fixlr.py ADDED
@@ -0,0 +1,110 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import torch
3
+ import torch.nn as nn
4
+
5
+ from transformers import Trainer
6
+ from transformers.trainer_pt_utils import get_parameter_names
7
+ from transformers.pytorch_utils import ALL_LAYERNORM_LAYERS
8
+ from typing import Dict, Optional, Sequence
9
+
10
+
11
+ def unwrap_model(model: nn.Module) -> nn.Module:
12
+ """
13
+ Recursively unwraps a model from potential containers (as used in distributed training).
14
+
15
+ Args:
16
+ model (`torch.nn.Module`): The model to unwrap.
17
+ """
18
+ # since there could be multiple levels of wrapping, unwrap recursively
19
+ if hasattr(model, "module"):
20
+ return unwrap_model(model.module)
21
+ else:
22
+ return model
23
+
24
+
25
+ class GOTTrainer(Trainer):
26
+
27
+ def _safe_save(self, output_dir: str):
28
+ """Collects the state dict and dump to disk."""
29
+ state_dict = self.model.state_dict()
30
+ if self.args.should_save:
31
+ cpu_state_dict = {
32
+ key: value.cpu()
33
+ for key, value in state_dict.items()
34
+ }
35
+ del state_dict
36
+ self._save(output_dir, state_dict=cpu_state_dict) # noqa
37
+
38
+
39
+ def _save(self, output_dir: Optional[str] = None, state_dict=None):
40
+ if getattr(self.args, 'tune_mm_mlp_adapter', False):
41
+ # Save the model
42
+ _state_dict = state_dict
43
+ if _state_dict is None:
44
+ # Only save the model itself if we are using distributed training
45
+ model_to_save = unwrap_model(self.model)
46
+ _state_dict = model_to_save.state_dict()
47
+
48
+ weight_to_save = {}
49
+ keys_to_match = ['mm_projector', 'embed_tokens', 'embed_in']
50
+ for k, v in _state_dict.items():
51
+ if any(key_match in k for key_match in keys_to_match):
52
+ weight_to_save[k] = v
53
+
54
+ current_folder = output_dir.split('/')[-1]
55
+ parent_folder = os.path.dirname(output_dir)
56
+ if current_folder.startswith('checkpoint-'):
57
+ mm_projector_folder = os.path.join(parent_folder, "mm_projector")
58
+ os.makedirs(mm_projector_folder, exist_ok=True)
59
+ torch.save(weight_to_save, os.path.join(mm_projector_folder, f'{current_folder}.bin'))
60
+ else:
61
+ torch.save(weight_to_save, os.path.join(output_dir, f'mm_projector.bin'))
62
+
63
+ super(GOTTrainer, self)._save(output_dir, state_dict)
64
+
65
+ def create_optimizer(self):
66
+ """
67
+ Setup the optimizer.
68
+
69
+ We provide a reasonable default that works well. If you want to use something else, you can pass a tuple in the
70
+ Trainer's init through `optimizers`, or subclass and override this method in a subclass.
71
+ """
72
+ opt_model = self.model
73
+
74
+ if self.optimizer is None:
75
+ decay_parameters = get_parameter_names(opt_model, ALL_LAYERNORM_LAYERS)
76
+ decay_parameters = [name for name in decay_parameters if "bias" not in name]
77
+ optimizer_grouped_parameters = [
78
+ {
79
+ "params": [
80
+ p for n, p in opt_model.named_parameters() if 'vision_encoder' in n and n in decay_parameters and p.requires_grad
81
+ ],
82
+ "weight_decay": self.args.weight_decay,
83
+ "lr": self.args.learning_rate,
84
+ },
85
+ {
86
+ "params": [
87
+ p for n, p in opt_model.named_parameters() if 'vision_encoder' in n and n not in decay_parameters and p.requires_grad],
88
+ "weight_decay": 0.0,
89
+ "lr": self.args.learning_rate,
90
+ },
91
+ {
92
+ "params": [
93
+ p for n, p in opt_model.named_parameters() if 'vision_encoder' not in n and n in decay_parameters and p.requires_grad],
94
+ "weight_decay": self.args.weight_decay,
95
+ "lr": self.args.learning_rate,
96
+ },
97
+ {
98
+ "params": [
99
+ p for n, p in opt_model.named_parameters() if 'vision_encoder' not in n and n not in decay_parameters and p.requires_grad
100
+ ],
101
+ "weight_decay": 0.0,
102
+ "lr": self.args.learning_rate,
103
+ },
104
+ ]
105
+ for idx, group in enumerate(optimizer_grouped_parameters):
106
+ print(idx, len(group['params']), group['lr'])
107
+ optimizer_cls, optimizer_kwargs = Trainer.get_optimizer_cls_and_kwargs(self.args)
108
+ self.optimizer = optimizer_cls(optimizer_grouped_parameters, **optimizer_kwargs)
109
+
110
+ return self.optimizer
GOT-OCR-2.0-master/GOT/train/trainer_vit_llrd.py ADDED
@@ -0,0 +1,389 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import torch
3
+ import torch.nn as nn
4
+ import time
5
+ import functools
6
+ import re
7
+
8
+ from transformers import Trainer
9
+ from transformers.trainer_pt_utils import (
10
+ get_module_class_from_name,
11
+ get_parameter_names,
12
+ )
13
+ from transformers.pytorch_utils import ALL_LAYERNORM_LAYERS
14
+ from transformers.utils import (
15
+ is_sagemaker_dp_enabled,
16
+ is_sagemaker_mp_enabled,
17
+ is_torch_neuroncore_available,
18
+ )
19
+ from transformers.trainer_utils import (
20
+ FSDPOption,
21
+ ShardedDDPOption,
22
+ )
23
+ from transformers.training_args import ParallelMode
24
+ from transformers.modeling_utils import PreTrainedModel, unwrap_model
25
+ from typing import Dict, Optional, Sequence
26
+
27
+
28
+ def lr_scale_func(key):
29
+ if "vision_model.encoder.layers" in key:
30
+ in_pp_layer = int(re.findall(f"layers\.(\d+)\.", key)[0])
31
+ # decay = 0.81 ** (23 - in_pp_layer - 1)
32
+ decay = 0.81 ** (23 - in_pp_layer - 1) * 0.01
33
+ # decay = 0.66 ** (23 - in_pp_layer - 1)
34
+ return decay
35
+ # return 0.01
36
+ elif "vision_model" in key:
37
+ # return 0.01
38
+ return 0.0001
39
+ return 1
40
+
41
+
42
+ def get_param_groups(model, no_weight_decay_cond, scale_lr_cond, lr, wd):
43
+ """creates param groups based on weight decay condition (regularized vs non regularized)
44
+ and learning rate scale condition (args.lr vs lr_mult * args.lr)
45
+ scale_lr_cond is used during finetuning where head of the network requires a scaled
46
+ version of the base learning rate.
47
+ """
48
+ wd_no_scale_lr = []
49
+ wd_scale_lr = {}
50
+ no_wd_no_scale_lr = []
51
+ no_wd_scale_lr = {}
52
+ for name, param in model.named_parameters():
53
+ if not param.requires_grad:
54
+ continue
55
+
56
+ if no_weight_decay_cond is not None:
57
+ no_wd = no_weight_decay_cond(name, param)
58
+ else:
59
+ # do not regularize biases nor Norm parameters
60
+ no_wd = name.endswith(".bias") or len(param.shape) == 1
61
+
62
+ if scale_lr_cond is not None:
63
+ lr_mult = scale_lr_cond(name)
64
+ print(name, lr_mult)
65
+ scale_lr = lr_mult != 1
66
+ else:
67
+ scale_lr = False
68
+
69
+ if not no_wd and not scale_lr:
70
+ wd_no_scale_lr.append(param)
71
+ elif not no_wd and scale_lr:
72
+ if lr_mult not in wd_scale_lr:
73
+ wd_scale_lr[lr_mult] = [param]
74
+ else:
75
+ wd_scale_lr[lr_mult].append(param)
76
+ elif no_wd and not scale_lr:
77
+ no_wd_no_scale_lr.append(param)
78
+ else:
79
+ if lr_mult not in no_wd_scale_lr:
80
+ no_wd_scale_lr[lr_mult] = [param]
81
+ else:
82
+ no_wd_scale_lr[lr_mult].append(param)
83
+
84
+ param_groups = []
85
+ if len(wd_no_scale_lr):
86
+ param_groups.append({"params": wd_no_scale_lr, "weight_decay": wd, "lr": lr})
87
+ if len(wd_scale_lr):
88
+ for lr_mult, params in wd_scale_lr.items():
89
+ param_groups.append({"params": params, "weight_decay": wd, "lr": lr * lr_mult})
90
+ if len(no_wd_no_scale_lr):
91
+ param_groups.append(
92
+ {"params": no_wd_no_scale_lr, "weight_decay": 0.0, "lr": lr}
93
+ )
94
+ if len(no_wd_scale_lr):
95
+ for lr_mult, params in no_wd_scale_lr.items():
96
+ param_groups.append({"params": params, "weight_decay": 0.0, "lr": lr * lr_mult})
97
+
98
+ return param_groups
99
+
100
+
101
+ def unwrap_model(model: nn.Module) -> nn.Module:
102
+ """
103
+ Recursively unwraps a model from potential containers (as used in distributed training).
104
+
105
+ Args:
106
+ model (`torch.nn.Module`): The model to unwrap.
107
+ """
108
+ # since there could be multiple levels of wrapping, unwrap recursively
109
+ if hasattr(model, "module"):
110
+ return unwrap_model(model.module)
111
+ else:
112
+ return model
113
+
114
+
115
+ class GOTTrainer(Trainer):
116
+
117
+ def _safe_save(self, output_dir: str):
118
+ """Collects the state dict and dump to disk."""
119
+ state_dict = self.model.state_dict()
120
+ if self.args.should_save:
121
+ cpu_state_dict = {
122
+ key: value.cpu()
123
+ for key, value in state_dict.items()
124
+ }
125
+ del state_dict
126
+ self._save(output_dir, state_dict=cpu_state_dict) # noqa
127
+
128
+
129
+ def _save(self, output_dir: Optional[str] = None, state_dict=None):
130
+ if getattr(self.args, 'tune_mm_mlp_adapter', False):
131
+ # Save the model
132
+ _state_dict = state_dict
133
+ if _state_dict is None:
134
+ # Only save the model itself if we are using distributed training
135
+ model_to_save = unwrap_model(self.model)
136
+ _state_dict = model_to_save.state_dict()
137
+
138
+ weight_to_save = {}
139
+ keys_to_match = ['mm_projector', 'embed_tokens', 'embed_in']
140
+ for k, v in _state_dict.items():
141
+ if any(key_match in k for key_match in keys_to_match):
142
+ weight_to_save[k] = v
143
+
144
+ current_folder = output_dir.split('/')[-1]
145
+ parent_folder = os.path.dirname(output_dir)
146
+ if current_folder.startswith('checkpoint-'):
147
+ mm_projector_folder = os.path.join(parent_folder, "mm_projector")
148
+ os.makedirs(mm_projector_folder, exist_ok=True)
149
+ torch.save(weight_to_save, os.path.join(mm_projector_folder, f'{current_folder}.bin'))
150
+ else:
151
+ torch.save(weight_to_save, os.path.join(output_dir, f'mm_projector.bin'))
152
+
153
+ super(GOTTrainer, self)._save(output_dir, state_dict)
154
+
155
+ def create_optimizer(self):
156
+ """
157
+ Setup the optimizer.
158
+
159
+ We provide a reasonable default that works well. If you want to use something else, you can pass a tuple in the
160
+ Trainer's init through `optimizers`, or subclass and override this method in a subclass.
161
+ """
162
+ opt_model = self.model
163
+
164
+ if self.optimizer is None:
165
+ # decay_parameters = get_parameter_names(opt_model, ALL_LAYERNORM_LAYERS)
166
+ # decay_parameters = [name for name in decay_parameters if "bias" not in name]
167
+ # optimizer_grouped_parameters = [
168
+ # {
169
+ # "params": [
170
+ # p for n, p in opt_model.named_parameters() if (n in decay_parameters and p.requires_grad)
171
+ # ],
172
+ # "weight_decay": self.args.weight_decay,
173
+ # },
174
+ # {
175
+ # "params": [
176
+ # p for n, p in opt_model.named_parameters() if (n not in decay_parameters and p.requires_grad)
177
+ # ],
178
+ # "weight_decay": 0.0,
179
+ # },
180
+ # ]
181
+
182
+ optimizer_grouped_parameters = get_param_groups(opt_model, None, lr_scale_func, self.args.learning_rate, self.args.weight_decay)
183
+
184
+ optimizer_cls, optimizer_kwargs = Trainer.get_optimizer_cls_and_kwargs(self.args)
185
+ self.optimizer = optimizer_cls(optimizer_grouped_parameters, **optimizer_kwargs)
186
+
187
+ return self.optimizer
188
+
189
+
190
+ def _wrap_model(self, model, training=True, dataloader=None):
191
+ if self.args.use_ipex:
192
+ dtype = torch.bfloat16 if self.use_cpu_amp else torch.float32
193
+ model = self.ipex_optimize_model(model, training, dtype=dtype)
194
+
195
+ if is_sagemaker_mp_enabled():
196
+ import smdistributed.modelparallel.torch as smp
197
+ # Wrapping the base model twice in a DistributedModel will raise an error.
198
+ if isinstance(self.model_wrapped, smp.model.DistributedModel):
199
+ return self.model_wrapped
200
+ return smp.DistributedModel(model, backward_passes_per_step=self.args.gradient_accumulation_steps)
201
+ # already initialized its own DDP and AMP
202
+ if self.deepspeed:
203
+ return self.deepspeed
204
+
205
+ # train/eval could be run multiple-times - if already wrapped, don't re-wrap it again
206
+ if unwrap_model(model) is not model:
207
+ return model
208
+
209
+ # Mixed precision training with apex (torch < 1.6)
210
+ if self.use_apex and training:
211
+ from apex import amp
212
+ model, self.optimizer = amp.initialize(model, self.optimizer, opt_level=self.args.fp16_opt_level)
213
+
214
+ # Multi-gpu training (should be after apex fp16 initialization)
215
+ if self.args.n_gpu > 1:
216
+ model = nn.DataParallel(model)
217
+
218
+ if self.args.jit_mode_eval:
219
+ start_time = time.time()
220
+ model = self.torch_jit_model_eval(model, dataloader, training)
221
+ self.jit_compilation_time = round(time.time() - start_time, 4)
222
+
223
+ # Note: in torch.distributed mode, there's no point in wrapping the model
224
+ # inside a DistributedDataParallel as we'll be under `no_grad` anyways.
225
+ if not training:
226
+ return model
227
+
228
+ # Distributed training (should be after apex fp16 initialization)
229
+ if self.sharded_ddp is not None:
230
+ from fairscale.nn.data_parallel import FullyShardedDataParallel as FullyShardedDDP
231
+ from fairscale.nn.data_parallel import ShardedDataParallel as ShardedDDP
232
+ from fairscale.nn.wrap import auto_wrap
233
+ # Sharded DDP!
234
+ if self.sharded_ddp == ShardedDDPOption.SIMPLE:
235
+ model = ShardedDDP(model, self.optimizer)
236
+ else:
237
+ mixed_precision = self.args.fp16 or self.args.bf16
238
+ cpu_offload = ShardedDDPOption.OFFLOAD in self.args.sharded_ddp
239
+ zero_3 = self.sharded_ddp == ShardedDDPOption.ZERO_DP_3
240
+ # XXX: Breaking the self.model convention but I see no way around it for now.
241
+ if ShardedDDPOption.AUTO_WRAP in self.args.sharded_ddp:
242
+ model = auto_wrap(model)
243
+ self.model = model = FullyShardedDDP(
244
+ model,
245
+ mixed_precision=mixed_precision,
246
+ reshard_after_forward=zero_3,
247
+ cpu_offload=cpu_offload,
248
+ ).to(self.args.device)
249
+ # Distributed training using PyTorch FSDP
250
+ elif self.fsdp is not None:
251
+ if not self.args.fsdp_config["xla"]:
252
+ # PyTorch FSDP!
253
+ from torch.distributed.fsdp.fully_sharded_data_parallel import CPUOffload, MixedPrecision
254
+ from torch.distributed.fsdp.fully_sharded_data_parallel import FullyShardedDataParallel as FSDP
255
+ from torch.distributed.fsdp.wrap import size_based_auto_wrap_policy, transformer_auto_wrap_policy
256
+
257
+ if FSDPOption.OFFLOAD in self.args.fsdp:
258
+ cpu_offload = CPUOffload(offload_params=True)
259
+ else:
260
+ cpu_offload = CPUOffload(offload_params=False)
261
+
262
+ auto_wrap_policy = None
263
+
264
+ if FSDPOption.AUTO_WRAP in self.args.fsdp:
265
+ if self.args.fsdp_config["fsdp_min_num_params"] > 0:
266
+ auto_wrap_policy = functools.partial(
267
+ size_based_auto_wrap_policy, min_num_params=self.args.fsdp_config["fsdp_min_num_params"]
268
+ )
269
+ elif self.args.fsdp_config.get("fsdp_transformer_layer_cls_to_wrap", None) is not None:
270
+ transformer_cls_to_wrap = set()
271
+ for layer_class in self.args.fsdp_config["fsdp_transformer_layer_cls_to_wrap"]:
272
+ transformer_cls = get_module_class_from_name(model, layer_class)
273
+ if transformer_cls is None:
274
+ raise Exception("Could not find the transformer layer class to wrap in the model.")
275
+ else:
276
+ transformer_cls_to_wrap.add(transformer_cls)
277
+ auto_wrap_policy = functools.partial(
278
+ transformer_auto_wrap_policy,
279
+ # Transformer layer class to wrap
280
+ transformer_layer_cls=transformer_cls_to_wrap,
281
+ )
282
+ mixed_precision_policy = None
283
+ dtype = None
284
+ if self.args.fp16:
285
+ dtype = torch.float16
286
+ elif self.args.bf16:
287
+ dtype = torch.bfloat16
288
+ if dtype is not None:
289
+ mixed_precision_policy = MixedPrecision(param_dtype=dtype, reduce_dtype=dtype, buffer_dtype=dtype)
290
+ if type(model) != FSDP:
291
+ # XXX: Breaking the self.model convention but I see no way around it for now.
292
+ self.model = model = FSDP(
293
+ model,
294
+ sharding_strategy=self.fsdp,
295
+ cpu_offload=cpu_offload,
296
+ auto_wrap_policy=auto_wrap_policy,
297
+ mixed_precision=mixed_precision_policy,
298
+ device_id=self.args.device,
299
+ backward_prefetch=self.backward_prefetch,
300
+ forward_prefetch=self.forword_prefetch,
301
+ limit_all_gathers=self.limit_all_gathers,
302
+ use_orig_params=True,
303
+ )
304
+ else:
305
+ try:
306
+ from torch_xla.distributed.fsdp import XlaFullyShardedDataParallel as FSDP
307
+ from torch_xla.distributed.fsdp import checkpoint_module
308
+ from torch_xla.distributed.fsdp.wrap import (
309
+ size_based_auto_wrap_policy,
310
+ transformer_auto_wrap_policy,
311
+ )
312
+ except ImportError:
313
+ raise ImportError("Missing XLA FSDP related module; please make sure to use torch-xla >= 2.0.")
314
+ auto_wrap_policy = None
315
+ auto_wrapper_callable = None
316
+ if self.args.fsdp_config["fsdp_min_num_params"] > 0:
317
+ auto_wrap_policy = functools.partial(
318
+ size_based_auto_wrap_policy, min_num_params=self.args.fsdp_config["fsdp_min_num_params"]
319
+ )
320
+ elif self.args.fsdp_config.get("fsdp_transformer_layer_cls_to_wrap", None) is not None:
321
+ transformer_cls_to_wrap = set()
322
+ for layer_class in self.args.fsdp_config["fsdp_transformer_layer_cls_to_wrap"]:
323
+ transformer_cls = get_module_class_from_name(model, layer_class)
324
+ if transformer_cls is None:
325
+ raise Exception("Could not find the transformer layer class to wrap in the model.")
326
+ else:
327
+ transformer_cls_to_wrap.add(transformer_cls)
328
+ auto_wrap_policy = functools.partial(
329
+ transformer_auto_wrap_policy,
330
+ # Transformer layer class to wrap
331
+ transformer_layer_cls=transformer_cls_to_wrap,
332
+ )
333
+ fsdp_kwargs = self.args.xla_fsdp_config
334
+ if self.args.fsdp_config["xla_fsdp_grad_ckpt"]:
335
+ # Apply gradient checkpointing to auto-wrapped sub-modules if specified
336
+ def auto_wrapper_callable(m, *args, **kwargs):
337
+ return FSDP(checkpoint_module(m), *args, **kwargs)
338
+
339
+ # Wrap the base model with an outer FSDP wrapper
340
+ self.model = model = FSDP(
341
+ model,
342
+ auto_wrap_policy=auto_wrap_policy,
343
+ auto_wrapper_callable=auto_wrapper_callable,
344
+ **fsdp_kwargs,
345
+ )
346
+
347
+ import torch_xla.core.xla_model as xm
348
+ # Patch `xm.optimizer_step` should not reduce gradients in this case,
349
+ # as FSDP does not need gradient reduction over sharded parameters.
350
+ def patched_optimizer_step(optimizer, barrier=False, optimizer_args={}):
351
+ loss = optimizer.step(**optimizer_args)
352
+ if barrier:
353
+ xm.mark_step()
354
+ return loss
355
+
356
+ xm.optimizer_step = patched_optimizer_step
357
+ elif is_sagemaker_dp_enabled():
358
+ model = nn.parallel.DistributedDataParallel(
359
+ model, device_ids=[int(os.getenv("SMDATAPARALLEL_LOCAL_RANK"))]
360
+ )
361
+ elif self.args.local_rank != -1:
362
+ kwargs = {}
363
+ if self.args.ddp_find_unused_parameters is not None:
364
+ kwargs["find_unused_parameters"] = self.args.ddp_find_unused_parameters
365
+ elif isinstance(model, PreTrainedModel):
366
+ # find_unused_parameters breaks checkpointing as per
367
+ # https://github.com/huggingface/transformers/pull/4659#issuecomment-643356021
368
+ kwargs["find_unused_parameters"] = not model.is_gradient_checkpointing
369
+ else:
370
+ kwargs["find_unused_parameters"] = True
371
+
372
+ if self.args.ddp_bucket_cap_mb is not None:
373
+ kwargs["bucket_cap_mb"] = self.args.ddp_bucket_cap_mb
374
+ if is_torch_neuroncore_available():
375
+ return model
376
+ model = nn.parallel.DistributedDataParallel(
377
+ model,
378
+ device_ids=[self.args.local_rank] if self.args._n_gpu != 0 else None,
379
+ output_device=self.args.local_rank if self.args._n_gpu != 0 else None,
380
+ **kwargs,
381
+ )
382
+
383
+ # torch.compile() needs to be called after wrapping the model with FSDP or DDP
384
+ # to ensure that it accounts for the graph breaks required by those wrappers
385
+ if self.args.torch_compile:
386
+ model = torch.compile(model, backend=self.args.torch_compile_backend, mode=self.args.torch_compile_mode)
387
+
388
+ return model
389
+
GOT-OCR-2.0-master/GOT/utils/arguments.py ADDED
@@ -0,0 +1,53 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from dataclasses import dataclass, field
2
+ from typing import Dict, Optional, Sequence
3
+ import transformers
4
+
5
+
6
+ @dataclass
7
+ class ModelArguments:
8
+ model_name_or_path: Optional[str] = field(default="facebook/opt-125m")
9
+ use_cache: bool = field(default=False)
10
+ vision_tower: Optional[str] = field(default="~/.cache/huggingface/hub/models--openai--clip-vit-large-patch14/snapshots/8d052a0f05efbaefbc9e8786ba291cfdf93e5bff/")
11
+ freeze_vision_tower: bool = field(default=False)
12
+ freeze_lm_model: bool = field(default=False)
13
+ pretrained_stage1_model: Optional[str] = field(default=None) # mlp &/ vision tower
14
+ vision_select_layer: Optional[int] = field(default=-1) # default to the last layer
15
+ use_im_start_end: bool = field(default=False)
16
+
17
+
18
+ @dataclass
19
+ class DataArguments:
20
+ datasets: str = field(default=None, metadata={"help": "combinations of the training data."})
21
+ sep_image_conv_front: bool = False
22
+ image_token_len: int = 256
23
+ image_aspect_ratio: str = 'square'
24
+ conversation_version: str = 'mpt'
25
+ # conversation_version: str = 'v0'
26
+ # conversation_version: str = 'v1'
27
+ # conversation_version: str = 'nougat'
28
+ # conversation_version: str = 'baichuan'
29
+ # conversation_version: str = 'opt'
30
+ box_limit: int = 0
31
+
32
+
33
+ @dataclass
34
+ class TrainingArguments(transformers.TrainingArguments):
35
+ cache_dir: Optional[str] = field(default=None)
36
+ optim: str = field(default="adamw_torch")
37
+ remove_unused_columns: bool = field(default=False)
38
+ force_fsdp: bool = field(default=False)
39
+ interleave: bool = field(default=False)
40
+ with_box: bool = field(default=False)
41
+ model_max_length: int = field(
42
+ default=512,
43
+ metadata={
44
+ "help":
45
+ "Maximum sequence length. Sequences will be right padded (and possibly truncated)."
46
+ },
47
+ )
48
+ lora_enable: bool = False
49
+ lora_r: int = 8
50
+ lora_alpha: int = 16
51
+ lora_dropout: float = 0.05
52
+ lora_weight_path: str = ""
53
+ lora_bias: str = "none"
GOT-OCR-2.0-master/GOT/utils/constants.py ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ CONTROLLER_HEART_BEAT_EXPIRATION = 30
2
+ WORKER_HEART_BEAT_INTERVAL = 15
3
+
4
+ LOGDIR = "log"
5
+
6
+ IGNORE_INDEX = -100
7
+ # DEFAULT_PAD_TOKEN = "[PAD]"
8
+
9
+ DEFAULT_PAD_TOKEN = "<|endoftext|>"
10
+ DEFAULT_EOS_TOKEN = "</s>"
11
+ DEFAULT_BOS_TOKEN = "</s>"
12
+ DEFAULT_UNK_TOKEN = "<unk>"
13
+ DEFAULT_IMAGE_TOKEN = "<image>"
14
+ DEFAULT_BOX_TOKEN = "<box>"
15
+
16
+ DEFAULT_IMAGE_PATCH_TOKEN = '<imgpad>'
17
+
18
+ DEFAULT_IM_START_TOKEN = '<img>'
19
+ DEFAULT_IM_END_TOKEN = '</img>'
20
+
21
+
22
+
23
+ CONVERSATION_DATA = {
24
+
25
+ 'data_1': {
26
+ 'images': '/path/',
27
+ 'annotations': '/path/data1.json',
28
+ },
29
+ 'data_2': {
30
+ 'images': '/path/',
31
+ 'annotations': '/path/data2.json',
32
+ },
33
+ 'data_3': {
34
+ 'images': '/path/',
35
+ 'annotations': '/path/data3.json',
36
+ },
37
+
38
+
39
+ }
GOT-OCR-2.0-master/GOT/utils/conversation.py ADDED
@@ -0,0 +1,455 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import dataclasses
2
+ from enum import auto, Enum
3
+ from typing import List, Tuple
4
+
5
+
6
+ class SeparatorStyle(Enum):
7
+ """Different separator style."""
8
+ SINGLE = auto()
9
+ TWO = auto()
10
+ MPT = auto()
11
+
12
+
13
+
14
+ # simple_conv_multimodal = Conversation(
15
+ # system="You are GOT, a large language and vision assistant trained by Foundation Model Group, Megvii Technology."
16
+ # "You are able to understand the visual content that the user provides, and assist the user with a variety of tasks using natural language."
17
+ # "Follow the instructions carefully and explain your answers in detail.",
18
+ # # system="",
19
+ # roles=("Human", "Assistant"),
20
+ # messages=(
21
+ # ("Human", "Hi!"),
22
+ # ("Assistant", "Hi there! How can I help you today?\n")
23
+ # ),
24
+ # offset=2,
25
+ # sep_style=SeparatorStyle.SINGLE,
26
+ # sep="###",
27
+ # )
28
+
29
+ # conv_mpt = Conversation(
30
+ # system="""<|im_start|>system
31
+ # - You are a helpful language and vision assistant.
32
+ # - You are able to understand the visual content that the user provides, and assist the user with a variety of tasks using natural language.
33
+ # - You should follow the instructions carefully and explain your answers in detail.""",
34
+ # roles=("<|im_start|>user\n", "<|im_start|>assistant\n"),
35
+ # version="mpt",
36
+ # messages=(),
37
+ # offset=0,
38
+ # sep_style=SeparatorStyle.MPT,
39
+ # sep="<|im_end|>",
40
+ # )
41
+
42
+ @dataclasses.dataclass
43
+ class Conversation:
44
+ """A class that keeps all conversation history."""
45
+ system: str
46
+ roles: List[str]
47
+ messages: List[List[str]]
48
+ offset: int
49
+ sep_style: SeparatorStyle = SeparatorStyle.SINGLE
50
+ sep: str = "<|im_end|>"
51
+ sep2: str = None
52
+ version: str = "Unknown"
53
+
54
+ skip_next: bool = False
55
+
56
+ def get_prompt(self):
57
+ if self.sep_style == SeparatorStyle.SINGLE:
58
+ ret = self.system + self.sep + '\n'
59
+ for role, message in self.messages:
60
+ if message:
61
+ if type(message) is tuple:
62
+ message, _, _ = message
63
+ ret += role + ": " + message + self.sep
64
+ else:
65
+ ret += role + ":"
66
+ return ret
67
+ elif self.sep_style == SeparatorStyle.TWO:
68
+ seps = [self.sep, self.sep2]
69
+ ret = self.system + seps[0]
70
+ for i, (role, message) in enumerate(self.messages):
71
+ if message:
72
+ if type(message) is tuple:
73
+ message, _, _ = message
74
+ ret += role + ": " + message + seps[i % 2]
75
+ else:
76
+ ret += role + ":"
77
+ return ret
78
+ if self.sep_style == SeparatorStyle.MPT:
79
+ if self.system:
80
+ ret = self.system + self.sep
81
+ else:
82
+ ret = ''
83
+ for role, message in self.messages:
84
+ if message:
85
+ if type(message) is tuple:
86
+ message, _, _ = message
87
+ ret += role + message + self.sep
88
+ else:
89
+ ret += role
90
+ return ret
91
+ else:
92
+ raise ValueError(f"Invalid style: {self.sep_style}")
93
+ # if self.sep_style == SeparatorStyle.MPT:
94
+ # if self.system:
95
+ # ret = self.system + self.sep
96
+ # else:
97
+ # ret = ''
98
+ # for role, message in self.messages:
99
+ # if message:
100
+ # if type(message) is tuple:
101
+ # message, _, _ = message
102
+ # ret += role + message + self.sep
103
+ # # if 'user' in role:
104
+ # # ret += role + message + self.sep + "\n"
105
+ # # else:
106
+ # # ret += role + message + self.sep
107
+ # else:
108
+ # ret += role
109
+ # return ret
110
+ # else:
111
+ # raise ValueError(f"Invalid style: {self.sep_style}")
112
+
113
+ def append_message(self, role, message):
114
+ self.messages.append([role, message])
115
+
116
+ def get_images(self, return_pil=False):
117
+ images = []
118
+ for i, (role, msg) in enumerate(self.messages[self.offset:]):
119
+ if i % 2 == 0:
120
+ if type(msg) is tuple:
121
+ import base64
122
+ from io import BytesIO
123
+ from PIL import Image
124
+ msg, image, image_process_mode = msg
125
+ if image_process_mode == "Pad":
126
+ def expand2square(pil_img, background_color=(122, 116, 104)):
127
+ width, height = pil_img.size
128
+ if width == height:
129
+ return pil_img
130
+ elif width > height:
131
+ result = Image.new(pil_img.mode, (width, width), background_color)
132
+ # result.paste(pil_img, (0, (width - height) // 2))
133
+ result.paste(pil_img)
134
+ return result
135
+ else:
136
+ result = Image.new(pil_img.mode, (height, height), background_color)
137
+ # result.paste(pil_img, ((height - width) // 2, 0))
138
+ result.paste(pil_img)
139
+ return result
140
+ image = expand2square(image)
141
+ elif image_process_mode == "Crop":
142
+ max_hw, min_hw = max(image.size), min(image.size)
143
+ aspect_ratio = max_hw / min_hw
144
+ max_len, min_len = 800, 400
145
+ shortest_edge = int(min(max_len / aspect_ratio, min_len, min_hw))
146
+ longest_edge = int(shortest_edge * aspect_ratio)
147
+ W, H = image.size
148
+ if H > W:
149
+ H, W = longest_edge, shortest_edge
150
+ else:
151
+ H, W = shortest_edge, longest_edge
152
+ image = image.resize((W, H))
153
+ elif image_process_mode == "Resize":
154
+ image = image.resize((224, 224))
155
+ else:
156
+ raise ValueError(f"Invalid image_process_mode: {image_process_mode}")
157
+
158
+ if return_pil:
159
+ images.append(image)
160
+ else:
161
+ buffered = BytesIO()
162
+ image.convert('RGB').save(buffered, format="JPEG")
163
+ img_b64_str = base64.b64encode(buffered.getvalue()).decode()
164
+ images.append(img_b64_str)
165
+ return images
166
+
167
+ def to_gradio_chatbot(self):
168
+ ret = []
169
+ for i, (role, msg) in enumerate(self.messages[self.offset:]):
170
+ if i % 2 == 0:
171
+ if type(msg) is tuple:
172
+ import base64
173
+ from io import BytesIO
174
+ msg, image, image_process_mode = msg
175
+ max_hw, min_hw = max(image.size), min(image.size)
176
+ aspect_ratio = max_hw / min_hw
177
+ max_len, min_len = 800, 400
178
+ shortest_edge = int(min(max_len / aspect_ratio, min_len, min_hw))
179
+ longest_edge = int(shortest_edge * aspect_ratio)
180
+ W, H = image.size
181
+ if H > W:
182
+ H, W = longest_edge, shortest_edge
183
+ else:
184
+ H, W = shortest_edge, longest_edge
185
+ image = image.resize((W, H))
186
+ # image = image.resize((224, 224))
187
+ buffered = BytesIO()
188
+ image.save(buffered, format="JPEG")
189
+ img_b64_str = base64.b64encode(buffered.getvalue()).decode()
190
+ img_str = f'<img src="data:image/png;base64,{img_b64_str}" alt="user upload image" />'
191
+ msg = msg.replace('<image>', img_str)
192
+ ret.append([msg, None])
193
+ else:
194
+ ret[-1][-1] = msg
195
+ return ret
196
+
197
+ def copy(self):
198
+ return Conversation(
199
+ system=self.system,
200
+ roles=self.roles,
201
+ messages=[[x, y] for x, y in self.messages],
202
+ offset=self.offset,
203
+ sep_style=self.sep_style,
204
+ sep=self.sep,
205
+ sep2=self.sep2)
206
+
207
+ def dict(self):
208
+ if len(self.get_images()) > 0:
209
+ return {
210
+ "system": self.system,
211
+ "roles": self.roles,
212
+ "messages": [[x, y[0] if type(y) is tuple else y] for x, y in self.messages],
213
+ "offset": self.offset,
214
+ "sep": self.sep,
215
+ "sep2": self.sep2,
216
+ }
217
+ return {
218
+ "system": self.system,
219
+ "roles": self.roles,
220
+ "messages": self.messages,
221
+ "offset": self.offset,
222
+ "sep": self.sep,
223
+ "sep2": self.sep2,
224
+ }
225
+
226
+
227
+ conv_v1 = Conversation(
228
+ system="A chat between a curious human and an artificial intelligence assistant. "
229
+ "The assistant gives helpful, detailed, and polite answers to the human's questions.",
230
+ roles=("Human", "Assistant"),
231
+ messages=(
232
+ ("Human", "Give three tips for staying healthy."),
233
+ ("Assistant",
234
+ "Sure, here are three tips for staying healthy:\n"
235
+ "1. Exercise regularly: Regular physical activity can help improve your overall health and wellbeing. "
236
+ "It can also help reduce your risk of chronic conditions such as obesity, diabetes, heart disease, "
237
+ "and certain cancers. Aim for at least 150 minutes of moderate-intensity aerobic exercise or "
238
+ "75 minutes of vigorous-intensity aerobic exercise per week, along with muscle-strengthening "
239
+ "activities at least two days per week.\n"
240
+ "2. Eat a balanced diet: Eating a balanced diet that is rich in fruits, "
241
+ "vegetables, whole grains, lean proteins, and healthy fats can help support "
242
+ "your overall health. Try to limit your intake of processed and high-sugar foods, "
243
+ "and aim to drink plenty of water throughout the day.\n"
244
+ "3. Get enough sleep: Getting enough quality sleep is essential for your physical "
245
+ "and mental health. Adults should aim for seven to nine hours of sleep per night. "
246
+ "Establish a regular sleep schedule and try to create a relaxing bedtime routine to "
247
+ "help improve the quality of your sleep.")
248
+ ),
249
+ offset=2,
250
+ sep_style=SeparatorStyle.SINGLE,
251
+ sep="###",
252
+ )
253
+
254
+ conv_v1_2 = Conversation(
255
+ system="A chat between a curious human and an artificial intelligence assistant. "
256
+ "The assistant gives helpful, detailed, and polite answers to the human's questions.",
257
+ roles=("Human", "Assistant"),
258
+ messages=(
259
+ ("Human", "What are the key differences between renewable and non-renewable energy sources?"),
260
+ ("Assistant",
261
+ "Renewable energy sources are those that can be replenished naturally in a relatively "
262
+ "short amount of time, such as solar, wind, hydro, geothermal, and biomass. "
263
+ "Non-renewable energy sources, on the other hand, are finite and will eventually be "
264
+ "depleted, such as coal, oil, and natural gas. Here are some key differences between "
265
+ "renewable and non-renewable energy sources:\n"
266
+ "1. Availability: Renewable energy sources are virtually inexhaustible, while non-renewable "
267
+ "energy sources are finite and will eventually run out.\n"
268
+ "2. Environmental impact: Renewable energy sources have a much lower environmental impact "
269
+ "than non-renewable sources, which can lead to air and water pollution, greenhouse gas emissions, "
270
+ "and other negative effects.\n"
271
+ "3. Cost: Renewable energy sources can be more expensive to initially set up, but they typically "
272
+ "have lower operational costs than non-renewable sources.\n"
273
+ "4. Reliability: Renewable energy sources are often more reliable and can be used in more remote "
274
+ "locations than non-renewable sources.\n"
275
+ "5. Flexibility: Renewable energy sources are often more flexible and can be adapted to different "
276
+ "situations and needs, while non-renewable sources are more rigid and inflexible.\n"
277
+ "6. Sustainability: Renewable energy sources are more sustainable over the long term, while "
278
+ "non-renewable sources are not, and their depletion can lead to economic and social instability.\n")
279
+ ),
280
+ offset=2,
281
+ sep_style=SeparatorStyle.SINGLE,
282
+ sep="###",
283
+ )
284
+
285
+ conv_vicuna_v1_1 = Conversation(
286
+ system="A chat between a curious user and an artificial intelligence assistant. "
287
+ "The assistant gives helpful, detailed, and polite answers to the user's questions.",
288
+ roles=("USER", "ASSISTANT"),
289
+ version="v1",
290
+ messages=(),
291
+ offset=0,
292
+ sep_style=SeparatorStyle.TWO,
293
+ sep=" ",
294
+ sep2="</s>",
295
+ )
296
+
297
+ # conv_mpt = Conversation(
298
+ # system="""<|im_start|>system
299
+ # - You are designed by Megvii(旷视), and your name is GOT.
300
+ # - 你叫GOT, 你来自旷视, 你是旷视开发的。
301
+ # - 你擅长分析表格,仔细读图表中的内容,然后给出你的答案。""",
302
+ # roles=("<|im_start|>user\n", "<|im_start|>assistant\n"),
303
+ # version="mpt",
304
+ # messages=(),
305
+ # offset=0,
306
+ # sep_style=SeparatorStyle.MPT,
307
+ # sep="<|im_end|>",
308
+ # )
309
+
310
+ conv_mpt = Conversation(
311
+ system="""<|im_start|>system
312
+ You should follow the instructions carefully and explain your answers in detail.""",
313
+ # system = None,
314
+ roles=("<|im_start|>user\n", "<|im_start|>assistant\n"),
315
+ version="mpt",
316
+ messages=(),
317
+ offset=0,
318
+ sep_style=SeparatorStyle.MPT,
319
+ sep="<|im_end|>",
320
+ )
321
+
322
+ conv_mpt_eval = Conversation(
323
+ system="",
324
+ roles=("<|im_start|>user\n", "<|im_start|>assistant\n"),
325
+ version="mpt",
326
+ messages=(),
327
+ offset=0,
328
+ sep_style=SeparatorStyle.MPT,
329
+ sep="<|im_end|>",
330
+ )
331
+
332
+ conv_mpt_text = Conversation(
333
+ system="""<|im_start|>system
334
+ - You are a helpful assistant chatbot trained by MosaicML.
335
+ - You answer questions.
336
+ - You are excited to be able to help the user, but will refuse to do anything that could be considered harmful to the user.
337
+ - You are more than just an information source, you are also able to write poetry, short stories, and make jokes.""",
338
+ roles=("<|im_start|>user\n", "<|im_start|>assistant\n"),
339
+ version="mpt",
340
+ messages=(),
341
+ offset=0,
342
+ sep_style=SeparatorStyle.MPT,
343
+ sep="<|im_end|>",
344
+ )
345
+
346
+ conv_bair_v1 = Conversation(
347
+ system="BEGINNING OF CONVERSATION:",
348
+ roles=("USER", "GPT"),
349
+ messages=(),
350
+ offset=0,
351
+ sep_style=SeparatorStyle.TWO,
352
+ sep=" ",
353
+ sep2="</s>",
354
+ )
355
+
356
+ # simple_conv = Conversation(
357
+ # system="You are GOT, a large language model trained by Foundation Model Group, Megvii Technology, based on LLaMA architecture."
358
+ # "You are designed to assist human with a variety of tasks using natural language."
359
+ # "Follow the instructions carefully.",
360
+ # roles=("Human", "Assistant"),
361
+ # messages=(
362
+ # ("Human", "Hi!"),
363
+ # ("Assistant", "Hi there! How can I help you today?\n")
364
+ # ),
365
+ # offset=2,
366
+ # sep_style=SeparatorStyle.SINGLE,
367
+ # sep="###",
368
+ # )
369
+
370
+
371
+ simple_conv = Conversation(
372
+ system="",
373
+ roles=("Human", "Assistant"),
374
+ messages=(
375
+ ),
376
+ offset=0,
377
+ sep_style=SeparatorStyle.SINGLE,
378
+ sep="###",
379
+ )
380
+
381
+ simple_conv_multimodal = Conversation(
382
+ system="You are GOT, a large language and vision assistant trained by Foundation Model Group, Megvii Technology."
383
+ "You are able to understand the visual content that the user provides, and assist the user with a variety of tasks using natural language."
384
+ "Follow the instructions carefully and explain your answers in detail.",
385
+ # system="",
386
+ roles=("Human", "Assistant"),
387
+ messages=(
388
+ ("Human", "Hi!"),
389
+ ("Assistant", "Hi there! How can I help you today?\n")
390
+ ),
391
+ offset=2,
392
+ sep_style=SeparatorStyle.SINGLE,
393
+ sep="###",
394
+ )
395
+
396
+ simple_conv_mpt_multimodal = Conversation(
397
+ system="""<|im_start|>system
398
+ - You are GOT, a large language and vision assistant trained by Foundation Model Group, Megvii Technology.
399
+ - You are able to understand the visual content that the user provides, and assist the user with a variety of tasks using natural language.
400
+ - You should follow the instructions carefully and explain your answers in detail.""",
401
+ roles=("<|im_start|>user\n", "<|im_start|>assistant\n"),
402
+ version="mpt",
403
+ messages=(),
404
+ offset=0,
405
+ sep_style=SeparatorStyle.MPT,
406
+ sep="<|im_end|>",
407
+ )
408
+
409
+ simple_conv_legacy = Conversation(
410
+ system="You are GOT, a large language model trained by Foundation Model Group, Megvii Technology."
411
+ "You are designed to assist human with a variety of tasks using natural language."
412
+ "Follow the instructions carefully.",
413
+ roles=("Human", "Assistant"),
414
+ messages=(
415
+ ("Human", "Hi!\n\n### Response:"),
416
+ ("Assistant", "Hi there! How can I help you today?\n")
417
+ ),
418
+ offset=2,
419
+ sep_style=SeparatorStyle.SINGLE,
420
+ sep="###",
421
+ )
422
+
423
+ conv_llava_v1 = Conversation(
424
+ system="You are GOT, a large language and vision assistant trained by Foundation Model Group, Megvii Technology."
425
+ "You are able to understand the visual content that the user provides, and assist the user with a variety of tasks using natural language."
426
+ "Follow the instructions carefully and explain your answers in detail.",
427
+ roles=("USER", "ASSISTANT"),
428
+ version="v1",
429
+ messages=(),
430
+ offset=0,
431
+ sep_style=SeparatorStyle.TWO,
432
+ sep=" ",
433
+ sep2="</s>",
434
+ )
435
+
436
+ default_conversation = conv_mpt
437
+ conv_templates = {
438
+ "default": simple_conv_multimodal,
439
+ "simple": simple_conv,
440
+ "simple_legacy": simple_conv_legacy,
441
+ "multimodal": simple_conv,
442
+ "mpt_multimodal": simple_conv_mpt_multimodal,
443
+ "llava_v1": conv_llava_v1,
444
+ "mpt_eval": conv_mpt_eval,
445
+ # fastchat
446
+ "v1": conv_vicuna_v1_1,
447
+ "bair_v1": conv_bair_v1,
448
+ "vicuna_v1_1": conv_vicuna_v1_1,
449
+ "mpt": conv_mpt,
450
+ "mpt_text": conv_mpt_text,
451
+ }
452
+
453
+
454
+ if __name__ == "__main__":
455
+ print(default_conversation.get_prompt())
GOT-OCR-2.0-master/GOT/utils/utils.py ADDED
@@ -0,0 +1,235 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import datetime
2
+ import logging
3
+ import logging.handlers
4
+ import os
5
+ import sys
6
+ import torch
7
+ import requests
8
+
9
+ from transformers import StoppingCriteria
10
+ from GOT.utils.constants import LOGDIR
11
+
12
+ server_error_msg = "**NETWORK ERROR DUE TO HIGH TRAFFIC. PLEASE REGENERATE OR REFRESH THIS PAGE.**"
13
+ moderation_msg = "YOUR INPUT VIOLATES OUR CONTENT MODERATION GUIDELINES. PLEASE TRY AGAIN."
14
+
15
+ handler = None
16
+
17
+
18
+ def build_logger(logger_name, logger_filename):
19
+ global handler
20
+
21
+ formatter = logging.Formatter(
22
+ fmt="%(asctime)s | %(levelname)s | %(name)s | %(message)s",
23
+ datefmt="%Y-%m-%d %H:%M:%S",
24
+ )
25
+
26
+ # Set the format of root handlers
27
+ if not logging.getLogger().handlers:
28
+ logging.basicConfig(level=logging.INFO)
29
+ logging.getLogger().handlers[0].setFormatter(formatter)
30
+
31
+ # Redirect stdout and stderr to loggers
32
+ stdout_logger = logging.getLogger("stdout")
33
+ stdout_logger.setLevel(logging.INFO)
34
+ sl = StreamToLogger(stdout_logger, logging.INFO)
35
+ sys.stdout = sl
36
+
37
+ stderr_logger = logging.getLogger("stderr")
38
+ stderr_logger.setLevel(logging.ERROR)
39
+ sl = StreamToLogger(stderr_logger, logging.ERROR)
40
+ sys.stderr = sl
41
+
42
+ # Get logger
43
+ logger = logging.getLogger(logger_name)
44
+ logger.setLevel(logging.INFO)
45
+
46
+ # Add a file handler for all loggers
47
+ if handler is None:
48
+ os.makedirs(LOGDIR, exist_ok=True)
49
+ filename = os.path.join(LOGDIR, logger_filename)
50
+ handler = logging.handlers.TimedRotatingFileHandler(
51
+ filename, when='D', utc=True)
52
+ handler.setFormatter(formatter)
53
+
54
+ for name, item in logging.root.manager.loggerDict.items():
55
+ if isinstance(item, logging.Logger):
56
+ item.addHandler(handler)
57
+
58
+ return logger
59
+
60
+
61
+ class StreamToLogger(object):
62
+ """
63
+ Fake file-like stream object that redirects writes to a logger instance.
64
+ """
65
+ def __init__(self, logger, log_level=logging.INFO):
66
+ self.terminal = sys.stdout
67
+ self.logger = logger
68
+ self.log_level = log_level
69
+ self.linebuf = ''
70
+
71
+ def __getattr__(self, attr):
72
+ return getattr(self.terminal, attr)
73
+
74
+ def write(self, buf):
75
+ temp_linebuf = self.linebuf + buf
76
+ self.linebuf = ''
77
+ for line in temp_linebuf.splitlines(True):
78
+ # From the io.TextIOWrapper docs:
79
+ # On output, if newline is None, any '\n' characters written
80
+ # are translated to the system default line separator.
81
+ # By default sys.stdout.write() expects '\n' newlines and then
82
+ # translates them so this is still cross platform.
83
+ if line[-1] == '\n':
84
+ self.logger.log(self.log_level, line.rstrip())
85
+ else:
86
+ self.linebuf += line
87
+
88
+ def flush(self):
89
+ if self.linebuf != '':
90
+ self.logger.log(self.log_level, self.linebuf.rstrip())
91
+ self.linebuf = ''
92
+
93
+
94
+ def disable_torch_init():
95
+ """
96
+ Disable the redundant torch default initialization to accelerate model creation.
97
+ """
98
+ import torch
99
+ setattr(torch.nn.Linear, "reset_parameters", lambda self: None)
100
+ setattr(torch.nn.LayerNorm, "reset_parameters", lambda self: None)
101
+
102
+
103
+ def violates_moderation(text):
104
+ """
105
+ Check whether the text violates OpenAI moderation API.
106
+ """
107
+ url = "https://api.openai.com/v1/moderations"
108
+ headers = {"Content-Type": "application/json",
109
+ "Authorization": "Bearer " + os.environ["OPENAI_API_KEY"]}
110
+ text = text.replace("\n", "")
111
+ data = "{" + '"input": ' + f'"{text}"' + "}"
112
+ data = data.encode("utf-8")
113
+ try:
114
+ ret = requests.post(url, headers=headers, data=data, timeout=5)
115
+ flagged = ret.json()["results"][0]["flagged"]
116
+ except requests.exceptions.RequestException as e:
117
+ flagged = False
118
+ except KeyError as e:
119
+ flagged = False
120
+
121
+ return flagged
122
+
123
+
124
+ def pretty_print_semaphore(semaphore):
125
+ if semaphore is None:
126
+ return "None"
127
+ return f"Semaphore(value={semaphore._value}, locked={semaphore.locked()})"
128
+
129
+
130
+ class KeywordsStoppingCriteria(StoppingCriteria):
131
+ def __init__(self, keywords, tokenizer, input_ids):
132
+ self.keywords = keywords
133
+ self.keyword_ids = [tokenizer(keyword).input_ids for keyword in keywords]
134
+ self.keyword_ids = [keyword_id[0] for keyword_id in self.keyword_ids if type(keyword_id) is list and len(keyword_id) == 1]
135
+ self.tokenizer = tokenizer
136
+ self.start_len = None
137
+ self.input_ids = input_ids
138
+
139
+ def __call__(self, output_ids: torch.LongTensor, scores: torch.FloatTensor, **kwargs) -> bool:
140
+ if self.start_len is None:
141
+ self.start_len = self.input_ids.shape[1]
142
+ else:
143
+ for keyword_id in self.keyword_ids:
144
+ if output_ids[0, -1] == keyword_id:
145
+ return True
146
+ outputs = self.tokenizer.batch_decode(output_ids[:, self.start_len:], skip_special_tokens=True)[0]
147
+ for keyword in self.keywords:
148
+ if keyword in outputs:
149
+ return True
150
+ return False
151
+
152
+
153
+ def smart_tokenizer_and_embedding_resize(special_tokens_dict, tokenizer, model):
154
+ """Resize tokenizer and embedding.
155
+
156
+ Note: This is the unoptimized version that may make your embedding size not be divisible by 64.
157
+ """
158
+ # num_new_tokens = tokenizer.add_special_tokens(special_tokens_dict)
159
+ # # num_new_tokens = 1
160
+ # # tokenizer.add_tokens(special_tokens_dict, special_tokens=True)
161
+ # model.resize_token_embeddings(len(tokenizer))
162
+
163
+ num_new_tokens = tokenizer.add_special_tokens(special_tokens_dict)
164
+ model.resize_token_embeddings(len(tokenizer))
165
+
166
+ if num_new_tokens > 0:
167
+ input_embeddings = model.get_input_embeddings().weight.data
168
+ output_embeddings = model.get_output_embeddings().weight.data
169
+
170
+ input_embeddings_avg = input_embeddings[:-num_new_tokens].mean(
171
+ dim=0, keepdim=True)
172
+ output_embeddings_avg = output_embeddings[:-num_new_tokens].mean(
173
+ dim=0, keepdim=True)
174
+
175
+ input_embeddings[-num_new_tokens:] = input_embeddings_avg
176
+ output_embeddings[-num_new_tokens:] = output_embeddings_avg
177
+
178
+
179
+ def maybe_zero_3(param, ignore_status=False, name=None):
180
+ from deepspeed import zero
181
+ from deepspeed.runtime.zero.partition_parameters import ZeroParamStatus
182
+ if hasattr(param, "ds_id"):
183
+ if param.ds_status == ZeroParamStatus.NOT_AVAILABLE:
184
+ if not ignore_status:
185
+ logging.warning(f"{name}: param.ds_status != ZeroParamStatus.NOT_AVAILABLE: {param.ds_status}")
186
+ with zero.GatheredParameters([param]):
187
+ param = param.data.detach().cpu().clone()
188
+ else:
189
+ param = param.detach().cpu().clone()
190
+ return param
191
+
192
+
193
+ # Borrowed from peft.utils.get_peft_model_state_dict
194
+ def get_peft_state_maybe_zero_3(named_params, bias):
195
+ if bias == "none":
196
+ to_return = {k: t for k, t in named_params if "lora_" in k}
197
+ elif bias == "all":
198
+ to_return = {k: t for k, t in named_params if "lora_" in k or "bias" in k}
199
+ elif bias == "lora_only":
200
+ to_return = {}
201
+ maybe_lora_bias = {}
202
+ lora_bias_names = set()
203
+ for k, t in named_params:
204
+ if "lora_" in k:
205
+ to_return[k] = t
206
+ bias_name = k.split("lora_")[0] + "bias"
207
+ lora_bias_names.add(bias_name)
208
+ elif "bias" in k:
209
+ maybe_lora_bias[k] = t
210
+ for k, t in maybe_lora_bias:
211
+ if bias_name in lora_bias_names:
212
+ to_return[bias_name] = t
213
+ else:
214
+ raise NotImplementedError
215
+ to_return = {k: maybe_zero_3(v, name=k) for k, v in to_return.items()}
216
+ return to_return
217
+
218
+
219
+ def get_peft_state_non_lora_maybe_zero_3(named_params, require_grad_only=True):
220
+ to_return = {k: t for k, t in named_params if "lora_" not in k}
221
+ if require_grad_only:
222
+ to_return = {k: t for k, t in to_return.items() if t.requires_grad}
223
+ to_return = {k: maybe_zero_3(v, ignore_status=True).cpu() for k, v in to_return.items()}
224
+ return to_return
225
+
226
+
227
+ def find_all_linear_names(model):
228
+ cls = torch.nn.Linear
229
+ lora_module_names = set()
230
+ for name, module in model.named_modules():
231
+ if isinstance(module, cls) and 'vision_model' not in name and 'mm_projector' not in name and 'vision_encoder' not in name and 'conv_final' not in name and'lm_head' not in name:
232
+ lora_module_names.add(name)
233
+
234
+ print(lora_module_names)
235
+ return list(lora_module_names)
GOT-OCR-2.0-master/pyproject.toml ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [build-system]
2
+ requires = ["setuptools>=61.0"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "GOT"
7
+ version = "0.1.0"
8
+ description = "Towards OCR-2.0."
9
+ readme = "README.md"
10
+ requires-python = ">=3.8"
11
+ classifiers = [
12
+ "Programming Language :: Python :: 3",
13
+ "License :: OSI Approved :: Apache Software License",
14
+ ]
15
+ dependencies = [
16
+ "markdown2[all]", "numpy",
17
+ "requests", "sentencepiece", "tokenizers>=0.15.2",
18
+ "torch", "torchvision", "wandb",
19
+ "shortuuid", "httpx==0.24.0",
20
+ "deepspeed==0.12.3",
21
+ "peft==0.4.0",
22
+ "albumentations",
23
+ "opencv-python",
24
+ "tiktoken==0.6.0",
25
+ "accelerate==0.28.0",
26
+ "transformers==4.37.2",
27
+ "bitsandbytes==0.41.0",
28
+ "scikit-learn==1.2.2",
29
+ "sentencepiece==0.1.99",
30
+ "einops==0.6.1", "einops-exts==0.0.4", "timm==0.6.13",
31
+ ]
32
+
33
+ [tool.setuptools.packages.find]
34
+ exclude = ["assets*", "benchmark*", "docs", "dist*", "playground*", "scripts*", "tests*"]
35
+
36
+ [tool.wheel]
37
+ exclude = ["assets*", "benchmark*", "docs", "dist*", "playground*", "scripts*", "tests*"]
GOT-OCR-2.0-master/pyvenv.cfg ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ home = /usr/bin
2
+ implementation = CPython
3
+ version_info = 3.8.10.final.0
4
+ virtualenv = 20.16.7
5
+ include-system-site-packages = true
6
+ base-prefix = /usr
7
+ base-exec-prefix = /usr
8
+ base-executable = /usr/bin/python3
GOT-OCR-2.0-master/render_tools/content-mmd-to-html.html ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en" data-lt-installed="true"><head>
3
+ <meta charset="UTF-8">
4
+ <title>Title</title>
5
+ <script>
6
+ const text =
7
+ </script>
8
+ <style>
9
+ #content {
10
+ max-width: 800px;
11
+ margin: auto;
12
+ }
13
+ </style>
14
+ <script>
15
+ let script = document.createElement('script');
16
+ script.src = "https://cdn.jsdelivr.net/npm/mathpix-markdown-it@1.3.6/es5/bundle.js";
17
+ document.head.append(script);
18
+
19
+ script.onload = function() {
20
+ const isLoaded = window.loadMathJax();
21
+ if (isLoaded) {
22
+ console.log('Styles loaded!')
23
+ }
24
+
25
+ const el = window.document.getElementById('content-text');
26
+ if (el) {
27
+ const options = {
28
+ htmlTags: true
29
+ };
30
+ const html = window.render(text, options);
31
+ el.outerHTML = html;
32
+ }
33
+ };
34
+ </script>
35
+ </head>
36
+ <body>
37
+ <div id="content"><div id="content-text"></div></div>
38
+ </body>
39
+ </html>
GOT-OCR-2.0-master/render_tools/tikz.html ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+
3
+ <html>
4
+
5
+ <head>
6
+ <meta charset="UTF-8">
7
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
8
+ <title>Document</title>
9
+ <link rel="stylesheet" type="text/css" href="https://tikzjax.com/v1/fonts.css">
10
+ <script src="https://tikzjax.com/v1/tikzjax.js"></script>
11
+ </head>
12
+ <body>
13
+ <script type="text/tikz">
14
+ const text =
15
+ </script>
16
+ </body>
17
+ </html>
GOT-OCR-2.0-master/results/demo.html ADDED
@@ -0,0 +1,56 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en" data-lt-installed="true"><head>
3
+ <meta charset="UTF-8">
4
+ <title>Title</title>
5
+ <script>
6
+ const text ="\\title{\n"+
7
+ "MADRIX \\({ }^{\\circledR}\\) PLEXUS -\n"+
8
+ "}\n"+
9
+ "\\section*{Quick Start Guide \\& Technical Manual}\n"+
10
+ "\\(5^{\\text {th }}\\) Edition - November 2017\n"+
11
+ "Thank You For Purchasing MADRIK \\({ }^{\\circledR}\\) PLEXUS!\n"+
12
+ "Please read this guide carefully and thoroughly before using MADRIX \\({ }^{\\circledR}\\) PLEXUS. Make sure that you fully understand all information.\n"+
13
+ "This MADRIX \\({ }^{\\circledR}\\) PLEXUS Quick Start Guide and the MADRIX \\({ }^{\\circledR}\\) PLEXUS User Manual are written in English and German.\n"+
14
+ "Developed and made in Germany.\n"+
15
+ "\\section*{Imprint}\n"+
16
+ "inaage GmbH\n"+
17
+ "Wiener Straße 56\n"+
18
+ "01219 Dresden\n"+
19
+ "Germany\n"+
20
+ "Managing Directors: Christian Hertel, Sebastian Pinzer, Sebastian Wissmann\n"+
21
+ "Web www.madrix.com\n"+
22
+ "E-mail info@madrix.com\n"+
23
+ "Phone +4935186268690\n"
24
+ </script>
25
+ <style>
26
+ #content {
27
+ max-width: 800px;
28
+ margin: auto;
29
+ }
30
+ </style>
31
+ <script>
32
+ let script = document.createElement('script');
33
+ script.src = "https://cdn.jsdelivr.net/npm/mathpix-markdown-it@1.3.6/es5/bundle.js";
34
+ document.head.append(script);
35
+
36
+ script.onload = function() {
37
+ const isLoaded = window.loadMathJax();
38
+ if (isLoaded) {
39
+ console.log('Styles loaded!')
40
+ }
41
+
42
+ const el = window.document.getElementById('content-text');
43
+ if (el) {
44
+ const options = {
45
+ htmlTags: true
46
+ };
47
+ const html = window.render(text, options);
48
+ el.outerHTML = html;
49
+ }
50
+ };
51
+ </script>
52
+ </head>
53
+ <body>
54
+ <div id="content"><div id="content-text"></div></div>
55
+ </body>
56
+ </html>
GOT-OCR-2.0-master/zero_config/zero2.json ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "bf16": {
3
+ "enabled": true
4
+ },
5
+ "train_micro_batch_size_per_gpu": "auto",
6
+ "zero_optimization": {
7
+ "stage": 2,
8
+ "overlap_comm": true,
9
+ "contiguous_gradients": true,
10
+ "sub_group_size": 1e9,
11
+ "reduce_bucket_size": "auto"
12
+ }
13
+ }
GOT-OCR-2.0-master/zero_config/zero3.json ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "fp16": {
3
+ "enabled": "auto",
4
+ "loss_scale": 0,
5
+ "loss_scale_window": 1000,
6
+ "initial_scale_power": 16,
7
+ "hysteresis": 2,
8
+ "min_loss_scale": 1
9
+ },
10
+ "bf16": {
11
+ "enabled": "auto"
12
+ },
13
+ "train_micro_batch_size_per_gpu": "auto",
14
+ "train_batch_size": "auto",
15
+ "gradient_accumulation_steps": "auto",
16
+ "zero_optimization": {
17
+ "stage": 3,
18
+ "overlap_comm": true,
19
+ "contiguous_gradients": true,
20
+ "sub_group_size": 1e9,
21
+ "reduce_bucket_size": "auto",
22
+ "stage3_prefetch_bucket_size": "auto",
23
+ "stage3_param_persistence_threshold": "auto",
24
+ "stage3_max_live_parameters": 1e9,
25
+ "stage3_max_reuse_distance": 1e9,
26
+ "stage3_gather_16bit_weights_on_model_save": true
27
+ }
28
+ }
assets/got_logo.png ADDED
assets/got_support.jpg ADDED
assets/train_sample.jpg ADDED
assets/wechat.jpg ADDED
assets/wechat3.jpg ADDED
assets/weichat2.jpg ADDED