Files
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

195 lines
8.9 KiB
Python

# Copyright (c) ModelScope Contributors. All rights reserved.
import torch
from dataclasses import dataclass, field
from PIL import Image
from transformers.dynamic_module_utils import get_class_from_dynamic_module
from typing import Any, Dict, List, Literal, Optional
from swift.utils import get_env_args
from ..base import Template
from ..constant import LLMTemplateType, MLLMTemplateType, RMTemplateType
from ..register import TemplateMeta, register_template
from ..template_inputs import StdTemplateInputs
from ..utils import Context, Prompt, Word
from ..vision_utils import load_file
from .utils import ChatmlTemplateMeta
INTERNLM_SYSTEM = (
'You are an AI assistant whose name is InternLM (书生·浦语).\n'
'- InternLM (书生·浦语) is a conversational language model that is developed by Shanghai AI Laboratory (上海人工智能实验室). '
'It is designed to be helpful, honest, and harmless.\n'
'- InternLM (书生·浦语) can understand and communicate fluently in the language chosen '
'by the user such as English and 中文.')
register_template(
TemplateMeta(
LLMTemplateType.internlm,
prefix=['<s>'],
prompt=['<|User|>:{{QUERY}}\n<|Bot|>:'],
chat_sep=['<eoa>\n'],
suffix=['<eoa>'],
default_system=INTERNLM_SYSTEM,
system_prefix=['<s><|System|>:{{SYSTEM}}\n']))
register_template(ChatmlTemplateMeta(LLMTemplateType.internlm2, default_system=INTERNLM_SYSTEM))
register_template(ChatmlTemplateMeta(RMTemplateType.internlm2_reward, suffix=['<|im_end|>\n<|reward|>']))
class InternLMXComposer2Template(Template):
image_placeholder = ['</s>']
version = 'v2'
skip_prompt = False
use_model = True
def replace_tag(self, media_type: Literal['image', 'video', 'audio'], index: int,
inputs: StdTemplateInputs) -> List[Context]:
if media_type == 'video':
inputs.images.insert(inputs.image_idx, inputs.videos[index])
inputs.image_idx += 1
return self.image_placeholder
def _encode(self, inputs: StdTemplateInputs) -> Dict[str, Any]:
model = self.model
encoded = super()._encode(inputs)
images = inputs.images or []
if self.version == 'v2.5':
hd_num = 24
if len(images) > 1:
hd_num = 6
hd_num = get_env_args('hd_num', int, hd_num)
images_origin = images
images = []
for image in images_origin:
if isinstance(image, Image.Image):
Image_transform = get_class_from_dynamic_module('ixc_utils.Image_transform', model.model_dir)
images.append(Image_transform(image, hd_num=hd_num))
else:
load_video = get_class_from_dynamic_module('ixc_utils.load_video', model.model_dir)
frame2img = get_class_from_dynamic_module('ixc_utils.frame2img', model.model_dir)
Video_transform = get_class_from_dynamic_module('ixc_utils.Video_transform', model.model_dir)
image = load_video(load_file(image))
image = frame2img(image, model.font)
images.append(Video_transform(image, hd_num=hd_num))
elif self.version == 'v2-4khd':
hd_num = 55
hd_num = get_env_args('hd_num', int, hd_num)
HD_transform = get_class_from_dynamic_module('ixc_utils.HD_transform', model.model_dir)
images = [HD_transform(image, hd_num=hd_num) for image in images]
images = [model.vis_processor(image).to(model.dtype) for image in images]
encoded['images'] = images
return encoded
def _post_encode(self, model, inputs: Dict[str, Any]) -> Dict[str, Any]:
batch_size = len(inputs['input_ids'])
res = []
im_mask = []
length = inputs['length']
for i in range(batch_size):
input_ids = inputs['input_ids'][i].tolist()[:length[i]]
input_ids.append(2) # add dummy </s>
labels = inputs.get('labels')
if labels is not None:
labels = labels[i].tolist()[:length[i]]
labels.append(2)
else:
labels = []
images = inputs['images'][i]
res_inputs_embeds = []
res_labels = []
wrap_im_mask = []
pre_i, i, idx = 0, 0, 0
device = model.device
internlm2_model = model.model
if not hasattr(internlm2_model, 'tok_embeddings'):
internlm2_model = internlm2_model.model
tok_embeddings = internlm2_model.tok_embeddings
if len(images) > 0:
images = torch.concat([model.img2emb(image[None])[0] for image in images], dim=0)
add_bos = False
while i < len(input_ids):
if input_ids[i] == 2: # replace_token
res_input_ids = torch.tensor(([1] if add_bos else []) + input_ids[pre_i:i], device=device)
if not add_bos and self.version != 'v2.5':
add_bos = True
res_inputs_embeds.append(tok_embeddings(res_input_ids[None])[0])
wrap_im_mask += [0] * len(res_input_ids)
res_labels += ([-100] if add_bos else []) + labels[pre_i:i]
if len(images) > 0 and idx < images.shape[0]:
res_inputs_embeds.append(images[idx].to(device))
wrap_im_mask += [1] * images.shape[1]
res_labels += [-100] * images.shape[1]
idx += 1
i += 1
pre_i = i
continue
i += 1
if len(labels) == 0:
res_labels = None
im_mask.append(torch.tensor(wrap_im_mask, dtype=torch.bool, device=device))
res.append({'inputs_embeds': torch.concat(res_inputs_embeds, dim=0), 'labels': res_labels})
res = Template._data_collator(self, res)
res['im_mask'] = self._pad_sequence(im_mask, 0)
return res
def _data_collator(self, batch: List[Dict[str, Any]], *, padding_to: Optional[int] = None) -> Dict[str, Any]:
res = super()._data_collator(batch, padding_to=padding_to)
res['length'] = [len(b['input_ids']) for b in batch]
res.update(self.fetch_inputs(batch, ['images']))
return res
@dataclass
class Xcomposer2TemplateMeta(TemplateMeta):
prefix: Prompt = field(default_factory=lambda: ['<s>'])
prompt: Prompt = field(
default_factory=lambda: ['[UNUSED_TOKEN_146]user\n{{QUERY}}[UNUSED_TOKEN_145]\n[UNUSED_TOKEN_146]assistant\n'])
chat_sep: Optional[Prompt] = field(default_factory=lambda: ['[UNUSED_TOKEN_145]\n'])
suffix: Prompt = field(default_factory=lambda: ['[UNUSED_TOKEN_145]'])
system_prefix: Optional[Prompt] = field(
default_factory=lambda: ['<s>[UNUSED_TOKEN_146]system\n{{SYSTEM}}[UNUSED_TOKEN_145]\n'])
stop_words: List[Word] = field(default_factory=lambda: ['<|im_end|>'])
register_template(
Xcomposer2TemplateMeta(
MLLMTemplateType.xcomposer2,
template_cls=InternLMXComposer2Template,
default_system=('You are an AI assistant whose name is InternLM-XComposer (浦语·灵笔).\n'
'- InternLM-XComposer (浦语·灵笔) is a conversational language model that is developed by '
'Shanghai AI Laboratory (上海人工智能实验室). '
'It is designed to be helpful, honest, and harmless.\n'
'- InternLM-XComposer (浦语·灵笔) can understand and communicate fluently in the language chosen '
'by the user such as English and 中文.'),
))
class InternLMXComposer2_5Template(InternLMXComposer2Template):
system = ('You are an AI assistant whose name is InternLM-XComposer (浦语·灵笔).\n'
'- InternLM-XComposer (浦语·灵笔) is a multi-modality conversational language model '
'that is developed by Shanghai AI Laboratory (上海人工智能实验室). '
'It is designed to be helpful, honest, and harmless.\n'
'- InternLM-XComposer (浦语·灵笔) can understand and communicate fluently in the language chosen '
'by the user such as English and 中文.\n'
'- InternLM-XComposer (浦语·灵笔) is capable of comprehending and articulating responses effectively '
'based on the provided image.')
version = 'v2.5'
class InternLMXComposer2_4khdTemplate(InternLMXComposer2Template):
version = 'v2-4khd'
register_template(
Xcomposer2TemplateMeta(
MLLMTemplateType.xcomposer2_5,
template_cls=InternLMXComposer2_5Template,
default_system=InternLMXComposer2_5Template.system))
register_template(
Xcomposer2TemplateMeta(
MLLMTemplateType.xcomposer2_4khd,
template_cls=InternLMXComposer2_4khdTemplate,
default_system=InternLMXComposer2_5Template.system))