在调用模型时,发送给LLM的消息、LLM返回的消息都包含以下几部分内容:
- role:消息所属角色,可以是system、user、assistant
- content:消息的内容
- metadata(可选):消息的元数据,例如:消息的ID、消耗的token等
之前我们都是自己用dict模拟消息:
python
response = agent.invoke({
"messages": [{"role": "user", "content": "月亮的首都是哪里?"}]
})
这太麻烦了。在LangChain中发送给LLM的消息、LLM返回的消息都统一被封装为BaseMessage,它是中基本的上下文单元。
3.1 消息类型
在LangChain中,我们并不需要自己创建BaseMessage对象,LangChain已经把常见消息根据角色(Role)创建了对应的BaseMessage的子类:
- SystemMessage:role是system,代表系统消息,用于设定模型角色和交互背景
- HumanMessage:role是user,代表用户输入的消息
- AIMessage:role是assistant,代表LLM生成的响应,包含:文本、工具调用、元数据
- ToolMessage:role是tool,代表工具调用时产生的结果
所以,我们可以这样传递消息列表:
python
from langchain.messages import HumanMessage, AIMessage
from langchain.agents import create_agent
# 创建Agent
agent = create_agent(model="deepseek-chat")
# 调用Agent,发送消息
response = agent.invoke({
"messages": [
HumanMessage(content="你好,我是张三"),
AIMessage(content="你好,张三,很高兴认识你。"),
HumanMessage(content="我的名字是什么?")
]
})
print(response)
注意看,Agent的返回结果中包含完整的消息列表(Messages):
python
{'messages': [HumanMessage(content='你好,我是张三', additional_kwargs={}, response_metadata={}, id='f5703ee9-f567-48d6-8e07-e6ddaf24547e'), AIMessage(content='你好,张三,很高兴认识你。', additional_kwargs={}, response_metadata={}, id='5c654447-828c-43b7-9505-a341e0d21b8a', tool_calls=[], invalid_tool_calls=[]), HumanMessage(content='我的名字是什么?', additional_kwargs={}, response_metadata={}, id='a3390334-85b8-4f5f-8528-782a18671ac9'), AIMessage(content='你刚才提到你的名字是"张三"。如果这是你希望我称呼你的方式,我会记住的。如果有其他偏好,随时告诉我哦! 😊', additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 33, 'prompt_tokens': 26, 'total_tokens': 59, 'completion_tokens_details': None, 'prompt_tokens_details': {'audio_tokens': None, 'cached_tokens': 0}, 'prompt_cache_hit_tokens': 0, 'prompt_cache_miss_tokens': 26}, 'model_provider': 'deepseek', 'model_name': 'deepseek-chat', 'system_fingerprint': 'fp_eaab8d114b_prod0820_fp8_kvcache', 'id': '9ea39267-c54a-4523-82e0-1377435ffde4', 'finish_reason': 'stop', 'logprobs': None}, id='lc_run--019cad79-8b7a-7861-855b-5a87ba11d38c-0', tool_calls=[], invalid_tool_calls=[], usage_metadata={'input_tokens': 26, 'output_tokens': 33, 'total_tokens': 59, 'input_token_details': {'cache_read': 0}, 'output_token_details': {}})]}
我们可以通过遍历Messages数组,更友好的打印结果:
python
for message in response['messages']:
message.pretty_print()
结果:
python
================================ Human Message =================================
你好,我是张三
================================== Ai Message ==================================
你好,张三,很高兴认识你。
================================ Human Message =================================
我的名字是什么?
================================== Ai Message ==================================
你刚才提到你的名字是"张三"。如果这是你希望我称呼你的方式,我会记住的。如果有其他偏好,随时告诉我哦! 😊
提示:
通过刚才的实现可以发现,拼接message列表可以让AI记住会话历史,产生记忆。
3.2 多模态消息
之前我们都是向模型发送文本消息,但是 LangChain 也支持向模型发送多模态消息,比如图片、音频、视频、文本等。但前提是必须是多模态模型才支持。
一些支持多模态的模型有:
- qwen3.5-plus
- gpt-5-nano
- ...
我们以qwen3.5-plus为例,演示向模型发送图片消息
3.2.1 在线图片
首先,我们演示如何发送一个在线图片给模型,也就是指定模型的url地址。
图片如下:

消息格式如下:
python
{
"role": "user",
"content": [
{"type": "image", "url": "https://xxx.com/a.jpeg"},
{"type": "text", "text": "这些图描绘了什么内容?"}
]
}
示例代码:
python
from langchain.chat_models import init_chat_model
import os
# 1.初始化模型
model = init_chat_model(
model="qwen3.5-plus", # 这里选择qwen3.5-plus,这是一个多模态模型,支持图片、文本、音频、视频
model_provider="openai",
base_url=os.getenv("DASHSCOPE_BASE_URL"),
api_key=os.getenv("DASHSCOPE_API_KEY")
)
# 2.创建智能体
agent = create_agent(model=model)
# 3.组织多模态消息
multimodal_message = HumanMessage(
content=[
{"type": "image",
"url": "https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20241022/emyrja/dog_and_girl.jpeg"},
{"type": "text", "text": "这些图描绘了什么内容?"}
])
# 4.调用Agent,发送多模态消息
for token, metadata in agent.stream({
"messages": [multimodal_message]
}, stream_mode="messages"):
if token.content:
print(token.content, end="", flush=True)
结果:
python
这张图片描绘了一个非常温馨、和谐的场景,主要包含以下内容:
1. **人物与动物**:
* 一位年轻女性坐在沙滩上,她留着长发,身穿黑白格纹衬衫和深色长裤(裤脚卷起),看起来非常休闲。
* 在她对面坐着一只体型较大的浅色犬(看起来像金毛寻回犬或拉布拉多),狗狗身上戴着带有彩色花纹的胸背带。
2. **互动动作**:
* 这是画面的核心:狗狗乖巧地抬起一只前爪,放在女子的手掌中,就像是在玩"握手"的游戏。
* 女子面带灿烂的笑容,温柔地注视着狗狗,一只手握着狗爪,另一只手似乎拿着小零食或者正准备抚摸它。这展现了人与宠物之间亲密无间的信任与爱。
3. **环境与背景**:
* 场景设定在海滩上,地面是细腻的沙子,上面布满了脚印和纹理。
* 背景是大海,可以看到海浪正在向岸边涌来。
4. **光影与氛围**:
* 光线非常温暖柔和,从画面右侧照射过来(看起来像是日落时分的"黄金时刻"),给女子的头发和沙滩镀上了一层金色的光晕。
* 整体氛围宁静、美好且充满幸福感。
此外,还可以看到一条红色的牵引绳散落在狗狗身后的沙地上,说明它们正在享受一段放松的散步时光。
3.2.2 本地图片
所谓本地图片,就是用户上传的图片数据或者本地存在的图片,而不是图片的url地址。我们需要将图片数据转换成base64字符串,然后发送给模型。
本地图片的消息格式:
python
{
"role": "user",
"content": [
{"type": "text", "text": "Describe the content of this image."},
{
"type": "image",
"base64": "AAAAIGZ0eXBtcDQyAAAAAGlzb21tcDQyAAACAGlzb2...",
"mime_type": "image/jpeg",
},
]
}
示例:
python
import base64
# 例如,有一个用户上传的文件,是字节格式img_bytes,我们先将其进行base64编码
img_b64 = base64.b64encode(img_bytes).decode("utf-8")
# 组织多模态消息
multimodal_question = HumanMessage(content=[
{
"type": "image",
"base64": img_b64,
"mime_type": "image/jpeg",
},
{"type": "text", "text": "给我讲讲图片中的城市"}
])
# 调用Agent,发送消息
response = agent.invoke(
{"messages": [multimodal_question]}
)
print(response['messages'][-1].content)