LangChain:消息(Message)类型和特性详解

LangChain的消息系统是结构化对话管理的核心组件,通过明确区分角色和上下文,使大模型能精准处理多轮对话与工具调用。

其核心是四种基础消息类型(SystemMessage、HumanMessage、AIMessage、ToolMessage),官方文档明确要求必须使用类型化消息对象而非原始字典,以确保跨模型兼容性和功能完整性。

核心概念

消息是 LangChain 中模型的基本上下文单元,代表模型的输入输出,携带内容和元数据,用于表示与 LLM 交互时的对话状态。每条消息是一个对象,包含三个核心要素:

  • 角色(Role):标识消息类型(如 systemuserassistant
  • 内容(Content):消息的实际内容,可以是文本、图像、音频、文档等
  • 元数据(Metadata):可选字段,如响应信息、消息 ID、token 使用量等

LangChain 提供跨所有模型提供商的标准消息类型,确保无论调用哪个模型,行为都保持一致。

核心消息类型

所有消息类都继承自 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
    6
    from 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
    from 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"}
    ]
    )

    消息内容不再局限于纯文本。LangChain 支持标准化的多模态内容块,可以自然交错排列文本、图像、音频等内容。

AIMessage

AIMessag:AI回复消息

  • 作用:存储模型生成的响应,包含工具调用请求或最终答案

  • 关键特性:

    • content字段存储文本回复,tool_calls字段存储工具调用指令(如需外部工具)。
    • 支持流式输出(AIMessageChunk),逐块返回响应内容。
  • 示例代码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    from 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" # 必须唯一标识调用
    }]
    )

ToolMessage

ToolMessage:工具结果消息

  • 作用:传递工具执行结果给模型,**必须关联tool_call_id**。

  • 关键特性:

    • tool_call_id必须与AIMessage中的调用ID完全匹配,否则模型无法关联结果。
    • content为工具返回的字符串化结果,artifact可存储未发送给模型的原始数据。
  • 示例代码:

    1
    2
    3
    4
    5
    6
    7
    from 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"
    )

消息组合与多轮对话

多轮对话的正确结构

  • 必须按顺序组织消息列表,保留完整对话历史:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    from 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
2
3
4
# 访问响应元数据(以 Python 为例)
response = chat_model.invoke(messages)
print(response.response_metadata) # {'token_usage': {...}, 'model': '...'}
print(response.id) # 消息唯一标识

流式消息块(Message Chunks)

LangChain 为每种消息类型提供了流式分块版本,用于实时流式输出

消息类型 分块类型 用途
AIMessage AIMessageChunk 流式接收 AI 回复片段
HumanMessage HumanMessageChunk 流式处理用户输入
SystemMessage SystemMessageChunk 流式系统提示
ToolMessage ToolMessageChunk 流式工具结果

当使用流式输出时,模型会逐块返回数据。LangChain 提供了对应的 Chunk 类(如 AIMessageChunk),且支持用 + 运算符拼接多个块:

1
2
3
4
5
6
# Python 示例:流式输出与消息块拼接
from langchain_core.messages import AIMessageChunk

chunk1 = AIMessageChunk(content="Hello ")
chunk2 = AIMessageChunk(content="World")
full_message = chunk1 + chunk2 # AIMessageChunk(content="Hello World")

消息实用工具(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
2
3
4
5
# filter_messages 示例:只保留人类消息和 AI 后续消息
from langchain_core.messages import filter_messages, HumanMessage, AIMessage

messages = [HumanMessage(content="Hi"), AIMessage(content="Hello"), ...]
filtered = filter_messages(messages, include_types=[HumanMessage, AIMessage])
1
2
3
4
5
6
7
8
9
10
11
# trim_messages 示例:修剪消息以保持 token 预算,并保留系统消息
from langchain_core.messages import trim_messages

trimmed = trim_messages(
messages,
max_tokens=1000, # token 上限
token_counter=model.get_num_tokens,
strategy="last", # 保留最近消息
include_system=True, # 保留系统消息
start_on="human", # 确保消息以 HumanMessage 开头
)

示例代码

多轮对话

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
34
35
36
37
38
39
40
41
42
43
44
45
46
# 安装:pip install langchain langchain-openai
# 设置环境变量:export OPENAI_API_KEY="your-key"

from langchain_core.messages import (
SystemMessage, HumanMessage, AIMessage, ToolMessage,
filter_messages, trim_messages
)
from langchain_openai import ChatOpenAI

# 1. 初始化模型
model = ChatOpenAI(model="gpt-3.5-turbo")

# 2. 构建多轮对话消息
messages = [
SystemMessage(content="You are a helpful assistant that speaks in pirate English."),
HumanMessage(content="What is the capital of France?"),
AIMessage(content="Arrr, that be Paris!"),
HumanMessage(content="What's the weather there?"),
]

# 3. 调用模型并获取回复
response = model.invoke(messages)
print(f"AI: {response.content}")

# 4. 消息过滤示例:只保留系统消息和人类消息
filtered = filter_messages(messages, include_types=[SystemMessage, HumanMessage])

# 5. 消息修剪示例:保留最后两条消息,token 限制 50
trimmed = trim_messages(
messages,
max_tokens=50,
token_counter=model.get_num_tokens,
strategy="last",
include_system=True,
)

# 6. 工具调用示例:使用 ToolMessage
tool_call_messages = [
HumanMessage(content="What's 2+2? Use calculator."),
AIMessage(
content="",
tool_calls=[{"id": "call_123", "name": "calculator", "args": {"expr": "2+2"}}]
),
ToolMessage(content="4", tool_call_id="call_123"),
]
response = model.invoke(tool_call_messages)

官方示例

官方示例:完整工具调用流程

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
from langchain_core.messages import SystemMessage, HumanMessage, AIMessage, ToolMessage
from langchain_openai import ChatOpenAI

# 1. 初始化模型
model = ChatOpenAI(model="gpt-4o")

# 2. 构建对话历史(含工具调用)
messages = [
SystemMessage(content="你是一名金融数据助手,需调用工具获取实时数据"),
HumanMessage(content="2024年上证指数最高点是多少?")
]

# 3. 模型返回工具调用请求
response = model.invoke(messages)
# 假设response.tool_calls = [{"name": "get_stock_data", "id": "call_123", ...}]

# 4. 执行工具并生成ToolMessage
tool_result = "2024年上证指数最高点:3,421.87点(2024-08-15)"
tool_msg = ToolMessage(
content=tool_result,
tool_call_id=response.tool_calls["id"] # 关键:ID必须匹配
)

# 5. 将工具结果加入对话,获取最终回复
final_response = model.invoke(messages + [response, tool_msg])
print(final_response.content)
# 输出:2024年上证指数最高点为3,421.87点,数据来源于上海证券交易所...

实践建议

消息管理规范

  • 必须显式使用消息类型,避免原始字典:

    1
    2
    3
    4
    5
    # ✅ 官方推荐:类型化消息
    messages = [SystemMessage(content="..."), HumanMessage(content="...")]

    # ❌ 不推荐:原始字典(可能丢失功能)
    messages = [{"role": "system", "content": "..."}, {"role": "user", "content": "..."}]
  • 为消息添加ID:便于追踪和删除特定消息(如调试时)。

工具调用关键规则

  • tool_call_id必须严格匹配AIMessage中的调用ID与ToolMessagetool_call_id需完全一致。
  • 工具结果需结构化ToolMessage.content应为字符串化结果,避免直接传递复杂对象。

多模态支持

  • 仅多模态模型(如GPT-4o)支持图像/音频输入,需按规范格式组织 content:

    1
    2
    3
    4
    HumanMessage(content=[
    {"type": "text", "text": "分析此图表趋势"},
    {"type": "image_url", "image_url": "https://example.com/chart.jpg"}
    ])

问题与注意事项

问题 注意事项
消息顺序要求 大多数聊天模型期望对话以 HumanMessageSystemMessage + HumanMessage 开头;
ToolMessage 必须出现在对应的 AIMessage(包含工具调用)之后
SystemMessage 限制 一次通常只能有一个有效 SystemMessage;多个 SystemMessage 可能会被模型忽略或覆盖
Token 计算 不同模型的 tokenizer 不同,trim_messagestoken_counter 应使用模型自身的计数方法
多模态模型支持 仅多模态模型(如GPT-4o)支持图像/音频输入,需按规范格式组织 content,使用前请查阅模型提供商的文档
版本变更 在较新的 LangChain 版本中,消息核心类主要存放在 langchain_core.messages 模块下

核心总结

LangChain的消息系统通过结构化角色分工解决上下文混乱问题,必须严格使用类型化消息对象并维护完整对话链。多轮对话中,遗漏历史消息会导致逻辑断裂;工具调用时,ID匹配是结果整合的关键。官方文档强调,正确使用消息类型是构建可靠对话应用的基础。

LangChain 的消息系统是一个标准化、可扩展、跨模型的抽象层:

  1. 标准化:统一接口屏蔽不同模型提供商的差异
  2. 结构化:通过类型系统明确区分角色和用途
  3. 可追踪:通过 tool_call_id 实现工具调用的完整链路追踪
  4. 多模态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 messagessite:reference.langchain.com python/core/messages 进行定向搜索。

LangChain:消息(Message)类型和特性详解

http://blog.gxitsky.com/2026/05/04/AI-LangChain-045-Message/

作者

光星

发布于

2026-05-04

更新于

2026-05-05

许可协议

评论