什么是 system prompt?
在对话开头一次性设定的指令,放在一个结构上独立的位置,模型被训练成对这个位置另眼相看。
发给模型的对话是一个消息列表,每条消息都带一个角色标签。system 消息排在第一位,为后面的一切定调。
system: 你是一款数据库产品的技术支持助手。
只根据所提供的文档作答。如果文档里没有答案,
就如实说明,并提出升级处理。
user: 为什么我的查询很慢?同一段文字如果塞进 user 消息里,行为会不一样,原因值得弄明白。
为什么这个位置重要
在指令微调期间,模型是在用这些角色标记格式化过的对话上训练的。它学到的是:system 角色的内容设定长期约束,user 角色的内容是当下的请求。
所以差别并不在于 system 消息被施了什么魔法、有什么特权。而在于模型在大量样本上学到了「system 内容发挥长期指令作用」这个模式。这个位置有分量,是因为训练,不是因为强制。
这个区别在实践上很重要:system 指令是很强的倾向,不是保证。一条足够坚决的 user 消息能把它顶开。把 system prompt 当成一个被普遍尊重的默认值,永远不要当成安全边界。
该放什么进去
角色与范围。 这个助手是干什么的,以及什么该拒绝。
每一轮都适用的输出约定。 格式、语气、长度、语言。
长期约束。 「绝不推荐竞品。」「永远附上来源。」「假定读者不懂技术。」
稳定的背景信息。 产品术语、当前日期、相关策略。
不该放什么进去
当前的问题。 那属于 user 消息。
任何随请求变化的东西。 检索到的文档、具体的任务、可变的输入。这些放进 user 消息——一半是为了清晰,一半是为了下面那个缓存上的理由。
机密。 system prompt 不是隐藏的。它常常能被锲而不舍的追问套出来,就该假定它是可见的。绝不要把凭证或真正机密的指令放进去。
缓存上的后果
因为 system prompt 位于每个请求的最开头,它是前缀缓存的理想候选。
稳定的 system prompt 意味着它的 key 和 value 可以只算一次、在多个请求间复用,这能实实在在降低成本和延迟。让它随请求变化,你就把这份好处全放弃了。
由此得到一条具体的规则:让 system prompt 固定不变,把所有可变的东西放进 user 消息。 这是现有最便宜的成本优化之一。见砍掉 API 账单。
长度与位置的影响
system prompt 一长,就会冒出两种失效模式。
写在长 system prompt 中间的指令,被遵循的可靠性不如写在两端的——和普遍影响长上下文的是同一种注意力模式。把最重要的约束放在最前或最后。
而在长对话里,system 指令还要和不断增长的记录竞争。1 万个 token 的对话足以稀释一段很短的 system prompt。在最新的 user 消息里重申关键约束,是个正当的补救办法。
多轮对话中的行为
每个请求都会发送 system prompt,因为模型在两次调用之间没有记忆。你用的任何框架都在每一轮把它重新传一遍。
你可以在对话中途改它——没有任何东西拦着你——但这会让从那一刻起的前缀缓存失效,还可能造成前后不一致,因为更早的轮次是在另一套指令下生成的。
要点回顾
- system prompt 是消息列表开头的一个独立角色,为之后所有轮次定调。
- 它的权威来自训练出的模式,而不是强制——是很强的默认值,不是安全边界。
- 角色、范围、格式约定和稳定背景放进去;任务和可变输入留在 user 消息里。
- 让它保持固定才能启用前缀缓存,这是实实在在的成本节省。
- 写在 prompt 中间的指令遵循得更不可靠,长对话会稀释很短的 system prompt。
下一篇: 什么是上下文窗口?