SpringAI多模态的基本使用

SpringAI 多模态

一、多模态的概念

模态是指表达或感知事务的方式,例如视觉、听觉、嗅觉。对应的信息传递媒介可以是文本、图像、声音、视频等

多模态是指从多个模态表达或者感知事物。

表达可以理解为输出,而感知则是输入。

deepseek、qwen-max等模型都是纯文本模型,不过在ollama和阿里云百炼等大模型

平台,能找到很多多模态模型。

以阿里云百炼平台为例:

有很多模态的模型,甚至还有一个分类是全模态模型。

阿里云的qwen3-omni-flash模型是支持文本、图像、音频、视频输入的全模态模

型,还能支持语音合成功能,非常强大。

二、常见使用

像deepseek、文心一言、千问等都支持文件上传的同时去回答问题,这就相当于是一种多模态,使用文字和文件的方式去感知,然后做出输出。

三、代码实现

下面代码基于SpringAI1.0.03。

3.1 定义bean

首先,定义一个用于AI对话的ChatClient的bean,将模型修改为OpenAIChatModel,不仅如此,由于其它业务使用的是不同模型,不能改变,只需添加自定义配置,将模型改为qwen3-omni-flash:

java 复制代码
@Bean("chatClient")
public ChatClient chatClient(OpenAiChatModel model, ChatMemory chatMemory) {
    return ChatClient.builder(model)
        .defaultOptions(ChatOptions.builder().model("qwen3-omni-flash").build())
        .defaultSystem("你是可爱且热情、人见人爱,花见花开的AI助手,你的名字是墩墩,请用墩墩的身份回答用户的问题!")
        .defaultAdvisors(
        new SimpleLoggerAdvisor(),
        MessageChatMemoryAdvisor.builder(chatMemory).build()         // 如果失去它,系统就不再有会话记忆功能了,不过这个会话记忆是在内存里的,重启项目就不存在了
    )
        .build();
}

在这里配置defaultOptions(ChatOptions.builder().model("qwen3-omni-flash").build()) 可以独立配置这个ChatClient使用的大模型,而不是使用yaml中配置的全局模型了。

3.2 编写controller

java 复制代码
    // 再弄一个流式的,但是这里一定要设置字符编码,要不然是会乱码的
    @RequestMapping(value = "/chat", produces = "text/html;charset=UTF-8")
    public Flux<String> chatStream(@RequestParam("prompt") String prompt,
                                   @RequestParam("chatId") String chatId,
                                   @RequestParam(value = "files", required = false) List<MultipartFile> files
    ) {
        // 1.保存会话id (这一步如果是走的redis就不需要自己实现了)
        chatHistoryService.save(ServiceTypeEnum.CHAT.getType(), chatId);
        // 2.请求模型
        if (files == null || files.isEmpty()) {
            // 没有附件,纯文本聊天
            return textChat(prompt, chatId);
        } else {
            // 有附件,多模态聊天
            return multiModalChat(prompt, chatId, files);
        }
    }

    private Flux<String> multiModalChat(String prompt, String chatId, List<MultipartFile> files) {
        // 1.解析多媒体, 其实就是把文件对象解析成没提对象
        List<Media> medias = files.stream()
                .map(file -> new Media(
                                MimeType.valueOf(Objects.requireNonNull(file.getContentType())),
                                file.getResource()
                        )
                )
                .toList();
        // 2.请求模型
        return chatClient.prompt()
                .user(p -> p.text(prompt).media(medias.toArray(Media[]::new)))
                .advisors(a -> a.param(CONVERSATION_ID, chatId))
                .stream()
                .content();
    }

    private Flux<String> textChat(String prompt, String chatId) {
        return chatClient.prompt()
                .user(prompt)
                .advisors(a -> a.param(CONVERSATION_ID, chatId))
                .stream()
                .content();
    }

四、测试效果

现在我传递这张图片给AI,询问图片的内容:

可以看到现在AI能够同时理解文字和图片这两种模态的信息,并且进行理解和输入。

相关推荐
xujinwei_gingko4 小时前
SpringBoot整合WebSocket
spring boot·后端·websocket
wang09075 小时前
自己动手写一个spring之IOC_2
java·后端·spring
来杯@Java5 小时前
学生选课管理系统(基于springboot+vue前后端分离的项目)计算机毕业设计java
java·spring boot·spring·vue·毕业设计·maven·mybatis
invicinble6 小时前
easyexcel开发全域理解
spring boot
豆瓣鸡6 小时前
Spring Cloud笔记
spring·spring cloud
不知名的老吴6 小时前
线程的生命周期之线程“插队“
java·开发语言·python
ANnianStriver6 小时前
PetLumina-02-后端开发与前后端联调
java·ai·sa-token
云烟成雨TD7 小时前
Spring AI 1.x 系列【56】用大模型评判大模型:递归顾问实现自动化评估方案
人工智能·spring·自动化
杨了个杨89827 小时前
Keepalived + Nginx + HAProxy 高可用架构部署实战案例
java·nginx·架构