项目地址
创建项目
打开IDEA创建一个新的spring boot项目,填写项目名称和位置,类型选择maven,组、工件、软件包名称可以自定义,JDK选择17+即可,java语言标准和JDK相同即可 配置Spring Boot版本和开发所需的依赖,主要如下图所示 Spring Boot版本可以选择3.2.5或者更高的版本(作者使用3.2.5和3.2.6(SNAPSHOT)可以正常开发) Spring Boot DevTools:spring项目热部署工具,修改完代码(不含application和pom配置文件)即刻热部署项目 Lombok:通过配置快速配置对象的get、set、toString Spring AI:Spring AI是一个用于AI工程的应用框架 创建完成后,项目结构大体如下(这里删除了无用的maven文件内容、修改application的文件格式为yaml)
配置项目
注意:修改pom文件,重新下载spring ai依赖需要科学上网,请确保网络连接没有问题
打开项目的pom文件,修改spring ai的版本(项目默认使用稳定版0.8.1) 主要注意默认的spring ai版本和配置依赖jar包仓库(maven仓库中还没有spring ai的依赖)
< properties> < java.version> 21</ java.version> < spring-ai.version> 0.8.1</ spring-ai.version>
</ properties> < repositories> < repository> < id> spring-snapshots</ id> < name> Spring Snapshots</ name> < url> https://repo.spring.io/snapshot</ url> < releases> < enabled> false</ enabled> </ releases> </ repository>
</ repositories>
配置application文件(api-key的获取参考Spring AI开发前期开发指导)
spring:application:name: ChatMultiModelai:openai:api-key: hk-xxx #请使用自己的api-keybase-url: https://api.openai-hk.com
server:port: 8084
接口开发
import jakarta. annotation. Resource ;
import org. springframework. ai. chat. ChatClient ;
import org. springframework. ai. chat. ChatResponse ;
import org. springframework. ai. chat. messages. Media ;
import org. springframework. ai. chat. messages. UserMessage ;
import org. springframework. ai. chat. prompt. Prompt ;
import org. springframework. ai. openai. OpenAiChatOptions ;
import org. springframework. ai. openai. api. OpenAiApi ;
import org. springframework. core. io. ClassPathResource ;
import org. springframework. http. MediaType ;
import org. springframework. util. MimeTypeUtils ;
import org. springframework. web. bind. annotation. PostMapping ;
import org. springframework. web. bind. annotation. RestController ;
import org. springframework. web. multipart. MultipartFile ; import java. io. IOException ;
import java. util. ArrayList ;
import java. util. List ;
import java. util. Objects ; @RestController
public class MultiModelController { @Resource private ChatClient chatClient; @PostMapping ( "/ai/multiChatTest" ) public Object multiChatTest ( ) throws IOException { byte [ ] imageData = new ClassPathResource ( "/multimodal.test.png" ) . getContentAsByteArray ( ) ; var userMessage = new UserMessage ( "请解释在图片中有什么?" , List . of ( new Media ( MimeTypeUtils . IMAGE_PNG , imageData) ) ) ; ChatResponse response = chatClient. call ( new Prompt ( List . of ( userMessage) , OpenAiChatOptions . builder ( ) . withModel ( OpenAiApi. ChatModel . GPT_4_VISION_PREVIEW . getValue ( ) ) . build ( ) ) ) ; return response. getResult ( ) . getOutput ( ) ; } @PostMapping ( "/ai/multiChat" ) public Object multiChat ( String msg, String imageUrl) { UserMessage userMessage = new UserMessage ( msg, List . of ( new Media ( MimeTypeUtils . IMAGE_PNG , imageUrl) ) ) ; ChatResponse response = chatClient. call ( new Prompt ( List . of ( userMessage) , OpenAiChatOptions . builder ( ) . withModel ( OpenAiApi. ChatModel . GPT_4_VISION_PREVIEW . getValue ( ) ) . build ( ) ) ) ; return response. getResult ( ) . getOutput ( ) ; } @PostMapping ( "/ai/multiChat2" ) public Object multiChatWithUploadImage ( String msg, List < MultipartFile > imageFiles) { List < Media > mediaList = new ArrayList < > ( ) ; for ( MultipartFile file : imageFiles) { try { byte [ ] imageData = file. getBytes ( ) ; MediaType mediaType = MediaType . valueOf ( Objects . requireNonNull ( file. getContentType ( ) ) ) ; mediaList. add ( new Media ( mediaType, imageData) ) ; } catch ( IOException e) { e. printStackTrace ( ) ; } } UserMessage userMessage = new UserMessage ( msg, mediaList) ; ChatResponse response = chatClient. call ( new Prompt ( List . of ( userMessage) , OpenAiChatOptions . builder ( ) . withModel ( OpenAiApi. ChatModel . GPT_4_VISION_PREVIEW . getValue ( ) ) . build ( ) ) ) ; return response. getResult ( ) . getOutput ( ) ; }
}
结果测试
测试接口测试
http://localhost:8084/ai/multiChatTest
{ "messageType" : "ASSISTANT" , "metadata" : { "finishReason" : "STOP" , "role" : "ASSISTANT" , "id" : "chatcmpl-9NbNVih5y0iFMCmC2UBJpc8D9kLms" , "messageType" : "ASSISTANT" } , "content" : "图片中是一个金属制的水果篮,篮子的设计简约但优雅,呈现出一种现代感。水果篮中放着两根黄色的香蕉和至少一个红色的苹果。香蕉的表面有斑点,显示它们成熟了,这通常意味着它们会更加甜。背景是模糊的,所以我们无法确定具体的环境,但可以猜测这可能是家庭厨房或餐厅的一角。" , "media" : [ ]
}
在线图片接口测试
{ "messageType" : "ASSISTANT" , "metadata" : { "finishReason" : "STOP" , "role" : "ASSISTANT" , "id" : "chatcmpl-9NbZyTNrExouUI9hwaEkLMQKR5mzh" , "messageType" : "ASSISTANT" } , "content" : "这张图片展示的是一台计算机的后部接口面板。从左至右,我们可以看到:\n\n- 一个PS/2接口,通常用于连接键盘或鼠标。\n- 两个蓝色的USB 3.1或更高版本接口。\n- 一个DisplayPort接口,用于连接显示器。\n- 一个HDMI接口,同样用于连接显示器。\n- 四个红色的USB 3.2 Gen2接口,提供高速数据传输能力。\n- 一个USB Type-C接口。\n- 一个以太网接口,标有\"2.5 Gbps LAN\",表示其支持最高2.5吉比特每秒的网络速度。\n- 一组音频接口,包括麦克风输入(粉色)、线出(绿色)、以及其他音频输入/输出(橙色、灰色、蓝色)。\n- 两个Wi-Fi天线连接口,用于连接无线网络。\n- 一个内置Wi-Fi模块的标识,有无线网络信号的图标。\n\n整个面板设计呈现出现代化和高性能的特点,适用于高端桌面计算机主板。" , "media" : [ ]
}
本地图片接口测试
{ "messageType" : "ASSISTANT" , "metadata" : { "finishReason" : "STOP" , "role" : "ASSISTANT" , "id" : "chatcmpl-9Nc3JZ3cVGCIlsdJrlHnJYT7O5rbu" , "messageType" : "ASSISTANT" } , "content" : "第一张图片是一幅数字艺术作品,展示了一个多边形风格的狼头图案。这幅图使用了丰富的颜色和几何形状,表现了一种现代和抽象的风格。背景是纯黑色的,突出了狼头的彩色轮廓。\n\n第二张图片显示的是一个电脑系统信息的截图,界面是中文。根据截图上的信息,这台电脑运行的是64位的Windows 10操作系统,版本为22H2,支持DirectX 12。处理器是英特尔Xeon E5-2698B v3,频率为2.00GHz,共有22个核心。内存为128GB,使用的是DDR3类型,频率为1866MHz,是32GB内存条组成的四通道配置。图形卡为NVIDIA GeForce RTX 3060,带12GB显存。主板型号是华硕X99M-PLUS D3,芯片组为Lynx Point Q87。存储方面,有一块2TB(2048GB)的固态硬盘。网络接口为Realtek RTL8168/8111/8112 Gigabit Ethernet Controller。声卡是High Definition Audio。系统版本底部提示有Win11的升级提示。" , "media" : [ ]
}