Messages-让Agent看懂图文多模态

    |     2026年8月18日   |   AI大模型应用, LangChain框架   |     0 条评论   |    5

上篇你把大脑接口钉死了——invoke 既能吃字符串,也能吃 Messages 列表。字符串只够打招呼;正式对话、工具回填、看图说话,全靠 Messages。这篇讲消息类型、怎么遍历,以及多模态(在线 URL / 本地 base64)怎么塞进同一条消息。


小明把角色搞混了

小明沿用上篇写法:

model.invoke("用一句话介绍 LangChain")

同事甩来需求:AI 私厨要「看冰箱照片认食材」。他随手把图片路径拼进字符串:

请看这张图 D:\fridge.jpg,里面有什么菜?

模型当然「看不见」文件路径。他又试过在字典里乱写:

{"role": "image", "content": "http://..."} # 想当然

同时,Agent 返回的 result["messages"] 里又冒出 ToolMessageAIMessage,他分不清和 SystemMessage / HumanMessage 谁先谁后。

小明去找老张:”Messages 到底有几类?看图又该怎么发?”

老张说:”先把文本消息协议站稳,再在 Human 消息的 content 里挂图——多模态不是新角色,是 content 变富了。”


什么是 Messages

老张在白板上画:

一条对话 = 有序列表 messages[] 常见类型(LangChain): SystemMessage → 人设 / 总规则(≈ role=system) HumanMessage → 用户输入(≈ role=user) AIMessage → 模型回复(≈ role=assistant) ToolMessage → 工具结果回填(≈ role=tool,带 tool_call_id) 多模态: 仍是 HumanMessage(或等价 user) 只是 content 从「纯字符串」 变成「文本块 + 图片块」的列表
  • 本地图片不是 URL,而是文件字节 → 转 base64 再发给模型
  • 另一条路:先上传 OSS,变成在线图片 URL

比喻:Messages 是话剧剧本的台词表。System 是旁白规矩,Human 是主角台词,AI 是对手戏,Tool 是场务递上来的道具清单。看图说话,只是主角台词里夹了一张剧照——角色还是 Human。”

类型 谁产生 典型用途
SystemMessage 你 / Agent 的 system_prompt 角色、禁编造、输出格式
HumanMessage 用户 问题、图文输入
AIMessage 模型 最终回答;或带 tool_calls
ToolMessage 你的工具执行结果 必须配对某个 tool_call_id

代码拆解:文本 Messages → 多模态 content

1. 最小 Messages 调用

from langchain_core.messages import HumanMessage, SystemMessage from llm import get_chat_model def demo_messages() -> None: model = get_chat_model(temperature=0.2) ai = model.invoke( [ SystemMessage(content="你是助教,回答不超过 50 字。"), HumanMessage(content="SystemMessage 和 role=system 是什么关系?"), ] ) print(type(ai).__name__, ":", ai.content)

“对照表:

LangChain 类 OpenAI 风格 role
SystemMessage system
HumanMessage user
返回的 AIMessage assistant

顺序很重要:一般先 System,再 Human。返回值是 AIMessage,读正文用 .content——上篇说过。”

2. 遍历 Messages 数组

Agent 跑完后,轨迹都在 messages 里。调试时养成遍历习惯:

result = agent.invoke({"messages": [{"role": "user", "content": question}]}) for m in result["messages"]: name = type(m).__name__ content = getattr(m, "content", "") print(f"- {name}: {str(content)[:80]}")

“你会看见:Human → AI(可能含 tool_calls)→ Tool → AI(最终话)……
遍历是为了排障:到底有没有调工具、工具结果有没有回填。”

手写循环里,回填长这样(真代码节奏):

messages.append(ai) # AIMessage,可能带 tool_calls # ... messages.append(ToolMessage(content=str(result), tool_call_id=tc["id"]))

“ToolMessage 必须带 tool_call_id,和当初的 tool_call 配对——这是协议铁律,和早期 Function Calling 篇同一个道理。”

3. 多模态:在线图片(URL)

导图:「在线图片」用图片 URL。Human 的 content 改成块列表

from langchain_core.messages import HumanMessage vision_msg = HumanMessage( content=[ {"type": "text", "text": "请用一句话描述图片里的食材。"}, { "type": "image_url", "image_url": {"url": "https://示例域名/demo-fridge.jpg"}, }, ] ) ai = model.invoke( [ SystemMessage(content="你是厨房助手,只描述看得见的食材,不编造。"), vision_msg, ] ) print(ai.content)

要点:

  1. 多模态仍走 model.invoke([SystemMessage, HumanMessage])
  2. 图片挂在 HumanMessage.content 列表里,不是新的 Message 子类
  3. Smoke 验收:换一张公网可访问的图片 URL(大纲要求)

模型需支持视觉;纯文本模型会无视或报错——换引擎是 Models 篇工厂的事。”

4. 多模态:本地图片(base64)与 OSS

导图原话:

所谓本地图片,就是用户上传的图片数据或者本地存在的图片,而不是图片的 url 地址。
我们需要将图片数据转换成 base64 字符串,然后发送给模型。
另一方式:上传 OSS 转成在线图片。

import base64 from pathlib import Path def image_file_to_data_url(path: str) -> str: raw = Path(path).read_bytes() b64 = base64.b64encode(raw).decode("ascii") # jpeg/png 按实际类型改 return f"data:image/jpeg;base64,{b64}" local_msg = HumanMessage( content=[ {"type": "text", "text": "冰箱里有哪些食材?列出名称即可。"}, { "type": "image_url", "image_url": {"url": image_file_to_data_url(r"D:\fridge.jpg")}, }, ] )

两条路怎么选:

方式 做法 适合
在线 URL image_url.url = https://... 已有公网图、CDN
本地 base64 data:image/...;base64,... 用户上传、本地文件
先 OSS 再 URL 上传后当在线图片 大图、要复用、控请求体体积

小明复述:”角色还是那几类;看图只是 Human 的 content 变列表;本地就 base64,或者先变 URL。”


总结

老张说:”第四篇只办一件事——让消息协议能承载文本和图片。”

“三个核心理解:

  1. Messages 是对话的剧本 —— System / Human / AI / Tool 各司其职
  2. 多模态不换角色 —— 在 Human 的 content 列表里挂 image_url
  3. 本地图两条路 —— base64 data URL,或 OSS 转在线 URL”

LangChain 支线进度:

认识 LangChain → Agent 快速入门 → Models ↓ Messages 与多模态(本篇) ↓ Prompts / LCEL / 结构化输出 → Tools → Memory → AI私厨…

小明说:”下一篇该把 Prompt 模板和 LCEL 管道系统化了——现在 Messages 手写列表,用模板会更省事。”

“对。下一篇:Prompts / LCEL / 结构化输出。”

字符串只能寒暄;Messages 才是应用协议。会看图,先学会把图放进 HumanMessage 的 content 里。

转载请注明来源:Messages-让Agent看懂图文多模态
本文链接地址:https://ai.zhousir.top/?p=3808
回复 取消