LangChain 消息与对话(Messages & Chat)

一、简介

LangChain 的 Messages & Chat 是构建对话式 AI、多轮聊天机器人、智能助手的核心模块,它统一了大模型的消息格式、对话历史管理、多角色交互,解决了原生大模型(如 GPT、文心一言、通义千问)消息格式不统一、对话历史难以维护的问题。

核心优势:

  1. 格式统一:一套代码适配所有聊天大模型
  2. 上下文管理:轻松实现多轮对话
  3. 工具丰富:截断、过滤、合并、记忆
  4. 可扩展:支持自定义消息、自定义记忆
  5. 生态兼容:无缝对接 LangChain 链、智能体、RAG

二、核心概念:消息基类

原生大模型的输入格式五花八门:

  • OpenAI:{"role": "user", "content": "你好"}
  • Claude:按用户 / 助手分段文本
  • 本地模型:格式完全自定义

在 LangChain 中,所有与模型交互的内容都被抽象为 BaseMessage 对象。每个消息对象包含两个主要属性:

  • content:消息的文本内容(字符串或内容块列表,用于多模态)。
  • type(或 role):标识消息的发送者角色。

三、5 种标准消息类型

LangChain 定义了5 种最常用的消息类,覆盖 99% 的对话场景:

  1. HumanMessage(用户消息)

    • 代表用户输入的内容
    • 对应大模型的 role: user
    python 复制代码
    from langchain_core.messages import HumanMessage
    msg = HumanMessage(content="你好,请介绍一下Python")
  2. AIMessage(AI 回复消息)

    • 代表大模型返回的回答
    • 对应大模型的 role: assistant
    • 支持附加工具调用、思考过程等元数据
    python 复制代码
    from langchain_core.messages import AIMessage
    msg = AIMessage(content="Python是一门解释型编程语言...")
  3. SystemMessage(系统提示消息)

    • 设定 AI 角色、行为、规则
    • 对话开头发送,全程生效
    • 对应大模型的 role: system
    python 复制代码
    from langchain_core.messages import SystemMessage
    # 让AI扮演专业的编程助手
    msg = SystemMessage(content="你是一名资深Python工程师,回答简洁专业")
  4. FunctionMessage / ToolMessage(工具调用消息)

    • 用于函数调用 / 工具调用场景
    • AI 调用工具后,返回工具执行结果
    • ToolMessage 是新版推荐用法
    python 复制代码
    from langchain_core.messages import ToolMessage
    msg = ToolMessage(content="当前温度25℃", tool_call_id="call_123")
  5. ChatMessage(通用自定义消息)

    • 支持自定义角色(如 moderator、system 以外的角色)
    • 极少使用,仅用于特殊场景
    python 复制代码
    from 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,方便存储到数据库、缓存、文件中:

  1. 消息 → 字典

    python 复制代码
    msg = HumanMessage(content="你好")
    dict_msg = msg.dict()
    # 结果:{"content": "你好", "type": "human", ...}
  2. 字典 → 消息

    python 复制代码
    from 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 工作流程

  1. 构造消息:用 SystemMessage/HumanMessage 定义对话内容
  2. 管理历史:用列表或 Memory 维护多轮上下文
  3. 调用模型:统一使用 ChatModel 接口
  4. 处理响应:接收 AIMessage,追加到历史
  5. 持久化:序列化消息,存储对话记录

在实际应用中,常见模式是:

  1. 初始化:创建 ChatMessageHistory 或维护消息列表。
  2. 系统消息:在对话开始时设置 SystemMessage。
  3. 多轮交互:每次用户输入 → 追加 HumanMessage → 调用模型 → 追加 AIMessage。
  4. 工具调用:模型返回 tool_calls → 执行工具 → 返回 ToolMessage → 再次调用模型。
  5. 历史管理:使用 trim_messages 或摘要避免超出上下文长度。
相关推荐
2601_950760792 小时前
FGF-basic蛋白的结构特征与生物学功能研究
人工智能·深度学习·蛋白
databook2 小时前
数据团队该醒醒了:AI智能体不是你的下一个仪表盘
人工智能·数据分析·agent
互联网科技看点2 小时前
2025-2026年研发管理软件推荐:产品研发全流程一体化靠谱解决方案评测
服务器·数据库·人工智能
imbackneverdie2 小时前
如何从海量文献中跨界汲取创新灵感?
论文阅读·人工智能·ai·自然语言处理·aigc·ai写作·ai工具
Dev7z2 小时前
基于LSTM新闻文本摘要系统的设计与实现
人工智能·rnn·lstm
无名-CODING2 小时前
计算机视觉技术底层原理说明文档(上篇):基础与图像处理
图像处理·人工智能·计算机视觉
实在智能RPA2 小时前
2026 企业 AI 选型博弈:自研大模型底座的“研发黑洞” vs. 标准化 Agent 平台的“效能突围”
人工智能·ai
fundoit2 小时前
OpenClaw通过ROS控制机器人完整教程
人工智能·ai·机器人·ai编程·openclaw
deephub2 小时前
TPU 架构与 Pallas Kernel 编程入门:从内存层次结构到 FlashAttention
人工智能·python·深度学习·tpu