在 LangChain 中,langchain_core.messages.BaseMessage
是 langchain_core.messages
模块中的核心抽象基类,用于表示对话中的消息。它为所有具体消息类型(如 HumanMessage
、AIMessage
、SystemMessage
等)提供了统一的接口和基础功能。BaseMessage
的设计目标是标准化消息的结构和行为,确保消息能够在聊天模型、代理、记忆模块和其他 LangChain 组件中无缝传递和处理。
以下是对 langchain_core.messages.BaseMessage
的详细介绍,涵盖其定义、功能、核心属性与方法、实现方式、应用场景、代码示例、优化建议、注意事项以及与 LangChain 生态的结合。
1. 什么是 BaseMessage
?
BaseMessage
是一个抽象基类,定义了对话消息的基本结构和行为。消息是 LangChain 对话系统的核心组件,表示用户、模型、工具或其他实体之间的交互内容。BaseMessage
提供了以下功能:
- 统一消息格式:标准化消息的属性(如内容、角色、元数据)。
- 支持多模态:允许消息内容包含文本、图像或其他数据类型。
- 序列化:支持消息的 JSON 序列化和反序列化,便于存储或传输。
- 扩展性:允许开发者继承并创建自定义消息类型。
核心目标:
- 提供一致的消息表示,简化对话管理和上下文传递。
- 支持复杂交互,如工具调用、多轮对话和多模态输入。
- 与 LangChain 的聊天模型、代理、记忆等模块无缝集成。
子类:
HumanMessage
:用户发送的消息。AIMessage
:模型生成的消息,可能包含工具调用。SystemMessage
:系统指令或提示。ToolMessage
:工具调用结果。ChatMessage
:任意角色的自定义消息。FunctionMessage
:旧版函数调用结果(已废弃,推荐ToolMessage
)。
2. 功能与特点
BaseMessage
提供了以下核心功能:
- 消息结构:
- 定义消息的核心属性:
content
(内容)、role
(角色)、additional_kwargs
(元数据)。 - 支持多模态内容(如文本+图像的列表)。
- 定义消息的核心属性:
- 序列化与反序列化:
- 支持将消息转换为 JSON 格式,或从 JSON 还原。
- 便于存储对话历史或跨系统传输。
- 类型安全:
- 使用 Pydantic 模型,确保字段验证和类型一致性。
- 扩展性:
- 允许子类添加特定字段(如
tool_calls
在AIMessage
中)。 - 支持自定义消息类型。
- 允许子类添加特定字段(如
- 对话上下文:
- 作为消息列表的一部分,传递给聊天模型或代理,构建对话历史。
- 工具调用支持:
- 通过子类(如
AIMessage
和ToolMessage
)支持工具调用请求和结果。
- 通过子类(如
特点:
- 抽象化:提供通用接口,屏蔽具体消息类型的实现细节。
- 模块化:与 LangChain 的提示模板、代理、记忆等模块无缝协作。
- 跨模型兼容:支持 OpenAI、Anthropic、HuggingFace 等模型的消息格式。
- 轻量高效:结构简单,易于序列化和处理。
3. 核心属性与方法
核心属性
属性 | 类型 | 描述 | 示例 |
---|---|---|---|
content | Union[str, List[Dict]] | 消息内容,可以是字符串或多模态内容(如文本+图像)。 | "Hello" 或 [{"type": "text", "text": "Hi"}, {"type": "image_url", "image_url": {"url": "image.jpg"}}] |
role | str | 消息的角色,子类定义具体值(如 "human" 、"assistant" )。 | "human" |
additional_kwargs | Dict[str, Any] | 附加元数据,如时间戳、ID 或模型特定参数。 | {"timestamp": "2025-05-15"} |
type | str | 消息类型,自动由子类设置。 | "human" (对于 HumanMessage ) |
注意:
content
通常是字符串,但在多模态模型(如 GPT-4o)中可以是包含文本、图像等的列表。role
由子类定义,BaseMessage
本身不强制具体值。additional_kwargs
用于存储任意元数据,增强灵活性。
核心方法
方法 | 描述 | 输入 | 输出 | 示例 |
---|---|---|---|---|
to_json | 将消息序列化为 JSON 格式。 | 无 | Dict | message.to_json() |
from_json | 从 JSON 还原消息对象(类方法)。 | Dict | BaseMessage | BaseMessage.from_json(json_data) |
__str__ | 返回消息的字符串表示。 | 无 | str | str(message) |
__eq__ | 比较两个消息是否相等。 | BaseMessage | bool | message1 == message2 |
子类特定属性/方法:
AIMessage
:添加tool_calls
(工具调用请求列表)。ToolMessage
:添加tool_call_id
(工具调用 ID)。- 其他子类可能定义特定行为或字段。
4. 使用方式与代码示例
(1) 创建基本消息
创建 HumanMessage
和 SystemMessage
:
from langchain_core.messages import HumanMessage, SystemMessage
from langchain_openai import ChatOpenAI
# 初始化模型
llm = ChatOpenAI(api_key="your-openai-key")
# 创建消息
messages = [
SystemMessage(content="你是一个量子计算专家,回答要简洁。"),
HumanMessage(content="量子计算是什么?")
]
# 调用模型
response = llm.invoke(messages)
print(response.content)
输出:
量子计算是一种基于量子力学原理的计算范式,使用量子比特进行计算。
说明:
SystemMessage
设置对话上下文。HumanMessage
表示用户输入。- 消息列表传递给
BaseChatModel
实例。
(2) 工具调用与 ToolMessage
处理工具调用和结果:
from langchain_core.messages import HumanMessage, AIMessage, ToolMessage
from langchain_openai import ChatOpenAI
from langchain_core.tools import tool
# 定义工具
@tool
def calculator(expression: str) -> str:
"""执行数学计算"""
return str(eval(expression))
# 初始化模型并绑定工具
llm = ChatOpenAI(api_key="your-openai-key").bind_tools([calculator])
# 创建消息
messages = [HumanMessage(content="计算 5 + 3")]
# 调用模型
response = llm.invoke(messages)
# 处理工具调用
if response.tool_calls:
tool_call = response.tool_calls[0]
tool_result = calculator.invoke(tool_call["args"])
messages.extend([
AIMessage(content="", tool_calls=[tool_call]),
ToolMessage(content=tool_result, tool_call_id=tool_call["id"])
])
# 继续对话
final_response = llm.invoke(messages)
print(final_response.content)
输出:
计算结果为 8。
说明:
AIMessage
包含tool_calls
,指定工具和参数。ToolMessage
反馈工具结果,通过tool_call_id
关联。
(3) 多模态消息
处理文本+图像输入(需要支持多模态的模型,如 GPT-4o):
from langchain_core.messages import HumanMessage
from langchain_openai import ChatOpenAI
# 初始化模型
llm = ChatOpenAI(model="gpt-4o", api_key="your-openai-key")
# 创建多模态消息
messages = [
HumanMessage(content=[
{"type": "text", "text": "描述这张图片的内容。"},
{"type": "image_url", "image_url": {"url": "https://example.com/quantum.jpg"}}
])
]
# 调用模型
response = llm.invoke(messages)
print(response.content)
输出(假设图片可用):
图片显示一台量子计算机的实验设备,周围有冷却装置和控制面板。
说明:
content
为列表,包含文本和图像 URL。- 仅支持多模态模型。
(4) 序列化与反序列化
将消息序列化为 JSON 并还原:
from langchain_core.messages import HumanMessage
# 创建消息
message = HumanMessage(content="量子计算是什么?", additional_kwargs={"id": "msg_001"})
# 序列化为 JSON
json_data = message.to_json()
print(json_data)
# 从 JSON 还原
restored_message = HumanMessage.from_json(json_data)
print(restored_message.content, restored_message.additional_kwargs)
输出:
{'type': 'human', 'content': '量子计算是什么?', 'additional_kwargs': {'id': 'msg_001'}}
量子计算是什么? {'id': 'msg_001'}
说明:
to_json
返回消息的字典表示。from_json
还原为BaseMessage
子类实例。
(5) 自定义消息类型
继承 BaseMessage
创建自定义消息:
from langchain_core.messages import BaseMessage
from typing import Any, Dict
# 自定义消息类
class CustomMessage(BaseMessage):
role: str = "custom"
custom_field: str
def __init__(self, content: str, custom_field: str, **kwargs: Any):
super().__init__(content=content, additional_kwargs=kwargs)
self.custom_field = custom_field
# 创建自定义消息
message = CustomMessage(content="Hello", custom_field="test")
print(message)
print(message.custom_field)
输出:
content='Hello' role='custom' additional_kwargs={}
test
说明:
- 继承
BaseMessage
添加自定义字段和逻辑。 - 需定义
role
和其他必要属性。
(6) 结合代理
在代理中使用 BaseMessage
子类:
from langchain_openai import ChatOpenAI
from langchain_core.messages import HumanMessage
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain.agents import create_openai_tools_agent, AgentExecutor
from langchain_core.tools import Tool
from langchain_core.callbacks import StdOutCallbackHandler
from langchain_core.runnables import RunnableConfig
# 定义工具
def search_web(query: str) -> str:
return f"搜索结果:{query} 的最新信息..."
search_tool = Tool(name="SearchWeb", func=search_web, description="搜索网络信息")
# 初始化模型
llm = ChatOpenAI(model="gpt-4o", api_key="your-openai-key")
# 设置提示模板
prompt = ChatPromptTemplate.from_messages([
("system", "你是一个研究助手,擅长搜索信息。"),
MessagesPlaceholder(variable_name="messages"),
MessagesPlaceholder(variable_name="agent_scratchpad")
])
# 创建代理
agent = create_openai_tools_agent(llm, [search_tool], prompt)
agent_executor = AgentExecutor(agent=agent, tools=[search_tool], verbose=True)
# 配置 RunnableConfig
config = RunnableConfig(callbacks=[StdOutCallbackHandler()], max_iterations=3)
# 执行任务
response = agent_executor.invoke({
"messages": [HumanMessage(content="量子计算的最新进展是什么?")]
}, config=config)
print(response["output"])
输出:
[AgentExecutor] 正在执行...
[Tool: SearchWeb] 输入:量子计算的最新进展
[Tool Output] 搜索结果:量子计算的最新信息...
[Final Answer] 量子计算的最新进展包括超导量子比特的突破...
5. 应用场景
BaseMessage
及其子类适用于以下场景:
- 多轮对话:
- 构建聊天机器人,维护对话历史。
- 示例:连续回答“量子计算是什么?”和“它有什么应用?”。
- 工具调用:
- 处理代理或链中的工具交互。
- 示例:代理调用搜索工具并反馈结果。
- 上下文增强:
- 使用
SystemMessage
设置模型行为或提供背景。 - 示例:指定“以专家身份回答”。
- 使用
- 多模态交互:
- 处理文本+图像或文本+音频的对话。
- 示例:描述图片内容。
- 对话记忆:
- 结合
ConversationBufferMemory
存储消息历史。 - 示例:实现长期对话的上下文保持。
- 结合
- 自定义交互:
- 创建自定义消息类型,满足特定需求。
- 示例:添加业务特定的元数据。
6. 优化建议
(1) 提高消息管理效率
- 精简消息:
- 仅保留必要的对话历史,减少 token 消耗。
messages = messages[-10:] # 保留最后 10 条消息
- 压缩历史:
- 使用
ConversationSummaryMemory
压缩长对话。
from langchain.memory import ConversationSummaryMemory memory = ConversationSummaryMemory(llm=llm)
- 使用
(2) 提高工具调用可靠性
- 验证工具调用:
- 检查
tool_calls
是否有效。
if not response.tool_calls: print("无工具调用") return response.content
- 检查
- 匹配
tool_call_id
:- 确保
ToolMessage
的tool_call_id
与AIMessage
一致。
tool_message = ToolMessage(content=result, tool_call_id=tool_call["id"])
- 确保
(3) 提高性能
- 序列化优化:
- 批量序列化消息,减少 I/O 开销。
json_data = [msg.to_json() for msg in messages]
- 异步处理:
- 结合异步模型调用处理消息。
response = await llm.ainvoke(messages)
(4) 监控与调试
- 回调:
- 使用回调记录消息处理。
from langchain_core.callbacks import BaseCallbackHandler class MessageCallback(BaseCallbackHandler): def on_chat_model_start(self, serialized, messages, **kwargs): print(f"输入消息:{messages}") config = {"callbacks": [MessageCallback()]}
- LangSmith:
- 分析消息流和性能。
from langsmith import Client config = {"callbacks": [Client(api_key="your-langsmith-key")]}
(5) 上下文优化
- 动态系统消息:
- 根据任务调整
SystemMessage
。
system_message = SystemMessage(content=f"今天是 {datetime.now().strftime('%Y-%m-%d')},回答要简洁。")
- 根据任务调整
- 元数据管理:
- 使用
additional_kwargs
存储上下文。
message = HumanMessage(content="Hi", additional_kwargs={"user_id": "user_001"})
- 使用
7. 注意事项
- 抽象基类:
BaseMessage
不可直接实例化,需使用子类(如HumanMessage
)。
- 模型兼容性:
- 多模态消息需要模型支持(如 GPT-4o)。
- 工具调用需要模型支持
tool_calls
(如 GPT-4、Claude)。
- 消息长度:
- 过多的消息或长内容可能超过模型的 token 限制。
- 使用截断或总结策略。
- 工具调用一致性:
- 确保
ToolMessage
的tool_call_id
与AIMessage
的tool_calls
匹配。
- 确保
- 序列化:
- 确保 JSON 数据格式正确,避免反序列化错误。
try: msg = HumanMessage.from_json(json_data) except ValueError as e: print(f"反序列化失败:{e}")
- 安全性:
- 避免在
content
或additional_kwargs
中包含敏感信息。 - 验证用户输入,防止注入攻击。
- 避免在
- 废弃警告:
FunctionMessage
已废弃,推荐使用ToolMessage
。
8. 与 LangChain 生态的结合
- 聊天模型(Chat Models):
- 消息传递给
BaseChatModel
实例(如ChatOpenAI
)。
llm.invoke(messages)
- 消息传递给
- 提示模板(Prompt Templates):
- 使用
ChatPromptTemplate
管理消息。
from langchain_core.prompts import ChatPromptTemplate prompt = ChatPromptTemplate.from_messages([("human", "{input}")])
- 使用
- 代理(Agents):
- 消息用于代理的输入和工具调用。
agent.invoke({"messages": [HumanMessage(content="Hi")]})
- 工具(Tools):
AIMessage
和ToolMessage
支持工具调用。
messages.append(ToolMessage(content=tool_result, tool_call_id=tool_call["id"]))
- 记忆(Memory):
- 结合
ConversationBufferMemory
存储消息。
from langchain.memory import ConversationBufferMemory memory = ConversationBufferMemory(return_messages=True)
- 结合
- 回调(Callbacks):
- 使用
RunnableConfig
配置回调。
config = {"callbacks": [StdOutCallbackHandler()]}
- 使用
9. 综合示例:多模态代理
以下是一个结合 BaseMessage
、多模态输入和代理的完整示例:
from langchain_openai import ChatOpenAI
from langchain_core.messages import HumanMessage, SystemMessage
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain.agents import create_openai_tools_agent, AgentExecutor
from langchain_core.tools import Tool
from langchain_core.callbacks import StdOutCallbackHandler
from langchain_core.runnables import RunnableConfig
import os
import getpass
# 配置 API 密钥
if not os.environ.get("OPENAI_API_KEY"):
os.environ["OPENAI_API_KEY"] = getpass.getpass("请输入 OpenAI API 密钥:")
# 定义工具
def search_web(query: str) -> str:
return f"搜索结果:{query} 的最新信息..."
search_tool = Tool(name="SearchWeb", func=search_web, description="搜索网络信息")
# 初始化模型
llm = ChatOpenAI(model="gpt-4o", temperature=0)
# 设置提示模板
prompt = ChatPromptTemplate.from_messages([
SystemMessage(content="你是一个研究助手,擅长处理多模态输入和搜索。"),
MessagesPlaceholder(variable_name="messages"),
MessagesPlaceholder(variable_name="agent_scratchpad")
])
# 创建代理
agent = create_openai_tools_agent(llm, [search_tool], prompt)
agent_executor = AgentExecutor(agent=agent, tools=[search_tool], verbose=True)
# 配置 RunnableConfig
config = RunnableConfig(callbacks=[StdOutCallbackHandler()], max_iterations=3)
# 创建多模态消息
messages = [
HumanMessage(content=[
{"type": "text", "text": "搜索量子计算的最新进展,并描述这张图片的内容。"},
{"type": "image_url", "image_url": {"url": "https://example.com/quantum.jpg"}}
])
]
# 执行任务
response = agent_executor.invoke({"messages": messages}, config=config)
print(response["output"])
输出(假设图片可用):
[AgentExecutor] 正在执行...
[Tool: SearchWeb] 输入:量子计算的最新进展
[Tool Output] 搜索结果:量子计算的最新信息...
[Final Answer] 量子计算的最新进展包括超导量子比特的突破。图片显示一台量子计算机的实验设备。
10. 学习资源
- 官方文档:https://python.langchain.com/docs/modules/messages
- GitHub 源码:https://github.com/langchain-ai/langchain/tree/master/libs/core/langchain_core/messages
- LangSmith:用于调试消息流(https://smith.langchain.com)。
- 社区教程:LangChain 官方博客、YouTube 视频。
11. 总结
- 定义:
BaseMessage
是 LangChain 中消息的抽象基类,定义对话消息的结构和行为。 - 核心属性:
content
:消息内容(字符串或多模态)。role
:消息角色。additional_kwargs
:元数据。
- 核心方法:
to_json
、from_json
:序列化/反序列化。__str__
、__eq__
:字符串表示和比较。
- 功能:统一消息格式、支持多模态、序列化、工具调用、上下文管理。
- 应用场景:多轮对话、工具调用、上下文增强、多模态交互、记忆管理、自定义交互。
- 优化点:消息管理、工具调用可靠性、性能、监控、上下文优化。
- 注意事项:抽象基类、模型兼容性、消息长度、工具调用一致性、序列化、安全性、废弃警告。