大模型聊天模板
文章目录
- 何为聊天模板
- 聊天模板具体长什么样
- 为什么会出现聊天模板
何为聊天模板
相信大多数本地离线使用过(特别是训练或微调过)LLM、VLM的人知道“Chat template/聊天模板”这个概念,但可能并没有对其有较多的了解。本文主要整合网络收集的知识,结合少数使用信息“聊天模板”这个对象进行简要说明,希望可以帮助到大家。
如果了解Alpaca、ShareGPT等数据集会知道,数据集都是结构化形式,其中会有各种各样的角色,如system、user、assistant等,每种角色有对应的content,模型训练时会基于设置的“聊天模板”将各角色和对应的内从信息通过一些特俗字符组合为完整的字符串。为推理场景,用户通过界面与大模型进行chat时,表面是一问一答的形式,底层也要通过“聊天模板”将所有历史数据组合为一个完整的上下文字符串送入大模型,大模型再进行推理生成结果。与分词器作用类似,模型推理时,应该使用与模型训练相同的聊天模板,不然会出现分布漂移问题,严重影响模型性能。
聊天模板定义了如何将用户消息、系统提示和助手回复等各类角色内容组织成模型可以理解的统一格式;其本质是一个文本格式化规则,将结构化的数据转换为模型训练时使用的特定格式,使模型清楚地区分对话中的不同角色(用户、助手、系统等)及其边界。
聊天模板具体长什么样
初始与LLM聊天往往以一句简单的问候开始,LLM也会简洁的回复一句,数据形式会如下所示;将此数据喂给LLM不是简单地将"Hi there!"和"Nice to meet you!"拼接,这样会完全丢掉角色信息,导致LLLM性能下降。
[{"role": "user", "content": "Hi there!"},{"role": "assistant", "content": "Nice to meet you!"}
]
因为模型开发商或团队不同,很多模型所使用的聊天模板不同,即存在不同的规则组合上述数据。如类似“即时消息”的格式:
User: Hey there!
Bot: Nice to meet you!
或通过特俗tokens标识角色信息及边界:
[USER] Hey there! [/USER]
[ASST] Nice to meet you! [/ASST]
使用被较多模型所使用的OpenAI推出的聊天模板ChatML转换后的数据如下:
<|im_start|>user
Hey there!<|im_end|>
<|im_start|>assistant
Nice to meet you!<|im_end|>
聊天模板是一种规则,在分词器层面应用,先基于其将数据构建成与训练时相同结构的上下文,然后再通过分词器进行离散化,最终送入大模型。聊天模板本质是Jinja模板字符串,包含格式信息,将聊天消息列表转换为模型所需的、格式正确的输入字符串所需要的全部信息。上述三种转换后数据对应的聊天模板依次如下所示:
{% for message in messages %}{% if message['role'] == 'user' %}{{ "User : " }}{% else %}{{ "Bot : " }}{{ message['content'] + '\n' }}
{% endfor %}
{% for message in messages %}{% if message['role'] == 'user' %}{{ "[USER]" + message['content'] + " [/USER]" }}{% else %}{{ "[ASST]" + message['content'] + " [/ASST]" }}{{ message['content'] + '\n' }}
{% endfor %}
"{% for message in messages %}""{{'<|im_start|>' + message['role'] + '\n' + message['content'] + '<|im_end|>' + '\n'}}"
"{% endfor %}"
Jinja模板其实和Python语法比较相似,上述三个模板的第一行就相当于一个for循环遍历聊天消息列表,然后基于不同的角色使用特定的tokens将角色信息和内容封装起来,然后使用一个换行符将其视为一行数据。
为什么会出现聊天模板
目前出名的大模型开源项目在发布模式时都会包含对应的聊天模板定义,便于开发者使用。当肯定有人会像,既然是一种规则,为什么不统一到一个标准?我认为主要有以下几个原因。最主要的就是,不同团队在自研模型时,不可能会提前达成共识,说大家一起研究一个高效的聊天模板,然后严格遵守;随着各家模型发展,即使如今大家意识到要统一的也已经为时已晚。
随着模型发展,LLM逐渐拥有了funciton call、tool等各种新能力,以及各种多模态模型丰富了输入数据形态和角色,这些都会导致输入数据的形态发生变化,相应的不同模型底层使用的聊天模板相应发生改变,此类场景就需要灵活、可控的聊天模板来实现数据构建,这也注定了聊天模板不会统一。
聊天模板可广泛用于多种类型模型的预处理,包括那些可能与标准聊天操作迥异的模型。硬设标准格式限制了模型开发人员使用此功能开发模型新功能的能力,而模板则为用户和开发人员提供了最大的自由度。
transformers库中的分词器类早已实现了chat_template属性,只需简单赋值即完成聊天模板设置。在增加chat_template属性之前,transformers将聊天模板这个功能储存在各个模型类中,即在“向后兼容”的开发理念下,目前在使用transformers加载模型及对应分词器时,即使未手动设置聊天模板,也是可以正常推理输出,但可能由于聊天模板不匹配导致静默错误,即在无任何错误信息的情况下大幅下降。