上下文角色深度解析:System、User、Assistant与Developer
深入剖析大模型通信协议中不同角色的定义、作用、优先级及实际应用场景,帮助开发者精准控制模型行为。
在大模型通信协议中,角色(Role) 是构建有效上下文的核心。它不仅仅是消息的标签,更是指导模型理解“谁在说话”以及“该如何回应”的关键指令。本文将深度解析 system、user、assistant 以及新兴的 developer 角色,并探讨它们在不同协议格式中的差异与最佳实践。
一、角色系统的设计目的
角色系统的设计主要解决以下问题:
- 指令分离:将不同来源、不同目的的指令清晰分开,避免混淆。
- 行为控制:通过系统指令(System Prompt)在对话开始前定义模型的人格、能力边界和行为准则。
- 对话模拟:通过区分用户和助手的消息,构建逼真的多轮对话历史。
- 安全与审核:不同角色可应用不同的内容审核策略(例如,对 system 指令的审核可能比对用户输入更严格)。
二、核心角色详解
1. System 角色(系统)
system 角色消息是对话的“宪法”或“基本法”,它为整个对话设定基调、规则和上下文。
核心特点与用途:
- 最高优先级:在模型的指令遵循层级中,system 指令通常具有最高优先级,会覆盖后续的 user 或 assistant 消息中的矛盾指令(但并非绝对,取决于模型和训练)。
- 设置人格与行为:“你是一个专业的法律助手,请用严谨、专业的语言回答问题。”
- 定义能力边界:“你只能回答关于 Python 编程的问题。如果用户问其他话题,请礼貌拒绝。”
- 提供背景知识:“以下是我们公司的产品目录:[...]。请基于此回答用户问题。”
- 注入格式要求:“请始终用 Markdown 格式回复,并包含代码示例。”
- 不可见性:在典型的聊天界面中,system 消息对终端用户是不可见的。
在不同协议格式中的差异:
- OpenAI Chat Completions:系统指令作为
messages数组中的system角色消息。 - OpenAI Responses:系统指令同样作为
input数组中的system角色消息。 - Anthropic Messages:系统指令通过单独的
system参数传递,不是 messages 数组的一部分。
最佳实践:
- 将核心指令放在 system 消息中。
- 保持清晰、无歧义。
- 避免过长,以免占用宝贵的上下文窗口(Context Window)。
示例:
// OpenAI Chat Completions / Responses 格式
{"role": "system", "content": "你是一个 helpful、 harmless、 and honest 的助手。请用中文回复。如果用户问题涉及危险或非法内容,请拒绝回答。"}
// Anthropic Messages 格式(在请求顶层)
{
"system": "你是一个 helpful、 harmless、 and honest 的助手。请用中文回复。如果用户问题涉及危险或非法内容,请拒绝回答。",
"messages": [...]
}
2. User 角色(用户)
user 角色代表与模型交互的终端用户或客户端应用程序。
核心特点与用途:
- 指令与输入:承载用户的直接问题、请求或指令。
- 对话驱动:每一轮对话通常由一条 user 消息触发。
- 可包含多模态内容:在支持多模态的模型中,user 消息的
content可以是文本、图片URL、音频数据等的组合。 - 优先级:在遵循 system 指令的前提下,模型会尽力满足 user 的请求。
在不同协议格式中的差异:
- OpenAI Chat Completions:
content可以是字符串或内容块数组,支持多模态。 - OpenAI Responses:
content可以是字符串或内容块数组,支持多模态。 - Anthropic Messages:
content可以是字符串或内容块数组,支持多模态。
示例:
// OpenAI Chat Completions 格式(纯文本)
{"role": "user", "content": "请帮我写一个 Python 函数,计算斐波那契数列的第 n 项。"}
// OpenAI Chat Completions 格式(多模态)
{
"role": "user",
"content": [
{"type": "text", "text": "这张图片里有什么?"},
{"type": "image_url", "image_url": {"url": "data:image/jpeg;base64,..."}}
]
}
// Anthropic Messages 格式(多模态)
{
"role": "user",
"content": [
{"type": "image", "source": {"type": "base64", "media_type": "image/jpeg", "data": "..."}},
{"type": "text", "text": "这张图片里有什么?"}
]
}
3. Assistant 角色(助手)
assistant 角色代表模型自身的回复。在对话历史中,它记录了模型之前的输出。
核心特点与用途:
- 模型输出记录:在多轮对话中,之前的 assistant 回复必须作为上下文的一部分提供给模型,以保持对话连贯性。
- 引导对话:模型的回复会影响下一轮 user 的提问方向。一个详细、有条理的 assistant 回复可能会引导 user 提出更深入的问题。
- 可能包含非文本内容:在 Function Calling 场景中,assistant 消息可能包含工具调用请求。
- 角色扮演:在模拟场景中,assistant 消息可以用来展示“期望的”或“示例的”回复格式。
在不同协议格式中的差异:
- OpenAI Chat Completions:工具调用通过
tool_calls字段表示。 - OpenAI Responses:工具调用通过
tool_calls字段表示。 - Anthropic Messages:工具调用通过
tool_use内容块表示。
示例:
// OpenAI Chat Completions 格式
{"role": "assistant", "content": "好的,这是一个计算斐波那契数列的 Python 函数:\n\n```python\ndef fibonacci(n):\n if n <= 1:\n return n\n else:\n return fibonacci(n-1) + fibonacci(n-2)\n```"}
// Anthropic Messages 格式(带工具调用)
{
"role": "assistant",
"content": [
{"type": "text", "text": "我需要查询当前天气。"},
{"type": "tool_use", "id": "toolu_abc123", "name": "get_weather", "input": {"location": "北京"}}
]
}
4. Developer 角色(开发者)——新兴角色
developer 角色是一个较新的概念,旨在更精细地区分系统级指令和应用开发者指令。它试图解决 system 角色过于“一元化”的问题。
设计理念:
- 指令分层:
system:代表模型提供商(如OpenAI)设定的基础、通用、不可违反的规则(如安全准则)。developer:代表应用开发者注入的、针对特定应用场景的指令和知识。
- 优先级与冲突解决:当
system、developer和user指令发生冲突时,需要有明确的优先级规则。目前,这更多是模型训练和API设计层面的考量。 - 应用场景:
- 开发者可以将自己的业务逻辑、私有知识库说明、格式要求等放在
developer消息中,与通用的system指令分离。 - 便于在不修改底层
system指令(可能由平台控制)的情况下,定制应用行为。
- 开发者可以将自己的业务逻辑、私有知识库说明、格式要求等放在
现状与展望:
- 目前,并非所有模型或API都正式支持
developer角色。OpenAI 在一些文档和讨论中提及过类似概念,但其 Chat Completions API 的官方规范中尚未将其列为标准角色。 - Anthropic Messages 格式目前也没有明确的
developer角色。 - 它代表了协议设计向更精细化、分层化控制发展的趋势。
- 开发者在使用时需查阅具体模型的文档,确认是否支持及如何使用。
三、角色交互与优先级模型
在一个典型的多轮对话中,消息序列如下:
// OpenAI Chat Completions 格式
[
{"role": "system", "content": "基础指令"},
{"role": "user", "content": "第一轮问题"},
{"role": "assistant", "content": "第一轮回答"},
{"role": "user", "content": "第二轮问题"},
...
]
模型如何解读? 模型(特别是经过指令微调的模型)被训练为理解这种结构,并遵循一个隐含的优先级:
- 安全与基础准则(通常由
system角色在训练中固化)。 system消息中的指令。developer消息中的指令(如果支持)。user消息中的指令(当前轮次的请求)。assistant历史消息(用于保持连贯性)。
当指令冲突时,模型会尝试权衡,但通常更高层级的指令更具约束力。例如,一个 system 指令说“不要生成代码”,而 user 请求“写代码”,模型很可能会拒绝 user 的请求。
四、实践建议
- 明确角色职责:将通用规则、安全设置放在
system;将应用特定逻辑、知识放在developer(如果支持)或system的末尾;user只放用户输入;assistant只放模型历史回复。 - 避免角色混淆:不要将用户输入伪装成
system消息来“注入”指令,这可能导致不可预测的行为和安全风险。 - 管理上下文长度:system 消息过长会占用 token 预算,影响对话历史长度。保持 system 指令简洁必要。
- 测试边界:通过故意发送冲突指令,测试你所使用的模型对角色优先级的遵循情况,以更好地控制输出。
- 注意格式差异:不同协议格式对角色的处理方式不同,特别是系统指令的位置(在 messages 数组内还是外)。务必查阅所使用模型的官方文档。
理解并善用角色系统,是构建可靠、可控的大模型应用的关键技能。在下一篇文章中,我们将探讨另一个关键机制——Function Calling,看看角色如何在工具调用中扮演新的角色。
系列文章导航:
- 大模型基础协议概览:OpenAI Chat Completions、OpenAI Responses与Anthropic Messages格式解析
- 上下文角色深度解析:System、User、Assistant与Developer(本文)
- Function Calling协议与调用过程深度剖析
本文为“大模型底层通信协议深究”系列第二篇。