
废土提示词秘典:系统提示词与用户提示词的终极对决
废土纪年2025,AI洪流席卷大地后的第十二个雷暴之夜…
在这个智能体遍地的数字废墟中,你坐在破旧的工作站前,屏幕上闪烁着字节跳动Coze平台的光芒。面前摆着两个输入框:一个标着”系统提示词”,另一个写着”用户提示词”。
曾经,某个培训视频里的”大师”告诉你:这两个框没什么区别,因为它们最终都会被拼成一个字符串传给Transformer。于是你信了,把所有内容都塞进了系统提示词,然后眼睁睁看着你的智能体像个喝醉的机器人一样胡言乱语…
今夜,雷声轰鸣,是时候揭开这个废土世界最容易被误解的技术秘密了。在这个AI统治的时代,掌握提示词的真正奥义,就是掌握了驾驭智能体的终极武器…
知乎主页:https://www.zhihu.com/people/feng-zhi-shen-yun-89
最近在使用字节的coze开发一个智能体,在使用大模型节点的时候,我再次思考”系统提示词” 和 “用户提示词”该如何填写。
之前看到有人说,用户提示词其实可以和系统提示词放在一起,因为他们最后在底层进入transformer预测之前都会被拼成一个完整的字符串。
非也!
二者一定是有区别的!
实战案例分析
下面是一个具体的提示词案例:
这是系统提示词:
1 | ## 角色 |
这是用户提示词:
1 | 用户 query: {{query}} |
如果我把用户提示词放到系统提示词的最后,然后用户提示词空着,会怎么样?
有什么区别?
最佳实践是什么?
我将从底层原理阐述。
这个问题,涉及到大型语言模型工作的核心机制,以及在 Coze 这种平台上如何最有效地引导模型产生我们期望的输出。
1. 底层原理:模型如何看待”系统提示词”与”用户提示词”
从最根本的层面来看,对于目前主流的 Transformer
架构的大模型,在最终被处理时,所有输入(无论是系统提示词、用户提示词,还是 few-shot examples)都会被拼接成一个单一的、连续的文本序列(token sequence)。模型的核心任务是基于这个完整的输入序列,预测下一个最有可能出现的词(token)。
那么,为什么还要区分”系统提示词”和”用户提示词”呢?这主要是因为在模型的预训练和指令微调 阶段,开发者特意引入了这种角色区分的格式。
指令微调:为了让模型能更好地遵循指令、扮演角色和进行对话,研究人员会用大量特定格式的数据来微调模型。这些数据通常会包含类似下面的结构:
1 | { |
通过在这种结构化数据上进行训练,模型学会了:
- 识别角色和指令:模型内部的注意力机制会学到,
<system>
标签(或类似的内部标识)后的内容是高级别的、全局性的指令和角色设定,其权重和影响范围应该贯穿整个对话。 - 识别任务输入:
<user>
标签后的内容是当前需要处理的具体任务或问题。 - 遵循指示:模型学会了在生成
<assistant>
部分的回答时,要同时遵循<system>
的设定和<user>
的具体要求。
总结底层原理:虽然最终输入是单一序列,但通过在训练数据中引入特定的角色标记(如 system
, user
),模型在内部学会了对不同角色的文本赋予不同的”权重”和”理解方式”。系统提示词被模型理解为”我是谁,我该做什么,我的行为准则是什么”;用户提示词则被理解为”这是我当前需要处理的具体任务”。Coze 平台正是利用了这一点,将你在不同框中输入的内容,在后台封装成这种模型能理解的结构化格式,再发送给大模型。
2. 实践差异:把用户提示词移入系统提示词会怎么样?
现在我们来分析具体操作:将 用户 query: {{query}}
和 搜索结果: {{input}}
这部分内容,从”用户提示词”区域移动到”系统提示词”区域的末尾,然后将”用户提示词”区域留空。
会发生什么?
模型可能仍然能”工作”:如前所述,所有内容最终都会被拼接在一起。如果你的
{{query}}
和{{input}}
内容足够清晰,模型很大概率上仍然能够理解这是一个任务并尝试去完成。它会看到一个非常长的系统指令,其中包含了角色定义、技能、限制,以及最后的用户问题和数据。但模型的”行为”会变得不稳定和模糊:这是关键区别所在。当你这样做时,就是混淆了模型的角色认知。
- 角色与任务混淆:模型可能会将
用户 query
和搜索结果
理解为它自身角色设定的一部分,而不是一个需要即时处理的任务。它可能会认为”我的角色就是处理一个固定的、名为’‘的查询和名为’‘的搜索结果”,而不是把{{query}}
视作一个动态变化的、来自外部用户的变量。 - 指令优先级降低:在模型的”注意力”分配中,高级别的、关于角色和能力的指令(比如”你是一个高效的生活小助理”)和低级别的具体任务(比如”今天北京天气如何?”)被放在了同一个”系统”筐子里。这可能导致模型在处理具体任务时,对高级别指令的遵循度下降。它可能会忘记自己的角色、技能或限制,因为任务本身也被标记为了”系统设定”。
- 对话历史和上下文管理困难:在多轮对话中,这种做法会产生严重问题。Coze(以及其他大模型应用)通常会将每一轮的”用户提示词”和”模型回答”作为历史记录。如果你把用户的 query 放进系统提示词,那么在下一轮对话中,系统提示词(包含了上一轮的 query)通常是固定的,而新的用户输入是空的或不存在的。模型将无法理解新的对话轮次,也无法正确地延续上下文。
- Coze 变量注入可能失效:Coze 平台的设计是,
{{query}}
这样的变量代表的是运行时由最终用户输入的动态内容。将它放在系统提示词中,可能会干扰 Coze 平台正确地解析和注入变量,导致{{query}}
无法被实时替换,或者出现非预期的行为。用户在对话框里输入的内容可能无法被传递到正确的位置。
- 角色与任务混淆:模型可能会将
简而言之,你等于是在对模型说:”你的身份设定包含了’总结天气’这个技能,并且,你的身份设定也包含了’用户的问题是某某某’以及’搜索结果是某某某’”。这在逻辑上是混乱的。
3. 最佳实践是什么?
遵循 Coze 以及所有大模型平台的既定设计,才是最高效、最稳定的方式。
严格区分系统与用户提示词
系统提示词 (System Prompt):只放稳定不变的、定义模型行为的元信息。
- 角色:模型应该扮演谁?(例如:”你是一个高效的生活小助理”)
- 能力/技能:模型能做什么,应该如何做?(例如:”技能 1: 搜索总结天气…”)
- 个性/语气:模型应该用什么样的风格说话?(例如:”语气要友好、亲切”)
- 规则/限制:模型绝对不能做什么?输出格式有什么要求?(例如:”只回答与生活相关的问题”、”总结部分不能超过 200 字”)
- 背景知识:一些模型需要预先知道的、在整个对话中都有效的背景信息。(例如:
用户画像是: {{user_profile}}
,这个画像信息在整个对话中都是模型的背景参考)
用户提示词:只放当前轮次需要模型处理的具体、动态的任务输入。
- 用户的问题:
{{query}}
- 运行时提供的上下文/数据:比如通过工具(如搜索)实时获取的数据,即你的
搜索结果: {{input}}
。这些是模型处理当前问题所需要依赖的”原材料”。
为什么这样是最佳实践?
- 逻辑清晰:完全符合模型的训练方式,让模型能最高效地理解自己的角色和任务,从而给出更精准、更符合要求的回答。
- 性能稳定:在单轮和多轮对话中都能保持稳定的表现。模型能清楚地区分哪些是”铁律”(系统提示词),哪些是”当下的任务”(用户提示词)。
- 易于维护和调试:当你的 Bot(智能体)出现问题时,你可以清晰地知道是角色定义(System Prompt)出了问题,还是传入的数据(User Prompt)有问题,便于快速定位和修改。
- 充分利用平台特性:能够最好地配合 Coze 的变量注入、工作流编排和多轮对话管理等功能。
结论
请务必将”系统提示词”和”用户提示词”分开,并按照其设计初衷来使用。将用户 query 强行放入系统提示词,是一种违反模型设计原理的做法,虽然在极其简单的单次任务中可能”碰巧”成功,但会牺牲模型的稳定性、可控性和扩展性,尤其是在构建更复杂的、需要进行多轮对话或依赖外部工具的 Bot 时,几乎肯定会导致失败。
雷暴渐息,废土上的夜空重归宁静…
你缓缓合上笔记本,屏幕上最后闪烁的光芒照亮了你满意的笑容。那两个看似相同的输入框,现在在你眼中已经截然不同:一个是智能体的灵魂(系统提示词),另一个是它的使命(用户提示词)。
你想起了那些曾经因为提示词混乱而失败的项目,那些在演示时突然”发疯”的智能体,那些本该精准回答却胡言乱语的助手。现在你明白了,在这个AI统治的废土世界里,掌握提示词的真正奥义,就是掌握了驾驭智能体的钥匙。
明天,当新的一轮开发开始,当你再次面对Coze平台上的那两个输入框时,你将不再困惑。你知道该把什么放在哪里,你知道如何让你的智能体成为废土中最可靠的伙伴。因为在这个技术迅猛发展的时代,细节决定成败,而你,已经掌握了最关键的细节…