你写了一条很长的 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:用 .cursorrules 或 CLAUDE.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 用量明显下降。
如果还是没修好
- 平台可能不支持真正 system prompt——查文档。
- 有些平台会截断过长 system prompt——精简排优先级。
- 模型可能不严格 system 优先于 user——故意写矛盾 user message 测一下。
- 聊天 UI 没持久规则就考虑切到 API,通道分离是强制的。
预防建议
- 默认:持久规则放 system prompt / project 指令。user message 只放本轮任务。
- 新对话发任何 user message 之前先设 system prompt。
- 每月审项目指令——过期规则会悄悄污染新任务。
- 团队工作流把 system prompt 和代码一起版本化。
- 想在 user message 里重打规则时反问:“这是不是该放 system?”
- API 工作流能力用 tools/functions,不用 prose 定义。