MathLLMs/MathCoder-VL-8B
677
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"""7 8import dataclasses9from enum import IntEnum, auto10from typing import Any, Dict, List, Tuple, Union11 12 13class SeparatorStyle(IntEnum):14 """Separator styles."""15 16 ADD_COLON_SINGLE = auto()17 ADD_COLON_TWO = auto()18 ADD_COLON_SPACE_SINGLE = auto()19 NO_COLON_SINGLE = auto()20 NO_COLON_TWO = auto()21 ADD_NEW_LINE_SINGLE = auto()22 LLAMA2 = auto()23 CHATGLM = auto()24 CHATML = auto()25 CHATINTERN = auto()26 DOLLY = auto()27 RWKV = auto()28 PHOENIX = auto()29 ROBIN = auto()30 FALCON_CHAT = auto()31 CHATGLM3 = auto()32 INTERNVL_ZH = auto()33 MPT = auto()34 35 36@dataclasses.dataclass37class Conversation:38 """A class that manages prompt templates and keeps all conversation history."""39 40 # The name of this template41 name: str42 # The template of the system prompt43 system_template: str = '{system_message}'44 # The system message45 system_message: str = ''46 # The names of two roles47 roles: Tuple[str] = ('USER', 'ASSISTANT')48 # All messages. Each item is (role, message).49 messages: List[List[str]] = ()50 # The number of few shot examples51 offset: int = 052 # The separator style and configurations53 sep_style: SeparatorStyle = SeparatorStyle.ADD_COLON_SINGLE54 sep: str = '\n'55 sep2: str = None56 # Stop criteria (the default one is EOS token)57 stop_str: Union[str, List[str]] = None58 # Stops generation if meeting any token in this list59 stop_token_ids: List[int] = None60 61 def get_prompt(self) -> str:62 """Get the prompt for generation."""63 system_prompt = self.system_template.format(system_message=self.system_message)64 if self.sep_style == SeparatorStyle.ADD_COLON_SINGLE:65 ret = system_prompt + self.sep66 for role, message in self.messages:67 if message:68 ret += role + ': ' + message + self.sep69 else:70 ret += role + ':'71 return ret72 elif self.sep_style == SeparatorStyle.ADD_COLON_TWO:73 seps = [self.sep, self.sep2]74 ret = system_prompt + seps[0]75 for i, (role, message) in enumerate(self.messages):76 if message:77 ret += role + ': ' + message + seps[i % 2]78 else:79 ret += role + ':'80 return ret81 elif self.sep_style == SeparatorStyle.ADD_COLON_SPACE_SINGLE:82 ret = system_prompt + self.sep83 for role, message in self.messages:84 if message:85 ret += role + ': ' + message + self.sep86 else:87 ret += role + ': ' # must be end with a space88 return ret89 elif self.sep_style == SeparatorStyle.ADD_NEW_LINE_SINGLE:90 ret = '' if system_prompt == '' else system_prompt + self.sep91 for role, message in self.messages:92 if message:93 ret += role + '\n' + message + self.sep94 else:95 ret += role + '\n'96 return ret97 elif self.sep_style == SeparatorStyle.NO_COLON_SINGLE:98 ret = system_prompt99 for role, message in self.messages:100 if message:101 ret += role + message + self.sep102 else:103 ret += role104 return ret105 elif self.sep_style == SeparatorStyle.NO_COLON_TWO:106 seps = [self.sep, self.sep2]107 ret = system_prompt108 for i, (role, message) in enumerate(self.messages):109 if message:110 ret += role + message + seps[i % 2]111 else:112 ret += role113 return ret114 elif self.sep_style == SeparatorStyle.RWKV:115 ret = system_prompt116 for i, (role, message) in enumerate(self.messages):117 if message:118 ret += (119 role120 + ': '121 + message.replace('\r\n', '\n').replace('\n\n', '\n')122 )123 ret += '\n\n'124 else:125 ret += role + ':'126 return ret127 elif self.sep_style == SeparatorStyle.LLAMA2:128 seps = [self.sep, self.sep2]129 if self.system_message:130 ret = system_prompt131 else:132 ret = '[INST] '133 for i, (role, message) in enumerate(self.messages):134 tag = self.roles[i % 2]135 if message:136 if i == 0:137 ret += message + ' '138 else:139 ret += tag + ' ' + message + seps[i % 2]140 else:141 ret += tag142 return ret143 elif self.sep_style == SeparatorStyle.CHATGLM:144 # source: https://huggingface.co/THUDM/chatglm-6b/blob/1d240ba371910e9282298d4592532d7f0f3e9f3e/modeling_chatglm.py#L1302-L1308145 # source2: https://huggingface.co/THUDM/chatglm2-6b/blob/e186c891cf64310ac66ef10a87e6635fa6c2a579/modeling_chatglm.py#L926146 round_add_n = 1 if self.name == 'chatglm2' else 0147 if system_prompt:148 ret = system_prompt + self.sep149 else:150 ret = ''151 152 for i, (role, message) in enumerate(self.messages):153 if i % 2 == 0:154 ret += f'[Round {i//2 + round_add_n}]{self.sep}'155 156 if message:157 ret += f'{role}:{message}{self.sep}'158 else:159 ret += f'{role}:'160 return ret161 elif self.sep_style == SeparatorStyle.CHATML:162 ret = '' if system_prompt == '' else system_prompt + self.sep + '\n'163 for role, message in self.messages:164 if message:165 ret += role + '\n' + message + self.sep + '\n'166 else:167 ret += role + '\n'168 return ret169 elif self.sep_style == SeparatorStyle.CHATGLM3:170 ret = ''171 if self.system_message:172 ret += system_prompt173 for role, message in self.messages:174 if message:175 ret += role + '\n' + ' ' + message176 else:177 ret += role178 return ret179 elif self.sep_style == SeparatorStyle.CHATINTERN:180 # source: https://huggingface.co/internlm/internlm-chat-7b-8k/blob/bd546fa984b4b0b86958f56bf37f94aa75ab8831/modeling_internlm.py#L771181 seps = [self.sep, self.sep2]182 ret = system_prompt183 for i, (role, message) in enumerate(self.messages):184 # if i % 2 == 0:185 # ret += "<s>"186 if message:187 ret += role + ':' + message + seps[i % 2] + '\n'188 else:189 ret += role + ':'190 return ret191 elif self.sep_style == SeparatorStyle.DOLLY:192 seps = [self.sep, self.sep2]193 ret = system_prompt194 for i, (role, message) in enumerate(self.messages):195 if message:196 ret += role + ':\n' + message + seps[i % 2]197 if i % 2 == 1:198 ret += '\n\n'199 else:200 ret += role + ':\n'201 return ret202 elif self.sep_style == SeparatorStyle.PHOENIX:203 ret = system_prompt204 for role, message in self.messages:205 if message:206 ret += role + ': ' + '<s>' + message + '</s>'207 else:208 ret += role + ': ' + '<s>'209 return ret210 elif self.sep_style == SeparatorStyle.ROBIN:211 ret = system_prompt + self.sep212 for role, message in self.messages:213 if message:214 ret += role + ':\n' + message + self.sep215 else:216 ret += role + ':\n'217 return ret218 elif self.sep_style == SeparatorStyle.FALCON_CHAT:219 ret = ''220 if self.system_message:221 ret += system_prompt + self.sep222 for role, message in self.messages:223 if message:224 ret += role + ': ' + message + self.sep225 else:226 ret += role + ':'227 228 return ret229 elif self.sep_style == SeparatorStyle.INTERNVL_ZH:230 seps = [self.sep, self.sep2]231 ret = self.system_message + seps[0]232 for i, (role, message) in enumerate(self.messages):233 if message:234 ret += role + ': ' + message + seps[i % 2]235 else:236 ret += role + ':'237 return ret238 elif self.sep_style == SeparatorStyle.MPT:239 ret = system_prompt + self.sep240 for role, message in self.messages:241 if message:242 if type(message) is tuple:243 message, _, _ = message244 ret += role + message + self.sep245 else:246 ret += role247 return ret248 else:249 raise ValueError(f'Invalid style: {self.sep_style}')250 251 def set_system_message(self, system_message: str):252 """Set the system message."""253 self.system_message = system_message254 255 def append_message(self, role: str, message: str):256 """Append a new message."""257 self.messages.append([role, message])258 259 def update_last_message(self, message: str):260 """Update the last output.261 262 The last message is typically set to be None when constructing the prompt,263 so we need to update it in-place after getting the response from a model.264 """265 self.messages[-1][1] = message266 267 def to_gradio_chatbot(self):268 """Convert the conversation to gradio chatbot format."""269 ret = []270 for i, (role, msg) in enumerate(self.messages[self.offset :]):271 if i % 2 == 0:272 ret.append([msg, None])273 else:274 ret[-1][-1] = msg275 return ret276 277 def to_openai_api_messages(self):278 """Convert the conversation to OpenAI chat completion format."""279 ret = [{'role': 'system', 'content': self.system_message}]280 281 for i, (_, msg) in enumerate(self.messages[self.offset :]):282 if i % 2 == 0:283 ret.append({'role': 'user', 'content': msg})284 else:285 if msg is not None:286 ret.append({'role': 'assistant', 'content': msg})287 return ret288 289 def copy(self):290 return Conversation(291 name=self.name,292 system_template=self.system_template,293 system_message=self.system_message,294 roles=self.roles,295 messages=[[x, y] for x, y in self.messages],296 offset=self.offset,297 sep_style=self.sep_style,298 sep=self.sep,299 sep2=self.sep2,300 stop_str=self.stop_str,301 stop_token_ids=self.stop_token_ids,302 )303 304 def dict(self):305 return {306 'template_name': self.name,307 'system_message': self.system_message,308 'roles': self.roles,309 'messages': self.messages,310 'offset': self.offset,311 }312 313 314# A global registry for all conversation templates315conv_templates: Dict[str, Conversation] = {}316 317 318def register_conv_template(template: Conversation, override: bool = False):319 """Register a new conversation template."""320 if not override:321 assert (322 template.name not in conv_templates323 ), f'{template.name} has been registered.'324 325 conv_templates[template.name] = template326 327 328def get_conv_template(name: str) -> Conversation:329 """Get a conversation template."""330 return conv_templates[name].copy()331 332 333# Both Hermes-2 and internlm2-chat are chatml-format conversation templates. The difference334# is that during training, the preprocessing function for the Hermes-2 template doesn't add335# <s> at the beginning of the tokenized sequence, while the internlm2-chat template does.336# Therefore, they are completely equivalent during inference.337register_conv_template(338 Conversation(339 name='Hermes-2',340 system_template='<|im_start|>system\n{system_message}',341 # note: The new system prompt was not used here to avoid changes in benchmark performance.342 # system_message='我是书生·万象,英文名是InternVL,是由上海人工智能实验室、清华大学及多家合作单位联合开发的多模态大语言模型。',343 system_message='你是由上海人工智能实验室联合商汤科技开发的书生多模态大模型,英文名叫InternVL, 是一个有用无害的人工智能助手。',344 roles=('<|im_start|>user\n', '<|im_start|>assistant\n'),345 sep_style=SeparatorStyle.MPT,346 sep='<|im_end|>',347 stop_token_ids=[348 2,349 6,350 7,351 8,352 ],353 stop_str='<|endoftext|>',354 )355)356 357 358register_conv_template(359 Conversation(360 name='internlm2-chat',361 system_template='<|im_start|>system\n{system_message}',362 # note: The new system prompt was not used here to avoid changes in benchmark performance.363 # system_message='我是书生·万象,英文名是InternVL,是由上海人工智能实验室、清华大学及多家合作单位联合开发的多模态大语言模型。',364 system_message='你是由上海人工智能实验室联合商汤科技开发的书生多模态大模型,英文名叫InternVL, 是一个有用无害的人工智能助手。',365 roles=('<|im_start|>user\n', '<|im_start|>assistant\n'),366 sep_style=SeparatorStyle.MPT,367 sep='<|im_end|>',368 stop_token_ids=[369 2,370 92543,371 92542372 ]373 )374)375 376 377register_conv_template(378 Conversation(379 name='phi3-chat',380 system_template='<|system|>\n{system_message}',381 # note: The new system prompt was not used here to avoid changes in benchmark performance.382 # system_message='我是书生·万象,英文名是InternVL,是由上海人工智能实验室、清华大学及多家合作单位联合开发的多模态大语言模型。',383 system_message='你是由上海人工智能实验室联合商汤科技开发的书生多模态大模型,英文名叫InternVL, 是一个有用无害的人工智能助手。',384 roles=('<|user|>\n', '<|assistant|>\n'),385 sep_style=SeparatorStyle.MPT,386 sep='<|end|>',387 stop_token_ids=[388 2,389 32000,390 32007391 ]392 )393)394 