LangChain:消息(Message)类型和特性详解
LangChain的消息系统是结构化对话管理的核心组件,通过明确区分角色和上下文,使大模型能精准处理多轮对话与工具调用。
其核心是四种基础消息类型(SystemMessage、HumanMessage、AIMessage、ToolMessage),官方文档明确要求必须使用类型化消息对象而非原始字典,以确保跨模型兼容性和功能完整性。
核心概念
消息是 LangChain 中模型的基本上下文单元,代表模型的输入和输出,携带内容和元数据,用于表示与 LLM 交互时的对话状态。
消息组成
每条消息是一个对象,包含三个核心要素:
- 角色(Role):标识消息类型(如
system、user、assistant) - 内容(Content):消息的实际内容,可以是文本、图像、音频、文档等
- 元数据(Metadata):可选字段,如响应信息、消息 ID、token 使用量等
LangChain 提供跨所有模型提供商的标准消息类型,确保无论调用哪个模型,行为都保持一致。
基本用法
创建消息对象并将其传递给模型:
1 | from langchain.chat_models import init_chat_model # 导入初始化聊天模型的函数 |
文本提示 vs 消息提示
| 类型 | 适用场景 |
|---|---|
| 文本提示(字符串) | 独立、单次生成任务,无需维护对话历史 |
| 消息提示(消息列表) | 多轮对话、多模态内容(图像/音频/文件)、系统指令注入 |
python
1 | # 字符串示例 |
提示:AIMessage 中可存储模型的回复内容。通过维护包含多条消息的列表,你可以实现多轮对话的上下文管理
字典格式
也可以直接使用 OpenAI 兼容的字典格式,为了多模型提供商的兼容,不建议使用。
1 | messages = [ |
核心消息类型
所有消息类都继承自 BaseMessage,LangChain 提供了以下主要类型:
| 消息类 | 字典Role | 用途 | 前提条件 |
|---|---|---|---|
| SystemMessage | system |
设定 AI 的行为规范、背景、角色定位、知识边界 | 通常位于对话开头,优先级最高 |
| HumanMessage | user |
代表用户(人类)的输入或提问 | — |
| AIMessage | assistant |
代表模型的回复,可能包含工具调用 | — |
| ToolMessage | tool |
代表工具执行后的结果,包含 tool_call_id |
必须在 AIMessage 包含工具调用之后出现 |
| ChatMessage | 自定义 | 当标准角色不够用时,手动指定 role 参数 |
— |
LangChain的消息系统通过结构化角色分工解决上下文混乱问题,必须严格使用类型化消息对象并维护完整对话链。
对比传统方式的好处:使用这些语义化的消息类,可以避免手动写 {"role": ...} 字典,更重要的是可以直接用 isinstance(last_message, AIMessage) 进行类型判断,代码可读性和可维护性显著提升。
SystemMessage
SystemMessage:系统消息
作用:定义AI的角色、行为规则及知识边界,优先级最高,通常作为消息列表的首条消息。
建议:系统消息通常放在对话列表的开头,以持续引导模型行为。
关键特性:
- 决定模型的“身份设定”,直接影响输出风格和内容范围。
- 若模型不支持系统消息(如部分旧版API),LangChain会自动将其合并到
HumanMessage中。
示例代码:
1
2
3
4
5
6from langchain_core.messages import SystemMessage
system_msg = SystemMessage(
content="你是一名金融分析师,仅回答2023年后的A股市场数据问题,"
"超出范围时回复'该问题超出我的知识边界'"
)
HumanMessage
HumanMessage:用户消息
作用:代表用户的输入和交互,支持文本、图像、音频、文件等多元内容,是对话的核心触发点。
关键特性:
- 支持纯文本或多模态输入(如文本+图片),需模型本身支持多模态能力。
- 可附加元数据(如用户ID、会话ID)用于上下文追踪。
示例代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19from langchain_core.messages import HumanMessage
# 纯文本输入
human_msg = HumanMessage(content="2024年上证指数最高点是多少?")
# 多模态输入(需模型支持,如GPT-4o)
human_msg_multimodal = HumanMessage(
content=[
{"type": "text", "text": "描述这张图片的金融含义"},
{"type": "image_url", "image_url": "https://example.com/chart.png"}
]
)
# 带元数据的消息
human_msg = HumanMessage(
content="Hello!", # 消息内容
name="alice", # 可选:标识不同用户
id="msg_123" # 可选:唯一标识符,便于追踪
)消息内容不再局限于纯文本。LangChain 支持标准化的多模态内容块,可以自然交错排列文本、图像、音频等内容。
name字段的行为因模型提供商而异:有些会用于识别用户,有些则忽略。建议查阅对应提供商文档。
AIMessage
AIMessag:AI回复消息
作用:代表模型的输出,可包含多种内容、工具调用和提供商特有的元数据,包含工具调用请求或最终答案。
可以手动创建 AIMessage 对象并插入对话历史,用于预设示例或多轮对话的上下文补充。
关键特性:
content字段存储文本回复,tool_calls字段存储工具调用指令(如需外部工具)。- 支持流式输出(
AIMessageChunk),逐块返回响应内容。
示例代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22from langchain_core.messages import AIMessage
# 普通文本回复
ai_msg = AIMessage(content="2024年上证指数最高点为3,400点(截至2024年12月)")
# 工具调用请求(模拟模型需查询实时数据)
ai_msg_with_tool = AIMessage(
content="",
tool_calls=[{
"name": "get_stock_data",
"args": {"market": "A股", "metric": "index_high"},
"id": "call_abc123" # 必须唯一标识调用
}]
)
response = model.invoke("Explain AI") # 直接获取模型输出
print(type(response)) # <class 'langchain.messages.AIMessage'>
# 内部属性举例
print(response.content) # 文本内容
print(response.tool_calls) # 工具调用(若有)
print(response.usage_metadata) # 令牌使用统计
ToolMessage
ToolMessage:工具结果消息
作用:传当模型发起工具调用后,工具的执行结果通过 ToolMessage 传回模型,**必须关联
tool_call_id**。关键特性:
tool_call_id必须与AIMessage中的调用ID完全匹配,否则模型无法关联结果。content为工具返回的字符串化结果,artifact可存储未发送给模型的原始数据。
示例代码:
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
27
28
29
30
31
32
33
34from langchain_core.messages import ToolMessage
tool_msg = ToolMessage(
content="2024年上证指数最高点:3,421.87点(2024-08-15)",
tool_call_id="call_abc123", # 必须与AIMessage中的ID一致
name="get_stock_data"
)
from langchain.messages import AIMessage, ToolMessage, HumanMessage
# 1. 模型决定调用工具
ai_msg = AIMessage(
content=[],
tool_calls=[{
"name": "get_weather",
"args": {"location": "San Francisco"},
"id": "call_123" # 唯一调用 ID
}]
)
# 2. 执行工具并创建结果消息
weather_result = "Sunny, 72°F"
tool_msg = ToolMessage(
content=weather_result,
tool_call_id="call_123" # 与调用 ID 匹配
)
# 3. 完整对话流
messages = [
HumanMessage("What's the weather in San Francisco?"),
ai_msg, # 模型的工具调用请求
tool_msg # 工具执行结果
]
response = model.invoke(messages) # 模型处理结果并最终回答tool_call_id必须与 AIMessage 中对应工具调用的 ID 一致,否则模型无法正确关联结果。
Artifact 字段
ToolMessage 还提供 artifact 字段,用于存储不会发送给模型的附加数据(如原始结果、调试信息、文档元数据等):
1 | tool_message = ToolMessage( |
Token 用量统计
AIMessage的usage_metadata` 字段保存令牌使用情况:
1 | response = model.invoke("Hello!") |
消息内容
每条消息的 核心负载 通过 content 属性传递。可以使用以下任意一种格式:
纯字符串
1 | response = model.invoke([HumanMessage("What is machine learning?")]) |
提供商原生格式
提供商原生格式,如 OpenAI
1 | human_msg = HumanMessage(content=[ |
LangChain 标准内容块
LangChain 标准内容块(推荐)
1 | human_msg = HumanMessage(content_blocks=[ |
content_blocks 是 LangChain v1 引入的新属性,它不会替代 content,而是提供额外的、跨提供商的标准化访问方式。
标准内容块类型
LangChain 提供了一套标准的内容块表示,可在不同提供商间通用。消息对象实现 content_blocks 属性,惰性解析 content 属性为类型安全的统一表示。
1 | # 来自 Anthropic 的消息包含 thinking 块 |
1 | # 来自 OpenAI 的 reasoning 块 |
各内容块参考
| 类型 | 描述 | 必须字段 | 可选字段 |
|---|---|---|---|
TextContentBlock |
标准文本 | type: “text”, text: 文本内容 |
annotations: 注解列表, extras |
ReasoningContentBlock |
模型的推理步骤 | type: “reasoning”, reasoning: 推理内容 |
extras |
ImageContentBlock |
图像数据 | type: “image” |
url, base64, mime_type, file_id |
AudioContentBlock |
音频数据 | type: “audio” |
url, base64, mime_type |
VideoContentBlock |
视频数据 | type: “video” |
url, base64, mime_type |
FileContentBlock |
通用文件(如 PDF) | type: “file” |
url, base64, mime_type |
PlainTextContentBlock |
纯文本文档 | type: “text-plain”, text: 文本内容 |
mime_type |
ToolCall |
工具调用 | type: “tool_call”, name, args, id |
- |
ServerToolCall |
服务端工具调用 | type: “server_tool_call”, id, name, args |
- |
提示:若遇到提供商独有的实验性字段,可使用 NonStandardContentBlock(type: “non_standard”)作为转义出口,或为每种专用块实现子类。
消息组合与多轮对话
多轮对话的正确结构
必须按顺序组织消息列表,保留完整对话历史:
1
2
3
4
5
6
7
8
9from langchain_core.messages import SystemMessage, HumanMessage, AIMessage, ToolMessage
messages = [
SystemMessage(content="你是一名金融分析师..."),
HumanMessage(content="2024年上证指数最高点是多少?"),
AIMessage(tool_calls=[{"name": "get_stock_data", "id": "call_abc123"}]),
ToolMessage(content="3,421.87点", tool_call_id="call_abc123"),
HumanMessage(content="这个数据来源可靠吗?") # 新问题需带上历史
]
错误 vs 正确实践
错误做法:每次仅传当前问题,丢失上下文:
1
2# ❌ 错误:无历史记录,模型无法关联问题
messages = [HumanMessage(content="这个数据来源可靠吗?")]正确做法:始终携带必要历史,确保逻辑连贯:
1
2
3
4
5
6
7
8# ✅ 正确:包含系统设定、历史问题与工具结果
messages = [
SystemMessage(content="..."),
HumanMessage(content="2024年上证指数最高点..."),
AIMessage(tool_calls=[...]),
ToolMessage(...),
HumanMessage(content="这个数据来源可靠吗?") # 当前问题
]
消息的高级特性
元数据(Metadata)
每条消息都可以携带丰富的元数据:
response_metadata:来自模型提供商的响应信息,如 token 使用量、finish_reason 等id:消息的唯一标识符additional_kwargs:模型供应商特有的额外字段
1 | # 访问响应元数据(以 Python 为例) |
流式消息块(Message Chunks)
LangChain 为每种消息类型提供了流式分块版本,用于实时流式输出
| 消息类型 | 分块类型 | 用途 |
|---|---|---|
AIMessage |
AIMessageChunk |
流式接收 AI 回复片段 |
HumanMessage |
HumanMessageChunk |
流式处理用户输入 |
SystemMessage |
SystemMessageChunk |
流式系统提示 |
ToolMessage |
ToolMessageChunk |
流式工具结果 |
当使用流式输出时,模型会逐块返回数据。LangChain 提供了对应的 Chunk 类(如 AIMessageChunk),且支持用 + 运算符拼接多个块:
1 | # Python 示例:流式输出与消息块拼接 |
使用 stream 方法获取增量内容块,它们可以合并成完整消息。
消息实用工具(Utilities)
langchain_core.messages.utils 模块提供了一系列消息处理工具函数:
| 函数 | 用途 |
|---|---|
convert_to_messages |
将多种格式(字典、消息列表等)统一转换为消息列表 |
messages_from_dict |
从字典序列反序列化为消息对象 |
get_buffer_string |
将消息列表拼接成一个字符串 |
filter_messages |
按名称、类型或 ID 过滤消息 |
trim_messages |
按 token 数量或消息数量修剪消息列表 |
merge_message_runs |
合并同类型的连续消息(ToolMessage 除外) |
1 | # filter_messages 示例:只保留人类消息和 AI 后续消息 |
1 | # trim_messages 示例:修剪消息以保持 token 预算,并保留系统消息 |
示例代码
多轮对话
1 | # 安装:pip install langchain langchain-openai |
官方示例
官方示例:完整工具调用流程
1 | from langchain_core.messages import SystemMessage, HumanMessage, AIMessage, ToolMessage |
多模态示例
1 | # 从 URL 加载图片 |
注意:并非所有模型都支持所有文件类型,请查阅具体提供商的文档。
实践建议
消息管理规范
必须显式使用消息类型,避免原始字典:
1
2
3
4
5# ✅ 官方推荐:类型化消息
messages = [SystemMessage(content="..."), HumanMessage(content="...")]
# ❌ 不推荐:原始字典(可能丢失功能)
messages = [{"role": "system", "content": "..."}, {"role": "user", "content": "..."}]为消息添加ID:便于追踪和删除特定消息(如调试时)。
工具调用关键规则
tool_call_id必须严格匹配:AIMessage中的调用ID与ToolMessage的tool_call_id需完全一致。- 工具结果需结构化:
ToolMessage.content应为字符串化结果,避免直接传递复杂对象。
多模态支持
仅多模态模型(如GPT-4o)支持图像/音频输入,需按规范格式组织 content:
1
2
3
4HumanMessage(content=[
{"type": "text", "text": "分析此图表趋势"},
{"type": "image_url", "image_url": "https://example.com/chart.jpg"}
])
问题与注意事项
| 问题 | 注意事项 |
|---|---|
| 消息顺序要求 | 大多数聊天模型期望对话以 HumanMessage 或 SystemMessage + HumanMessage 开头;ToolMessage 必须出现在对应的 AIMessage(包含工具调用)之后 |
| SystemMessage 限制 | 一次通常只能有一个有效 SystemMessage;多个 SystemMessage 可能会被模型忽略或覆盖 |
| Token 计算 | 不同模型的 tokenizer 不同,trim_messages 的 token_counter 应使用模型自身的计数方法 |
| 多模态模型支持 | 仅多模态模型(如GPT-4o)支持图像/音频输入,需按规范格式组织 content,使用前请查阅模型提供商的文档 |
| 版本变更 | 在较新的 LangChain 版本中,消息核心类主要存放在 langchain_core.messages 模块下 |
核心总结
LangChain的消息系统通过结构化角色分工解决上下文混乱问题,必须严格使用类型化消息对象并维护完整对话链。多轮对话中,遗漏历史消息会导致逻辑断裂;工具调用时,ID匹配是结果整合的关键。官方文档强调,正确使用消息类型是构建可靠对话应用的基础。
LangChain 的消息系统是一个标准化、可扩展、跨模型的抽象层:
- 标准化:统一接口屏蔽不同模型提供商的差异
- 结构化:通过类型系统明确区分角色和用途
- 可追踪:通过
tool_call_id实现工具调用的完整链路追踪 - 多模态:
content支持文本、图像、音频等混合内容
掌握消息系统是构建复杂 Agent 应用的基础,特别是在处理多轮对话、工具调用、流式输出等场景时。
快速参考表
| 场景 | 推荐的消息类型 | 关键点 |
|---|---|---|
| 设定 AI 角色/行为 | SystemMessage |
放在对话开头,只设置一次 |
| 用户输入 | HumanMessage(content=user_input) |
— |
| 模型回复 | AIMessage |
由 model.invoke() 返回 |
| 工具执行结果 | ToolMessage(content=result, tool_call_id=id) |
必须在工具调用之后 |
| 图片输入 | HumanMessage(content=[{type: "image_url", ...}]) |
需模型支持 |
| 流式输出 | AIMessageChunk |
可用 + 拼接 |
| 过滤消息 | filter_messages() |
按类型、名称或 ID 筛选 |
| 控制 token 预算 | trim_messages() |
保留系统消息,确保有效开头 |
| 自定义角色 | ChatMessage(role="custom", content=...) |
用于标准角色之外的场景 |
提示:官方文档入口常变,需要查阅最新资料时,建议使用 site:docs.langchain.com messages 或 site:reference.langchain.com python/core/messages 进行定向搜索。
LangChain:消息(Message)类型和特性详解
http://blog.gxitsky.com/2026/05/04/AI-LangChain-045-Message/

