LangChain Messages 篇章学习笔记 — 模型交互的输入输出单元
LangChain Messages 篇章学习笔记 — 模型交互的输入输出单元
本文基于 LangChain 官方文档 Messages 章节学习整理,梳理消息对象的结构、四种消息类型、多种传参格式与多轮对话机制,适合 AI Agent 开发入门者理解模型交互的数据载体。
一、Message 是什么
Message 是 LangChain 中从模型获取上下文的基础工具(fundamental utility)。Model 是基础单元,而 Message 反映了模型的输入和输出。它携带 content(内容)和 metadata(元数据),用于与 AI 交流。
Message 是一个对象(object),包含以下核心字段:
| 字段 | 说明 | 示例 |
|---|---|---|
| role | 消息类型(角色) | system / user / assistant / tool |
| content | 消息内容 | 文本、图片、音频、文档等 |
| metadata | 可选元数据 | message id、token usage 等 |
LangChain 提供了标准的 Message 模型类别,可以在所有模型提供商中工作,确保一致性行为,不管你用的是哪个模型。
二、基础使用
2.1 创建 Message 对象
最简单的方式是直接创建 Message 实体,然后把它们放到 invoke / stream / batch 里调用。
from langchain.messages import SystemMessage, HumanMessage
# SystemMessage:给模型定义角色、背景、风格
SystemMessage(content="你是一个专业的 Python 翻译助手")
# HumanMessage:用户的问题
HumanMessage(content="Translate: I love programming.")
2.2 三种传参方式
方式一:Text Prompts(字符串简写)
调用时直接传入字符串,LangChain 自动包装为 HumanMessage。
response = llm.invoke("什么是递归?")
# 等价于 llm.invoke(HumanMessage(content="什么是递归?"))
方式二:Message Prompts(消息对象列表)
创建一个 list,放入各种 Message 对象。适用于多轮对话和 system instruction。
from langchain.messages import SystemMessage, HumanMessage, AIMessage
messages = [
SystemMessage(content="你是英文到法文翻译助手"),
HumanMessage(content="Translate: I love programming."),
AIMessage(content="J'adore la programmation."), # 上一轮 AI 的回答
HumanMessage(content="Translate: I love building applications."),
]
response = llm.invoke(messages)
多轮对话的关键:把 AI 之前说的内容(AIMessage)放回消息列表,让 AI 有了短暂的记忆能力。你说一句、AI 说一句,再把 AI 说的内容传回去,形成多轮对话。
方式三:Dictionary Format(字典格式)
用字典构建消息,OpenAI 兼容最简洁的写法。
messages = [
{"role": "system", "content": "你是翻译助手"},
{"role": "user", "content": "Translate: I love programming."},
{"role": "assistant", "content": "J'adore la programmation."},
{"role": "user", "content": "Translate: I love building applications."},
]
response = llm.invoke(messages)
Q:字典格式里的 role 和 content 是规定好的吗?能随便传吗?
A:不能随便传。 role 只能是
system/user/assistant/tool这 4 个固定值,这是 OpenAI API 规范,所有兼容端点(包括百炼)都遵循。content 是你自己传的内容字符串。字典格式只是对象格式的简写,底层 LangChain 自动转成对应对象。
| 字典 role | LangChain 对象 | 作用 |
|---|---|---|
"system" |
SystemMessage |
定义模型角色 |
"user" |
HumanMessage |
用户输入 |
"assistant" |
AIMessage |
模型输出 |
"tool" |
ToolMessage |
工具返回结果 |
三、四种 Message 类型详解
3.1 SystemMessage — 角色定义
告诉模型行为并提供交互上下文,给模型定角色、提供背景。
SystemMessage(content="你是一个专业的 Python 翻译助手,只回答翻译结果")
用途:
- 设置语调(正式/幽默/简洁)
- 定义模型角色(翻译助手/代码专家/数据分析师)
- 为 response 建立指导规则
- 给模型一个"性格"和"回答风格"
3.2 HumanMessage — 用户输入
代表用户 input 和 interaction,是用户与模型交互的开始。
HumanMessage(content="什么是装饰器?")
多模态内容:HumanMessage 的 content 不仅可以是文本,还可以包含 audio、图片、files 等多模态内容。
HumanMessage 的字段:
| 字段 | 是否必填 | 类型 | 用途 |
|---|---|---|---|
content |
必填 | str 或 list | 消息内容(文本/图片/音频) |
name |
选填 | str | 多用户场景区分发言者 |
id |
选填 | str | 消息唯一标识,用于追踪/删除 |
Q:content、name、id 是规定好的还是自己创建的?
A:字段名是 LangChain 预定义的(不能改),值是你自己传的。 类比 Java:就像一个 HumanMessage 类有三个属性,字段名是类定义好的,但属性值是你 new 的时候传的。
3.3 AIMessage — 模型输出
代表大语言模型返回的生成内容,包括信息、工具调用(tool_calls)和元数据等。
# 普通回答
AIMessage(content="递归是一种函数调用自身的编程思想...")
# 带工具调用的回答
AIMessage(
content="",
tool_calls=[{
"id": "call_001",
"name": "get_weather",
"args": {"city": "杭州"},
}]
)
Q:AIMessage 是动态的,下轮问答时需要先提取 content 再传进去吗?
A:不需要手动提取,直接把整个 AIMessage 对象追加到消息列表就行。
# ✅ 正确:直接追加 AIMessage 对象 messages = [SystemMessage("你是助手"), HumanMessage("你好")] resp = llm.invoke(messages) messages.append(resp) # AIMessage 直接追加 messages.append(HumanMessage("那明天呢?")) resp2 = llm.invoke(messages) # 模型能看到完整多轮对话底层原理:模型 API 本身就接受
assistant角色的消息。在 Agent 中,这个"追加消息→调用模型→再追加"的循环是 Agent 框架自动做的,你不需要手写循环。
3.4 ToolMessage — 工具返回结果
Agent 可以使用工具调用,ToolMessage 用于把工具执行结果回传给模型。
ToolMessage(
content="晴,25度",
tool_call_id="call_001", # 必须与 AIMessage.tool_calls[i]["id"] 严格对应
name="get_weather",
)
Q:ToolMessage 里的工具返回信息是放在 AIMessage 里面吗?
A:不是!ToolMessage 是独立的消息类型,和 AIMessage 是并列关系。
完整流程:
1. 模型返回 AIMessage(带 tool_calls) → "我想调用 get_weather(杭州)" 2. 你执行工具,得到结果 → "晴,25度" 3. 你把结果包成 ToolMessage 放回消息列表 → ToolMessage("晴,25度") 4. 再次调用模型,模型看到 ToolMessage → 生成最终回答
为什么 tool_call_id 必须对应? 因为一次对话中模型可能同时调多个工具,模型靠 id 知道哪个 ToolMessage 对应哪个 tool_call:
AIMessage 的 tool_calls:
├── {id: "call_001", name: "get_weather", args: {city: "杭州"}}
└── {id: "call_002", name: "get_time", args: {}}
ToolMessage(tool_call_id="call_001", content="晴,25度") ← 对应 weather
ToolMessage(tool_call_id="call_002", content="14:30") ← 对应 time
四、多轮对话的消息流转
用户提问 模型回答
│ │
▼ ▼
HumanMessage("你好") → AIMessage("你好!有什么帮你的?")
│ │
└──── 都追加到 messages 列表 ────┘
│
▼
HumanMessage("那明天呢?") → AIMessage("明天有什么需要帮忙的?")
│ │
└──── 继续追加 ─────────────┘
手动多轮对话(理解原理用,实际用 Agent 自动处理):
messages = [SystemMessage(content="你是助手")]
for round in range(3):
user_input = input("你:")
messages.append(HumanMessage(user_input))
resp = llm.invoke(messages)
messages.append(resp) # AIMessage 直接追加
print(f"AI:{resp.content}")
五、三种传参格式对比
| 格式 | 代码 | 适合场景 |
|---|---|---|
| 字符串简写 | llm.invoke("你好") |
单次快速问答 |
| 消息对象列表 | [SystemMessage(...), HumanMessage(...)] |
多轮对话、需要附加 id/name、类型安全 |
| 字典格式 | [{"role": "user", "content": "..."}] |
OpenAI 兼容最简洁、从 API 文档快速移植 |
选择建议:
- 学习/调试:消息对象列表(类型明确,IDE 补全好)
- 快速验证:字符串简写
- 生产环境:字典格式(简洁,易序列化)
六、总结
| 概念 | 一句话理解 |
|---|---|
| Message | 模型交互的输入输出单元,携带 role + content + metadata |
| SystemMessage | 角色定义,给模型设定背景和风格 |
| HumanMessage | 用户输入,可含多模态内容 |
| AIMessage | 模型输出,可带 tool_calls(工具调用意图) |
| ToolMessage | 工具返回结果,tool_call_id 必须与 AIMessage 对应 |
| 字符串简写 | 最简调用,自动包装为 HumanMessage |
| 消息对象列表 | 多轮对话标配,类型安全 |
| 字典格式 | OpenAI 兼容最简写,role 固定 4 值 |
| 多轮对话 | 把 AIMessage 直接追加回列表,模型即有"记忆" |
核心认知:Message 是模型交互的"信封",role 标识谁说的,content 是说的内容。四种 Message 类型对应对话中的四个角色,ToolMessage 是工具调用闭环的关键一环。
更多推荐

所有评论(0)