Prompt 把 system 与 user 指令混用:3 个原因 + 修复路径

角色 / 全局规则塞进 user message,模型分不清优先级——输出乱跳。

你写了一条很长的 user message,里面有角色(“你是一名资深工程师”)、全局规则(“始终返回 JSON、不用 emoji”)、任务(“重写下面这个函数”)和输入代码。模型有时遵守规则,有时无视。聊到第 5 轮规则就完全被忘——因为它们和任务在同一通道里,被最新输入挤掉。问题不在模型,在于你把持久规则放进了单轮通道。system prompt、project instructions、user message 生命周期不同;混用就把层级拍扁。

本文讲为什么有 system / user 分层,以及怎么把 prompt 各部分路由到对的通道。

常见原因

1. 全塞一条 user message

你写了一条长 message 没用 system prompt。规则和任务争注意力。

如何判断:API 调用里只有一条 role 为 “user” 的消息,或聊天 UI 里所有规则都在输入框。

2. 完全没用 system prompt

有些平台把 system prompt 藏在”Custom Instructions”或”项目指令”里。很多用户不知道它存在。

如何判断:你有想每轮都生效的规则,却每次重打。

3. 每条 user message 都重申全局规则

你发现模型会忘,就每轮重贴。这能工作但浪费 token 且脆弱。某些规则会和 system prompt 静默冲突。

如何判断:每条 user message 开头都是同样 5 行 preamble。

4. system prompt 和 user message 矛盾

你昨天 system prompt 写”正式”,今天 message 写”口语化”。模型平均。

如何判断:你已经记不清 system prompt 里写了什么。

5. tools / functions 配置在 user message

Agent 工作流里工具定义应该有专门槽位。塞到 user message 里能解析,但模型把它们当建议而不是合约。

如何判断:工具描述写在 user prose 里。

动手前先确认

  • 列出当前 prompt 每一行。
  • 分类:system(持久)、user(单轮)、tool(能力)、assistant(历史)。
  • 标出哪些每轮变、哪些持久。
  • 查你平台真正支持什么(chat UI 和 API 不同)。
  • 计划每部分放哪里。

需要收集的信息

  • 完整发送的 prompt。
  • 你的 system prompt / project instructions(如果有)。
  • 相关对话历史。
  • 无视规则的输出。
  • 模型 + 平台。

最短修复路径

Step 1:分清持久 vs 单轮

持久(system prompt):
- 角色:"你是一名资深后端工程师。"
- 输出格式:"只返回符合 schema X 的合法 JSON。"
- 语气规则:"无 emoji。无感叹号。"

单轮(user message):
- "把下面这个函数加上指数退避的重试逻辑。"
- <粘代码>

分开两半都更清爽。

Step 2:持久规则挪到 system prompt

API:

messages = [
  {"role": "system", "content": "<所有持久规则>"},
  {"role": "user", "content": "<本轮任务>"}
]

ChatGPT / Claude / Gemini:用 Custom Instructions、Project 指令、Saved Info 等。

Cursor / Claude Code:用 .cursorrulesCLAUDE.md

Step 3:user message 聚焦本轮任务

单轮 message 只放:新请求、新输入、会变的东西。不放每轮通用的。

差:  "记住:返回 JSON、不用 emoji、你是资深工程师。
       现在:重写这个函数。"
好:  "重写这个函数:"
      <代码>

Step 4:API 工作流 system 必须是第一条

messages = [
  {"role": "system", "content": "..."},   # 必须在最前
  {"role": "user", "content": "..."},
  {"role": "assistant", "content": "..."},
  {"role": "user", "content": "..."}
]

system 出现在对话中间时各 provider 行为不一致。

Step 5:能力用 tools / functions

Agent 工作流把工具定义在 API 的 tools 参数里,不要写在 prose。模型把它们当带 schema 验证的合约。

tools = [{
  "name": "search_codebase",
  "description": "...",
  "input_schema": {...}
}]

Step 6:审矛盾

打印 system prompt 和最新 user message。找矛盾。system 通常赢;想让 user 单独点赢就显式说:“本轮覆盖 system 关于 X 的规则。“

怎么确认已经修好

  • 同规则跨 10 轮不需要重贴。
  • user message 短而聚焦任务。
  • 删 user message 前的 preamble 行为不变(规则在 system 里活着)。
  • 不同轮次任务输出不同,但语气 / 格式 / 角色一致。
  • 单轮 token 用量明显下降。

如果还是没修好

  1. 平台可能不支持真正 system prompt——查文档。
  2. 有些平台会截断过长 system prompt——精简排优先级。
  3. 模型可能不严格 system 优先于 user——故意写矛盾 user message 测一下。
  4. 聊天 UI 没持久规则就考虑切到 API,通道分离是强制的。

预防建议

  • 默认:持久规则放 system prompt / project 指令。user message 只放本轮任务。
  • 新对话发任何 user message 之前先设 system prompt。
  • 每月审项目指令——过期规则会悄悄污染新任务。
  • 团队工作流把 system prompt 和代码一起版本化。
  • 想在 user message 里重打规则时反问:“这是不是该放 system?”
  • API 工作流能力用 tools/functions,不用 prose 定义。

相关阅读

标签: #Prompt #排查