Upload folder using huggingface_hub
Browse files- config.json +4 -6
- image_processing_phi3_v.py +274 -0
- preprocessor_config.json +20 -0
- processing_phi3_v.py +217 -0
- sample_inference.py +129 -0
- special_tokens_map.json +36 -0
- tokenizer.json +0 -0
- tokenizer_config.json +408 -0
config.json
CHANGED
@@ -1,5 +1,5 @@
|
|
1 |
{
|
2 |
-
"_name_or_path": "
|
3 |
"architectures": [
|
4 |
"Phi3VForCausalLM"
|
5 |
],
|
@@ -16,7 +16,6 @@
|
|
16 |
"use_hd_transform": true,
|
17 |
"with_learnable_separator": true
|
18 |
},
|
19 |
-
"embd_pdrop": 0.0,
|
20 |
"eos_token_id": 2,
|
21 |
"hidden_act": "silu",
|
22 |
"hidden_size": 3072,
|
@@ -34,8 +33,6 @@
|
|
34 |
"num_hidden_layers": 32,
|
35 |
"num_key_value_heads": 32,
|
36 |
"original_max_position_embeddings": 4096,
|
37 |
-
"pad_token_id": 32000,
|
38 |
-
"resid_pdrop": 0.0,
|
39 |
"rms_norm_eps": 1e-05,
|
40 |
"rope_scaling": {
|
41 |
"long_factor": [
|
@@ -144,7 +141,8 @@
|
|
144 |
"sliding_window": 131072,
|
145 |
"tie_word_embeddings": false,
|
146 |
"torch_dtype": "bfloat16",
|
147 |
-
"transformers_version": "4.
|
148 |
"use_cache": true,
|
149 |
-
"vocab_size": 32064
|
|
|
150 |
}
|
|
|
1 |
{
|
2 |
+
"_name_or_path": "Phi-3-vision-128k-instruct",
|
3 |
"architectures": [
|
4 |
"Phi3VForCausalLM"
|
5 |
],
|
|
|
16 |
"use_hd_transform": true,
|
17 |
"with_learnable_separator": true
|
18 |
},
|
|
|
19 |
"eos_token_id": 2,
|
20 |
"hidden_act": "silu",
|
21 |
"hidden_size": 3072,
|
|
|
33 |
"num_hidden_layers": 32,
|
34 |
"num_key_value_heads": 32,
|
35 |
"original_max_position_embeddings": 4096,
|
|
|
|
|
36 |
"rms_norm_eps": 1e-05,
|
37 |
"rope_scaling": {
|
38 |
"long_factor": [
|
|
|
141 |
"sliding_window": 131072,
|
142 |
"tie_word_embeddings": false,
|
143 |
"torch_dtype": "bfloat16",
|
144 |
+
"transformers_version": "4.38.1",
|
145 |
"use_cache": true,
|
146 |
+
"vocab_size": 32064,
|
147 |
+
"_attn_implementation": "flash_attention_2"
|
148 |
}
|
image_processing_phi3_v.py
ADDED
@@ -0,0 +1,274 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# coding=utf-8
|
2 |
+
# Copyright 2024 Microsoft and the HuggingFace Inc. team. All rights reserved.
|
3 |
+
#
|
4 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
5 |
+
# you may not use this file except in compliance with the License.
|
6 |
+
# You may obtain a copy of the License at
|
7 |
+
#
|
8 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
9 |
+
#
|
10 |
+
# Unless required by applicable law or agreed to in writing, software
|
11 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
12 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13 |
+
# See the License for the specific language governing permissions and
|
14 |
+
# limitations under the License.
|
15 |
+
|
16 |
+
"""Image processor class for Phi3-V."""
|
17 |
+
|
18 |
+
from typing import List, Optional, Union
|
19 |
+
|
20 |
+
import numpy as np
|
21 |
+
|
22 |
+
from transformers.image_processing_utils import BaseImageProcessor, BatchFeature
|
23 |
+
from transformers.image_transforms import (
|
24 |
+
convert_to_rgb,
|
25 |
+
)
|
26 |
+
from transformers.image_utils import (
|
27 |
+
OPENAI_CLIP_MEAN,
|
28 |
+
OPENAI_CLIP_STD,
|
29 |
+
ImageInput,
|
30 |
+
make_list_of_images,
|
31 |
+
valid_images,
|
32 |
+
)
|
33 |
+
from transformers.utils import TensorType, is_vision_available, logging
|
34 |
+
|
35 |
+
from transformers import AutoImageProcessor
|
36 |
+
|
37 |
+
logger = logging.get_logger(__name__)
|
38 |
+
|
39 |
+
|
40 |
+
if is_vision_available():
|
41 |
+
from PIL import Image
|
42 |
+
|
43 |
+
import torch
|
44 |
+
import torchvision
|
45 |
+
|
46 |
+
def padding_336(b):
|
47 |
+
width, height = b.size
|
48 |
+
tar = int(np.ceil(height / 336) * 336)
|
49 |
+
top_padding = int((tar - height)/2)
|
50 |
+
bottom_padding = tar - height - top_padding
|
51 |
+
left_padding = 0
|
52 |
+
right_padding = 0
|
53 |
+
b = torchvision.transforms.functional.pad(b, [left_padding, top_padding, right_padding, bottom_padding], fill=[255,255,255])
|
54 |
+
|
55 |
+
return b
|
56 |
+
|
57 |
+
def calc_padded_size(width, height, padding_unit=336):
|
58 |
+
target_height = int(np.ceil(height / padding_unit) * padding_unit)
|
59 |
+
top_padding = int((target_height - height) / 2)
|
60 |
+
bottom_padding = target_height - height - top_padding
|
61 |
+
left_padding = 0
|
62 |
+
right_padding = 0
|
63 |
+
padded_width = width + left_padding + right_padding
|
64 |
+
padded_height = height + top_padding + bottom_padding
|
65 |
+
return padded_width, padded_height
|
66 |
+
|
67 |
+
def HD_transform(img, hd_num=16):
|
68 |
+
width, height = img.size
|
69 |
+
trans = False
|
70 |
+
if width < height:
|
71 |
+
img = img.transpose(Image.TRANSPOSE)
|
72 |
+
trans = True
|
73 |
+
width, height = img.size
|
74 |
+
ratio = (width/ height)
|
75 |
+
scale = 1
|
76 |
+
while scale*np.ceil(scale/ratio) <= hd_num:
|
77 |
+
scale += 1
|
78 |
+
scale -= 1
|
79 |
+
new_w = int(scale * 336)
|
80 |
+
new_h = int(new_w / ratio)
|
81 |
+
|
82 |
+
img = torchvision.transforms.functional.resize(img, [new_h, new_w],)
|
83 |
+
img = padding_336(img)
|
84 |
+
width, height = img.size
|
85 |
+
if trans:
|
86 |
+
img = img.transpose(Image.TRANSPOSE)
|
87 |
+
|
88 |
+
return img
|
89 |
+
|
90 |
+
def calc_hd_transform_size(width, height, hd_num=16):
|
91 |
+
transposed = False
|
92 |
+
if width < height:
|
93 |
+
width, height = height, width
|
94 |
+
transposed = True
|
95 |
+
|
96 |
+
ratio = width / height
|
97 |
+
scale = 1
|
98 |
+
while scale * np.ceil(scale / ratio) <= hd_num:
|
99 |
+
scale += 1
|
100 |
+
scale -= 1
|
101 |
+
|
102 |
+
new_width = int(scale * 336)
|
103 |
+
new_height = int(new_width / ratio)
|
104 |
+
|
105 |
+
padded_width, padded_height = calc_padded_size(new_width, new_height)
|
106 |
+
|
107 |
+
if transposed:
|
108 |
+
padded_width, padded_height = padded_height, padded_width
|
109 |
+
|
110 |
+
return padded_width, padded_height
|
111 |
+
|
112 |
+
def pad_to_max_num_crops_tensor(images, max_crops=5):
|
113 |
+
"""
|
114 |
+
images: B x 3 x H x W, B<=max_crops
|
115 |
+
"""
|
116 |
+
B, _, H, W = images.shape
|
117 |
+
if B < max_crops:
|
118 |
+
pad = torch.zeros(max_crops - B, 3, H, W, dtype=images.dtype, device=images.device)
|
119 |
+
images = torch.cat([images, pad], dim=0)
|
120 |
+
return images
|
121 |
+
|
122 |
+
|
123 |
+
class Phi3VImageProcessor(BaseImageProcessor):
|
124 |
+
r"""
|
125 |
+
Constructs a Phi3 image processor. Based on [`CLIPImageProcessor`] with incorporation of additional techniques
|
126 |
+
for processing high resolution images as explained in the [InternLM-XComposer2-4KHD](https://arxiv.org/abs/2401.16420)
|
127 |
+
|
128 |
+
Args:
|
129 |
+
image_mean (`float` or `List[float]`, *optional*, defaults to `[0.48145466, 0.4578275, 0.40821073]`):
|
130 |
+
Mean to use if normalizing the image. This is a float or list of floats the length of the number of
|
131 |
+
channels in the image. Can be overridden by the `image_mean` parameter in the `preprocess` method.
|
132 |
+
image_std (`float` or `List[float]`, *optional*, defaults to `[0.26862954, 0.26130258, 0.27577711]`):
|
133 |
+
Standard deviation to use if normalizing the image. This is a float or list of floats the length of the
|
134 |
+
number of channels in the image. Can be overridden by the `image_std` parameter in the `preprocess` method.
|
135 |
+
Can be overridden by the `image_std` parameter in the `preprocess` method.
|
136 |
+
do_convert_rgb (`bool`, *optional*, defaults to `True`):
|
137 |
+
Whether to convert the image to RGB.
|
138 |
+
"""
|
139 |
+
|
140 |
+
model_input_names = ["pixel_values"]
|
141 |
+
|
142 |
+
def __init__(
|
143 |
+
self,
|
144 |
+
num_crops: int = 1,
|
145 |
+
image_mean: Optional[Union[float, List[float]]] = None,
|
146 |
+
image_std: Optional[Union[float, List[float]]] = None,
|
147 |
+
do_convert_rgb: bool = True,
|
148 |
+
**kwargs,
|
149 |
+
) -> None:
|
150 |
+
super().__init__(**kwargs)
|
151 |
+
self.num_crops = num_crops
|
152 |
+
self.image_mean = image_mean if image_mean is not None else OPENAI_CLIP_MEAN
|
153 |
+
self.image_std = image_std if image_std is not None else OPENAI_CLIP_STD
|
154 |
+
self.do_convert_rgb = do_convert_rgb
|
155 |
+
|
156 |
+
def calc_num_image_tokens(
|
157 |
+
self,
|
158 |
+
images: ImageInput
|
159 |
+
):
|
160 |
+
""" Calculate the number of image tokens for each image.
|
161 |
+
Args:
|
162 |
+
images (`ImageInput`):
|
163 |
+
Image to preprocess. Expects a single or batch of images with pixel values ranging from 0 to 255. If
|
164 |
+
passing in images with pixel values between 0 and 1, set `do_rescale=False`.
|
165 |
+
"""
|
166 |
+
images = make_list_of_images(images)
|
167 |
+
|
168 |
+
if not valid_images(images):
|
169 |
+
raise ValueError(
|
170 |
+
"Invalid image type. Must be of type PIL.Image.Image, numpy.ndarray, "
|
171 |
+
"torch.Tensor, tf.Tensor or jax.ndarray."
|
172 |
+
)
|
173 |
+
|
174 |
+
images = [image.convert('RGB') for image in images]
|
175 |
+
# (H, W, C)
|
176 |
+
elems = [HD_transform(im, hd_num = self.num_crops) for im in images]
|
177 |
+
shapes = [[im.size[1], im.size[0]] for im in elems]
|
178 |
+
num_img_tokens = [int((h//336*w//336+1)*144 + 1 + (h//336+1)*12) for h, w in shapes]
|
179 |
+
return num_img_tokens
|
180 |
+
|
181 |
+
def calc_num_image_tokens_from_image_size(self, width, height):
|
182 |
+
"""
|
183 |
+
Calculate the number of image tokens for a given image size.
|
184 |
+
Args:
|
185 |
+
width (`int`): Width of the image.
|
186 |
+
height (`int`): Height of the image.
|
187 |
+
"""
|
188 |
+
new_width, new_height = calc_hd_transform_size(width, height, hd_num=self.num_crops)
|
189 |
+
num_img_tokens = int((new_height // 336 * new_width // 336 + 1) * 144 + 1 + (new_height // 336 + 1) * 12)
|
190 |
+
return num_img_tokens
|
191 |
+
|
192 |
+
def preprocess(
|
193 |
+
self,
|
194 |
+
images: ImageInput,
|
195 |
+
image_mean: Optional[Union[float, List[float]]] = None,
|
196 |
+
image_std: Optional[Union[float, List[float]]] = None,
|
197 |
+
do_convert_rgb: bool = None,
|
198 |
+
return_tensors: Optional[Union[str, TensorType]] = None,
|
199 |
+
):
|
200 |
+
"""
|
201 |
+
Args:
|
202 |
+
images (`ImageInput`):
|
203 |
+
Image to preprocess. Expects a single or batch of images with pixel values ranging from 0 to 255. If
|
204 |
+
passing in images with pixel values between 0 and 1, set `do_rescale=False`.
|
205 |
+
image_mean (`float` or `List[float]`, *optional*, defaults to `self.image_mean`):
|
206 |
+
Image mean to use for normalization. Only has an effect if `do_normalize` is set to `True`.
|
207 |
+
image_std (`float` or `List[float]`, *optional*, defaults to `self.image_std`):
|
208 |
+
Image standard deviation to use for normalization. Only has an effect if `do_normalize` is set to
|
209 |
+
`True`.
|
210 |
+
do_convert_rgb (`bool`, *optional*, defaults to `self.do_convert_rgb`):
|
211 |
+
Whether to convert the image to RGB.
|
212 |
+
return_tensors (`str` or `TensorType`, *optional*):
|
213 |
+
The type of tensors to return. Can be one of:
|
214 |
+
- Unset: Return a list of `np.ndarray`.
|
215 |
+
- `TensorType.TENSORFLOW` or `'tf'`: Return a batch of type `tf.Tensor`.
|
216 |
+
- `TensorType.PYTORCH` or `'pt'`: Return a batch of type `torch.Tensor`.
|
217 |
+
- `TensorType.NUMPY` or `'np'`: Return a batch of type `np.ndarray`.
|
218 |
+
- `TensorType.JAX` or `'jax'`: Return a batch of type `jax.numpy.ndarray`.
|
219 |
+
"""
|
220 |
+
image_mean = image_mean if image_mean is not None else self.image_mean
|
221 |
+
image_std = image_std if image_std is not None else self.image_std
|
222 |
+
do_convert_rgb = do_convert_rgb if do_convert_rgb is not None else self.do_convert_rgb
|
223 |
+
|
224 |
+
images = make_list_of_images(images)
|
225 |
+
|
226 |
+
if not valid_images(images):
|
227 |
+
raise ValueError(
|
228 |
+
"Invalid image type. Must be of type PIL.Image.Image, numpy.ndarray, "
|
229 |
+
"torch.Tensor, tf.Tensor or jax.ndarray."
|
230 |
+
)
|
231 |
+
|
232 |
+
if do_convert_rgb:
|
233 |
+
images = [convert_to_rgb(image) for image in images]
|
234 |
+
|
235 |
+
image_sizes = []
|
236 |
+
img_processor = torchvision.transforms.Compose([
|
237 |
+
torchvision.transforms.ToTensor(),
|
238 |
+
torchvision.transforms.Normalize(image_mean, image_std)
|
239 |
+
])
|
240 |
+
|
241 |
+
# PIL images
|
242 |
+
# HD_transform pad images to size of multiiply of 336, 336
|
243 |
+
# convert to RGB first
|
244 |
+
images = [image.convert('RGB') for image in images]
|
245 |
+
elems = [HD_transform(im, hd_num = self.num_crops) for im in images]
|
246 |
+
# tensor transform and normalize
|
247 |
+
hd_images = [img_processor(im) for im in elems]
|
248 |
+
# create global image
|
249 |
+
global_image = [torch.nn.functional.interpolate(im.unsqueeze(0).float(), size=(336, 336), mode='bicubic',).to(im.dtype) for im in hd_images]
|
250 |
+
|
251 |
+
# [(3, h, w)], where h, w is multiple of 336
|
252 |
+
shapes = [[im.size(1), im.size(2)] for im in hd_images]
|
253 |
+
num_img_tokens = [int((h//336*w//336+1)*144 + 1 + (h//336+1)*12) for h, w in shapes]
|
254 |
+
# reshape to channel dimension -> (num_images, num_crops, 3, 336, 336)
|
255 |
+
# (1, 3, h//336, 336, w//336, 336) -> (1, h//336, w//336, 3, 336, 336) -> (h//336*w//336, 3, 336, 336)
|
256 |
+
hd_images_reshape = [im.reshape(1, 3, h//336, 336, w//336, 336).permute(0,2,4,1,3,5).reshape(-1, 3, 336, 336).contiguous() for im, (h, w) in zip(hd_images, shapes)]
|
257 |
+
# concat global image and local image
|
258 |
+
hd_images_reshape = [torch.cat([_global_image] + [_im], dim=0) for _global_image, _im in zip(global_image, hd_images_reshape)]
|
259 |
+
|
260 |
+
# pad to max_num_crops
|
261 |
+
image_transformed = [pad_to_max_num_crops_tensor(im, self.num_crops+1) for im in hd_images_reshape]
|
262 |
+
image_transformed = torch.stack(image_transformed, dim=0)
|
263 |
+
image_sizes = [torch.LongTensor(_shapes) for _shapes in shapes]
|
264 |
+
padded_images = image_transformed
|
265 |
+
image_sizes = shapes
|
266 |
+
|
267 |
+
data = {"pixel_values": padded_images,
|
268 |
+
"image_sizes": image_sizes,
|
269 |
+
"num_img_tokens": num_img_tokens
|
270 |
+
}
|
271 |
+
|
272 |
+
return BatchFeature(data=data, tensor_type=return_tensors)
|
273 |
+
|
274 |
+
AutoImageProcessor.register("Phi3VImageProcessor", Phi3VImageProcessor)
|
preprocessor_config.json
ADDED
@@ -0,0 +1,20 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"auto_map": {
|
3 |
+
"AutoProcessor": "processing_phi3_v.Phi3VProcessor",
|
4 |
+
"AutoImageProcessor": "image_processing_phi3_v.Phi3VImageProcessor"
|
5 |
+
},
|
6 |
+
"num_crops": 16,
|
7 |
+
"image_mean": [
|
8 |
+
0.48145466,
|
9 |
+
0.4578275,
|
10 |
+
0.40821073
|
11 |
+
],
|
12 |
+
"image_processor_type": "Phi3VImageProcessor",
|
13 |
+
"image_std": [
|
14 |
+
0.26862954,
|
15 |
+
0.26130258,
|
16 |
+
0.27577711
|
17 |
+
],
|
18 |
+
"processor_class": "Phi3VProcessor",
|
19 |
+
"num_img_tokens": 144
|
20 |
+
}
|
processing_phi3_v.py
ADDED
@@ -0,0 +1,217 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# coding=utf-8
|
2 |
+
# Copyright 2024 Microsoft and the HuggingFace Inc. team. All rights reserved.
|
3 |
+
#
|
4 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
5 |
+
# you may not use this file except in compliance with the License.
|
6 |
+
# You may obtain a copy of the License at
|
7 |
+
#
|
8 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
9 |
+
#
|
10 |
+
# Unless required by applicable law or agreed to in writing, software
|
11 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
12 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13 |
+
# See the License for the specific language governing permissions and
|
14 |
+
# limitations under the License.
|
15 |
+
|
16 |
+
"""
|
17 |
+
Processor class for Phi3-V.
|
18 |
+
"""
|
19 |
+
import re
|
20 |
+
from typing import List, Optional, Union
|
21 |
+
|
22 |
+
import torch
|
23 |
+
|
24 |
+
import transformers
|
25 |
+
from transformers.feature_extraction_utils import BatchFeature
|
26 |
+
from transformers.image_utils import ImageInput
|
27 |
+
from transformers.processing_utils import ProcessorMixin
|
28 |
+
from transformers.tokenization_utils_base import PaddingStrategy, TextInput, TruncationStrategy
|
29 |
+
from transformers.utils import TensorType
|
30 |
+
from .image_processing_phi3_v import Phi3VImageProcessor
|
31 |
+
transformers.Phi3VImageProcessor = Phi3VImageProcessor
|
32 |
+
|
33 |
+
class Phi3VProcessor(ProcessorMixin):
|
34 |
+
r"""
|
35 |
+
Constructs a Phi3-V processor which wraps a Phi3-V image processor and a LLaMa tokenizer into a single processor.
|
36 |
+
|
37 |
+
[`Phi3VProcessor`] offers all the functionalities of [`Phi3VImageProcessor`] and [`LlamaTokenizerFast`]. See the
|
38 |
+
[`~Phi3VProcessor.__call__`] and [`~Phi3VProcessor.decode`] for more information.
|
39 |
+
|
40 |
+
Args:
|
41 |
+
image_processor ([`Phi3VImageProcessor`], *optional*):
|
42 |
+
The image processor is a required input.
|
43 |
+
tokenizer ([`LlamaTokenizerFast`], *optional*):
|
44 |
+
The tokenizer is a required input.
|
45 |
+
"""
|
46 |
+
|
47 |
+
attributes = ["image_processor", "tokenizer"]
|
48 |
+
image_processor_class = "Phi3VImageProcessor"
|
49 |
+
tokenizer_class = ("LlamaTokenizer", "LlamaTokenizerFast")
|
50 |
+
special_image_token = "<|image|>"
|
51 |
+
|
52 |
+
def __init__(self, image_processor, tokenizer):
|
53 |
+
self.image_processor = image_processor
|
54 |
+
self.tokenizer = tokenizer
|
55 |
+
self.num_img_tokens = image_processor.num_img_tokens
|
56 |
+
self.img_tokens = [f"<|image_{i+1}|>" for i in range(1000000)]
|
57 |
+
|
58 |
+
def __call__(
|
59 |
+
self,
|
60 |
+
text: Union[TextInput, List[TextInput]],
|
61 |
+
images: ImageInput = None,
|
62 |
+
padding: Union[bool, str, PaddingStrategy] = False,
|
63 |
+
truncation: Union[bool, str, TruncationStrategy] = None,
|
64 |
+
max_length=None,
|
65 |
+
return_tensors: Optional[Union[str, TensorType]] = TensorType.PYTORCH,
|
66 |
+
) -> BatchFeature:
|
67 |
+
"""
|
68 |
+
Main method to prepare for the model one or several sequences(s) and image(s). This method forwards the `text`
|
69 |
+
and `kwargs` arguments to LlamaTokenizerFast's [`~LlamaTokenizerFast.__call__`] if `text` is not `None` to encode
|
70 |
+
the text. To prepare the image(s), this method forwards the `images` and `kwrags` arguments to
|
71 |
+
Phi3ImageProcessor's [`~Phi3ImageProcessor.__call__`] if `images` is not `None`. Please refer to the doctsring
|
72 |
+
of the above two methods for more information.
|
73 |
+
|
74 |
+
Args:
|
75 |
+
text (`str`, `List[str]`, `List[List[str]]`):
|
76 |
+
The sequence or batch of sequences to be encoded. Each sequence can be a string or a list of strings
|
77 |
+
(pretokenized string). If the sequences are provided as list of strings (pretokenized), you must set
|
78 |
+
`is_split_into_words=True` (to lift the ambiguity with a batch of sequences).
|
79 |
+
images (`PIL.Image.Image`, `np.ndarray`, `torch.Tensor`, `List[PIL.Image.Image]`, `List[np.ndarray]`, `List[torch.Tensor]`):
|
80 |
+
The image or batch of images to be prepared. Each image can be a PIL image, NumPy array or PyTorch
|
81 |
+
tensor. Both channels-first and channels-last formats are supported.
|
82 |
+
padding (`bool`, `str` or [`~utils.PaddingStrategy`], *optional*, defaults to `False`):
|
83 |
+
Select a strategy to pad the returned sequences (according to the model's padding side and padding
|
84 |
+
index) among:
|
85 |
+
- `True` or `'longest'`: Pad to the longest sequence in the batch (or no padding if only a single
|
86 |
+
sequence if provided).
|
87 |
+
- `'max_length'`: Pad to a maximum length specified with the argument `max_length` or to the maximum
|
88 |
+
acceptable input length for the model if that argument is not provided.
|
89 |
+
- `False` or `'do_not_pad'` (default): No padding (i.e., can output a batch with sequences of different
|
90 |
+
lengths).
|
91 |
+
max_length (`int`, *optional*):
|
92 |
+
Maximum length of the returned list and optionally padding length (see above).
|
93 |
+
truncation (`bool`, *optional*):
|
94 |
+
Activates truncation to cut input sequences longer than `max_length` to `max_length`.
|
95 |
+
return_tensors (`str` or [`~utils.TensorType`], *optional*):
|
96 |
+
If set, will return tensors of a particular framework. Acceptable values are:
|
97 |
+
|
98 |
+
- `'tf'`: Return TensorFlow `tf.constant` objects.
|
99 |
+
- `'pt'`: Return PyTorch `torch.Tensor` objects.
|
100 |
+
- `'np'`: Return NumPy `np.ndarray` objects.
|
101 |
+
- `'jax'`: Return JAX `jnp.ndarray` objects.
|
102 |
+
|
103 |
+
Returns:
|
104 |
+
[`BatchFeature`]: A [`BatchFeature`] with the following fields:
|
105 |
+
|
106 |
+
- **input_ids** -- List of token ids to be fed to a model. Returned when `text` is not `None`.
|
107 |
+
- **attention_mask** -- List of indices specifying which tokens should be attended to by the model (when
|
108 |
+
`return_attention_mask=True` or if *"attention_mask"* is in `self.model_input_names` and if `text` is not
|
109 |
+
`None`).
|
110 |
+
- **pixel_values** -- Pixel values to be fed to a model. Returned when `images` is not `None`.
|
111 |
+
"""
|
112 |
+
if images is not None:
|
113 |
+
image_inputs = self.image_processor(images, return_tensors=return_tensors)
|
114 |
+
else:
|
115 |
+
image_inputs = {}
|
116 |
+
inputs = self._convert_images_texts_to_inputs(image_inputs, text, padding=padding, truncation=truncation, max_length=max_length, return_tensors=return_tensors)
|
117 |
+
return inputs
|
118 |
+
|
119 |
+
def calc_num_image_tokens(self, images: ImageInput):
|
120 |
+
""" Calculate the number of image tokens for each image.
|
121 |
+
Args:
|
122 |
+
images (`ImageInput`):
|
123 |
+
Image to preprocess. Expects a single or batch of images with pixel values ranging from 0 to 255. If
|
124 |
+
passing in images with pixel values between 0 and 1, set `do_rescale=False`.
|
125 |
+
"""
|
126 |
+
return self.image_processor.calc_num_image_tokens(images)
|
127 |
+
|
128 |
+
def calc_num_image_tokens_from_image_size(self, width, height):
|
129 |
+
""" Calculate the number of image token for an image with given width and height.
|
130 |
+
Args:
|
131 |
+
width (`int`):
|
132 |
+
Width of the image.
|
133 |
+
height (`int`):
|
134 |
+
Height of the image.
|
135 |
+
"""
|
136 |
+
return self.image_processor.calc_num_image_tokens_from_image_size(width, height)
|
137 |
+
|
138 |
+
|
139 |
+
@property
|
140 |
+
def special_image_token_id(self):
|
141 |
+
return self.tokenizer.convert_tokens_to_ids(self.special_image_token)
|
142 |
+
|
143 |
+
def get_special_image_token_id(self):
|
144 |
+
return self.tokenizer.convert_tokens_to_ids(self.special_image_token)
|
145 |
+
|
146 |
+
def _convert_images_texts_to_inputs(self, images, texts, padding=False, truncation=None, max_length=None, return_tensors=None):
|
147 |
+
|
148 |
+
if not len(images):
|
149 |
+
model_inputs = self.tokenizer(texts, return_tensors=return_tensors, padding=padding, truncation=truncation, max_length=max_length)
|
150 |
+
return BatchFeature(data={**model_inputs})
|
151 |
+
|
152 |
+
pattern = r"<\|image_\d+\|>"
|
153 |
+
prompt_chunks = [self.tokenizer(chunk).input_ids for chunk in re.split(pattern, texts)]
|
154 |
+
|
155 |
+
if 'num_img_tokens' in images:
|
156 |
+
num_img_tokens = images['num_img_tokens']
|
157 |
+
else:
|
158 |
+
assert 'num_crops' in images, 'num_crops must be provided in images if num_img_tokens is not provided'
|
159 |
+
num_crops = images['num_crops']
|
160 |
+
num_img_tokens = [_num_crops * self.num_img_tokens for _num_crops in num_crops]
|
161 |
+
|
162 |
+
images, image_sizes = images['pixel_values'], images['image_sizes']
|
163 |
+
|
164 |
+
# image_tags needs to start from 1 to n
|
165 |
+
image_tags = re.findall(pattern, texts)
|
166 |
+
# image_ids = [int(s.split("|")[1].split("_")[-1]) * -1 for s in image_tags]
|
167 |
+
# image_ids_pad = [[iid]*num_img_tokens[i] for i, iid in enumerate(image_ids)]
|
168 |
+
image_ids = [int(s.split("|")[1].split("_")[-1]) for s in image_tags]
|
169 |
+
unique_image_ids = sorted(list(set(image_ids)))
|
170 |
+
# image_ids must start from 1, and must be continuous int, e.g. [1, 2, 3], cannot be [1, 4, 5]
|
171 |
+
# check the condition
|
172 |
+
assert unique_image_ids == list(range(1, len(unique_image_ids)+1)), f"image_ids must start from 1, and must be continuous int, e.g. [1, 2, 3], cannot be {unique_image_ids}"
|
173 |
+
# total images must be the same as the number of image tags
|
174 |
+
assert len(unique_image_ids) == len(images), f"total images must be the same as the number of image tags, got {len(unique_image_ids)} image tags and {len(images)} images"
|
175 |
+
|
176 |
+
image_ids_pad = [[-iid]*num_img_tokens[iid-1] for iid in image_ids]
|
177 |
+
|
178 |
+
def insert_separator(X, sep_list):
|
179 |
+
if len(X) > len(sep_list):
|
180 |
+
sep_list.append([])
|
181 |
+
return [ele for sublist in zip(X, sep_list) for ele in sublist]
|
182 |
+
input_ids = []
|
183 |
+
offset = 0
|
184 |
+
for x in insert_separator(prompt_chunks, image_ids_pad):
|
185 |
+
input_ids.extend(x[offset:])
|
186 |
+
|
187 |
+
input_ids = torch.tensor(input_ids, dtype=torch.long).unsqueeze(0)
|
188 |
+
attention_mask = (input_ids > -1000000).to(torch.long)
|
189 |
+
|
190 |
+
return BatchFeature(data={"input_ids": input_ids,
|
191 |
+
"attention_mask": attention_mask,
|
192 |
+
"pixel_values": images,
|
193 |
+
"image_sizes": image_sizes})
|
194 |
+
|
195 |
+
|
196 |
+
# Copied from transformers.models.clip.processing_clip.CLIPProcessor.batch_decode with CLIP->Llama
|
197 |
+
def batch_decode(self, *args, **kwargs):
|
198 |
+
"""
|
199 |
+
This method forwards all its arguments to LlamaTokenizerFast's [`~PreTrainedTokenizer.batch_decode`]. Please
|
200 |
+
refer to the docstring of this method for more information.
|
201 |
+
"""
|
202 |
+
return self.tokenizer.batch_decode(*args, **kwargs)
|
203 |
+
|
204 |
+
# Copied from transformers.models.clip.processing_clip.CLIPProcessor.decode with CLIP->Llama
|
205 |
+
def decode(self, *args, **kwargs):
|
206 |
+
"""
|
207 |
+
This method forwards all its arguments to LlamaTokenizerFast's [`~PreTrainedTokenizer.decode`]. Please refer to
|
208 |
+
the docstring of this method for more information.
|
209 |
+
"""
|
210 |
+
return self.tokenizer.decode(*args, **kwargs)
|
211 |
+
|
212 |
+
@property
|
213 |
+
# Copied from transformers.models.clip.processing_clip.CLIPProcessor.model_input_names
|
214 |
+
def model_input_names(self):
|
215 |
+
tokenizer_input_names = self.tokenizer.model_input_names
|
216 |
+
image_processor_input_names = self.image_processor.model_input_names
|
217 |
+
return list(dict.fromkeys(tokenizer_input_names + image_processor_input_names))
|
sample_inference.py
ADDED
@@ -0,0 +1,129 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
|
2 |
+
|
3 |
+
from PIL import Image
|
4 |
+
import requests
|
5 |
+
import torch
|
6 |
+
from transformers import AutoModelForCausalLM
|
7 |
+
from transformers import AutoProcessor
|
8 |
+
model_path = "./"
|
9 |
+
|
10 |
+
kwargs = {}
|
11 |
+
kwargs['torch_dtype'] = torch.bfloat16
|
12 |
+
|
13 |
+
processor = AutoProcessor.from_pretrained(model_path, trust_remote_code=True)
|
14 |
+
model = AutoModelForCausalLM.from_pretrained(model_path, trust_remote_code=True, torch_dtype="auto").cuda()
|
15 |
+
|
16 |
+
user_prompt = '<|user|>\n'
|
17 |
+
assistant_prompt = '<|assistant|>\n'
|
18 |
+
prompt_suffix = "<|end|>\n"
|
19 |
+
|
20 |
+
#################################################### text-only ####################################################
|
21 |
+
# single-image prompt
|
22 |
+
prompt = f"{user_prompt}what is the answer for 1+1? Explain it.{prompt_suffix}{assistant_prompt}"
|
23 |
+
print(f">>> Prompt\n{prompt}")
|
24 |
+
inputs = processor(prompt, images=None, return_tensors="pt").to("cuda:0")
|
25 |
+
generate_ids = model.generate(**inputs,
|
26 |
+
max_new_tokens=1000,
|
27 |
+
eos_token_id=processor.tokenizer.eos_token_id,
|
28 |
+
)
|
29 |
+
generate_ids = generate_ids[:, inputs['input_ids'].shape[1]:]
|
30 |
+
response = processor.batch_decode(generate_ids,
|
31 |
+
skip_special_tokens=True,
|
32 |
+
clean_up_tokenization_spaces=False)[0]
|
33 |
+
print(f'>>> Response\n{response}')
|
34 |
+
|
35 |
+
#################################################### text-only 2 ####################################################
|
36 |
+
# single-image prompt
|
37 |
+
prompt = f"{user_prompt}Give me the code for sloving two-sum problem.{prompt_suffix}{assistant_prompt}"
|
38 |
+
print(f">>> Prompt\n{prompt}")
|
39 |
+
inputs = processor(prompt, images=None, return_tensors="pt").to("cuda:0")
|
40 |
+
generate_ids = model.generate(**inputs,
|
41 |
+
max_new_tokens=1000,
|
42 |
+
eos_token_id=processor.tokenizer.eos_token_id,
|
43 |
+
)
|
44 |
+
generate_ids = generate_ids[:, inputs['input_ids'].shape[1]:]
|
45 |
+
response = processor.batch_decode(generate_ids,
|
46 |
+
skip_special_tokens=True,
|
47 |
+
clean_up_tokenization_spaces=False)[0]
|
48 |
+
print(f'>>> Response\n{response}')
|
49 |
+
|
50 |
+
|
51 |
+
#################################################### EXAMPLE 1 ####################################################
|
52 |
+
# single-image prompt
|
53 |
+
prompt = f"{user_prompt}<|image_1|>\nWhat is shown in this image?{prompt_suffix}{assistant_prompt}"
|
54 |
+
url = "https://www.ilankelman.org/stopsigns/australia.jpg"
|
55 |
+
print(f">>> Prompt\n{prompt}")
|
56 |
+
image = Image.open(requests.get(url, stream=True).raw)
|
57 |
+
inputs = processor(prompt, image, return_tensors="pt").to("cuda:0")
|
58 |
+
generate_ids = model.generate(**inputs,
|
59 |
+
max_new_tokens=1000,
|
60 |
+
eos_token_id=processor.tokenizer.eos_token_id,
|
61 |
+
)
|
62 |
+
generate_ids = generate_ids[:, inputs['input_ids'].shape[1]:]
|
63 |
+
response = processor.batch_decode(generate_ids,
|
64 |
+
skip_special_tokens=True,
|
65 |
+
clean_up_tokenization_spaces=False)[0]
|
66 |
+
print(f'>>> Response\n{response}')
|
67 |
+
|
68 |
+
#################################################### EXAMPLE 2 ####################################################
|
69 |
+
# multiple image prompt
|
70 |
+
# Note: image tokens must start from <|image_1|>
|
71 |
+
prompt = f"{user_prompt}<|image_1|>\n<|image_2|>\n What is shown in this two images?{prompt_suffix}{assistant_prompt}"
|
72 |
+
print(f">>> Prompt\n{prompt}")
|
73 |
+
url = "https://www.ilankelman.org/stopsigns/australia.jpg"
|
74 |
+
image_1 = Image.open(requests.get(url, stream=True).raw)
|
75 |
+
url = "https://img.freepik.com/free-photo/painting-mountain-lake-with-mountain-background_188544-9126.jpg?w=2000"
|
76 |
+
image_2 = Image.open(requests.get(url, stream=True).raw)
|
77 |
+
images = [image_1, image_2]
|
78 |
+
inputs = processor(prompt, images, return_tensors="pt").to("cuda:0")
|
79 |
+
generate_ids = model.generate(**inputs,
|
80 |
+
max_new_tokens=1000,
|
81 |
+
eos_token_id=processor.tokenizer.eos_token_id,
|
82 |
+
)
|
83 |
+
generate_ids = generate_ids[:, inputs['input_ids'].shape[1]:]
|
84 |
+
response = processor.batch_decode(generate_ids, skip_special_tokens=True, clean_up_tokenization_spaces=False)[0]
|
85 |
+
print(f'>>> Response\n{response}')
|
86 |
+
|
87 |
+
#################################################### EXAMPLE 3 ####################################################
|
88 |
+
# chat template
|
89 |
+
chat = [
|
90 |
+
{"role": "user", "content": "<|image_1|>\nWhat is shown in this image?"},
|
91 |
+
{"role": "assistant", "content": "The image depicts a street scene with a prominent red stop sign in the foreground. The background showcases a building with traditional Chinese architecture, characterized by its red roof and ornate decorations. There are also several statues of lions, which are common in Chinese culture, positioned in front of the building. The street is lined with various shops and businesses, and there's a car passing by."},
|
92 |
+
{"role": "user", "content": "What is so special about this image"}
|
93 |
+
]
|
94 |
+
url = "https://www.ilankelman.org/stopsigns/australia.jpg"
|
95 |
+
image = Image.open(requests.get(url, stream=True).raw)
|
96 |
+
prompt = processor.tokenizer.apply_chat_template(chat, tokenize=False, add_generation_prompt=True)
|
97 |
+
# need to remove last <|endoftext|> if it is there, which is used for training, not inference. For training, make sure to add <|endoftext|> in the end.
|
98 |
+
if prompt.endswith("<|endoftext|>"):
|
99 |
+
prompt = prompt.rstrip("<|endoftext|>")
|
100 |
+
|
101 |
+
print(f">>> Prompt\n{prompt}")
|
102 |
+
|
103 |
+
inputs = processor(prompt, [image], return_tensors="pt").to("cuda:0")
|
104 |
+
generate_ids = model.generate(**inputs,
|
105 |
+
max_new_tokens=1000,
|
106 |
+
eos_token_id=processor.tokenizer.eos_token_id,
|
107 |
+
)
|
108 |
+
generate_ids = generate_ids[:, inputs['input_ids'].shape[1]:]
|
109 |
+
response = processor.batch_decode(generate_ids, skip_special_tokens=True, clean_up_tokenization_spaces=False)[0]
|
110 |
+
print(f'>>> Response\n{response}')
|
111 |
+
|
112 |
+
|
113 |
+
############################# to markdown #############################
|
114 |
+
# single-image prompt
|
115 |
+
prompt = f"{user_prompt}<|image_1|>\nCan you convert the table to markdown format?{prompt_suffix}{assistant_prompt}"
|
116 |
+
url = "https://support.content.office.net/en-us/media/3dd2b79b-9160-403d-9967-af893d17b580.png"
|
117 |
+
image = Image.open(requests.get(url, stream=True).raw)
|
118 |
+
inputs = processor(prompt, image, return_tensors="pt").to("cuda:0")
|
119 |
+
|
120 |
+
print(f">>> Prompt\n{prompt}")
|
121 |
+
generate_ids = model.generate(**inputs,
|
122 |
+
max_new_tokens=1000,
|
123 |
+
eos_token_id=processor.tokenizer.eos_token_id,
|
124 |
+
)
|
125 |
+
generate_ids = generate_ids[:, inputs['input_ids'].shape[1]:]
|
126 |
+
response = processor.batch_decode(generate_ids,
|
127 |
+
skip_special_tokens=False,
|
128 |
+
clean_up_tokenization_spaces=False)[0]
|
129 |
+
print(f'>>> Response\n{response}')
|
special_tokens_map.json
ADDED
@@ -0,0 +1,36 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"additional_special_tokens": [
|
3 |
+
"<|system|>",
|
4 |
+
"<|end|>",
|
5 |
+
"<|user|>",
|
6 |
+
"<|end|>"
|
7 |
+
],
|
8 |
+
"bos_token": {
|
9 |
+
"content": "<s>",
|
10 |
+
"lstrip": false,
|
11 |
+
"normalized": false,
|
12 |
+
"rstrip": false,
|
13 |
+
"single_word": false
|
14 |
+
},
|
15 |
+
"eos_token": {
|
16 |
+
"content": "<|endoftext|>",
|
17 |
+
"lstrip": false,
|
18 |
+
"normalized": false,
|
19 |
+
"rstrip": false,
|
20 |
+
"single_word": false
|
21 |
+
},
|
22 |
+
"pad_token": {
|
23 |
+
"content": "<|endoftext|>",
|
24 |
+
"lstrip": false,
|
25 |
+
"normalized": false,
|
26 |
+
"rstrip": false,
|
27 |
+
"single_word": false
|
28 |
+
},
|
29 |
+
"unk_token": {
|
30 |
+
"content": "<unk>",
|
31 |
+
"lstrip": false,
|
32 |
+
"normalized": false,
|
33 |
+
"rstrip": false,
|
34 |
+
"single_word": false
|
35 |
+
}
|
36 |
+
}
|
tokenizer.json
ADDED
The diff for this file is too large to render.
See raw diff
|
|
tokenizer_config.json
ADDED
@@ -0,0 +1,408 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"add_bos_token": true,
|
3 |
+
"add_eos_token": false,
|
4 |
+
"added_tokens_decoder": {
|
5 |
+
"0": {
|
6 |
+
"content": "<unk>",
|
7 |
+
"lstrip": false,
|
8 |
+
"normalized": false,
|
9 |
+
"rstrip": false,
|
10 |
+
"single_word": false,
|
11 |
+
"special": true
|
12 |
+
},
|
13 |
+
"1": {
|
14 |
+
"content": "<s>",
|
15 |
+
"lstrip": false,
|
16 |
+
"normalized": false,
|
17 |
+
"rstrip": false,
|
18 |
+
"single_word": false,
|
19 |
+
"special": true
|
20 |
+
},
|
21 |
+
"2": {
|
22 |
+
"content": "</s>",
|
23 |
+
"lstrip": false,
|
24 |
+
"normalized": false,
|
25 |
+
"rstrip": true,
|
26 |
+
"single_word": false,
|
27 |
+
"special": false
|
28 |
+
},
|
29 |
+
"32000": {
|
30 |
+
"content": "<|endoftext|>",
|
31 |
+
"lstrip": false,
|
32 |
+
"normalized": false,
|
33 |
+
"rstrip": false,
|
34 |
+
"single_word": false,
|
35 |
+
"special": true
|
36 |
+
},
|
37 |
+
"32001": {
|
38 |
+
"content": "<|assistant|>",
|
39 |
+
"lstrip": false,
|
40 |
+
"normalized": false,
|
41 |
+
"rstrip": true,
|
42 |
+
"single_word": false,
|
43 |
+
"special": true
|
44 |
+
},
|
45 |
+
"32002": {
|
46 |
+
"content": "<|placeholder1|>",
|
47 |
+
"lstrip": false,
|
48 |
+
"normalized": false,
|
49 |
+
"rstrip": true,
|
50 |
+
"single_word": false,
|
51 |
+
"special": true
|
52 |
+
},
|
53 |
+
"32003": {
|
54 |
+
"content": "<|placeholder2|>",
|
55 |
+
"lstrip": false,
|
56 |
+
"normalized": false,
|
57 |
+
"rstrip": true,
|
58 |
+
"single_word": false,
|
59 |
+
"special": true
|
60 |
+
},
|
61 |
+
"32004": {
|
62 |
+
"content": "<|placeholder3|>",
|
63 |
+
"lstrip": false,
|
64 |
+
"normalized": false,
|
65 |
+
"rstrip": true,
|
66 |
+
"single_word": false,
|
67 |
+
"special": true
|
68 |
+
},
|
69 |
+
"32005": {
|
70 |
+
"content": "<|placeholder4|>",
|
71 |
+
"lstrip": false,
|
72 |
+
"normalized": false,
|
73 |
+
"rstrip": true,
|
74 |
+
"single_word": false,
|
75 |
+
"special": true
|
76 |
+
},
|
77 |
+
"32006": {
|
78 |
+
"content": "<|system|>",
|
79 |
+
"lstrip": false,
|
80 |
+
"normalized": false,
|
81 |
+
"rstrip": false,
|
82 |
+
"single_word": false,
|
83 |
+
"special": true
|
84 |
+
},
|
85 |
+
"32007": {
|
86 |
+
"content": "<|end|>",
|
87 |
+
"lstrip": false,
|
88 |
+
"normalized": false,
|
89 |
+
"rstrip": false,
|
90 |
+
"single_word": false,
|
91 |
+
"special": true
|
92 |
+
},
|
93 |
+
"32008": {
|
94 |
+
"content": "<|placeholder5|>",
|
95 |
+
"lstrip": false,
|
96 |
+
"normalized": false,
|
97 |
+
"rstrip": true,
|
98 |
+
"single_word": false,
|
99 |
+
"special": true
|
100 |
+
},
|
101 |
+
"32009": {
|
102 |
+
"content": "<|placeholder6|>",
|
103 |
+
"lstrip": false,
|
104 |
+
"normalized": false,
|
105 |
+
"rstrip": true,
|
106 |
+
"single_word": false,
|
107 |
+
"special": true
|
108 |
+
},
|
109 |
+
"32010": {
|
110 |
+
"content": "<|user|>",
|
111 |
+
"lstrip": false,
|
112 |
+
"normalized": false,
|
113 |
+
"rstrip": false,
|
114 |
+
"single_word": false,
|
115 |
+
"special": true
|
116 |
+
},
|
117 |
+
"32011": {
|
118 |
+
"content": "<|placeholder7|>",
|
119 |
+
"lstrip": false,
|
120 |
+
"normalized": false,
|
121 |
+
"rstrip": true,
|
122 |
+
"single_word": false,
|
123 |
+
"special": true
|
124 |
+
},
|
125 |
+
"32012": {
|
126 |
+
"content": "<|placeholder8|>",
|
127 |
+
"lstrip": false,
|
128 |
+
"normalized": false,
|
129 |
+
"rstrip": true,
|
130 |
+
"single_word": false,
|
131 |
+
"special": true
|
132 |
+
},
|
133 |
+
"32013": {
|
134 |
+
"content": "<|placeholder9|>",
|
135 |
+
"lstrip": false,
|
136 |
+
"normalized": false,
|
137 |
+
"rstrip": true,
|
138 |
+
"single_word": false,
|
139 |
+
"special": true
|
140 |
+
},
|
141 |
+
"32014": {
|
142 |
+
"content": "<|placeholder10|>",
|
143 |
+
"lstrip": false,
|
144 |
+
"normalized": false,
|
145 |
+
"rstrip": true,
|
146 |
+
"single_word": false,
|
147 |
+
"special": true
|
148 |
+
},
|
149 |
+
"32015": {
|
150 |
+
"content": "<|placeholder11|>",
|
151 |
+
"lstrip": false,
|
152 |
+
"normalized": false,
|
153 |
+
"rstrip": true,
|
154 |
+
"single_word": false,
|
155 |
+
"special": true
|
156 |
+
},
|
157 |
+
"32016": {
|
158 |
+
"content": "<|placeholder12|>",
|
159 |
+
"lstrip": false,
|
160 |
+
"normalized": false,
|
161 |
+
"rstrip": true,
|
162 |
+
"single_word": false,
|
163 |
+
"special": true
|
164 |
+
},
|
165 |
+
"32017": {
|
166 |
+
"content": "<|placeholder13|>",
|
167 |
+
"lstrip": false,
|
168 |
+
"normalized": false,
|
169 |
+
"rstrip": true,
|
170 |
+
"single_word": false,
|
171 |
+
"special": true
|
172 |
+
},
|
173 |
+
"32018": {
|
174 |
+
"content": "<|placeholder14|>",
|
175 |
+
"lstrip": false,
|
176 |
+
"normalized": false,
|
177 |
+
"rstrip": true,
|
178 |
+
"single_word": false,
|
179 |
+
"special": true
|
180 |
+
},
|
181 |
+
"32019": {
|
182 |
+
"content": "<|placeholder15|>",
|
183 |
+
"lstrip": false,
|
184 |
+
"normalized": false,
|
185 |
+
"rstrip": true,
|
186 |
+
"single_word": false,
|
187 |
+
"special": true
|
188 |
+
},
|
189 |
+
"32020": {
|
190 |
+
"content": "<|placeholder16|>",
|
191 |
+
"lstrip": false,
|
192 |
+
"normalized": false,
|
193 |
+
"rstrip": true,
|
194 |
+
"single_word": false,
|
195 |
+
"special": true
|
196 |
+
},
|
197 |
+
"32021": {
|
198 |
+
"content": "<|placeholder17|>",
|
199 |
+
"lstrip": false,
|
200 |
+
"normalized": false,
|
201 |
+
"rstrip": true,
|
202 |
+
"single_word": false,
|
203 |
+
"special": true
|
204 |
+
},
|
205 |
+
"32022": {
|
206 |
+
"content": "<|placeholder18|>",
|
207 |
+
"lstrip": false,
|
208 |
+
"normalized": false,
|
209 |
+
"rstrip": true,
|
210 |
+
"single_word": false,
|
211 |
+
"special": true
|
212 |
+
},
|
213 |
+
"32023": {
|
214 |
+
"content": "<|placeholder19|>",
|
215 |
+
"lstrip": false,
|
216 |
+
"normalized": false,
|
217 |
+
"rstrip": true,
|
218 |
+
"single_word": false,
|
219 |
+
"special": true
|
220 |
+
},
|
221 |
+
"32024": {
|
222 |
+
"content": "<|placeholder20|>",
|
223 |
+
"lstrip": false,
|
224 |
+
"normalized": false,
|
225 |
+
"rstrip": true,
|
226 |
+
"single_word": false,
|
227 |
+
"special": true
|
228 |
+
},
|
229 |
+
"32025": {
|
230 |
+
"content": "<|placeholder21|>",
|
231 |
+
"lstrip": false,
|
232 |
+
"normalized": false,
|
233 |
+
"rstrip": true,
|
234 |
+
"single_word": false,
|
235 |
+
"special": true
|
236 |
+
},
|
237 |
+
"32026": {
|
238 |
+
"content": "<|placeholder22|>",
|
239 |
+
"lstrip": false,
|
240 |
+
"normalized": false,
|
241 |
+
"rstrip": true,
|
242 |
+
"single_word": false,
|
243 |
+
"special": true
|
244 |
+
},
|
245 |
+
"32027": {
|
246 |
+
"content": "<|placeholder23|>",
|
247 |
+
"lstrip": false,
|
248 |
+
"normalized": false,
|
249 |
+
"rstrip": true,
|
250 |
+
"single_word": false,
|
251 |
+
"special": true
|
252 |
+
},
|
253 |
+
"32028": {
|
254 |
+
"content": "<|placeholder24|>",
|
255 |
+
"lstrip": false,
|
256 |
+
"normalized": false,
|
257 |
+
"rstrip": true,
|
258 |
+
"single_word": false,
|
259 |
+
"special": true
|
260 |
+
},
|
261 |
+
"32029": {
|
262 |
+
"content": "<|placeholder25|>",
|
263 |
+
"lstrip": false,
|
264 |
+
"normalized": false,
|
265 |
+
"rstrip": true,
|
266 |
+
"single_word": false,
|
267 |
+
"special": true
|
268 |
+
},
|
269 |
+
"32030": {
|
270 |
+
"content": "<|placeholder26|>",
|
271 |
+
"lstrip": false,
|
272 |
+
"normalized": false,
|
273 |
+
"rstrip": true,
|
274 |
+
"single_word": false,
|
275 |
+
"special": true
|
276 |
+
},
|
277 |
+
"32031": {
|
278 |
+
"content": "<|placeholder27|>",
|
279 |
+
"lstrip": false,
|
280 |
+
"normalized": false,
|
281 |
+
"rstrip": true,
|
282 |
+
"single_word": false,
|
283 |
+
"special": true
|
284 |
+
},
|
285 |
+
"32032": {
|
286 |
+
"content": "<|placeholder28|>",
|
287 |
+
"lstrip": false,
|
288 |
+
"normalized": false,
|
289 |
+
"rstrip": true,
|
290 |
+
"single_word": false,
|
291 |
+
"special": true
|
292 |
+
},
|
293 |
+
"32033": {
|
294 |
+
"content": "<|placeholder29|>",
|
295 |
+
"lstrip": false,
|
296 |
+
"normalized": false,
|
297 |
+
"rstrip": true,
|
298 |
+
"single_word": false,
|
299 |
+
"special": true
|
300 |
+
},
|
301 |
+
"32034": {
|
302 |
+
"content": "<|placeholder30|>",
|
303 |
+
"lstrip": false,
|
304 |
+
"normalized": false,
|
305 |
+
"rstrip": true,
|
306 |
+
"single_word": false,
|
307 |
+
"special": true
|
308 |
+
},
|
309 |
+
"32035": {
|
310 |
+
"content": "<|placeholder31|>",
|
311 |
+
"lstrip": false,
|
312 |
+
"normalized": false,
|
313 |
+
"rstrip": true,
|
314 |
+
"single_word": false,
|
315 |
+
"special": true
|
316 |
+
},
|
317 |
+
"32036": {
|
318 |
+
"content": "<|placeholder32|>",
|
319 |
+
"lstrip": false,
|
320 |
+
"normalized": false,
|
321 |
+
"rstrip": true,
|
322 |
+
"single_word": false,
|
323 |
+
"special": true
|
324 |
+
},
|
325 |
+
"32037": {
|
326 |
+
"content": "<|placeholder33|>",
|
327 |
+
"lstrip": false,
|
328 |
+
"normalized": false,
|
329 |
+
"rstrip": true,
|
330 |
+
"single_word": false,
|
331 |
+
"special": true
|
332 |
+
},
|
333 |
+
"32038": {
|
334 |
+
"content": "<|placeholder34|>",
|
335 |
+
"lstrip": false,
|
336 |
+
"normalized": false,
|
337 |
+
"rstrip": true,
|
338 |
+
"single_word": false,
|
339 |
+
"special": true
|
340 |
+
},
|
341 |
+
"32039": {
|
342 |
+
"content": "<|placeholder35|>",
|
343 |
+
"lstrip": false,
|
344 |
+
"normalized": false,
|
345 |
+
"rstrip": true,
|
346 |
+
"single_word": false,
|
347 |
+
"special": true
|
348 |
+
},
|
349 |
+
"32040": {
|
350 |
+
"content": "<|placeholder36|>",
|
351 |
+
"lstrip": false,
|
352 |
+
"normalized": false,
|
353 |
+
"rstrip": true,
|
354 |
+
"single_word": false,
|
355 |
+
"special": true
|
356 |
+
},
|
357 |
+
"32041": {
|
358 |
+
"content": "<|placeholder37|>",
|
359 |
+
"lstrip": false,
|
360 |
+
"normalized": false,
|
361 |
+
"rstrip": true,
|
362 |
+
"single_word": false,
|
363 |
+
"special": true
|
364 |
+
},
|
365 |
+
"32042": {
|
366 |
+
"content": "<|placeholder38|>",
|
367 |
+
"lstrip": false,
|
368 |
+
"normalized": false,
|
369 |
+
"rstrip": true,
|
370 |
+
"single_word": false,
|
371 |
+
"special": true
|
372 |
+
},
|
373 |
+
"32043": {
|
374 |
+
"content": "<|placeholder39|>",
|
375 |
+
"lstrip": false,
|
376 |
+
"normalized": false,
|
377 |
+
"rstrip": true,
|
378 |
+
"single_word": false,
|
379 |
+
"special": true
|
380 |
+
},
|
381 |
+
"32044": {
|
382 |
+
"content": "<|image|>",
|
383 |
+
"lstrip": false,
|
384 |
+
"normalized": false,
|
385 |
+
"rstrip": true,
|
386 |
+
"single_word": false,
|
387 |
+
"special": true
|
388 |
+
}
|
389 |
+
},
|
390 |
+
"additional_special_tokens": [
|
391 |
+
"<|system|>",
|
392 |
+
"<|end|>",
|
393 |
+
"<|user|>",
|
394 |
+
"<|end|>"
|
395 |
+
],
|
396 |
+
"bos_token": "<s>",
|
397 |
+
"chat_template": "{% for message in messages %}{{'<|' + message['role'] + '|>' + '\n' + message['content'] + '<|end|>\n' }}{% endfor %}{% if add_generation_prompt and messages[-1]['role'] != 'assistant' %}{{- '<|assistant|>\n' -}}{% endif %}",
|
398 |
+
"clean_up_tokenization_spaces": false,
|
399 |
+
"eos_token": "<|endoftext|>",
|
400 |
+
"legacy": false,
|
401 |
+
"model_max_length": 131072,
|
402 |
+
"pad_token": "<|endoftext|>",
|
403 |
+
"padding_side": "right",
|
404 |
+
"sp_model_kwargs": {},
|
405 |
+
"tokenizer_class": "LlamaTokenizer",
|
406 |
+
"unk_token": "<unk>",
|
407 |
+
"use_default_system_prompt": false
|
408 |
+
}
|