LangChain 消息类型
在 LangChain 中,聊天模型和 Agent 主要通过消息(Message)进行交互。
消息不仅可以包含普通文本,还可以包含系统指令、工具调用、工具执行结果,以及图片等多模态内容。
理解 LangChain 的消息类型,有助于开发多轮对话、Agent、工具调用和多模态 AI 应用。
本章节基于 LangChain 1.x 的消息 API,介绍常用消息类型、消息属性、流式消息以及消息历史管理。
一、LangChain 的核心消息类型
LangChain 常用的四种消息类型分别是:
| 消息类型 | 角色 | 主要用途 |
|---|---|---|
HumanMessage |
用户 | 表示用户发送的问题或内容 |
AIMessage |
AI 助手 | 表示模型回复,也可能包含工具调用 |
SystemMessage |
系统 | 设置模型的角色、任务和行为规则 |
ToolMessage |
工具 | 保存工具执行结果,关联对应的工具调用 |
一个简单的对话可以表示为:
SystemMessage:你是一名 Python 编程助手。 HumanMessage:什么是 Python? AIMessage:Python 是一种通用编程语言。
如果使用工具,消息流程可能变成:
HumanMessage
↓
AIMessage(包含 tool_calls)
↓
ToolMessage(工具执行结果)
↓
AIMessage(最终回答)
这些消息会组成消息列表,用于向聊天模型提供对话上下文。
二、HumanMessage:用户消息
HumanMessage 用于表示用户发送给聊天模型的内容。
例如:
实例
# 创建用户消息
message = HumanMessage(
content="菜鸟教程 RUNOOB 是什么?"
)
print("消息类型:", message.type)
print("消息内容:", message.content)
print("消息 ID:", message.id)
可能输出:
消息类型: human 消息内容: 菜鸟教程 RUNOOB 是什么? 消息 ID: None
其中:
content:消息内容。type:LangChain 消息类型,HumanMessage 为human。id:消息标识,可能为 None,也可能由调用方或模型提供商设置。
注意:不能直接假设 HumanMessage 对象存在 role 属性。LangChain 消息对象通常使用 type 标识消息类型,而 OpenAI 风格的消息字典使用 role 字段。
使用 HumanMessage 调用模型
实例
from langchain.messages import HumanMessage
from langchain.chat_models import init_chat_model
load_dotenv()
model = init_chat_model(
"deepseek:deepseek-flash"
)
messages = [
HumanMessage(
content="用一句话介绍菜鸟教程 RUNOOB。"
)
]
response = model.invoke(messages)
print(response.content)
模型通常返回一个 AIMessage 对象,其中包含生成的回复。
本例需要提前安装 langchain、langchain-deepseek 和 python-dotenv,并配置 DEEPSEEK_API_KEY。
HumanMessage 的快捷写法
除了直接创建消息对象,LangChain 还支持通过元组和字典描述消息。
实例
# 方式一:消息对象
msg1 = HumanMessage(content="你好")
# 方式二:元组
msg2 = ("user", "你好")
# 方式三:字典
msg3 = {
"role": "user",
"content": "你好"
}
print(type(msg1))
print(msg2)
print(msg3)
需要注意,元组和字典本身不会立即变成 HumanMessage 对象。
只有在传入接受 MessageLike 格式的 LangChain API 时,框架才会按需进行消息转换。
例如:
messages = [
("system", "你是一名编程助手"),
("user", "介绍 Python")
]
response = model.invoke(messages)
这种写法可以减少重复创建消息对象的代码。
三、AIMessage:AI 回复
AIMessage 表示语言模型生成的消息。
除了普通文本,AIMessage 还可以包含工具调用信息、Token 使用统计和响应元数据。
创建普通 AIMessage
实例
message = AIMessage(
content="菜鸟教程是一个在线编程学习平台。"
)
print("类型:", message.type)
print("内容:", message.content)
print("工具调用:", message.tool_calls)
执行结果:
类型: ai 内容: 菜鸟教程是一个在线编程学习平台。 工具调用: []
这里的 tool_calls 是空列表,说明这条消息没有提供标准化的工具调用请求。
包含工具调用的 AIMessage
当模型需要调用工具时,可以通过 tool_calls 返回工具名称与参数。
实例
message = AIMessage(
content="",
tool_calls=[
{
"name": "get_weather",
"args": {
"city": "杭州"
},
"id": "call_001",
"type": "tool_call"
}
]
)
print("消息内容:", message.content)
for call in message.tool_calls:
print("工具名称:", call["name"])
print("工具参数:", call["args"])
print("调用 ID:", call["id"])
执行结果:
消息内容:
工具名称: get_weather
工具参数: {'city': '杭州'}
调用 ID: call_001
这里手动构造了一条带有工具调用请求的消息,仅用于展示数据结构。
实际调用时,工具调用 ID 通常由模型服务生成。
需要特别注意:AIMessage 中出现 tool_calls,并不表示工具已经执行。
工具需要由应用程序或 Agent 执行。
AIMessage 的附加信息
模型返回的 AIMessage 还可能提供以下信息:
| 属性 | 说明 |
|---|---|
content |
模型生成的内容 |
tool_calls |
有效的工具调用请求 |
invalid_tool_calls |
未能正常解析的工具调用 |
response_metadata |
模型响应元数据 |
usage_metadata |
标准化 Token 使用统计 |
id |
消息标识 |
实例:查看模型响应信息
实例
model = init_chat_model(
"deepseek:deepseek-flash"
)
response = model.invoke(
"介绍菜鸟教程 RUNOOB。"
)
print("内容:", response.content)
print("消息 ID:", response.id)
# 提供商返回的响应元数据
print("响应元数据:")
print(response.response_metadata)
# 标准化 Token 使用情况
usage = response.usage_metadata
if usage:
print("输入 Token:", usage.get("input_tokens"))
print("输出 Token:", usage.get("output_tokens"))
print("总 Token:", usage.get("total_tokens"))
else:
print("没有返回标准化 Token 统计")
不同模型提供商返回的 response_metadata 字段可能不同。
例如,模型名称、结束原因等字段的名称并不保证完全一致,因此不应依赖固定的元数据结构。
usage_metadata 是 LangChain 提供的标准化使用量字段,但也取决于服务商是否返回相关数据。
四、SystemMessage:系统指令
SystemMessage 通常用于向模型提供系统级指令,例如角色设定、回答风格和任务要求。
它一般放在消息列表的开头。
实例:设置回答风格
实例
SystemMessage,
HumanMessage
)
from langchain.chat_models import init_chat_model
model = init_chat_model(
"deepseek:deepseek-flash"
)
messages = [
SystemMessage(
content=(
"你是一名 Python 编程教程作者。"
"回答应该简洁、准确,"
"尽量使用初学者容易理解的语言。"
)
),
HumanMessage(
content="什么是 Python 装饰器?"
)
]
response = model.invoke(messages)
print(response.content)
模型会参考系统指令来组织回答。
例如,可以通过 SystemMessage 要求:
- 使用中文回答。
- 限制回答长度。
- 采用指定的解释风格。
- 优先使用提供的资料。
- 对未知信息明确说明。
注意:系统指令能够影响模型行为,但不能保证模型严格遵守所有要求。
对于必须执行的业务规则,例如用户权限、文件访问范围和支付校验,仍应在应用程序中实现,不能只依赖 SystemMessage。
五、ToolMessage:工具执行结果
ToolMessage 用于保存工具执行后返回的信息。
每个工具结果需要通过 tool_call_id 与先前的工具调用请求关联。
实例:完整的工具调用消息
实例
HumanMessage,
AIMessage,
ToolMessage
)
from langchain.chat_models import init_chat_model
# 手动构造一段工具调用历史
messages = [
HumanMessage(
content="根据模拟数据,杭州天气怎么样?"
),
# 模拟模型请求调用工具
AIMessage(
content="",
tool_calls=[
{
"name": "get_weather",
"args": {
"city": "杭州"
},
"id": "call_weather_001",
"type": "tool_call"
}
]
),
# 模拟工具已执行并返回结果
ToolMessage(
content="晴,25°C,湿度60%",
name="get_weather",
tool_call_id="call_weather_001"
)
]
model = init_chat_model(
"deepseek:deepseek-flash"
)
response = model.invoke(messages)
print(response.content)
模型可以基于工具结果生成类似回答:
根据提供的模拟数据,杭州天气晴, 气温25°C,湿度60%。
这里需要注意:
AIMessage.tool_calls[0]["id"]是工具调用 ID。ToolMessage.tool_call_id必须与对应的调用 ID 匹配。- 如果一条 AIMessage 包含多个工具调用,就需要提供对应的工具结果。
- 工具消息通常不能作为与上下文无关的独立用户输入。
不匹配或缺失的工具结果可能导致模型 API 拒绝请求,具体行为取决于提供商。
注意:本例中的天气数据是模拟数据,不是实时查询结果。
ToolMessage 的其他属性
除了 content 和 tool_call_id,ToolMessage 还支持一些附加字段。
例如,部分场景可以使用 artifact 保存不需要直接发送给模型的完整工具结果:
实例
message = ToolMessage(
content="找到3条匹配记录",
tool_call_id="call_search_001",
name="search_database",
artifact={
"records": [
{"id": 1, "name": "Python"},
{"id": 2, "name": "Java"},
{"id": 3, "name": "Go"}
]
}
)
print(message.content)
print(message.artifact)
content 可以保存供模型使用的简要结果,artifact 则可以保存应用需要的补充数据。
不过,artifact 不是模型自动理解或使用的内容,具体处理方式取决于应用程序。
六、AIMessageChunk:流式消息片段
使用 stream() 时,模型可以逐步返回消息片段。
对于常见聊天模型,流式响应通常包含 AIMessageChunk。
与完整的 AIMessage 不同,消息片段可能只包含部分文本或部分工具调用信息。
实例:流式输出
实例
model = init_chat_model(
"deepseek:deepseek-flash"
)
print("开始流式输出:")
for chunk in model.stream(
"用一句话介绍菜鸟教程 RUNOOB。"
):
print(
chunk.text,
end="",
flush=True
)
print()
chunk.text 用于获取消息片段中的文本内容。
需要注意,流式响应不一定只包含文本。部分模型可能返回思考信息、工具调用片段或其他内容。
合并消息片段
LangChain 支持使用 + 合并兼容的消息片段。
实例
model = init_chat_model(
"deepseek:deepseek-flash"
)
full_chunk = None
for chunk in model.stream("介绍 Python。"):
if full_chunk is None:
full_chunk = chunk
else:
full_chunk = full_chunk + chunk
if full_chunk is not None:
print("完整文本:")
print(full_chunk.text)
print("消息类型:")
print(type(full_chunk))
这种方式适合需要累积流式响应、工具调用参数片段或统计信息的应用。
注意:当流式输出包含工具调用时,不应将每个工具调用片段直接当作完整 JSON 参数使用,应等待并合并必要的片段。
七、LangChain 消息属性速查表
| 消息类型 | type | 常用属性 | 主要用途 |
|---|---|---|---|
HumanMessage |
human | content、id | 用户输入 |
AIMessage |
ai | content、tool_calls、usage_metadata | 模型回复 |
SystemMessage |
system | content | 系统指令 |
ToolMessage |
tool | content、tool_call_id、name、artifact | 工具结果 |
AIMessageChunk |
ai | content、tool_call_chunks | 流式模型响应 |
RemoveMessage |
remove | id | 状态更新中删除指定消息 |
AIMessageChunk 虽然同样可以显示 type="ai",但它与完整的 AIMessage 是不同的 Python 类型。
另外,LangChain 消息类型在不断扩展,除了上面的常用类型,还有 ChatMessage 等用于自定义角色的消息类。
八、ContentBlock:结构化消息内容
前面的示例大多使用字符串作为 content。
但在实际应用中,消息还可能包含图片、音频、视频、文件以及其他结构化信息。
LangChain 1.x 提供标准化内容块(Content Blocks)机制,用于表示这些不同类型的内容。
常见 ContentBlock 类型
| 类型 | 说明 |
|---|---|
TextContentBlock |
普通文本内容 |
ImageContentBlock |
图片内容 |
AudioContentBlock |
音频内容 |
VideoContentBlock |
视频内容 |
FileContentBlock |
PDF、Word 等文件内容 |
PlainTextContentBlock |
纯文本文件内容,例如 TXT 文件 |
ReasoningContentBlock |
模型提供的标准化推理内容 |
需要特别区分:
TextContentBlock:普通聊天文本。PlainTextContentBlock:主要用于表示文本文件或纯文本数据资源。
另外,ToolCall 通常保存在 AIMessage 的 tool_calls 中,而不是简单地当作图片或文本内容块处理。
实例:构建文本内容块
实例
# 普通字符串消息
simple_message = HumanMessage(
content="你好,LangChain!"
)
# 使用标准化文本内容块
block_message = HumanMessage(
content_blocks=[
{
"type": "text",
"text": "你好,LangChain!"
}
]
)
print(simple_message.content)
print(block_message.content_blocks)
通过 content_blocks 可以访问标准化后的消息内容块。
与 content 不同,content_blocks 更适合用于处理不同提供商的多模态内容格式。
九、多模态消息:文本与图片
对于支持图片输入的模型,可以在同一条消息中同时提供文本和图片。
例如,让模型描述一张网页截图。
注意:不是所有聊天模型都支持图片输入。是否支持多模态,需要核对当前模型及其 API 的实际能力。
本节使用 OpenAI 的视觉模型展示消息结构,不使用 DeepSeek Flash 作为默认图片示例。
实例:通过图片 URL 提问
实例
from langchain.chat_models import init_chat_model
from langchain.messages import HumanMessage
load_dotenv()
# 使用支持图片输入的模型
model = init_chat_model(
"openai:gpt-4o"
)
messages = [
HumanMessage(
content=[
{
"type": "text",
"text": "请描述这张图片的主要内容。"
},
{
"type": "image_url",
"image_url": {
"url": "https://www.langchain.com/images/brand/langchain_logo_text_w_white.png"
}
}
]
)
]
response = model.invoke(messages)
print(response.content)
上面使用的是 OpenAI 兼容的多模态消息格式。
如果使用其他提供商,其底层图片格式可能不同。LangChain 也提供标准化的 ImageContentBlock 来减少不同提供商之间的格式差异。
实例:标准化图片内容块
实例
message = HumanMessage(
content_blocks=[
{
"type": "text",
"text": "请描述这张图片。"
},
{
"type": "image",
"url": "https://www.langchain.com/images/brand/langchain_logo_text_w_white.png"
}
]
)
for block in message.content_blocks:
print(block)
标准化图片块通常使用 type="image"。
图片可以通过 URL、Base64 数据或部分提供商支持的文件 ID 等方式提供。
实例:读取本地图片
如果需要使用本地图片,可以先将图片转换为 Base64 编码。
实例
from pathlib import Path
from langchain.messages import HumanMessage
# 读取本地 PNG 图片
image_path = Path("screenshot.png")
image_base64 = base64.b64encode(
image_path.read_bytes()
).decode("utf-8")
message = HumanMessage(
content_blocks=[
{
"type": "text",
"text": "请描述截图中的主要内容。"
},
{
"type": "image",
"base64": image_base64,
"mime_type": "image/png"
}
]
)
print("内容块数量:", len(message.content_blocks))
以上代码展示如何创建包含本地图片数据的消息,不会自动调用模型。
后续可以将 message 传入支持图片输入的聊天模型。
注意:图片上传可能产生额外 Token 或费用,实际限制由模型提供商决定。
十、ToolCall:工具调用请求
在 Agent 和 Tool Calling 场景中,模型可能返回一个或多个工具调用请求。
每个工具调用通常包含:
- 工具名称。
- 调用参数。
- 工具调用 ID。
实例:手动构建 ToolCall
实例
tool_call = {
"name": "get_weather",
"args": {
"city": "杭州"
},
"id": "call_001",
"type": "tool_call"
}
message = AIMessage(
content="",
tool_calls=[tool_call]
)
print(message.tool_calls[0]["name"])
print(message.tool_calls[0]["args"])
print(message.tool_calls[0]["id"])
执行结果:
get_weather
{'city': '杭州'}
call_001
LangChain 的 ToolCall 是结构化的数据类型。教学代码中可以直接使用符合格式的字典构建工具调用。
正确判断是否存在工具调用
应该检查:
if response.tool_calls:
print("模型请求调用工具")
不建议使用:
if not response.content:
print("模型请求调用工具")
因为 content 为空,并不一定意味着模型请求了工具。
如果需要检查解析失败的工具调用,还可以查看:
print(response.invalid_tool_calls)
十一、trim_messages():裁剪消息历史
当对话越来越长时,消息历史可能超过模型允许的上下文窗口。
trim_messages() 用于根据指定的数量或 Token 预算裁剪消息列表。
例如,可以优先保留最近的对话,同时保留最开始的系统指令。
常用参数
| 参数 | 说明 |
|---|---|
messages |
需要裁剪的消息列表 |
max_tokens |
消息长度预算,含义取决于计数器 |
token_counter |
Token 计数函数、模型或 approximate |
strategy |
first 保留最早内容,last 保留最近内容 |
include_system |
在符合条件时保留开头的系统消息 |
start_on |
指定裁剪后消息从哪种类型开始 |
allow_partial |
是否允许保留消息的部分内容 |
end_on |
指定裁剪结果结束的消息类型 |
实例:保留最近对话
实例
HumanMessage,
AIMessage,
SystemMessage,
trim_messages
)
messages = [
SystemMessage(
content="你是菜鸟教程 RUNOOB 的 AI 助手。"
),
HumanMessage(content="Python 怎么入门?"),
AIMessage(content="建议先学习基础语法。"),
HumanMessage(content="推荐什么 IDE?"),
AIMessage(content="可以使用 VS Code 或 PyCharm。"),
HumanMessage(content="如何安装第三方库?"),
AIMessage(content="可以使用 pip install。"),
HumanMessage(content="什么是 NumPy?"),
AIMessage(content="NumPy 是 Python 数值计算库。"),
HumanMessage(content="pandas 和 NumPy 有什么区别?")
]
# 通过消息数量演示裁剪,结果更直观
trimmed = trim_messages(
messages,
max_tokens=5,
strategy="last",
token_counter=len,
include_system=True,
start_on="human"
)
print("裁剪前:", len(messages))
print("裁剪后:", len(trimmed))
for message in trimmed:
print(message.type, message.content)
这里使用 token_counter=len,因此 max_tokens=5 代表以消息数量为预算,而不是实际 Token 数。
这样更适合展示裁剪机制。
实际使用中,应根据模型上下文窗口使用 Token 计数方式。
按近似 Token 数裁剪
实例
trimmed = trim_messages(
messages,
max_tokens=100,
strategy="last",
token_counter="approximate",
include_system=True,
start_on="human"
)
for message in trimmed:
print(message.type, message.content)
token_counter="approximate" 使用近似计数,适合希望减少精确 Token 计算开销的场景。
但近似计数并不等于具体模型最终使用的真实 Token 数。
此外,trim_messages() 会根据预算和消息结构决定保留多少条消息,不应假设它始终返回固定数量的消息。
裁剪时需要注意工具消息
当历史记录包含工具调用时,需要尽量保持消息结构完整。
例如:
AIMessage(tool_calls=[...]) ToolMessage(tool_call_id="...") AIMessage(content="最终回答")
如果只保留 ToolMessage,却删除了对应的工具调用消息,可能导致请求无效。
对于复杂 Agent,不应简单地按字符数删除消息;可以结合 LangChain 的消息工具、中间件或上下文压缩策略进行管理。
十二、RemoveMessage:删除状态中的消息
RemoveMessage 用于在支持消息状态归并的流程中表示删除某条消息的操作。
它通常与 LangGraph 的 add_messages reducer 或 Agent 状态管理机制配合使用。
需要注意:创建 RemoveMessage 对象,不会自动从普通 Python 列表中删除消息。
实例:创建删除指令
实例
HumanMessage,
AIMessage,
RemoveMessage
)
messages = [
HumanMessage(
content="你好",
id="msg_1"
),
AIMessage(
content="你好!",
id="msg_2"
),
HumanMessage(
content="查询天气",
id="msg_3"
)
]
# 构造删除指定消息的指令
removal = RemoveMessage(
id="msg_3"
)
print("删除目标:", removal.id)
print("消息类型:", removal.type)
# 普通列表不会自动变化
print("原始列表长度:", len(messages))
执行结果:
删除目标: msg_3 消息类型: remove 原始列表长度: 3
如果需要真正更新消息状态,应将 RemoveMessage 交给支持此操作的状态归并器处理。
例如,在 LangGraph 工作流中,可以结合对应的消息状态更新机制实现删除。
注意:RemoveMessage 主要用于修改工作流中的消息状态,不能代替数据库删除、日志清理或其他持久化数据删除操作。
十三、消息对象的常用属性与方法
LangChain 的消息类型通常继承自 BaseMessage,共享一些常见属性和方法。
实例
实例
message = HumanMessage(
content="你好,菜鸟教程 RUNOOB"
)
# 消息内容
print("content:", message.content)
# LangChain 消息类型
print("type:", message.type)
# 消息 ID(可能为空)
print("id:", message.id)
# 提取文本
print("text:", message.text)
# 标准化内容块
print("content_blocks:", message.content_blocks)
# 格式化输出
print(message.pretty_repr())
其中:
| 属性或方法 | 作用 |
|---|---|
content |
原始消息内容 |
content_blocks |
标准化的内容块列表 |
type |
消息类型 |
id |
消息标识,可能为 None |
text |
提取消息中的文本内容 |
pretty_repr() |
生成便于调试的消息描述 |
例如,pretty_repr() 可以输出带有消息类型标题的文本,便于在终端查看对话记录。
不同 LangChain 版本可能对文本访问接口存在差异,使用旧版教程时应注意区分 text 属性与历史版本中采用的方法写法。
十四、完整实例:使用消息列表构建对话
下面通过一个完整的 Python 程序,将系统消息、用户消息、AI 回复以及对话历史组合起来。
文件名:langchain_messages.py
完整实例
from langchain.chat_models import init_chat_model
from langchain.messages import (
HumanMessage,
SystemMessage
)
load_dotenv()
# 初始化模型
model = init_chat_model(
"deepseek:deepseek-flash"
)
# 初始化对话历史
messages = [
SystemMessage(
content=(
"你是一名 Python 编程教程助手。"
"请使用简洁、准确的中文回答。"
)
)
]
def chat(question: str):
"""向模型发送问题并保存对话历史。"""
# 添加用户消息
messages.append(
HumanMessage(content=question)
)
# 调用模型
response = model.invoke(messages)
# 保存 AI 回复
messages.append(response)
print("用户:", question)
print("AI:", response.text)
print("-" * 40)
# 第一轮
chat("什么是 Python?")
# 第二轮
chat("它适合初学者吗?")
# 第三轮
chat("给我一个简单的学习计划。")
print("\n当前消息历史:")
for message in messages:
print(
f"[{message.type}]",
message.text
)
在这个示例中,messages 列表会保存之前的用户消息和模型回复。
因此,第二轮和第三轮调用时,模型可以参考前面的对话内容。
需要注意:
- 这种方式只在当前 Python 进程中保存历史。
- 程序重新启动后,消息列表会重新初始化。
- 真实项目应注意上下文长度限制。
- 多个用户不能直接共享同一个全局消息列表,否则可能造成对话串扰。
如果需要支持多用户会话和持久化历史,可以使用独立的会话存储,以及 LangGraph 的状态检查点等机制。
十五、常见问题
1、HumanMessage 和 AIMessage 有什么区别?
HumanMessage 表示用户输入;AIMessage 表示模型输出。
AIMessage 还可能包含工具调用信息和模型响应元数据。
2、为什么 message.role 会报错?
因为 LangChain 的消息对象通常使用 type 属性区分消息类型。
例如:
message.type
而下面这种字典表示方式使用 role:
{
"role": "user",
"content": "你好"
}
不能将两种表示方式中的属性完全混用。
3、为什么 AIMessage 的 content 为空?
可能是模型返回了工具调用,也可能是其他非文本内容或特殊响应情况。
应检查:
response.tool_calls response.invalid_tool_calls response.content_blocks
不要只根据 content 是否为空判断是否调用工具。
4、ToolMessage 可以直接发送给模型吗?
ToolMessage 通常需要与前面的工具调用请求对应。
如果缺少相关 AIMessage 或工具调用 ID 不匹配,部分模型服务可能直接拒绝请求。
5、LangChain 可以处理图片、音频和视频吗?
LangChain 提供标准化的多模态消息结构。
但真正能够处理哪些内容,取决于具体模型提供商、模型版本与 API 的支持情况。
6、如何限制消息历史长度?
可以使用 trim_messages() 按消息数量或 Token 预算裁剪历史。
例如:
trimmed = trim_messages(
messages,
max_tokens=1000,
token_counter="approximate",
strategy="last",
include_system=True,
start_on="human"
)
对于包含工具调用的复杂历史,还应检查裁剪后消息之间的关联是否完整。
7、消息 ID 是否会自动生成?
不能假设所有消息都有自动生成的 ID。
手动创建的消息可能没有 ID,而模型响应或状态管理流程可能分配相应标识。
如果需要自行管理消息,可以显式指定:
message = HumanMessage(
content="你好",
id="user_message_001"
)
8、RemoveMessage 会删除数据库中的聊天记录吗?
不会。
它主要用于支持消息状态归并的工作流中,表示删除指定消息的状态更新操作。
数据库或其他持久化存储中的删除,需要通过对应的存储接口处理。
总结
LangChain 的消息系统是聊天模型、Agent 和多模态应用的重要基础。
需要重点掌握以下内容:
HumanMessage:表示用户输入。AIMessage:表示模型回复,也可能包含工具调用。SystemMessage:提供系统级指令。ToolMessage:保存工具执行结果,并关联对应的工具调用。AIMessageChunk:用于流式消息输出。ContentBlock:用于表示文本、图片、音频等结构化内容。trim_messages():根据预算裁剪聊天历史。RemoveMessage:在支持的工作流中删除指定消息。
在开发 LangChain 应用时,应特别区分消息对象与消息字典、工具调用请求与工具执行结果,以及消息内容和标准化内容块。
掌握这些概念后,再学习 Agent 工具调用、会话记忆、多模态模型和 LangGraph 状态管理会更加容易。
