项目文件夹

文件
wehub-resource-sync a203934033
Lint test / lint (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:34:58 +08:00

117 行
5.7 KiB
Python

此文件含有模棱两可的 Unicode 字符
此文件含有可能会与其他字符混淆的 Unicode 字符。 如果您是想特意这样的,可以安全地忽略该警告。 使用 Escape 按钮显示他们。
# Copyright (c) ModelScope Contributors. All rights reserved.
import torch
from dataclasses import dataclass, field
from typing import Any, Dict, List, Literal, Optional
from ..base import Template
from ..constant import MLLMTemplateType
from ..register import TemplateMeta, register_template
from ..template_inputs import StdTemplateInputs
from ..utils import Context, Prompt, findall
@dataclass
class HunYuanVLTemplateMeta(TemplateMeta):
prefix: Prompt = field(default_factory=lambda: ['<hy_begin▁of▁sentence>'])
prompt: Prompt = field(default_factory=lambda: ['{{QUERY}}<hy_User>'])
chat_sep: Optional[Prompt] = field(default_factory=lambda: ['<hy_Assistant><hy_begin▁of▁sentence>'])
suffix: Prompt = field(default_factory=lambda: ['<hy_Assistant>'])
system_prefix: Optional[Prompt] = field(
default_factory=lambda: ['<hy_begin▁of▁sentence>{{SYSTEM}}<hy_place▁holder▁no▁3>'])
class HunYuanVLTemplate(Template):
image_token_id = 120120
placeholder_tokens = ['<hy_place▁holder▁no▁102>']
# support_padding_free = True # position_ids with batch_dim of 0 does not support padding_free
def replace_tag(self, media_type: Literal['image', 'video', 'audio'], index: int,
inputs: StdTemplateInputs) -> List[Context]:
assert media_type == 'image'
if self.mode == 'vllm':
return ['<hy_place▁holder▁no▁100><hy_place▁holder▁no▁102><hy_place▁holder▁no▁101>']
return [[-100]]
def _encode(self, inputs: StdTemplateInputs) -> Dict[str, Any]:
encoded = super()._encode(inputs)
input_ids = encoded['input_ids']
labels = encoded['labels']
loss_scale = encoded.get('loss_scale', None)
idx_list = findall(input_ids, -100)
processor = self.processor
images = inputs.images
if images:
image_inputs = processor.image_processor(images=images, return_tensors='pt')
image_grid_thw = image_inputs['image_grid_thw']
merge_size = processor.image_processor.merge_size
def _get_new_tokens(i):
grid_h, grid_w = image_grid_thw[i][-2:]
patch_h = grid_h // merge_size
patch_w = grid_w // merge_size
img_tokens: List[int] = [self.image_token_id] * (patch_h * (patch_w + 1) + 2)
return img_tokens
encoded['input_ids'], encoded['labels'], encoded['loss_scale'] = self._extend_tokens(
input_ids, labels, loss_scale, idx_list, _get_new_tokens)
encoded['pixel_values'] = image_inputs['pixel_values']
encoded['image_grid_thw'] = image_grid_thw
input_ids = encoded['input_ids']
position_ids = torch.arange(len(input_ids))
position_ids_w = torch.arange(len(input_ids))
position_ids_h = torch.arange(len(input_ids))
position_ids_t = torch.arange(len(input_ids))
image_tokens_cumsum = [0]
for i in range(len(image_grid_thw)):
grid_h, grid_w = image_grid_thw[i][-2:]
patch_h = grid_h // merge_size
patch_w = grid_w // merge_size
num_image_tokens = patch_h * (patch_w + 1) + 2
image_tokens_cumsum.append(image_tokens_cumsum[-1] + int(num_image_tokens))
image_token_pos_indices = torch.where(torch.tensor(input_ids) == self.image_token_id)
start_pos = image_token_pos_indices[0][image_tokens_cumsum[i]] + 1
replace_num = (patch_w + 1) * patch_h
position_ids_w[start_pos:start_pos + replace_num] = torch.tensor(
list(range(patch_w + 1)) * patch_h, dtype=torch.int64)
patch_h_list = []
for h in range(patch_h):
patch_h_list += [h] * (patch_w + 1)
position_ids_h[start_pos:start_pos + replace_num] = torch.tensor(patch_h_list, dtype=torch.int64)
position_ids_t[start_pos:start_pos + replace_num] = 0
position_ids = torch.stack([position_ids, position_ids_w, position_ids_h, position_ids_t]).unsqueeze(0)
encoded['position_ids'] = position_ids
attention_mask = torch.tensor(input_ids).ne(processor.pad_id)
encoded['attention_mask'] = attention_mask
return encoded
def _post_encode(self, model, inputs: Dict[str, Any]) -> Dict[str, Any]:
if not self.is_training:
return inputs
input_ids = inputs['input_ids']
pixel_values = inputs.get('pixel_values')
image_grid_thw = inputs.get('image_grid_thw')
base_model = self.get_base_model(model)
inputs_embeds = base_model.model.embed_tokens(input_ids)
if pixel_values is not None:
pixel_values = pixel_values.to(base_model.dtype)
image_embeds = base_model.vit(pixel_values, image_grid_thw)
image_embeds = image_embeds.to(input_ids.device, non_blocking=True)
image_mask, _ = base_model.get_placeholder_mask(
input_ids, inputs_embeds=inputs_embeds, image_features=image_embeds)
inputs_embeds = inputs_embeds.masked_scatter(image_mask, image_embeds)
return {'inputs_embeds': inputs_embeds}
def _pad_3d_position_ids(self,
position_ids: List[torch.Tensor],
padding_value: float = 0.,
batch_dim: int = 1) -> torch.Tensor:
batch_dim = 0
return super()._pad_3d_position_ids(position_ids, padding_value, batch_dim)
register_template(HunYuanVLTemplateMeta(MLLMTemplateType.hunyuan_ocr, template_cls=HunYuanVLTemplate))