提示词不累积,对话才累积:LLM 中系统、用户、助手与工具的本质差异
本文结合公开权威资料与实测会话,系统梳理 LLM 中 System / User / Assistant 三类角色提示词的传递机制、上下文窗口占用规律,以及工具元数据与可见性开关的逐轮注入原理。核心结论:系统提示与工具定义是会话级常量,只注入不累积;对话历史线性累积;工具可见性可逐轮动态控制,模型无跨轮记忆。
1. 三层提示结构与角色语义
现代对话式 LLM 的输入由三类角色消息构成:
- system / 系统提示:设定模型身份、行为约束、安全规则、输出格式等全局指令,常包含工具注册表的元数据。属于会话级常量。
- user / 用户提示:用户输入的任务、问题或指令。
- assistant / 助手提示 :模型的历史回复,包括文本回答和
tool_call。
Prompt Engineering Guide 明确将 Prompt Engineering 定义为"开发和优化提示以高效使用语言模型"的学科,强调系统设置、模型参数、提示元素共同构成框架。Prompt Engineering Guide
推理时每轮输入的组装逻辑为:
- System + Tools 元数据 → 会话级常量,逐轮注入
- 历史对话消息列表 → 线性累积
- 当前轮 user 消息 → 本轮触发
系统提示在逻辑上存在于每轮,但在存储上不作为历史消息重复拷贝。
2. 系统提示词与工具元数据的处理方式
- 会话级常量,逐轮注入不累积:System 指令和工具的原型 schema/描述在会话初始化时加载,模型侧常驻。后续每轮由系统层重新注入,历史记录中不保留多份拷贝。上下文窗口的增长主要来自对话历史,而非系统定义重复。
- 元数据与实例分离:工具定义属于元数据,实际推理中模型只感知到"本次可见的工具子集"。完整 schema 保留在系统侧,轮次间不通过历史消息传递。
- 引用而非内联:模型看到的是工具名与参数结构,系统按需注入。不会把整套工具定义每轮复制进上下文,因此能区分工具又不导致上下文被重复撑爆。
系统提示是框架,对话历史是内容,二者存储与传递机制不同。
注意:不累积 ≠ 不占用
系统提示与工具元数据虽然不进入历史累积,但每一轮推理时仍会被系统层注入到当轮输入中,因此会占用当轮的上下文窗口。区别在于:对话历史是"永久占用且持续增长",而系统提示是"每轮临时占用,轮间不累加"。
3. 上下文窗口的累积机制
- 对话历史线性累积 :每轮
user+assistant消息追加到消息列表,窗口长度随轮次增加。超出窗口时采用截断、滑动窗口或摘要压缩。 - 系统提示不重复占位:系统提示每轮逻辑上存在,存储上只保留一份常量引用,不在历史中重复拷贝。
- 工具调用属于历史 :
assistant生成的tool_call与返回的tool_result作为普通消息进入历史,用于保持多轮推理连贯性。工具定义本身不进入历史。
因此上下文占用主要由用户问答和工具调用结果驱动,系统提示与工具元数据不贡献累积增长。
4. 工具可见性与逐轮动态注入
工具注册表在会话内是静态的,但可见性/开关是逐轮控制的。实现上通常为:
- 系统侧维护完整工具注册表。
- 每轮请求时按策略挑选子集,只注入该子集到本轮输入。
- 模型本轮只能从可见集合中选择,下轮集合可不同。
因此会出现"上一轮看到 7 个工具,本轮看到 10 个,下轮变成 1 个"的现象。模型没有跨轮的工具可见历史记忆,只能忠实反映当轮被注入的集合。历史中只记录"调用了哪个工具、返回了什么",不记录"上一轮哪些工具被隐藏"。
这解释了工具数量变化≠系统提示被修改,也≠上下文被重复累积。
OpenAI 兼容格式示例
以下是一轮典型的 OpenAI Chat Completions 消息结构,可直观看到 System / User / Assistant / Tool 的分离:
json
[
{
"role": "system",
"content": "You are a helpful assistant. Available tools: get_system_time, get_workspace."
},
{
"role": "user",
"content": "现在几点了?"
},
{
"role": "assistant",
"content": null,
"tool_calls": [
{
"id": "call_1",
"type": "function",
"function": {
"name": "get_system_time",
"arguments": "{}"
}
}
]
},
{
"role": "tool",
"tool_call_id": "call_1",
"content": "2026-10-15 01:00:03.690"
},
{
"role": "assistant",
"content": "现在是 2026-10-15 01:00:03。"
}
]
system为会话级常量,每轮注入不累积user/assistant/tool为历史消息,线性累积- 工具定义不在消息体中重复出现,只在系统侧作为元数据存在,可见子集逐轮决定
5. 不同角色提示词与上下文的关系总结
| 角色 | 存储方式 | 是否累积 | 上下文占用 | 典型内容 | 变化频率 |
|---|---|---|---|---|---|
| system | 会话级常量,逐轮注入 | 否 | 每轮临时占用,不累积 | 角色、约束、安全规则、工具元数据 | 低,整会话不变 |
| user | 消息列表 | 是 | 永久累积,持续增长 | 用户提问、指令 | 每轮新增 |
| assistant | 消息列表 | 是 | 永久累积,持续增长 | 模型回复、tool_call、tool_result | 每轮新增 |
| tools | 元数据注册表 + 逐轮可见子集 | 元数据不累积,可见性逐轮 | 元数据每轮临时占用,可见性影响本轮可调用集合 | 函数原型、参数 schema | 可见性可动态 |
系统提示与工具元数据是常量注入;用户/助手消息是历史累积;工具可见性是逐轮开关。
6. 实践建议
- 不要在 user 消息里重复写系统指令,会浪费窗口且可能冲突。
- 工具设计保持稳定,动态控制可见性而非修改 schema,保证可预测性。
- 长对话需做历史压缩、摘要或滑动窗口,避免窗口被对话历史撑爆。
- 记录工具调用轨迹用于审计,但不要把工具定义重复写入历史。
- 设计提示时区分"框架层"与"内容层",框架层走系统注入,内容层走历史累积。
参考
- Prompt Engineering Guide 官方介绍:Prompt engineering is a relatively new discipline for developing and optimizing prompts to efficiently use language models... Prompt Engineering Guide
- Prompt Engineering Guide 导航中明确区分 System / User / Assistant 角色与提示元素,系统级指令用于设定整体行为框架。
- 上下文窗口处理遵循"常量注入 + 历史累积"模型,工具可见性为逐轮控制层。