在 LangChain 中,消息是模型上下文的基本单元。它们代表模型的输入和输出,既包含内容,也包含与大语言模型(LLM)交互时用于表示对话状态所需的元数据。
消息对象包含以下组成部分:
- 角色 — 标识消息类型(例如
system、user)
- 内容 — 表示消息的实际内容(如文本、图像、音频、文档等)
- 元数据 — 可选字段,例如响应信息、消息 ID 和令牌用量
LangChain 提供了一种标准消息类型,可在所有模型提供商之间通用,确保无论调用哪个模型,行为都保持一致。
基本用法
使用消息最简单的方法是创建消息对象,并在调用模型时将其传入。
from langchain.chat_models import init_chat_model
from langchain_core.messages import HumanMessage, AIMessage, SystemMessage
model = init_chat_model("openai:gpt-5-nano")
system_msg = SystemMessage("你是一个乐于助人的助手。")
human_msg = HumanMessage("你好,你怎么样?")
# 与聊天模型一起使用
messages = [system_msg, human_msg]
response = model.invoke(messages) # 返回 AIMessage
文本提示
文本提示是字符串,适用于不需要保留对话历史的简单生成任务。
response = model.invoke("写一首关于春天的俳句")
何时使用文本提示:
- 你有一个独立的单次请求
- 你不需要对话历史
- 你希望代码复杂度最低
消息提示
或者,你可以通过提供消息对象列表,将消息列表传递给模型。
from langchain_core.messages import SystemMessage, HumanMessage, AIMessage
messages = [
SystemMessage("你是一位诗歌专家"),
HumanMessage("写一首关于春天的俳句"),
AIMessage("樱花绽放...")
]
response = model.invoke(messages)
何时使用消息提示:
- 管理多轮对话
- 处理多模态内容(图像、音频、文件)
- 包含系统指令
字典格式
你也可以直接使用 OpenAI 聊天补全格式指定消息。
messages = [
{"role": "system", "content": "你是一位诗歌专家"},
{"role": "user", "content": "写一首关于春天的俳句"},
{"role": "assistant", "content": "樱花绽放..."}
]
response = model.invoke(messages)
消息类型
- 系统消息 — 告诉模型如何行为,并为交互提供上下文
- 人类消息 — 表示用户输入和与模型的交互
- AI 消息 — 模型生成的响应,包括文本内容、工具调用和元数据
- 工具消息 — 表示工具调用的输出
系统消息
SystemMessage 代表一组初始指令,用于引导模型的行为。你可以使用系统消息来设定语气、定义模型的角色,并为响应建立准则。
system_msg = SystemMessage("你是一个乐于助人的编程助手。")
messages = [
system_msg,
HumanMessage("我如何创建一个 REST API?")
]
response = model.invoke(messages)
from langchain_core.messages import SystemMessage, HumanMessage
system_msg = SystemMessage("""
你是一位精通 Web 框架的资深 Python 开发者。
始终提供代码示例并解释你的推理过程。
解释要简洁但详尽。
""")
messages = [
system_msg,
HumanMessage("我如何创建一个 REST API?")
]
response = model.invoke(messages)
人类消息
HumanMessage 表示用户输入和交互。它们可以包含文本、图像、音频、文件以及其他任意数量的多模态内容。
文本内容
human_msg = HumanMessage("什么是机器学习?")
response = model.invoke([human_msg])
消息元数据
human_msg = HumanMessage(
content="你好!",
name="alice", # 可选:标识不同用户
id="msg_123", # 可选:用于追踪的唯一标识符
)
name 字段的行为因提供商而异——有些将其用于用户标识,有些则忽略它。要确认,请参考模型提供商的@[reference][参考文档]。
AI 消息
AIMessage 表示模型调用的输出。它们可以包含多模态数据、工具调用和提供商特定的元数据,供你后续访问。
response = model.invoke("解释人工智能")
print(type(response)) # <class 'langchain_core.messages.AIMessage'>
当调用模型时,会返回 AIMessage 对象,其中包含响应中的所有关联元数据。但这并不意味着只能从该处创建或修改它们。
不同的提供商对消息类型的权重/上下文处理方式不同,因此有时手动创建一个新的 AIMessage 对象并将其插入消息历史中(如同它来自模型一样)会很有帮助。
from langchain_core.messages import AIMessage, SystemMessage, HumanMessage
# 手动创建 AI 消息(例如用于对话历史)
ai_msg = AIMessage("我很乐意帮你解答这个问题!")
# 添加到对话历史
messages = [
SystemMessage("你是一个乐于助人的助手"),
HumanMessage("你能帮我吗?"),
ai_msg, # 插入,如同来自模型
HumanMessage("太好了!2+2 等于多少?")
]
response = model.invoke(messages)
消息的唯一标识符(由 LangChain 自动生成或由提供商响应返回)
工具调用响应
当模型调用工具时,这些调用会包含在 AI 消息中:
model_with_tools = model.bind_tools([GetWeather])
response = model_with_tools.invoke("巴黎的天气如何?")
for tool_call in response.tool_calls:
print(f"工具: {tool_call['name']}")
print(f"参数: {tool_call['args']}")
print(f"ID: {tool_call['id']}")
流式传输与分块
在流式传输过程中,你会收到 AIMessageChunk 对象,可以将它们合并:
chunks = []
for chunk in model.stream("写一首诗"):
chunks.append(chunk)
print(chunk.text)
工具消息
对于支持工具调用的模型,AI 消息可以包含工具调用。工具消息用于将单个工具执行的结果传递回模型。
# 模型进行工具调用后
ai_message = AIMessage(
content=[],
tool_calls=[{
"name": "get_weather",
"args": {"location": "旧金山"},
"id": "call_123"
}]
)
# 执行工具并创建结果消息
weather_result = "晴天,72°F"
tool_message = ToolMessage(
content=weather_result,
tool_call_id="call_123" # 必须与调用 ID 匹配
)
# 继续对话
messages = [
HumanMessage("旧金山的天气如何?"),
ai_message, # 模型的工具调用
tool_message, # 工具执行结果
]
response = model.invoke(messages) # 模型处理结果
此消息所响应的工具调用 ID。(必须与 AI 消息中的工具调用 ID 匹配)
artifact 字段存储不会发送给模型但可编程访问的补充数据。这对于存储原始结果、调试信息或用于下游处理的数据非常有用,而不会使模型上下文变得混乱。
from langchain_core.messages import ToolMessage
import json
# 工具执行返回结构化数据
raw_data = {"temperature": 72, "condition": "晴天"}
tool_message = ToolMessage(
content="天气晴朗,气温为 72°F。",
tool_call_id="call_123",
name="get_weather",
artifact={"raw_data": raw_data} # 存储结构化数据
)
# 稍后,以编程方式访问原始数据
weather_info = tool_message.artifact.get("raw_data")
print(f"原始天气数据: {json.dumps(weather_info)}")
你可以将消息的内容视为发送给模型的数据载荷。消息具有一个 content 属性,其类型较为宽松,支持字符串和未类型化对象(例如字典)的列表。这使得 LangChain 聊天模型可以直接支持提供商原生结构,例如多模态内容和其他数据。
此外,LangChain 为文本、推理、引用、多模态数据、服务器端工具调用及其他消息内容提供了专用的内容类型。请参见下面的标准内容块。
LangChain 聊天模型接受消息内容的 .content 属性,可以包含:
- 一个字符串
- 一个提供商原生格式的内容块列表
- 一个 LangChain 标准内容块 列表
请参见以下使用多模态输入的示例:
from langchain_core.messages import HumanMessage
# 字符串内容
human_message = HumanMessage("你好,你怎么样?")
# 提供商原生格式(例如 OpenAI)
human_message = HumanMessage(content=[
{"type": "text", "text": "你好,你怎么样?"},
{"type": "image_url", "image_url": {"url": "https://example.com/image.jpg"}}
])
# 标准内容块列表
human_message = HumanMessage(content_blocks=[
{"type": "text", "text": "你好,你怎么样?"},
{"type": "image", "url": "https://example.com/image.jpg"},
])
在初始化消息时指定 content_blocks 仍会填充消息的 content,但提供了类型安全的接口。
标准内容块
LangChain 维护了一组跨提供商的标准消息内容类型(请参见下面的参考部分)。
消息还实现了一个 content_blocks 属性,它会将 content 属性惰性解析为这种标准的类型安全表示。例如,从 ChatAnthropic 或 ChatOpenAI 生成的消息将包含各自提供商格式的 thinking 或 reasoning 块,但这些块可以惰性解析为一致的 ReasoningContentBlock 表示:
from langchain_core.messages import AIMessage
message = AIMessage(
content=[
{"type": "thinking", "thinking": "...", "signature": "WaUjzkyp..."},
{"type": "text", "text": "..."},
],
response_metadata={"model_provider": "anthropic"}
)
message.content_blocks
[{'type': 'reasoning',
'reasoning': '...',
'extras': {'signature': 'WaUjzkyp...'}},
{'type': 'text', 'text': '...'}]
请参阅集成指南以开始使用你选择的推理提供商。
序列化标准内容如果 LangChain 之外的应用程序需要访问标准内容块表示,你可以选择将内容块存储在消息内容中。为此,你可以将 LC_OUTPUT_VERSION 环境变量设置为 v1。或者,在初始化任何聊天模型时设置 output_version="v1":from langchain.chat_models import init_chat_model
model = init_chat_model("openai:gpt-5-nano", output_version="v1")
多模态
多模态是指能够处理以不同形式出现的数据,例如文本、音频、图像和视频。LangChain 包含了跨提供商使用的这些数据的标准类型。
聊天模型 可以接受多模态数据作为输入并生成多模态数据作为输出。下面我们展示了一些包含多模态数据的输入消息的简短示例:
# 来自 URL
message = {
"role": "user",
"content": [
{"type": "text", "text": "描述这张图像的内容。"},
{"type": "image", "url": "https://example.com/path/to/image.jpg"},
]
}
# 来自 base64 数据
message = {
"role": "user",
"content": [
{"type": "text", "text": "描述这张图像的内容。"},
{
"type": "image",
"base64": "AAAAIGZ0eXBtcDQyAAAAAGlzb21tcDQyAAACAGlzb2...",
"mime_type": "image/jpeg",
},
]
}
# 来自提供商管理的文件 ID
message = {
"role": "user",
"content": [
{"type": "text", "text": "描述这张图像的内容。"},
{"type": "image", "file_id": "file-abc123"},
]
}
并非所有模型都支持所有文件类型。请查阅模型提供商的参考文档以了解支持的格式和大小限制。
内容块参考
内容块(无论是创建消息时还是访问 content_blocks 属性时)均表示为类型化字典列表。列表中的每一项必须符合以下块类型之一:
用途: 标准文本输出示例:{
"type": "text",
"text": "Hello world",
"annotations": []
}
用途: 模型推理步骤示例:{
"type": "reasoning",
"reasoning": "用户正在询问关于...",
"extras": {"signature": "abc123"},
}
用途: 图像数据对外部存储图像的引用 ID(例如,在提供商的文件系统或存储桶中)。
图像 MIME 类型(例如,image/jpeg、image/png)
用途: 音频数据对外部存储音频文件的引用 ID(例如,在提供商的文件系统或存储桶中)。
音频 MIME 类型(例如,audio/mpeg、audio/wav)
用途: 视频数据对外部存储视频文件的引用 ID(例如,在提供商的文件系统或存储桶中)。
视频 MIME 类型(例如,video/mp4、video/webm)
用途: 通用文件(PDF 等)对外部存储文件的引用 ID(例如,在提供商的文件系统或存储桶中)。
用途: 文档文本(.txt、.md)文本的 MIME 类型(例如,text/plain、text/markdown)
用途: 搜索结果返回: 附带 URL 的顶级搜索结果。
用途: 代码执行始终为 "code_interpreter_call"
要执行的编程语言(例如 python、javascript、sql)
用途: 执行结果始终为 "code_interpreter_result"
用途: 提供商特定的转义机制用法: 用于实验性或提供商独有的功能 其他提供商特定的内容类型可在每个模型提供商的参考文档中找到。
内容块是在 LangChain v1 中作为消息的新属性引入的,旨在跨提供商标准化内容格式,同时保持与现有代码的向后兼容性。内容块并非 content 属性的替代品,而是一个新属性,可用于以标准化格式访问消息内容。
多轮对话
构建对话应用程序需要管理消息历史和上下文:
from langchain_core.messages import HumanMessage, AIMessage
# 初始化对话
messages = [
SystemMessage("您是一位专门研究 Python 编程的助手")
]
# 模拟多轮对话
while True:
user_input = input("您: ")
if user_input.lower() == "quit":
break
# 添加用户消息
messages.append(HumanMessage(user_input))
# 获取模型响应
response = model.invoke(messages)
# 将助手响应添加到历史记录中
messages.append(response)
print(f"助手: {response.content}")