知识目录 / 大模型协议

上下文角色深度解析:System、User、Assistant与Developer

深入剖析大模型通信协议中不同角色的定义、作用、优先级及实际应用场景,帮助开发者精准控制模型行为。

在大模型通信协议中,角色(Role) 是构建有效上下文的核心。它不仅仅是消息的标签,更是指导模型理解“谁在说话”以及“该如何回应”的关键指令。本文将深度解析 systemuserassistant 以及新兴的 developer 角色,并探讨它们在不同协议格式中的差异与最佳实践。

一、角色系统的设计目的

角色系统的设计主要解决以下问题:

  1. 指令分离:将不同来源、不同目的的指令清晰分开,避免混淆。
  2. 行为控制:通过系统指令(System Prompt)在对话开始前定义模型的人格、能力边界和行为准则。
  3. 对话模拟:通过区分用户和助手的消息,构建逼真的多轮对话历史。
  4. 安全与审核:不同角色可应用不同的内容审核策略(例如,对 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)。

示例:

json
// 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 Completionscontent 可以是字符串或内容块数组,支持多模态。
  • OpenAI Responsescontent 可以是字符串或内容块数组,支持多模态。
  • Anthropic Messagescontent 可以是字符串或内容块数组,支持多模态。

示例:

json
// 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 内容块表示。

示例:

json
// 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:代表应用开发者注入的、针对特定应用场景的指令和知识。
  • 优先级与冲突解决:当 systemdeveloperuser 指令发生冲突时,需要有明确的优先级规则。目前,这更多是模型训练和API设计层面的考量。
  • 应用场景
    • 开发者可以将自己的业务逻辑、私有知识库说明、格式要求等放在 developer 消息中,与通用的 system 指令分离。
    • 便于在不修改底层 system 指令(可能由平台控制)的情况下,定制应用行为。

现状与展望:

  • 目前,并非所有模型或API都正式支持 developer 角色。OpenAI 在一些文档和讨论中提及过类似概念,但其 Chat Completions API 的官方规范中尚未将其列为标准角色。
  • Anthropic Messages 格式目前也没有明确的 developer 角色。
  • 它代表了协议设计向更精细化、分层化控制发展的趋势。
  • 开发者在使用时需查阅具体模型的文档,确认是否支持及如何使用。

三、角色交互与优先级模型

在一个典型的多轮对话中,消息序列如下:

json
// OpenAI Chat Completions 格式
[
  {"role": "system", "content": "基础指令"},
  {"role": "user", "content": "第一轮问题"},
  {"role": "assistant", "content": "第一轮回答"},
  {"role": "user", "content": "第二轮问题"},
  ...
]

模型如何解读? 模型(特别是经过指令微调的模型)被训练为理解这种结构,并遵循一个隐含的优先级:

  1. 安全与基础准则(通常由 system 角色在训练中固化)。
  2. system 消息中的指令
  3. developer 消息中的指令(如果支持)。
  4. user 消息中的指令(当前轮次的请求)。
  5. assistant 历史消息(用于保持连贯性)。

当指令冲突时,模型会尝试权衡,但通常更高层级的指令更具约束力。例如,一个 system 指令说“不要生成代码”,而 user 请求“写代码”,模型很可能会拒绝 user 的请求。

四、实践建议

  1. 明确角色职责:将通用规则、安全设置放在 system;将应用特定逻辑、知识放在 developer(如果支持)或 system 的末尾;user 只放用户输入;assistant 只放模型历史回复。
  2. 避免角色混淆:不要将用户输入伪装成 system 消息来“注入”指令,这可能导致不可预测的行为和安全风险。
  3. 管理上下文长度:system 消息过长会占用 token 预算,影响对话历史长度。保持 system 指令简洁必要。
  4. 测试边界:通过故意发送冲突指令,测试你所使用的模型对角色优先级的遵循情况,以更好地控制输出。
  5. 注意格式差异:不同协议格式对角色的处理方式不同,特别是系统指令的位置(在 messages 数组内还是外)。务必查阅所使用模型的官方文档。

理解并善用角色系统,是构建可靠、可控的大模型应用的关键技能。在下一篇文章中,我们将探讨另一个关键机制——Function Calling,看看角色如何在工具调用中扮演新的角色。


系列文章导航:

  1. 大模型基础协议概览:OpenAI Chat Completions、OpenAI Responses与Anthropic Messages格式解析
  2. 上下文角色深度解析:System、User、Assistant与Developer(本文)
  3. Function Calling协议与调用过程深度剖析

本文为“大模型底层通信协议深究”系列第二篇。