首页 / Spring AI 入门教程 / 多模态消息

Spring AI 入门教程

多模态消息

本教程共 45 篇 · 第 9 篇 · 更新于 2026-08-16 · 约 6 分钟阅读

Spring AI多模态UserMessageMedia图片识别GeminiGPT-4oJava

本节目标:学会用 UserMessage 的 media 字段发送图片等非文本内容,让模型”看图说话”。

前几章的对话只有文字。现实里很多输入是图片、音频、视频。多模态模型能同时理解这些不同形态的输入。Spring AI 用一套消息抽象支持它们。

9.1 模型能”看”什么

传统机器学习把任务拆成单模态。音频模型管语音,视觉模型管图像,各管一摊。文本转语音、语音转文本、目标检测、图像分类,每个任务一个专用模型。这种路线在单一领域很强,但跨模态就抓瞎。人类的体验不是这样,看说明书、听讲解、读文字常常同时发生。

多模态不是新理念。17 世纪的教育家夸美纽斯就主张,把相互联系的事物放在一起教。多模态模型正在实践这个理念。新一代大模型能同时接收文本、图像、音频、视频,再生成文本回答。OpenAI 的 GPT、Google 的 Gemini、Anthropic 的 Claude,还有开源的 Llama、LLaVA、BakLLaVA,都属于这一类。

多模态,指模型同时理解和处理多种来源信息的能力。对开发者来说,这意味着一个接口能处理”帮我看看这张照片里有什么”这种请求。文本、图像、音频、视频可以混在一起发,模型统一理解。注意,多模态是模型能力,不是框架能力。模型不支持时,media 字段可能被忽略或直接报错,接入前先确认模型文档。

9.2 UserMessage 的 media 字段

Spring AI 的多模态支持集中在 UserMessage 上。它有两个关键字段:

  • content:文本内容,主要输入
  • media:可选的媒体列表,附加图片、音频、视频

Media 包含两部分:MimeType 指明媒体类型,数据可以是 Resource 对象或 URI。用哪种形式取决于具体模型,有的模型接受资源对象,有的接受网络地址。两者都指向同一种媒体内容,只是传递方式不同。

MimeType 用 Spring 的 MimeTypeUtils 常量就行,比如 IMAGE_PNGIMAGE_JPEG。媒体类型选对,模型才能正确解码。

两种形式各有用途。Resource 适合本地文件:ClassPathResource 读 classpath,FileSystemResource 读磁盘路径,UrlResource 读网络地址。URI 适合直接传图片链接,省去下载步骤。选哪种看模型文档的要求。

MimeType 必须和实际内容一致。传了 IMAGE_PNG 却给一张 JPEG,模型可能拒收或乱读。

ChatClient 里的写法:

String response = ChatClient.create(chatModel).prompt()
    .user(u -> u.text("这张图里有什么?")
                .media(MimeTypeUtils.IMAGE_PNG, new ClassPathResource("/multimodal.test.png")))
    .call()
    .content();

底层 API 的写法:

var imageResource = new ClassPathResource("/multimodal.test.png");

var userMessage = UserMessage.builder()
    .text("这张图里有什么?")
    .media(new Media(MimeTypeUtils.IMAGE_PNG, imageResource))
    .build();

ChatResponse response = chatModel.call(new Prompt(userMessage));

两段代码做的是同一件事,选择取决于项目风格。用 ChatClient 更简洁,用底层 API 能更清楚地看到消息结构。多模态消息也支持流式输出,.stream() 一样能用——官方文档没有单列这一条,媒体消息走的是同一条调用管道。

图片放进 src/main/resources/,模型就会描述图片内容。官方文档的示例图是一张水果碗照片:模型能说出碗是金属材质、边缘是弯曲的金属丝结构,里面有两根香蕉和一个红苹果;它甚至注意到香蕉皮上的棕色斑点,说明香蕉有点过熟。细节还原度相当高。

文本和图片是组合使用的:先给一张图,再问”这里有什么""哪里出了问题”,模型结合两者回答。

Note

media 字段目前只对用户消息有意义,系统消息不支持。模型回答(AssistantMessage)只有文本。要生成图片、音频这类非文本输出,得用专门的单模态模型。

9.3 多张图片与 MediaContent

media 支持多条。传 List<Media> 可以一次带多张图片。消息接口里的 MediaContent 负责这件事:

public interface MediaContent extends Content {
    Collection<Media> getMedia();
}

实现 MediaContent 的消息类型都携带媒体列表。目前主要是 UserMessage。做商品识别、票据比对这类任务时,一次传多张图很常见。模型会结合所有图片和文本一起理解。比如两张照片对比”这两张图里的商品有什么区别”,比逐张问再自己对比省事。

9.4 音频与视频

media 字段不只装图片。音频、视频同样支持,只要模型厂商接受。MimeType 换成对应的音频、视频类型即可。文本、图片、音频混合输入,接口写法不变。目前实际场景还是图片为主,音频和视频支持取决于具体模型,接入前先确认模型能力。

9.5 什么场景用多模态

多模态能解决的问题很广。客服系统识别用户上传的截图;电商平台分析商品图片;文档应用扫描票据提取信息;教育应用让模型讲解图表。接入方式都一样:把媒体塞进 media 字段。区别只在业务逻辑。

一个典型的本地试验流程:本地跑 Ollama,拉一个支持图片的模型,写一个带图片的 UserMessage,跑通后换云厂商模型。成本低,反馈快。先用自家项目里的真实截图试效果,确认没问题再上生产。

9.6 支持多模态的模型

Spring AI 官方文档列出的支持列表:

  • OpenAI:GPT 系列
  • Google Gemini
  • Anthropic Claude
  • Mistral AI:Pixtral 系列
  • Ollama:LLaVA、BakLLaVA、Llama 3.2 等
  • AWS Bedrock Converse

选模型时确认它支持图片输入。本地 Ollama 拉一个 LLaVA 就能试,不用注册任何云服务,也不用花钱。想在生产环境用,优先选 GPT-4o、Gemini、Claude 这些主流模型,文档和社区资料都更全。

每个模型的接入 starter 不同,但消息构造是同一套 API。换模型只换依赖和配置,UserMessage 的写法不用大改。这套抽象的价值就在这里:厂商差异被挡在框架后面,业务代码保持稳定。

什么时候用多模态?凡是输入里有图的任务都值得考虑:截图问答、票据识别、图表解读、图片审核。先小范围试,确认模型效果再铺开。

9.7 小结

多模态的核心就一个点:UserMessagemediaMimeType 说明格式,ResourceURI 提供内容。给模型一张图,它就能回答问题。文本之外的世界,从这一行代码开始。先把图片跑通,再试音频视频,逐步扩展。多模态消息和其他章节的知识不冲突,PromptTemplate、Advisor 这些能力照常可用。