LangChain 如何在 ChatPromptTemplate 中传入 base64 图片?
报错的直接原因是 MessagesPlaceholder.variable_name 要求传入字符串,代码却传入了列表 ["im64", str(image_data)]。要让模型分析图片,还需要将 base64 数据放进图片内容块。仅修正变量名,或把 base64 放入普通文本,都无法完成图片消息的构造。
为什么会出现这个错误?
MessagesPlaceholder 用于在模板中插入一组消息。variable_name 指定调用时读取哪个变量,不能同时保存变量名和变量值。例如:
MessagesPlaceholder(variable_name="im64")
这样定义后,调用模板时传入的 im64 应当是一组消息,而不是裸 base64 字符串。这个参数约定可见 MessagesPlaceholder 官方参考。
原代码中的 str(image_data) 只转换了列表的第二个元素,整个 variable_name 仍然是列表,因此触发了类型校验错误。
直接在 ChatPromptTemplate 中定义图片消息
如果只需要传入一张图片,可以不用 MessagesPlaceholder,直接在 human 消息中定义文本和图片内容块。
下面以 PNG 文件为例,请把 food.png 替换成实际图片路径。示例采用 OpenAI 风格的 image_url 格式,前提是所用模型及其 LangChain 集成支持这种图片输入格式。LangChain 的 ImageURL 参考介绍了这种结构的用途。
import base64
from pathlib import Path
from langchain_core.prompts import ChatPromptTemplate
image_data = base64.b64encode(
Path("food.png").read_bytes()
).decode("ascii")
generation_prompt = ChatPromptTemplate.from_messages(
[
(
"system",
"You are an expert assistant. Analyze the food items "
"in the supplied image and provide detailed information about them.",
),
(
"human",
[
{
"type": "text",
"text": "Please analyze the food items in this image.",
},
{
"type": "image_url",
"image_url": {
"url": "data:image/png;base64,{im64}",
},
},
],
),
]
)
prompt_value = generation_prompt.invoke({"im64": image_data})
如果 image_data 已经是编码完成的 base64 字符串,可以直接复用,不要再执行一次 base64.b64encode()。
这里的 invoke() 只生成提示消息。配置好支持图片输入的聊天模型对象 llm 后,再调用:
response = llm.invoke(prompt_value)
如果需要保留 MessagesPlaceholder
可以先构造带图片内容块的 HumanMessage,再通过消息列表传入。下面沿用上例中的 image_data:
from langchain_core.messages import HumanMessage
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
generation_prompt = ChatPromptTemplate.from_messages(
[
(
"system",
"You are an expert assistant. Analyze the food items "
"in the supplied image and provide detailed information about them.",
),
MessagesPlaceholder(variable_name="image_messages"),
]
)
image_message = HumanMessage(
content=[
{
"type": "text",
"text": "Please analyze the food items in this image.",
},
{
"type": "image_url",
"image_url": {
"url": f"data:image/png;base64,{image_data}",
},
},
]
)
prompt_value = generation_prompt.invoke(
{"image_messages": [image_message]}
)
模板中的 "image_messages" 是变量名,调用时的 [image_message] 是变量值。需要动态插入多条消息时,这种方式更合适。
还需要检查哪些地方?
- 模板花括号:
ChatPromptTemplate默认使用f-string模板格式。模板字符串中的{im64}表示变量,{{im64}}会转义为字面文本{im64},不会插入图片数据。模板用法可参见 ChatPromptTemplate 官方参考。即使换成单层花括号,放在普通文本里的 base64 也仍然只是文本。 - 编码结果类型:
base64.b64encode()返回bytes,应使用.decode("ascii")得到字符串。对bytes直接调用str()会产生带b'...'的表示形式,不能作为正确的图片编码内容。 - 图片格式:示例使用
data:image/png;base64,。如果实际图片是 JPEG,应使用data:image/jpeg;base64,。已有完整 Data URL 时,不要重复添加前缀。 - 模型和集成支持:模板能够生成消息,并不代表下游模型支持图片。还需确认模型、服务端接口及所安装的集成包支持示例中的输入格式;仅凭
langchain==0.3.24无法确定这些条件。
错误信息还显示,tool_x 收到的 image_data 是 'description of the image',这是一段描述文字,不是图片的 base64 数据。修正模板后,如果仍通过工具调用处理图片,需要继续检查实际传入的工具参数。由于没有提供 tool_x 的实现,无法判断该值为何被传入。
备注:内容仅供参考。
