一、前言
ChatGPT从问世到现在,热度一直不减,GPT的广泛推广和使用,让AI领域变得越来越热闹,于是基于ChatGPT的核心,越来越多的公司和技术团队加入了大模型的领域。在这其中,作为技术框架语言,像主流的python,java等,为了方便开发者对ChatGPT的使用,以及后续生态的融合,也开始在框架层面引入对ChatGPT的支持,本文聊聊spring框架下对ChatGPT的支持的一个新组件spring ai的使用。
二、spring ai介绍
2.1 什么是Spring AI
spring ai官网文档地址:Prompts :: Spring AI Reference ,官网对Spring AI的定义如下:
Spring AI is an application framework for AI engineering. Its goal is to apply to the AI domain Spring ecosystem design principles such as portability and modular design and promote using POJOs as the building blocks of an application to the AI domain.
2.2 Spring AI 特点
Spring AI 是一个AI工程领域的应用程序框架,它的目标是将Spring生态系统的设计原则应用于人工智能领域,比如Spring生态系统的可移植性和模块化设计,并推广使用POJO来构建人工智能领域应用程序,但它并不是要构建一个自己的AI大模型,而是让你对接各种AI大模型,官网介绍Spring AI 具备如下特征:
- 支持所有主要的模型提供商,如OpenAI、微软、亚马逊、谷歌和Huggingface;
- 支持的模型类型有聊天和文本到图像,还有更多;
- 可移植的API跨人工智能提供商聊天和嵌入模型。同时支持同步和流API选项。还支持下拉访问特定于型号的功能;
- 人工智能模型输出到POJO的映射;
- 支持所有主要的矢量数据库提供商,如Azure矢量搜索、Chroma、Milvus、Neo4j、PostgreSQL/PGVector、PineCone、Qdrant、Redis和Weaviate;
- 跨矢量存储提供商的可移植API,包括一个新的类似SQL的元数据过滤器API,它也是可移植的;
- 支持函数调用;
- 用于AI模型和矢量存储的Spring Boot自动配置和启动器;
- 可以用于数据工程的ETL框架;
2.3 Spring AI 为开发带来的便利
Spring Framework 和AI技术的结合,将为java生态对接人工智能,大模型提供了非常大的便利,尤其是技术组件生态完善的Spring 框架来说,这更是为项目开发对接AI应用提供了基础支撑,具体来说,好处如下:
- 整合简单- Spring Framework 提供了广泛的功能和模块,结合人工智能技术可以打造完整的AI对接与解决方案。
- 简化开发- Spring Framework 的框架和工具可以大大简化开发流程,而人工智能技术可以增强应用程序的智能化水平。
- 高效性- 结合 Spring Framework 的性能优势和人工智能技术的高效处理能力,可以实现高性能的智能化应用程序。
- 灵活性- 可能在 Spring Framework 的基础上开发出灵活、可扩展的人工智能模块,以满足不同应用场景的需求。
2.4 Spring AI应用领域
从上文对Spring AI的特点介绍,不难发现,Spring AI将会在众多的领域提供有力的支撑,下面做详细说明。
2.4.1 聊天模型
Chat Models支持很多种聊天模型,基于不同的聊天模型,可以打造多场景下的聊天应用,比如当下各种聊天应用。
2.4.2 文本到图像模型
即Text-to-image Models,目前支持:
- OpenAI with DALL-E;
- StabilityAI;
文本转图像在现实中有着广泛的需求场景,用户按照自身的需求,输入特定的参数,即可生成预期的图片。目前在市场上,已经出现很多类似的大模型产品可供商用。
2.4.3 音频转文本
与上面的文本转图像类似,可将一段音频中提取出文本内容,在某些商业领域有着较多的使用。
2.4.4 嵌入大模型使用
GPT问世之后,陆陆续续出现了很多可以商用的开源大模型,比如Ollama,ONNX等,使用spring ai作为底层开发框架,利用open ai就可以对接大模型,从而打造属于企业自身的大模型应用。
2.4.5 矢量数据库支持
Vector Store API提供了跨不同提供商的可移植性,其特点是提供了一种新颖的类似SQL的元数据过滤API,以保持可移植性,目前对矢量数据库的支持包括:
- Azure Vector Search;
- Chroma;
- Milvus;
- Neo4j;
- PostgreSQL/PGVector;
- PineCone;
- Redis;
- Weaviate;
- Qdrant;
2.4.6 用于数据工程ETL框架
利用spring ai作为连接GPT的支撑,结合java自身优秀的数据处理特点,可以将其用于大数据ETL领域中,具体来说:
- ETL框架的核心功能是使用Vector Store促进文档向模型提供者的传输。ETL框架基于Java函数式编程概念,可帮助您将多个步骤链接在一起;
- 支持阅读各种格式的文档,包括PDF、JSON等;
- 该框架允许数据操作以满足您的需求。这通常包括拆分文档以遵守上下文窗口限制,并使用关键字增强它们以提高文档检索效率;
- 最后,处理后的文档存储在矢量数据库中,以便将来检索;
三、Spring AI对接ChatGPT
3.1 前置准备
在正式开始使用java对接ChatGPT之前,你需要做下面几件事,确保在后面的代码层面可以正常调用ChatGPT的相关接口。
- api-key- 调用open-ai接口必须传递的参数,api-key的获取方式很多,可以通过官网注册,或者通过中转的渠道获取;- 如果是自己注册获得的api-key,需要解决本地的魔法上网问题;- 如果是通过中转渠道获取的api-key,注意拿到中转的url,这个其实就是使用被人的代理服务器解决本地魔法上网的问题;
- jdk17环境- 如果纯粹是调用open-ai接口,不用jdk17也没问题,但是后面需要使用spring ai集成调用,建议使用jdk17。
- 提前搭建springboot工程;
3.2 添加依赖
本例使用springboot 3.2的版本,核心依赖如下
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.2.4</version>
<relativePath/>
</parent>
<properties>
<java.version>17</java.version>
<spring-ai.version>1.0.0-SNAPSHOT</spring-ai.version>
</properties>
<dependencies>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.13</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-openai-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-bom</artifactId>
<version>${spring-ai.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<!--maven中心仓库还没有更新spring ai的jar包,所以使用spring的仓库ai包-->
<repositories>
<!--快照版本的仓库-->
<repository>
<id>spring-snapshot</id>
<name>Spring Snapshots</name>
<url>https://repo.spring.io/snapshot</url>
<releases>
<enabled>false</enabled>
</releases>
</repository>
</repositories>
这里重点补充一下,由于目前maven中央仓库还没有spring ai的包,所以需要从spring官方提供的仓库里下载,所以在pom中需要配置官网提供的仓库地址
3.3 接入流程
3.3.1 配置文件
在配置文件中主要配置你的apkey,和base-url信息
server:
port: 8088
spring:
application:
name: chat-001
ai:
openai:
api-key: 你的apikey
base-url: 默认的是openai的地址
3.3.2 增加一个测试接口
编写一个测试接口,使用OpenAiChatClient这个聊天对象api进行调用
import org.springframework.ai.openai.OpenAiChatClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class ChatController {
@Autowired
private OpenAiChatClient openAiChatClient;
//http://localhost:8088/chat?message=介绍下上海这个城市
@GetMapping("/chat")
public Object chat(@RequestParam("message") String message){
String result = openAiChatClient.call(message);
return result;
}
}
3.3.3 接口测试
启动工程之后,调用一下接口,可以看到下面的效果
3.4 OpenAiChatClient 使用
上面通过一个简单的案例介绍了spring ai如何快速调用gpt的接口,在OpenAiChatClient这个对象中,还提供了很多种方式调用call的方法,从而返回响应结果,如下:
下面来分别聊聊几种不同API的用法
3.4.1 call使用Prompt传递参数方式1
传递一个字符串参数,使用call调用方法的时候,也可以传递一个Prompt的对象,返回的是一个ChatResponse对象,如下:
//http://localhost:8088/chat/pro?message=介绍下上海这个城市
@GetMapping("/chat/pro")
public Object chatCallPrompt(@RequestParam("message") String message){
ChatResponse call = openAiChatClient.call(new Prompt(message));
return call;
}
调用一下该接口,看到如下的响应结果,此时返回的是一个json对象,也可以使用ChatResponse 获取单纯的文本结果
3.4.2 call使用Prompt传递参数2
从Prompt的对象参数中不难发现,支持传递的构造对象方式有很多,上面是传递一个简单的字符串作为参数,也可以使用其他的方式
在官网的api文档中有详细的介绍:OpenAI Chat :: Spring AI Reference
看下面的写法,通过这种方式,可以更好的控制gpt接口返回的响应结果的质量,当然,Prompt里面可以传递的参数还有很多,可以结合官网的解释进一步理解
//http://localhost:8088/chat/v2?message=介绍下上海这个城市
@GetMapping("/chat/v2")
public Object chatCallPromptV2(@RequestParam("message") String message){
Prompt prompt = new Prompt(
message,
OpenAiChatOptions.builder()
.withModel("gpt-4-32k") //32k 参数量,参数量越大,越准确
.withTemperature(0.4f) //温度值,温度值越高,准确率下降,但是创新性好
.build()
);
return openAiChatClient.call(prompt);
}
补充说明
Prompt对象中的参数,也可以通过配置文件的形式进行配置,如果配置文件和代码中同时配置了,以代码中的生效
3.5 OpenAiImageClient使用
OpenAiImageClient是spring ai中提供的用于生成图片的核心对象,借助这个对象,可以传递相关的参数和描述,生成符合要求的图片,下面看一个具体的案例,如下,提供一个生成图片的接口:
import org.springframework.ai.image.ImagePrompt;
import org.springframework.ai.image.ImageResponse;
import org.springframework.ai.openai.OpenAiImageClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class ImageChatController {
@Autowired
private OpenAiImageClient openAiImageClient;
//http://localhost:8088/image/generate?message=生成一张猫的图片
@GetMapping("/image/generate")
public Object chat(@RequestParam("message") String message){
ImagePrompt imagePrompt = new ImagePrompt(message);
ImageResponse imageResponse = openAiImageClient.call(imagePrompt);
return imageResponse.getResult().getOutput();
}
}
在这段代码中,通过传递一个message参数,从而构造出一个ImagePrompt的对象,最后调用openAiImageClient的call方法生成图片,调用接口,看的如下返回结果
然后将返回结果中的url输入到浏览器,就能看到一张猫的图片
注意点:
调用生成图片的接口,你的apikey需要使用GPT4.0的模型,3.5的会报错,不支持生成图片
3.5.1 其他参数传递使用情况
在ImagePrompt对象的参数中,除了传递一个message之外,从下面的参数展示中,还可以传递其他类型的参数
在spring ai官方文档中,关于ImagePrompt对象的构造参数中,提供了如下的示例,即可以通过OpenAiImageOptions构造出第二个参数,一起传给ImagePrompt进行使用
下面看具体的接口示例
//http://localhost:8088/image/generate/v2?message=生成一只狗的图片
@GetMapping("/image/generate/v2")
public Object genImageV2(@RequestParam("message") String message){
ImagePrompt imagePrompt = new ImagePrompt(message, OpenAiImageOptions.builder()
.withQuality("hd") //高清图像
.withN(1) //生成1张图片,不同的模型可以生成的数量不一样
.withHeight(1024)
.withWidth(1024).build());
ImageResponse imageResponse = openAiImageClient.call(imagePrompt);
return imageResponse.getResult().getOutput();
}
每个参数的具体含义,在官网的文档中也有详细的说说明,需要注意的是,这些参数也可以在工程的配置文件中进行配置,如果配置文件和代码中都设置了,以代码中的设置为准;
调用接口,看的如下返回信息
浏览器中输入这段url,可以看的正好是一张小狗的图片
3.6 OpenAiAudioTranscriptionClient 使用
即音频转文本的API对象,音频转文本的场景在日常生活中也比较常见,在GPT问世之前,也有一些厂商提供相关的商用软件,spring ai 官方的示例代码:spring-ai/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/audio/transcription/OpenAiTranscriptionClientWithTranscriptionResponseMetadataTests.java at main · spring-projects/spring-ai · GitHub
看下面的示例代码,需要提前在本地目录下提供一个音频文件;
@RestController
public class TranslateController {
@Autowired
private OpenAiAudioTranscriptionClient openAiAudioTranscriptionClient;
//http://localhost:8088/audio/translate/text
@GetMapping("/audio/translate/text")
public Object audioTranslateText(){
Resource resource = new FileSystemResource("D:\\cat.mp3");
String call = openAiAudioTranscriptionClient.call(resource);
return call;
}
}
3.7 OpenAiAudioSpeechClient使用
文本转语音的API对象,即将一段文本转为语音,参考如下代码
@Autowired
private OpenAiAudioSpeechClient openAiAudioSpeechClient;
//http://localhost:8088/text/translate/audio?msg=春天悄然而至,绿意盎然的枝头绽放出无尽的生命力,仿佛是大自然的调色板,绘出一幅幅美妙的画卷。
@GetMapping("/text/translate/audio")
public Object textToAudio(@RequestParam String msg) throws Exception{
byte[] call = openAiAudioSpeechClient.call(msg);
FileOutputStream fos = new FileOutputStream("D:\\output.mp3");
fos.write(call);
System.out.println("字节数组写入文件成功!");
return "success";
}
执行完成后,本地将会生成一个音频文件
四、Spring AI对接Ollama
4.1 Ollama介绍
Ollama是一个用于部署和运行各种开源大模型的工具,能够帮助用户快速在本地运行各种大模型,极大地简化了大模型在本地运行的过程。对用户来说,只需要通过执行几条命令就能在本地运行开源大模型,如Llama 2等。
官网:Ollama
4.2 Ollama本地部署
进入网站之后,点击右上角的 Download按钮,根据个人的实际情况,选择不同类型的安装包进行部署,我这里选择的是Windows的版本;
注意
Ollama部署的时候,对服务器或机器是有一定要求的,所以需要根据你的机器配置情况进行选择,在Ollama的官网通过github的链接点进去,可以看到如下的相关参数指导说明,在这里,你部署的大模型参数越多,理论上来说,对机器的配置要求就越高,目前先关注这一点即可。
4.2.1 下载安装包
这里选择下载的是windows版本
4.2.2 执行安装
Ollama的安装比较简单,双击执行这个exe文件,等待安装完成即可
安装完成之后,点击开始进入下面的shell窗口
Ollama常用命令
cmd窗口输入Ollama,即可了解常用的Ollama命令
如何理解本机部署的这个Ollama呢?如果使用过Docker的同学对docker部署一些中间件应该不陌生,比如使用docker中部署mysql或redis,只需要运行一段docker命令即可完成,非常方便,类比于Ollama,是一个大模型的部署管理工具,只需要使用Ollama的命令,也可以快速部署起一个本地的大模型进行使用。
如果你需要使用Ollama部署大模型,可以在Ollama官网进行搜索,类似于你使用docker search 镜像名一样
如下,进入到某个大模型中,拷贝命令到shell窗口中执行即可
4.2.3 Ollama部署千问大模型
“通义千问大模型”是阿里云推出的一个超大规模的语言模型,具有强大的归纳和理解能力,可以处理各种自然语言处理任务,包括但不限于文本分类、文本生成、情感分析等。此模型能够极大地提高了自然语言处理的效率和准确性,给用户提供了一种新的、简便的工具。
在Ollama中搜索关键字qwen,然后选择一个参数相对较少(对本地的空间和资源占用减小)的进行运行
使用下面的命令运行
ollama run qwen:0.5b-chat
然后等待模型下载完成运行起来之后就可以使用了,下面这个进度窗口是不是与docker部署中间件很相像
然后就可以输入文本,与大千问模型进行对话,而后,就可以基于部署的模型应用于实际工作或业务中进行结合使用
4.2.4 补充说明
大模型参数数量与资源消耗具有如下关系:
- 大模型参数越多 - 模型的尺寸就越大;- 模型的输出结果越准确;- 允许所需要的资源成本越高;
- 本地开发不适合使用尺寸较大的模型;
- 折中的方案 - 开发时在本地运行参数较少的模型;- 集成测试时使用外部服务
4.3 Spring Ai接入Ollama
接下来演示如何在springboot项目中集成Ollama,参考下面的操作步骤
4.3.1 引入Ollama依赖
基于上述的spring ai版本,添加下面的依赖
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-ollama-spring-boot-starter</artifactId>
</dependency>
4.3.2 添加配置文件
配置文件中添加Ollama相关的配置信息,注意的是,Ollama默认端口为11434
server:
port: 8088
spring:
application:
name: chat-001
ai:
ollama:
base-url: http://localhost:11434
chat:
options:
model: qwen:0.5b-chat
openai:
api-key: 你的apikey
base-url: openai地址
4.3.3 使用Ollama聊天api
Ollama聊天API的核心对象为OllamaChatClient,与上述的spring ai中提供的client对象类似,在程序中可以直接调用其api,如下,传入一个msg参数,返回响应的文本内容
import jakarta.annotation.Resource;
import org.springframework.ai.ollama.OllamaChatClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class OllamaChatController {
@Resource
private OllamaChatClient ollamaChatClient;
//http://localhost:8088/ollama/chat?msg=大数据的技术栈有哪些
@GetMapping("/ollama/chat")
public String ollamaChat(@RequestParam String msg){
String resMsg = ollamaChatClient.call(msg);
return resMsg;
}
}
启动服务,调用一下接口,可以看到响应的内容,通过这种方式,相当于是利用spring ai接入了本地的大模型进行对话聊天
也可以使用Prompt进行参数传递,看下面的接口
@GetMapping("/ollama/chat/v2")
public Object ollamaChatV2(@RequestParam String msg){
Prompt prompt = new Prompt(msg);
ChatResponse chatResponse = ollamaChatClient.call(prompt);
return chatResponse;
}
返回结果如下,返回这种结构的数据在实际使用的时候,需要对json中的字段进行解析即可
spring ai官网中也提供了Ollama的相关文档,地址:Ollama Chat :: Spring AI Reference,在文档中,可以找到很多有关Ollama的详细的配置参数,这些配置参数,都可以在Prompt对象或者配置文件中进行合理的使用,达到最佳的实践效果
比如,在下面的接口中,仍然使用Prompt对象,里面传入更多的参数选项做控制
//http://localhost:8088/ollama/chat/v3?msg=中国排名前十的大学
@GetMapping("/ollama/chat/v3")
public Object ollamaChatV3(@RequestParam String msg){
Prompt prompt = new Prompt(
msg,
OllamaOptions.create()
.withModel("qwen:0.5b-chat")
.withTemperature(0.4F)
);
ChatResponse chatResponse = ollamaChatClient.call(prompt);
return chatResponse.getResult().getOutput().getContent();
}
再次调用一下接口,当然这个结果是否一定准确呢?对于结果的使用还需要做认真的鉴别
五、写在文末
本文详细介绍了spring ai的使用,并通过案例详细介绍了spring ai中常用的api使用方法,最后通过本地安装安装Ollama并部署大模型接入通义千问,希望对看到的同学有用,本篇到此结束感谢观看。
版权归原作者 小码农叔叔 所有, 如有侵权,请联系我们删除。