乐途乐途
主页
  • 计算机基础

    • TCP/IP
    • Linux
    • HTTP
  • 数据库

    • SQL
    • MySQL 5.7
  • 编程语言

    • C
    • C++
    • Java SE
    • Python2
    • Python3
  • 数据格式

    • JSON
    • XML
  • 认证与安全

    • JWT
  • 工具

    • Markdown
  • Git

    • GitFlow
  • Quartz

    • Quartz
  • Java

    • Maven 入门
    • Maven 进阶
    • MyBatis
    • Spring
    • Spring MVC
  • Java

    • Spring Boot
    • Spring Cloud
    • Spring Cloud Alibaba
    • Spring Security
    • Spring AI
    • Spring Batch
    • Kafka
    • Java 设计模式
  • 缓存

    • Redis
  • 搜索引擎

    • Elasticsearch
  • 分布式协调

    • ZooKeeper
联系
阿里云
主页
  • 计算机基础

    • TCP/IP
    • Linux
    • HTTP
  • 数据库

    • SQL
    • MySQL 5.7
  • 编程语言

    • C
    • C++
    • Java SE
    • Python2
    • Python3
  • 数据格式

    • JSON
    • XML
  • 认证与安全

    • JWT
  • 工具

    • Markdown
  • Git

    • GitFlow
  • Quartz

    • Quartz
  • Java

    • Maven 入门
    • Maven 进阶
    • MyBatis
    • Spring
    • Spring MVC
  • Java

    • Spring Boot
    • Spring Cloud
    • Spring Cloud Alibaba
    • Spring Security
    • Spring AI
    • Spring Batch
    • Kafka
    • Java 设计模式
  • 缓存

    • Redis
  • 搜索引擎

    • Elasticsearch
  • 分布式协调

    • ZooKeeper
联系
阿里云
  • Spring AI 学习路径
  • 第1章 Spring AI 概述与核心理念

    • 章节导读
    • Spring AI 概述与可移植 API
    • 核心模块与依赖关系
  • 第2章 快速入门与第一个AI应用

    • 章节导读
    • 环境准备与配置
    • 第一个 AI 对话应用
  • 第3章 聊天模型与ChatClient

    • 章节导读
    • ChatClient 详解
    • ChatModel 底层抽象
    • 多轮对话与 ChatMemory
  • 第4章 提示词管理与模板

    • 章节导读
    • Prompt 与 Message 体系
    • 提示词模板与动态构建
  • 第5章 输出解析与结构化响应

    • 章节导读
    • 输出解析器与 BeanOutputConverter
  • 第6章 嵌入模型与向量存储

    • 章节导读
    • EmbeddingModel 与文本向量化
    • ETL 数据注入流水线
    • 向量存储抽象与配置
  • 第7章 检索增强生成(RAG)

    • 章节导读
    • RAG 核心机制与流程
    • QuestionAnswerAdvisor 详解
    • RAG 实战案例
  • 第8章 函数调用(Function Calling)

    • 章节导读
    • Tool 注解与函数声明
    • 函数调用实战
  • 第9章 多模态

    • 章节导读
    • 图像输入与视觉模型
    • 图像生成
  • 第10章 Advisor拦截器链

    • 章节导读
    • Advisor 链与内置拦截器
  • 第11章 MCP 协议与跨语言工具集成

    • 章节导读
    • MCP 协议深入
  • 第12章 可观测性测试与最佳实践

    • 章节导读
    • 可观测性与指标监控
    • 测试策略与 Mock 实践
    • 最佳实践与面试考点汇总

孔蓝把一张手写试卷摊在桌上:"AI 能看懂这个吗?"白歌接过话:"Spring AI 的 Media 类就是为这种场景设计的——把图片封装好,塞进 UserMessage,视觉模型就能理解内容。"

图像输入与视觉模型

定义与作用

Spring AI 通过 Media 类封装非文本数据(图片、音频等),将其附加到 UserMessage 中,实现多模态交互——AI 可以"看到"图片并基于视觉内容回答问题。

核心原理

图释:图片经过 Media 封装后成为 UserMessage 的一部分,与文本 Prompt 一并发送给视觉模型。视觉模型分析图片内容后生成文本回复。

完整示例一:试卷批改

场景说明

孔蓝要给"飞翔大学在线考试系统"加上自动批改功能——学生拍照上传手写试卷,AI 识别答案并评分。

依赖引入与配置

<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-openai-spring-boot-starter</artifactId>
</dependency>
spring:
  ai:
    openai:
      api-key: ${OPENAI_API_KEY}
      chat:
        options:
          model: gpt-4o    # GPT-4o 支持视觉

关键代码

@RestController
public class ExamController {

    private final ChatClient chatClient;

    public ExamController(ChatClient.Builder builder) {
        this.chatClient = builder
                .defaultSystem("""
                    你是一个专业阅卷老师。收到试卷图片后:
                    1. 识别所有题目和学生的答案
                    2. 逐题判断对错,给出得分
                    3. 最后给出总分和评语
                    """)
                .build();
    }

    @PostMapping("/exam/grade")
    public String gradeExam(@RequestParam("file") MultipartFile file) 
            throws IOException {
        // 封装图片为 Media 对象
        Media examImage = new Media(
            MimeTypeUtils.IMAGE_PNG,
            new InputStreamResource(file.getInputStream())
        );

        return chatClient.prompt()
                .user(userSpec -> userSpec
                    .text("请批改这张试卷")
                    .media(examImage))
                .call()
                .content();
    }
}

运行结果

POST /exam/grade  (上传手写试卷图片)

AI 回复:
「试卷批改结果:
  一、选择题(每题 5 分)
  1. B ✓  2. C ✓  3. A ✗(正确答案 D)  4. D ✓
  二、填空题(每题 10 分)
  5. "多态" ✓  6. "1536" ✗(正确答案 "768")
  三、简答题(20 分)
  7. 学生答案基本正确,描述了 RAG 的核心流程,扣 5 分(缺少 ETL 阶段说明)

  总分:70 / 100
  评语:基础知识扎实,简答题逻辑清晰但细节需加强。加油!」

完整示例二:证件信息提取

场景说明

飞翔科技人事系统需要自动提取学生证上的姓名、学号等信息。

关键代码

@RestController
public class IdCardController {

    private final ChatClient chatClient;

    public IdCardController(ChatClient.Builder builder) {
        this.chatClient = builder
                .defaultSystem("""
                    你是一个证件信息提取助手。从图片中提取:
                    - 姓名、学号、院系、专业
                    以 JSON 格式返回:
                    {"name":"...","studentId":"...","department":"...","major":"..."}
                    """)
                .build();
    }

    @PostMapping("/idcard/extract")
    public String extractInfo(@RequestParam("file") MultipartFile file) 
            throws IOException {
        Media cardImage = new Media(
            MimeTypeUtils.IMAGE_JPEG,
            new InputStreamResource(file.getInputStream())
        );

        return chatClient.prompt()
                .user(userSpec -> userSpec
                    .text("提取这张学生证上的信息")
                    .media(cardImage))
                .call()
                .content();
    }
}

多模态支持矩阵

提供商模型视觉音频适用场景
OpenAIGPT-4o / GPT-4V支持支持试卷批改、证件识别
OllamaLLaVA支持—本地离线图片分析
AnthropicClaude 3支持—高精度文档解析
GoogleGemini支持支持多模态全场景

易错场景与面试考点

易错场景一:Media 未正确传入

// ❌ 错误:user() 只传文字,图片被忽略
chatClient.prompt()
    .user("描述这张图片")     // 未使用 userSpec
    .call()
    .content();

问题分析

普通 .user(String) 只能传文本,图片必须通过 .user(Consumer<UserSpec>) 的 .media() 方法附加。

// ✅ 正确:使用 userSpec + media()
chatClient.prompt()
    .user(userSpec -> userSpec
        .text("描述这张图片")
        .media(imageMedia))
    .call()
    .content();

面试高频题

Q1:Spring AI 如何实现多模态输入?

通过 Media 类封装非文本数据(图片、音频),使用 MimeTypeUtils 指定类型(如 IMAGE_PNG),将 Media 对象通过 userSpec.media() 附加到 UserMessage 中。ChatClient 将整条消息发送给视觉模型处理。

Q2:多模态输入会增加多少 Token 消耗?

视觉模型的 Token 计算与文本不同:图片按分辨率和复杂度计费,GPT-4o 大约是每 512x512 分辨率区域消耗 85-170 Token。一张标准 1024x1024 图片约消耗 765 Token。

本章小结

  • Media 类封装图片/音频等非文本数据
  • userSpec.text().media() 构建多模态 UserMessage
  • 视觉模型分析图片后返回文本,不需要额外的 OCR 管道
  • GPT-4o、LLaVA、Claude 3、Gemini 均支持视觉输入
上一页
章节导读
下一页
图像生成