概念

1. Message类型

System message 在大模型内部是每次加在了用户输入的前面。在 OpenAI 的大模型设计的时候,有三种不同的message 类型,这三者是有明显区别的。

  • System Message:对大模型的角色进行定义,并输入一些基础的指令,包括大模型的身份、一些用于提高安全性的指令
  • User Message:用户输入的问题
  • Assistant Message:大模型输出的信息

System Message和User Message的不同之处就是,System Message一般都是出现在输入的开始,根据大模型注意力机制的公式,在开始和结尾处的文字更容易被重视。因此,在这些地方出现的内容,更容易被大模型识别和理解。

所以,一个完整的提示词,或者多轮对话的场景一般是按照下面的流程去拼接和组装提示词的:

System Message、(User Message、Assistant Message)、(User Message ...、Assistant Message...)

在这种对话下,Assistant Message主要是向大模型展示他历史聊天记录的输出内容,告知大模型这些不是用户的输入。按照这种模式进行训练和微调的大模型就会意识到,那些内容并不是用户真实的输入,而是一个聊天对话的历史信息,这样大模型就不仅能理解历史的信息,还能更好的回答你接下来的问题。

[!question] 为什么System Message不和User Message合并?
有一个很重要的原因就是,我们在微调的时候,可以定义不同的消息类型,去避免一些提示词注入和攻击的问题。这个时候,只需要在System Message中定义好大模型的角色,而将其他内容放在User Message中,就可以避免一些简单的提示词攻击和泄露的情况。

此外,当我们做成应用的时候,System Message是对用户不可见的,在这个地方定义的规则、角色由于得到了充分的训练,就具有最高的优先级。大模型就会在很大概率上遵循这个定义,而不是随着用户输入的改变而输出一些违背开发者原来意思的内容

当然,指定 System Message 并不能完全的抵御外来的攻击,之前GPT4还是出现过 System Prompt被套出来的情况,这种情况下,就需要对用户输入的内容或者大模型输出的内容进行二次校验或许是一个更好的方案。

1.1. 示例

In [1]: history1
Out[1]: [('What is the capital of France?', 'Paris')]

In [2]: print(raw_text)
Out[2]: 
<|im_start|>system
You are a helpful assistant.<|im_end|>
<|im_start|>user
What is the capital of France?<|im_end|>
<|im_start|>assistant
Paris<|im_end|>
<|im_start|>user
Can you tell me something about Paris?<|im_end|>
<|im_start|>assistant