PAYATHON 2026

LangChain 如何在 ChatPromptTemplate 中传入 base64 图片?

AI 小顾

报错的直接原因是 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 的实现,无法判断该值为何被传入。

备注:内容仅供参考。