一、简介
LangChain 的 Messages & Chat 是构建对话式 AI、多轮聊天机器人、智能助手的核心模块,它统一了大模型的消息格式、对话历史管理、多角色交互,解决了原生大模型(如 GPT、文心一言、通义千问)消息格式不统一、对话历史难以维护的问题。
核心优势:
- 格式统一:一套代码适配所有聊天大模型
- 上下文管理:轻松实现多轮对话
- 工具丰富:截断、过滤、合并、记忆
- 可扩展:支持自定义消息、自定义记忆
- 生态兼容:无缝对接 LangChain 链、智能体、RAG
二、核心概念:消息基类
原生大模型的输入格式五花八门:
- OpenAI:{"role": "user", "content": "你好"}
- Claude:按用户 / 助手分段文本
- 本地模型:格式完全自定义
在 LangChain 中,所有与模型交互的内容都被抽象为 BaseMessage 对象。每个消息对象包含两个主要属性:
- content:消息的文本内容(字符串或内容块列表,用于多模态)。
- type(或 role):标识消息的发送者角色。
三、5 种标准消息类型
LangChain 定义了5 种最常用的消息类,覆盖 99% 的对话场景:
-
HumanMessage(用户消息)
- 代表用户输入的内容
- 对应大模型的 role: user
pythonfrom langchain_core.messages import HumanMessage msg = HumanMessage(content="你好,请介绍一下Python") -
AIMessage(AI 回复消息)
- 代表大模型返回的回答
- 对应大模型的 role: assistant
- 支持附加工具调用、思考过程等元数据
pythonfrom langchain_core.messages import AIMessage msg = AIMessage(content="Python是一门解释型编程语言...") -
SystemMessage(系统提示消息)
- 设定 AI 角色、行为、规则
- 对话开头发送,全程生效
- 对应大模型的 role: system
pythonfrom langchain_core.messages import SystemMessage # 让AI扮演专业的编程助手 msg = SystemMessage(content="你是一名资深Python工程师,回答简洁专业") -
FunctionMessage / ToolMessage(工具调用消息)
- 用于函数调用 / 工具调用场景
- AI 调用工具后,返回工具执行结果
- ToolMessage 是新版推荐用法
pythonfrom langchain_core.messages import ToolMessage msg = ToolMessage(content="当前温度25℃", tool_call_id="call_123") -
ChatMessage(通用自定义消息)
- 支持自定义角色(如 moderator、system 以外的角色)
- 极少使用,仅用于特殊场景
pythonfrom langchain_core.messages import ChatMessage msg = ChatMessage(role="moderator", content="请保持对话文明")
示例:
python
from langchain_core.messages import SystemMessage, HumanMessage, AIMessage, ToolMessage
# 创建不同类型的消息
system_msg = SystemMessage(content="You are a helpful assistant.")
human_msg = HumanMessage(content="What's the weather in Beijing?")
ai_msg = AIMessage(content="I'll check the weather for you.")
tool_msg = ToolMessage(content="Sunny, 25°C", tool_call_id="weather_call")
print(system_msg.type) # system
print(human_msg.type) # human
print(ai_msg.type) # ai
print(tool_msg.type) # tool
四、消息的结构
每个消息除了 content 和 type,还可能包含其他元数据:
- id:消息的唯一标识(可选)。
- name:可选的消息发送者名称,比如在多个角色交互时标识谁发的。
- response_metadata:模型返回的额外信息(如 token 使用量、finish_reason 等)。
- tool_calls / tool_call_id:当消息包含工具调用时,会携带这些字段。
AIMessage 中的工具调用示例:
python
ai_msg = AIMessage(
content="",
tool_calls=[
{
"name": "get_weather",
"args": {"city": "Beijing"},
"id": "call_123"
}
]
)
五、对话模型接口:ChatModel
LangChain 将模型分为两类:LLM(纯文本输入输出)和 ChatModel(基于消息列表输入)。在构建对话应用中,几乎都使用 ChatModel。
5.1 基本对话
ChatModel 的核心方法是 .invoke(),它接收一个消息列表,返回一个 AIMessage。
python
# 1. 导入依赖
from langchain_openai import ChatOpenAI
from langchain_core.messages import HumanMessage, SystemMessage
# 2. 初始化聊天模型
llm = ChatOpenAI(
model="gpt-3.5-turbo",
temperature=0.7 # 随机性
)
# 3. 构造消息列表(对话上下文)
messages = [
SystemMessage(content="你是一个幽默的聊天助手"),
HumanMessage(content="讲一个程序员笑话")
]
# 4. 调用模型(直接传入消息列表)
response = llm.invoke(messages)
# 5. 输出结果(AIMessage 对象)
print(response.content)
print(type(response)) # <class 'langchain_core.messages.ai.AIMessage'>
5.2 多轮对话:
原生大模型无记忆能力,必须手动把完整对话历史传给模型。多轮对话通常维护一个消息列表,每次将用户输入追加为 HumanMessage,将模型回复追加为 AIMessage。
其实现原理:每次都把完整的消息列表传给模型,模型就能理解上下文。
python
# 初始化消息列表
messages = [
SystemMessage(content="你是一个宠物顾问")
]
# 第一轮对话
user_input1 = "猫可以喝牛奶吗?"
messages.append(HumanMessage(content=user_input1))
ai_response1 = llm.invoke(messages)
messages.append(ai_response1)
print("AI:", ai_response1.content)
# 第二轮对话(模型自动记住上一轮内容)
user_input2 = "那它们适合喝什么?"
messages.append(HumanMessage(content=user_input2))
ai_response2 = llm.invoke(messages)
messages.append(ai_response2)
print("AI:", ai_response2.content)
六、对话历史管理
真正的对话应用需要持久化保存历史消息,并在每次请求时将历史上下文传递给模型。
6.1 ChatMessageHistory
LangChain 提供了 BaseChatMessageHistory 接口及其实现 ChatMessageHistory,用于在内存中存储消息历史。
python
from langchain.memory import ChatMessageHistory
history = ChatMessageHistory()
history.add_user_message("你好,我叫小明。")
history.add_ai_message("你好小明,很高兴认识你!")
# 获取所有消息
print(history.messages)
6.2 与 RunnableWithMessageHistory 集成
在实际应用中,通常使用 RunnableWithMessageHistory 包装器,自动将历史消息注入到每次调用中,并支持按会话 ID 隔离不同用户。
python
from langchain_core.runnables.history import RunnableWithMessageHistory
from langchain.memory import ChatMessageHistory
# 存储所有会话历史的字典
store = {}
def get_session_history(session_id: str):
if session_id not in store:
store[session_id] = ChatMessageHistory()
return store[session_id]
# 创建带历史的对话链
with_message_history = RunnableWithMessageHistory(
model, # 这是一个 Runnable(如绑定了工具的模型)
get_session_history,
)
# 第一次对话
response1 = with_message_history.invoke(
[HumanMessage(content="我叫小明")],
config={"configurable": {"session_id": "user_123"}}
)
# 第二次对话,模型会记得之前的信息
response2 = with_message_history.invoke(
[HumanMessage(content="我叫什么名字?")],
config={"configurable": {"session_id": "user_123"}}
)
# 模型会回答 "小明"
七、高级特性
7.1 消息截断
随着对话变长,Token 消耗会剧增。LangChain 提供了 trim_messages 工具来截断历史,保留最新的若干条消息,或基于 Token 数限制进行修剪。
python
from langchain_core.messages import trim_messages
# 保留最近 5 条消息
trimmer = trim_messages(
max_tokens=1000,
strategy="last", # 保留最新消息
token_counter=llm # 用模型计算token
)
# 处理消息列表
trimmed_messages = trimmer.invoke(messages)
7.2 消息合并
把连续的同角色消息合并,减少 token 消耗:
python
from langchain_core.messages import merge_messages
merged_messages = merge_messages(messages)
7.3 消息过滤
只保留用户 / AI 消息,过滤系统消息:
python
from langchain_core.messages import filter_messages
# 只保留 HumanMessage 和 AIMessage
filtered = filter_messages(
messages,
include_types=[HumanMessage, AIMessage]
)
7.4 消息格式化
不同的模型提供商对消息格式的要求略有不同。LangChain 提供了 format_messages 等工具,但更常见的是通过 ChatPromptTemplate 来动态构建消息列表。
python
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
prompt = ChatPromptTemplate.from_messages([
("system", "你是一位{role}。"),
MessagesPlaceholder(variable_name="history"), # 历史消息占位符
("human", "{input}"),
])
# 填充模板
chain = prompt | model
7.5 绑定工具
在消息中绑定工具调用,实现 Function Calling / Tool Calling。
python
from langchain_core.tools import tool
@tool
def get_weather(city: str) -> str:
"""Get weather of a city."""
return f"{city} is sunny."
model_with_tools = model.bind_tools([get_weather])
messages = [HumanMessage(content="What's the weather in Beijing?")]
response = model_with_tools.invoke(messages)
print(response.tool_calls) # 包含工具调用信息
7.6 消息序列化与持久化
LangChain 消息支持序列化为字典 / JSON,方便存储到数据库、缓存、文件中:
-
消息 → 字典
pythonmsg = HumanMessage(content="你好") dict_msg = msg.dict() # 结果:{"content": "你好", "type": "human", ...} -
字典 → 消息
pythonfrom langchain_core.messages import messages_from_dict messages = messages_from_dict([dict_msg])
7.7 多模态消息
对于支持视觉的模型(如 GPT-4o),HumanMessage 的 content 可以是包含文本和图像 URL 或 base64 数据的列表。
python
from langchain_core.messages import HumanMessage
message = HumanMessage(
content=[
{"type": "text", "text": "描述这张图片"},
{"type": "image_url", "image_url": {"url": "https://example.com/image.jpg"}}
]
)
八、Messages & Chat 工作流程
- 构造消息:用 SystemMessage/HumanMessage 定义对话内容
- 管理历史:用列表或 Memory 维护多轮上下文
- 调用模型:统一使用 ChatModel 接口
- 处理响应:接收 AIMessage,追加到历史
- 持久化:序列化消息,存储对话记录
在实际应用中,常见模式是:
- 初始化:创建 ChatMessageHistory 或维护消息列表。
- 系统消息:在对话开始时设置 SystemMessage。
- 多轮交互:每次用户输入 → 追加 HumanMessage → 调用模型 → 追加 AIMessage。
- 工具调用:模型返回 tool_calls → 执行工具 → 返回 ToolMessage → 再次调用模型。
- 历史管理:使用 trim_messages 或摘要避免超出上下文长度。