OpenGVLab/InternVL3-1B-Instruct
92.2k
1"""2Conversation prompt templates.3 4We kindly request that you import fastchat instead of copying this file if you wish to use it.5If you have changes in mind, please contribute back so the community can benefit collectively and continue to maintain these valuable templates.6 7Modified from https://github.com/lm-sys/FastChat/blob/main/fastchat/conversation.py8"""9 10import dataclasses11from enum import IntEnum, auto12from typing import Dict, List, Tuple, Union13 14 15class SeparatorStyle(IntEnum):16 """Separator styles."""17 18 ADD_COLON_SINGLE = auto()19 ADD_COLON_TWO = auto()20 ADD_COLON_SPACE_SINGLE = auto()21 NO_COLON_SINGLE = auto()22 NO_COLON_TWO = auto()23 ADD_NEW_LINE_SINGLE = auto()24 LLAMA2 = auto()25 CHATGLM = auto()26 CHATML = auto()27 CHATINTERN = auto()28 DOLLY = auto()29 RWKV = auto()30 PHOENIX = auto()31 ROBIN = auto()32 FALCON_CHAT = auto()33 CHATGLM3 = auto()34 INTERNVL_ZH = auto()35 MPT = auto()36 37 38@dataclasses.dataclass39class Conversation:40 """A class that manages prompt templates and keeps all conversation history."""41 42 # The name of this template43 name: str44 # The template of the system prompt45 system_template: str = '{system_message}'46 # The system message47 system_message: str = ''48 # The names of two roles49 roles: Tuple[str] = ('USER', 'ASSISTANT')50 # All messages. Each item is (role, message).51 messages: List[List[str]] = ()52 # The number of few shot examples53 offset: int = 054 # The separator style and configurations55 sep_style: SeparatorStyle = SeparatorStyle.ADD_COLON_SINGLE56 sep: str = '\n'57 sep2: str = None58 # Stop criteria (the default one is EOS token)59 stop_str: Union[str, List[str]] = None60 # Stops generation if meeting any token in this list61 stop_token_ids: List[int] = None62 63 def get_prompt(self) -> str:64 """Get the prompt for generation."""65 system_prompt = self.system_template.format(system_message=self.system_message)66 if self.sep_style == SeparatorStyle.ADD_COLON_SINGLE:67 ret = system_prompt + self.sep68 for role, message in self.messages:69 if message:70 ret += role + ': ' + message + self.sep71 else:72 ret += role + ':'73 return ret74 elif self.sep_style == SeparatorStyle.ADD_COLON_TWO:75 seps = [self.sep, self.sep2]76 ret = system_prompt + seps[0]77 for i, (role, message) in enumerate(self.messages):78 if message:79 ret += role + ': ' + message + seps[i % 2]80 else:81 ret += role + ':'82 return ret83 elif self.sep_style == SeparatorStyle.ADD_COLON_SPACE_SINGLE:84 ret = system_prompt + self.sep85 for role, message in self.messages:86 if message:87 ret += role + ': ' + message + self.sep88 else:89 ret += role + ': ' # must be end with a space90 return ret91 elif self.sep_style == SeparatorStyle.ADD_NEW_LINE_SINGLE:92 ret = '' if system_prompt == '' else system_prompt + self.sep93 for role, message in self.messages:94 if message:95 ret += role + '\n' + message + self.sep96 else:97 ret += role + '\n'98 return ret99 elif self.sep_style == SeparatorStyle.NO_COLON_SINGLE:100 ret = system_prompt101 for role, message in self.messages:102 if message:103 ret += role + message + self.sep104 else:105 ret += role106 return ret107 elif self.sep_style == SeparatorStyle.NO_COLON_TWO:108 seps = [self.sep, self.sep2]109 ret = system_prompt110 for i, (role, message) in enumerate(self.messages):111 if message:112 ret += role + message + seps[i % 2]113 else:114 ret += role115 return ret116 elif self.sep_style == SeparatorStyle.RWKV:117 ret = system_prompt118 for i, (role, message) in enumerate(self.messages):119 if message:120 ret += (121 role122 + ': '123 + message.replace('\r\n', '\n').replace('\n\n', '\n')124 )125 ret += '\n\n'126 else:127 ret += role + ':'128 return ret129 elif self.sep_style == SeparatorStyle.LLAMA2:130 seps = [self.sep, self.sep2]131 if self.system_message:132 ret = system_prompt133 else:134 ret = '[INST] '135 for i, (role, message) in enumerate(self.messages):136 tag = self.roles[i % 2]137 if message:138 if i == 0:139 ret += message + ' '140 else:141 ret += tag + ' ' + message + seps[i % 2]142 else:143 ret += tag144 return ret145 elif self.sep_style == SeparatorStyle.CHATGLM:146 # source: https://huggingface.co/THUDM/chatglm-6b/blob/1d240ba371910e9282298d4592532d7f0f3e9f3e/modeling_chatglm.py#L1302-L1308147 # source2: https://huggingface.co/THUDM/chatglm2-6b/blob/e186c891cf64310ac66ef10a87e6635fa6c2a579/modeling_chatglm.py#L926148 round_add_n = 1 if self.name == 'chatglm2' else 0149 if system_prompt:150 ret = system_prompt + self.sep151 else:152 ret = ''153 154 for i, (role, message) in enumerate(self.messages):155 if i % 2 == 0:156 ret += f'[Round {i//2 + round_add_n}]{self.sep}'157 158 if message:159 ret += f'{role}:{message}{self.sep}'160 else:161 ret += f'{role}:'162 return ret163 elif self.sep_style == SeparatorStyle.CHATML:164 ret = '' if system_prompt == '' else system_prompt + self.sep + '\n'165 for role, message in self.messages:166 if message:167 ret += role + '\n' + message + self.sep + '\n'168 else:169 ret += role + '\n'170 return ret171 elif self.sep_style == SeparatorStyle.CHATGLM3:172 ret = ''173 if self.system_message:174 ret += system_prompt175 for role, message in self.messages:176 if message:177 ret += role + '\n' + ' ' + message178 else:179 ret += role180 return ret181 elif self.sep_style == SeparatorStyle.CHATINTERN:182 # source: https://huggingface.co/internlm/internlm-chat-7b-8k/blob/bd546fa984b4b0b86958f56bf37f94aa75ab8831/modeling_internlm.py#L771183 seps = [self.sep, self.sep2]184 ret = system_prompt185 for i, (role, message) in enumerate(self.messages):186 # if i % 2 == 0:187 # ret += "<s>"188 if message:189 ret += role + ':' + message + seps[i % 2] + '\n'190 else:191 ret += role + ':'192 return ret193 elif self.sep_style == SeparatorStyle.DOLLY:194 seps = [self.sep, self.sep2]195 ret = system_prompt196 for i, (role, message) in enumerate(self.messages):197 if message:198 ret += role + ':\n' + message + seps[i % 2]199 if i % 2 == 1:200 ret += '\n\n'201 else:202 ret += role + ':\n'203 return ret204 elif self.sep_style == SeparatorStyle.PHOENIX:205 ret = system_prompt206 for role, message in self.messages:207 if message:208 ret += role + ': ' + '<s>' + message + '</s>'209 else:210 ret += role + ': ' + '<s>'211 return ret212 elif self.sep_style == SeparatorStyle.ROBIN:213 ret = system_prompt + self.sep214 for role, message in self.messages:215 if message:216 ret += role + ':\n' + message + self.sep217 else:218 ret += role + ':\n'219 return ret220 elif self.sep_style == SeparatorStyle.FALCON_CHAT:221 ret = ''222 if self.system_message:223 ret += system_prompt + self.sep224 for role, message in self.messages:225 if message:226 ret += role + ': ' + message + self.sep227 else:228 ret += role + ':'229 230 return ret231 elif self.sep_style == SeparatorStyle.INTERNVL_ZH:232 seps = [self.sep, self.sep2]233 ret = self.system_message + seps[0]234 for i, (role, message) in enumerate(self.messages):235 if message:236 ret += role + ': ' + message + seps[i % 2]237 else:238 ret += role + ':'239 return ret240 elif self.sep_style == SeparatorStyle.MPT:241 ret = system_prompt + self.sep242 for role, message in self.messages:243 if message:244 if type(message) is tuple:245 message, _, _ = message246 ret += role + message + self.sep247 else:248 ret += role249 return ret250 else:251 raise ValueError(f'Invalid style: {self.sep_style}')252 253 def set_system_message(self, system_message: str):254 """Set the system message."""255 self.system_message = system_message256 257 def append_message(self, role: str, message: str):258 """Append a new message."""259 self.messages.append([role, message])260 261 def update_last_message(self, message: str):262 """Update the last output.263 264 The last message is typically set to be None when constructing the prompt,265 so we need to update it in-place after getting the response from a model.266 """267 self.messages[-1][1] = message268 269 def to_gradio_chatbot(self):270 """Convert the conversation to gradio chatbot format."""271 ret = []272 for i, (role, msg) in enumerate(self.messages[self.offset :]):273 if i % 2 == 0:274 ret.append([msg, None])275 else:276 ret[-1][-1] = msg277 return ret278 279 def to_openai_api_messages(self):280 """Convert the conversation to OpenAI chat completion format."""281 ret = [{'role': 'system', 'content': self.system_message}]282 283 for i, (_, msg) in enumerate(self.messages[self.offset :]):284 if i % 2 == 0:285 ret.append({'role': 'user', 'content': msg})286 else:287 if msg is not None:288 ret.append({'role': 'assistant', 'content': msg})289 return ret290 291 def copy(self):292 return Conversation(293 name=self.name,294 system_template=self.system_template,295 system_message=self.system_message,296 roles=self.roles,297 messages=[[x, y] for x, y in self.messages],298 offset=self.offset,299 sep_style=self.sep_style,300 sep=self.sep,301 sep2=self.sep2,302 stop_str=self.stop_str,303 stop_token_ids=self.stop_token_ids,304 )305 306 def dict(self):307 return {308 'template_name': self.name,309 'system_message': self.system_message,310 'roles': self.roles,311 'messages': self.messages,312 'offset': self.offset,313 }314 315 316# A global registry for all conversation templates317conv_templates: Dict[str, Conversation] = {}318 319 320def register_conv_template(template: Conversation, override: bool = False):321 """Register a new conversation template."""322 if not override:323 assert (324 template.name not in conv_templates325 ), f'{template.name} has been registered.'326 327 conv_templates[template.name] = template328 329 330def get_conv_template(name: str) -> Conversation:331 """Get a conversation template."""332 return conv_templates[name].copy()333 334 335# Both Hermes-2 and internlm2-chat are chatml-format conversation templates. The difference336# is that during training, the preprocessing function for the Hermes-2 template doesn't add337# <s> at the beginning of the tokenized sequence, while the internlm2-chat template does.338# Therefore, they are completely equivalent during inference.339register_conv_template(340 Conversation(341 name='Hermes-2',342 system_template='<|im_start|>system\n{system_message}',343 # note: The new system prompt was not used here to avoid changes in benchmark performance.344 # system_message='我是书生·万象,英文名是InternVL,是由上海人工智能实验室、清华大学及多家合作单位联合开发的多模态大语言模型。',345 system_message='你是由上海人工智能实验室联合商汤科技开发的书生多模态大模型,英文名叫InternVL, 是一个有用无害的人工智能助手。',346 roles=('<|im_start|>user\n', '<|im_start|>assistant\n'),347 sep_style=SeparatorStyle.MPT,348 sep='<|im_end|>',349 stop_str='<|endoftext|>',350 )351)352 353 354register_conv_template(355 Conversation(356 name='internlm2-chat',357 system_template='<|im_start|>system\n{system_message}',358 # note: The new system prompt was not used here to avoid changes in benchmark performance.359 # system_message='我是书生·万象,英文名是InternVL,是由上海人工智能实验室、清华大学及多家合作单位联合开发的多模态大语言模型。',360 system_message='你是由上海人工智能实验室联合商汤科技开发的书生多模态大模型,英文名叫InternVL, 是一个有用无害的人工智能助手。',361 roles=('<|im_start|>user\n', '<|im_start|>assistant\n'),362 sep_style=SeparatorStyle.MPT,363 sep='<|im_end|>',364 )365)366 367 368register_conv_template(369 Conversation(370 name='phi3-chat',371 system_template='<|system|>\n{system_message}',372 # note: The new system prompt was not used here to avoid changes in benchmark performance.373 # system_message='我是书生·万象,英文名是InternVL,是由上海人工智能实验室、清华大学及多家合作单位联合开发的多模态大语言模型。',374 system_message='你是由上海人工智能实验室联合商汤科技开发的书生多模态大模型,英文名叫InternVL, 是一个有用无害的人工智能助手。',375 roles=('<|user|>\n', '<|assistant|>\n'),376 sep_style=SeparatorStyle.MPT,377 sep='<|end|>',378 )379)380 381 382register_conv_template(383 Conversation(384 name='internvl2_5',385 system_template='<|im_start|>system\n{system_message}',386 system_message='你是书生·万象,英文名是InternVL,是由上海人工智能实验室、清华大学及多家合作单位联合开发的多模态大语言模型。',387 roles=('<|im_start|>user\n', '<|im_start|>assistant\n'),388 sep_style=SeparatorStyle.MPT,389 sep='<|im_end|>\n',390 )391)392 