消息角色 - 构建 Agent 对话的基础 / Message Roles as the Foundation of Agent Conversations
📅 创建时间:2026-04-28 🏷️ 标签:#消息角色 #System #User #Assistant #对话结构 📚 前置知识:[[03 - 解码策略]]
📋 本章目标
- 理解消息角色的概念和作用
- 掌握 System、User、Assistant 三种角色的用法
- 理解消息格式的演变历史
- 能够构建有效的多轮对话结构
- 理解 Token 消耗与消息结构的关系
第1部分:消息角色的概念
1.1 什么是消息角色?
消息角色(Role)= 对话中每个参与者的身份标识
┌─────────────────────────────────────────────────────────────┐
│ 对话结构 │
├─────────────────────────────────────────────────────────────┤
│ │
│ System(系统) │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ "你是一个乐于助人的AI助手,擅长回答各种问题。" │ │
│ └─────────────────────────────────────────────────────┘ │
│ ↓ │
│ User(用户) │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ "什么是人工智能?" │ │
│ └─────────────────────────────────────────────────────┘ │
│ ↓ │
│ Assistant(助手) │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ "人工智能是..." │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
1.2 三种核心角色
| 角色 | 英文 | 作用 | 特点 |
|---|---|---|---|
| 系统 | System | 定义 AI 的行为和约束 | 通常只出现一次,位于开头 |
| 用户 | User | 人类输入的问题或指令 | 可以出现多次,多轮对话 |
| 助手 | Assistant | AI 的回复 | 可以出现多次,历史记录 |
第2部分:System 角色 - AI 的"人设"
2.1 System 的作用
System = 给 AI 定义"人设"、规则和约束
┌─────────────────────────────────────────────────────────────┐
│ System 消息的作用 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 1. 定义角色身份 │
│ "你是一个Python编程专家" │
│ │
│ 2. 设置行为规则 │
│ "回答要简洁,不要超过100字" │
│ │
│ 3. 提供背景知识 │
│ "假设用户是一个完全没有编程经验的初学者" │
│ │
│ 4. 指定输出格式 │
│ "用JSON格式回复,包含code和explanation字段" │
│ │
└─────────────────────────────────────────────────────────────┘1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2.2 System 的使用示例
示例1:角色定义
python
messages = [
{
"role": "system",
"content": "你是一个专业的中英文翻译专家,擅长将中文翻译成地道的英文"
}
]1
2
3
4
5
6
2
3
4
5
6
示例2:多规则设置
python
messages = [
{
"role": "system",
"content": """你是一个技术文档助手。
规则:
1. 回答要简洁明了
2. 代码示例要完整可运行
3. 使用中文回复
4. 如果不确定,说明不知道"""
}
]1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
示例3:Few-shot 示例在 System 中
python
messages = [
{
"role": "system",
"content": """将下列中文翻译成英文。
示例:
中文:我爱你 → English: I love you
中文:今天天气很好 → English: The weather is nice today."""
},
{
"role": "user",
"content": "我喜欢学习编程"
}
]1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
2.3 System 的最佳实践
| 实践 | 说明 |
|---|---|
| 放在最前面 | System 消息应该在所有消息的最前面 |
| 简洁明了 | 避免过于冗长的系统提示,效果不一定更好 |
| 具体而非模糊 | "你是Python专家" 比 "你很聪明" 更有效 |
| 渐进式设置 | 如果复杂,可以先用简单 System,后续动态添加 |
第3部分:User 角色 - 人类输入
3.1 User 的作用
User = 用户的提问、指令或请求
┌─────────────────────────────────────────────────────────────┐
│ User 消息的特点 │
├─────────────────────────────────────────────────────────────┤
│ │
│ • 可以出现任意多次 │
│ • 每次对话开始时必须有 │
│ • 应该是清晰、具体的指令 │
│ • 可以包含上下文信息 │
│ │
└─────────────────────────────────────────────────────────────┘1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
3.2 User 消息的常见类型
类型1:直接提问
python
{"role": "user", "content": "什么是Python?"}1
类型2:带上下文的提问
python
{"role": "user", "content": "我正在学习Python,以下代码报错请帮我修复:\n\nprint('Hello World)"}1
类型3:明确的任务指令
python
{"role": "user", "content": "请帮我写一个Python函数,计算两个数的和。"}1
类型4:多轮对话中的追问
python
{"role": "user", "content": "能再详细解释一下吗?"}1
3.3 优化 User 消息
好例子:
❌ 模糊:"那个问题"
✅ 明确:"关于你刚才解释的神经网络,能举个例子吗?"
❌ 过长:"帮我看看代码,有个bug,代码是这样的..."
✅ 简洁:"以下Python代码报错:x = 1 + '2',请修复"1
2
3
4
5
2
3
4
5
第4部分:Assistant 角色 - AI 回复
4.1 Assistant 的作用
Assistant = AI 模型的回复
┌─────────────────────────────────────────────────────────────┐
│ Assistant 消息的作用 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 1. 存储历史对话 │
│ 让模型"记得"之前的上下文 │
│ │
│ 2. Few-shot 示例 │
│ 提供输入-输出对,让模型学习模式 │
│ │
│ 3. 引导模型行为 │
│ 通过示例告诉模型期望的回复格式 │
│ │
└─────────────────────────────────────────────────────────────┘1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
4.2 用于历史记录
多轮对话示例:
python
messages = [
{"role": "system", "content": "你是一个友好的助手"},
# 第一轮
{"role": "user", "content": "你好,我叫小明"},
{"role": "assistant", "content": "你好小明!很高兴认识你。有什么我可以帮你的吗?"},
# 第二轮
{"role": "user", "content": "我叫小明"},
# 第三轮(这里模型需要"记得"小明)
{"role": "user", "content": "你还记得我叫什么吗?"}
]1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
注意:
User 消息中重复"我叫小明"是必要的
因为上下文窗口有限时,可能需要重复关键信息1
2
2
4.3 用于 Few-shot 示例
翻译任务示例:
python
messages = [
{"role": "system", "content": "你是一个翻译专家"},
# Few-shot 示例
{"role": "assistant", "content": "Hello, how are you?"},
{"role": "user", "content": "你好,你好吗?"},
# 继续示例
{"role": "assistant", "content": "Python is a great language."},
{"role": "user", "content": "Python是一门很棒的语言。"},
# 真实任务
{"role": "user", "content": "I love learning new things."}
]1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
4.4 Assistant 的 Token 消耗
重要:Assistant 的回复也会消耗 Token 并计入成本!
┌─────────────────────────────────────────────────────────────┐
│ Token 消耗示例 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 输入 Token 数(User + 历史 Assistant): │
│ • 用户输入:50 tokens │
│ • 历史对话:500 tokens │
│ • 系统提示:30 tokens │
│ 总输入:580 tokens │
│ │
│ 输出 Token 数(当前 Assistant): │
│ • 模型回复:200 tokens │
│ 总输出:200 tokens │
│ │
│ 本次请求总消耗:580 + 200 = 780 tokens │
│ │
└─────────────────────────────────────────────────────────────┘1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
第5部分:消息格式的演变
5.1 Completion 时代(GPT-2 及之前)
原始 API:
python
response = openai.Completion.create(
model="davinci",
prompt="The capital of France is",
)1
2
3
4
2
3
4
特点:
• 只有一个 prompt 参数
• 模型是"补全"(Completion)模式
• 给定上文,预测下文
• 不支持多角色1
2
3
4
2
3
4
5.2 Chat Completion 时代(GPT-3.5 及之后)
现代 API:
python
response = openai.chat.completions.create(
model="gpt-3.5-turbo",
messages=[
{"role": "system", "content": "..."},
{"role": "user", "content": "..."},
]
)1
2
3
4
5
6
7
2
3
4
5
6
7
特点:
• messages 数组,支持多角色
• 更自然的多轮对话
• System 角色提供行为约束
• 结构化更强1
2
3
4
2
3
4
5.3 格式对比
| 特性 | Completion | Chat Completion |
|---|---|---|
| 输入格式 | 纯文本 prompt | 结构化 messages |
| 多角色 | 不支持 | System/User/Assistant |
| Few-shot | 直接拼接在 prompt 中 | 通过 messages 示例 |
| 多轮对话 | 需要手动拼接 | 天然支持 |
| 成本 | 通常更低 | GPT-3.5 便宜很多 |
5.4 为什么 Chat Completion 更流行?
1. 更自然的交互方式
人类对话 = 多轮消息交换
Chat Completion 模拟这种方式
2. 更好的 System 控制
System 消息可以统一设置行为
3. 成本更低
GPT-3.5-turbo 是 GPT-3 davinci 的 1/60
4. 更强的指令遵循
专门为对话优化1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
第6部分:多轮对话结构详解
6.1 典型对话流程
┌─────────────────────────────────────────────────────────────┐
│ 多轮对话流程 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 轮次1: │
│ messages = [ │
│ {role: "system", content: "..."}, ← 只在开始时添加 │
│ {role: "user", content: "问题1"} │
│ ] │
│ response = model.predict(messages) │
│ messages.append({role: "assistant", content: "回答1"}) │
│ │
│ 轮次2: │
│ messages.append({role: "user", content: "追问"}) │
│ response = model.predict(messages) │
│ messages.append({role: "assistant", content: "回答2"}) │
│ │
│ 轮次3: │
│ messages.append({role: "user", content: "再问"}) │
│ response = model.predict(messages) │
│ ... │
│ │
└─────────────────────────────────────────────────────────────┘1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
6.2 实际代码示例
python
from openai import OpenAI
client = OpenAI()
# 初始化对话
messages = [
{
"role": "system",
"content": "你是一个Python编程助手,擅长解释代码和修复bug。"
}
]
def chat(user_input):
global messages
# 添加用户消息
messages.append({"role": "user", "content": user_input})
# 调用 API
response = client.chat.completions.create(
model="gpt-3.5-turbo",
messages=messages,
temperature=0.7,
)
# 获取回复
assistant_message = response.choices[0].message.content
# 保存回复到历史
messages.append({"role": "assistant", "content": assistant_message})
return assistant_message
# 多轮对话
print(chat("什么是递归?")) # 轮次1
print(chat("能举个具体的例子吗?")) # 轮次2
print(chat("这个和循环有什么区别?")) # 轮次31
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
6.3 Token 限制下的对话管理
问题:对话太长会超出上下文限制
解决方案:
1. 摘要策略(Summarization)
当对话超过阈值时,调用模型摘要历史
┌─────────────────────────────────────────┐
│ messages = [ │
│ system, │
│ 摘要: "用户在学习Python递归..." │ ← 替换为摘要
│ user: "动态规划是什么?", │
│ ] │
└─────────────────────────────────────────┘
2. 滑动窗口(Sliding Window)
只保留最近 N 轮对话
┌─────────────────────────────────────────┐
│ messages = [ │
│ system, │
│ user: "上一轮问题", │
│ assistant: "上一轮回答", │
│ user: "当前问题", │
│ ] │
│ ↑ 丢弃更早的对话 │
└─────────────────────────────────────────┘
3. RAG(检索增强)
从外部知识库检索相关信息1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
第7部分:实用模板
7.1 问答助手模板
python
messages = [
{
"role": "system",
"content": """你是一个专业的知识问答助手。
要求:
1. 回答准确、简洁
2. 如果不确定答案,诚实地说明
3. 在回答的最后提供信息来源(如果知道)"""
}
]1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
7.2 代码助手模板
python
messages = [
{
"role": "system",
"content": """你是一个经验丰富的Python开发工程师。
擅长:
1. 编写和优化Python代码
2. 调试和修复bug
3. 解释代码逻辑
回复格式:
1. 先解释问题原因
2. 提供修复后的代码
3. 解释关键改动"""
}
]1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
7.3 翻译助手模板
python
messages = [
{
"role": "system",
"content": """你是一个专业的中英文翻译专家。
规则:
1. 翻译要地道,符合目标语言习惯
2. 保持原文的语气和风格
3. 对于专有名词,保留英文或使用通用译法"""
},
{
"role": "assistant",
"content": "I am very happy to meet you."
},
{
"role": "user",
"content": "我非常高兴见到你。"
}
]1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
核心总结
总结1:三种角色的分工
| 角色 | 位置 | 作用 | 出现次数 |
|---|---|---|---|
| System | 开头 | 定义AI行为和约束 | 通常1次 |
| User | 任意 | 人类输入 | 多次 |
| Assistant | 任意 | AI回复/历史 | 多次 |
总结2:多轮对话的关键
1. 保留完整历史
2. 合理管理 Token 消耗
3. 必要时进行摘要或截断1
2
3
2
3
总结3:Chat Completion vs Completion
| 特性 | Chat Completion | Completion |
|---|---|---|
| 格式 | messages数组 | 纯文本 |
| 多角色 | 支持 | 不支持 |
| 多轮对话 | 简单 | 复杂 |
| 成本 | 低 | 高 |
章节测试
测试1:角色识别
以下消息应该使用什么角色? "请帮我写一个计算圆面积的Python函数"
测试2:System 位置
System 消息应该放在 messages 数组的什么位置?
测试3:历史记录
在多轮对话中,为什么需要把 Assistant 的回复也加入 messages?
测试4:Token 消耗
如果用户发送了 100 tokens,助手回复了 200 tokens,历史还有 1000 tokens,总共消耗了多少输入 Token?
测试5:格式选择
如果要实现一个多轮对话聊天机器人,应该使用 Completion API 还是 Chat Completion API?
参考答案
测试1答案
答案:User
解析:用户发出的请求/指令使用 User 角色
测试2答案
答案:messages 数组的最前面
解析:System 消息定义 AI 的整体行为,应该在其他消息之前被模型"看到"
测试3答案
答案:为了保持对话上下文,让模型知道之前说了什么
解析:
1. 模型本身没有"记忆"
2. 它只能"看到"发送给它的 messages
3. 如果不保存历史,后续轮次就无法知道之前的内容
4. 把 Assistant 回复加入 messages,可以让模型"看到"对话历史1
2
3
4
2
3
4
测试4答案
答案:1100 tokens
解析:
输入 Token 数 = User消息 + 历史(包含Assistant回复) = 100 + 1000 = 1100
注意:助手的回复(200 tokens)是"输出"Token,不计入输入1
2
3
2
3
测试5答案
答案:Chat Completion API
解析:
1. Chat Completion 原生支持多角色
2. 多轮对话更简单(只需要追加 messages)
3. 成本更低(GPT-3.5-turbo 非常便宜)
4. 更好地支持 System 消息定义 AI 行为1
2
3
4
2
3
4
相关笔记
- [[02 - Token 与上下文窗口]] - 消息的 Token 消耗计算
- [[05 - 流式输出]] - 如何实时显示助手回复
- [[06 - Prompt 工程]] - 通过 System 消息优化输出
下一步学习
- [ ] 阅读 05 - 流式输出
学习状态:✅ 已完成