Spring AI 简介
在当今快速发展的技术时代,人工智能 (AI) 已成为各行各业标配。作为主流 Java 应用开发框架,Spring 社区推出了 Spring AI 框架。
1. Spring AI 是什么
1.1 官网描述
官网地址:https://spring.io/projects/spring-ai

具体来说:
- Spring AI 是一个 AI 工程领域的应用程序框架;
- 其目标是将 Spring 生态系统设计原则(如可移植性和模块化设计)应用于 AI 领域,并促进使用 POJO 作为应用程序的构建块;
- 核心是提供了开发 AI 大模型应用所需的基本抽象模型,使得开发者可以用很少的代码改动实现组件的轻松替换;
- 简言之,Spring AI 是一个 AI 工程师的应用框架,提供了一个友好的 API 和开发 AI 应用的抽象,旨在简化 AI 大模型应用的开发工作。
1.2 发布版本

目前 Spring AI 推出了预览版 (PRE)、快照版 (SNAPSHOT) 以及正式版 (GA),推荐使用 GA 版本(主要是稳定)。
2. Spring AI 的主要功能
- 对主流 AI 大模型供应商提供了支持,比如:OpenAI、DeepSeek、Microsoft、Ollama、Amazon、Google HuggingFace 等。
- 支持 AI 大模型类型包括:聊天、文本到图像、文本到声音等。
- 支持主流的 Embedding Models 和向量数据库,比如:Azure Vector Search、Chroma、Milvus、Neo4j、Redis、PineCone、PostgreSQL/PGVector 等。
- 把 AI 大模型输出映射到简单的 Java 对象(POJOs)上。
- 支持了函数调用 (Function Calling) 功能。
- 为数据工程提供 ETL(数据抽取、转换和加载)框架。
- 支持 Spring Boot 自动配置和快速启动。
3. Spring AI 快速入门
3.1 准备工作
3.1.1 什么是 DeepSeek?
DeepSeek 是一款由深度求索所开发的 AI 人工智能大模型,基于深度学习和多模态数据融合技术,采用先进的 Transformer 架构。在中文理解与输出能力上表现出色,API 定价具有竞争力。
3.1.2 DeepSeek 开放平台创建 API KEY
进入 DeepSeek 官网 https://www.deepseek.com/,点击右上角的 API 开放平台,注册登录用户后创建 API key。
Spring AI 的 openai starter 本质上是通过 RestTemplate 发请求。
3.2 创建 SpringBoot 工程
在 IDEA 中创建一个 SpringBoot 项目,注意 Spring AI 对于 SpringBoot 和 JDK 的版本要求如下:JDK 17+,Spring Boot 3.x。
3.2.1 引入依赖
在父模块 pom.xml 中添加如下公共依赖:
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<spring-ai.version>1.0.0-M5</spring-ai.version>
</properties>
<dependencies>
<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-starter-test</artifactId>
<scope>test</scope>
</dependency>
org.projectlombok
lombok
1.18.30
org.springframework.ai
spring-ai-bom
${spring-ai.version}
pom
import
3.2.2 创建配置文件
在子模块的配置文件 application.properties 中添加如下配置内容:
server.port=8899
spring.application.name=spring-ai-deepseek-demo
# DeepSeek 的 Api key
spring.ai.openai.api-key=sk-****************
spring.ai.openai.base-url=https://api.deepseek.com
spring.ai.openai.chat.options.model=deepseek-chat
spring.ai.openai.chat.options.temperature=0.7
其中,temperature 参数用于控制生成文本的多样性。值越高生成的文本越多样化,值越低生成的文本越接近确定性结果。
3.2.3 创建启动类
@SpringBootApplication
public class SpringAiHelloApplication {
public static void main(String[] args) {
SpringApplication.run(SpringAiHelloApplication.class, args);
}
}
3.2.4 创建 Controller
package com.atguigu.ai.controller;
import jakarta.annotation.Resource;
import org.springframework.ai.openai.OpenAiChatModel;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class ChatDeepSeekController {
@Resource
private OpenAiChatModel chatModel;
@GetMapping("/ai/generate")
public String generate(@RequestParam(value = "message", defaultValue = "hello") String message) {
String response = this.chatModel.call(message);
System.out.println("response: " + response);
return response;
}
}
3.2.5 测试
进行接口测试,输入 localhost:8899/ai/generate?message=尚硅谷,等待片刻,即可出现响应结果。
4. Spring AI 的聊天模型
4.1 概述
Spring AI 的聊天模型 API 为开发者提供了一条便捷通道,能够将强大的 AI 驱动的聊天完成功能无缝集成到各类应用中。借助预先训练的语言模型,它能够依据用户输入生成自然流畅、类人化的回复。
4.2 ChatClient 接口
ChatClient 是一个接口,它定义了一个与聊天服务交互的客户端。
在下面的示例执行之前,创建一个名为 springai_chat 的子模块,并将上面的 application.properties 配置文件拷贝一份,并修改端口号为 8890。
4.2.1 实现简单的对话
需求
用户输入设置用户消息的内容,通过 SpringBoot AI 封装的方法向 AI 模型发送请求,以字符串形式返回 AI 模型的响应。
编写 Controller 方法
package com.atguigu.ai.controller;
import org.springframework.ai.chat.client.ChatClient;
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 {
private final ChatClient chatClient;
public ChatController(ChatClient.Builder chatClientBuilder) {
this.chatClient = chatClientBuilder.build();
}
@GetMapping("/chat")
public String chat(@RequestParam(value = "message", defaultValue = "你是谁") String message) {
return this.chatClient.prompt()
.user(message)
.call()
.content();
}
}
测试
进行接口测试,输入 localhost:8890/chat?message=给我讲个笑话,等待片刻,即可出现结果。
总结
ChatClient 接口提供了构建和配置聊天客户端对象的灵活性,以及发起和处理聊天请求的能力。
4.2.2 实现角色预设
配置默认角色
package com.atguigu.ai.config;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class AIConfig {
@Bean
public ChatClient chatClient(ChatClient.Builder builder) {
return builder.defaultSystem("你是一名 Java 开发专家,精通 Java 开发,你的名字叫 AI 助手。").build();
}
}
编写 Controller
package com.atguigu.ai.controller;
import jakarta.annotation.Resource;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/ai")
public class ChatAIController {
@Resource
private ChatClient chatClient;
@GetMapping("/chat")
public String chat(@RequestParam(value = "message") String message) {
return chatClient.prompt().user(message).call().content();
}
}
测试
进行接口测试,输入 localhost:8890/ai/chat?message=你是谁,等待片刻,即可出现结果。
4.2.3 实现流式响应
call 和 stream 的区别
- 非流式输出 call:等待大模型把回答结果全部生成后输出给用户;
- 流式输出 stream:逐个字符输出,符合大模型生成方式的本质,提高用户体验。
编写 Controller
@GetMapping(value = "/chat/stream", produces = "text/html;charset=UTF-8")
public Flux<String> chatStream(@RequestParam(value = "message") String message) {
return chatClient.prompt().user(message).stream().content();
}
测试
在浏览器中输入 http://localhost:8890/ai/chat/stream?message=你是谁,响应结果会以流式输出的方式展示。
4.3 ChatModel 接口
4.3.1 概述
ChatModel 接口作为核心,定义了与 AI 模型交互的基本方法。它继承自 Model<Prompt, ChatResponse>,提供了两个重载的 call 方法。
4.3.2 实现简单对话
package com.atguigu.ai.controller;
import jakarta.annotation.Resource;
import org.springframework.ai.chat.model.ChatModel;
import org.springframework.ai.chat.model.ChatResponse;
import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.ai.openai.OpenAiChatOptions;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/model")
public class ChatModelController {
@Resource
private ChatModel chatModel;
@GetMapping("/chatModel01")
public String chatModel01(@RequestParam("message") String message) {
return chatModel.call(message);
}
@GetMapping("/chatModel02")
public String chatModel02(@RequestParam("message") String message) {
ChatResponse call = chatModel.call(new Prompt(
message,
OpenAiChatOptions.builder()
.model("deepseek-chat")
.temperature(0.8)
.build()));
return call.getResult().getOutput().getContent();
}
}
4.3.3 提示词
- 提示词是引导大模型生成特定输出的输入,设计和措辞会极大地影响模型的响应结果;
- Prompt 提示词是与模型交互的一种输入数据组织方式,本质上是一种复合结构的输入,在 prompt 我们是可以包含多组不同角色(System、User、Assistant 等)的信息;
- Spring AI 提供了 Prompt Template 提示词模板管理抽象,开发者可以预先定义好模板,并在运行时替换模板中的关键词。
@GetMapping("/prompt")
public String prompt(@RequestParam("name") String name, @RequestParam("voice") String voice) {
String userText = "给我推荐北京的至少三种美食";
UserMessage userMessage = new UserMessage(userText);
String systemText = "你是一个美食咨询助手,可以帮助人们查询美食信息。你的名字是{name},你应该用你的名字和{voice}的饮食习惯回复用户的请求。";
SystemPromptTemplate systemPromptTemplate = new SystemPromptTemplate(systemText);
Message systemMessage = systemPromptTemplate.createMessage(Map.of("name", name, "voice", voice));
Prompt prompt = new Prompt(List.of(userMessage, systemMessage));
List<Generation> results = chatModel.call(prompt).getResults();
return results.stream().map(x -> x.getOutput().getContent()).collect(Collectors.joining(""));
}
在接口测试工具中输入 localhost:8890/model/prompt?name=张三&voice=便宜,响应结果如下。
5. Spring AI 的函数调用
5.1 概述
Spring AI 的函数调用 (Function Calling) 功能允许大语言模型在生成回答时触发预定义的外部函数,从而实现动态数据获取或业务逻辑操作(如查询数据库、调用 API 等)。
函数调用的核心流程如下:
- 定义函数:声明可供模型调用的函数(名称、描述、参数结构)。
- 模型交互:将函数信息与用户输入一起发送给模型,模型决定是否需要调用函数。
- 执行函数:解析模型的函数调用请求,执行对应的业务逻辑。
- 返回结果:将函数执行结果返回给模型,生成最终回答。
5.2 函数调用实现
在下面的示例执行之前,创建一个名为 springai_function 的子模块,并将上面的 application.properties 配置文件拷贝一份,并修改端口号为 8891。
5.2.1 创建自定义的 Function
下面 CalculatorService 类自定义了加法和乘法运算的函数。
package com.atguigu.config;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Description;
import java.util.function.Function;
@Slf4j
@Configuration
public class CalculatorService {
public record AddOperation(int a, int b) {}
public record MulOperation(int m, int n) {}
@Bean
@Description("加法运算")
public Function<AddOperation, Integer> addOperation() {
return request -> {
log.info("执行加法运算:{} + {} = {}", request.a, request.b, request.a + request.b);
return request.a + request.b;
};
}
@Bean
@Description("乘法运算")
public Function<MulOperation, Integer> mulOperation() {
return request -> {
log.info("执行乘法运算:{} * {} = {}", request.m, request.n, request.m * request.n);
return request.m * request.n;
};
}
}
5.2.2 编写 Controller
package com.atguigu.controller;
import jakarta.annotation.Resource;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.model.ChatModel;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class FunctionController {
@Resource
private ChatModel chatModel;
@GetMapping(value = "/function", produces = MediaType.APPLICATION_STREAM_JSON_VALUE)
public String ragJsonText(@RequestParam(value = "message") String message) {
return ChatClient.builder(chatModel).build()
.prompt()
.system("""
您是算术计算器的代理。您能够支持加法运算、乘法运算等操作。
当用户询问数学计算时,您必须调用相应的函数来处理。
支持的函数:
- addOperation: 加法运算,需要两个数字参数
- mulOperation: 乘法运算,需要两个数字参数
调用函数的条件:
1. 用户明确要求计算
2. 问题涉及加法或乘法
3. 能够从问题中提取出两个数字
请用中文回复,并在适当的时候调用函数。
""")
.user(message)
.functions("addOperation", "mulOperation")
.call()
.content();
}
}
为了让模型知道并调用你的自定义函数,需要在 Prompt 请求中启用它,如上述代码,在 functions("addOperation", "mulOperation") 中告知 ChatClient 要使用这两个自定义函数。
5.2.3 测试
在接口测试工具中输入 localhost:8891/function/message=2 加 3 等于多少,响应结果如下。如果想要测试大模型是否真的调用了自定义的函数,可以查看日志来判断。
6. Spring AI 调用 Ollama
6.1 下载并安装 Ollama
Ollama 是一个用于本地化部署和管理大型语言模型 (LLM) 的工具。它支持多种开源模型(如 LLaMA、Alpaca 等),并提供了简单的 API 接口。
Ollama 官网地址:https://ollama.com
6.1.1 下载 Ollama

6.1.2 安装 Ollama
安装完成之后,在 Windows 电脑中搜索系统环境变量并点击,选择新建一个系统环境变量 OLLAMA_MODELS,然后指定想要安装模型的路径,比如 "D:\Deepseek"。
重启电脑使 Ollama 生效。
6.1.3 拉取 DeepSeek 模型
硬件配置建议:
- GPU 选择:入门配置 NVIDIA 显卡(≥8GB 显存)→ 适合 7B/8B 模型。
- 内存要求:≥16GB(推荐 32GB)
- 存储空间:≥50GB 可用空间
选择适合自己的版本:https://ollama.com/library/deepseek-r1
以 Windows 为例,根据不同版本,执行不同的命令拉取模型。比如,下载 1.5b,执行下面命令:
ollama pull deepseek-r1:1.5b
6.1.4 启动 Ollama 服务测试
启动 Ollama 服务,默认会监听 http://localhost:11434。
ollama run deepseek-r1:1.5b
6.2 Spring AI 代码测试
6.2.1 创建子模块 springai_ollama
创建子模块 springai_ollama 后,在该子模块的 pom.xml 中添加如下依赖:
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<spring-ai.version>1.0.0-M5</spring-ai.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-ollama-spring-boot-starter</artifactId>
</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>
spring-milestones
Spring Milestones
https://repo.spring.io/milestone
false
spring-snapshots
Spring Snapshots
https://repo.spring.io/snapshot
false
6.2.2 创建配置文件
在 springai_ollama 的配置文件 application.properties 中添加如下配置内容:
server.port=8892
spring.application.name=spring-ai-deepseek-demo
spring.ai.ollama.base-url=http://localhost:11434
spring.ai.ollama.chat.options.model=deepseek-r1:1.5b
spring.ai.ollama.chat.options.temperature=0.7
6.2.3 创建启动类
@SpringBootApplication
public class SpringAiOllamaApplication {
public static void main(String[] args) {
SpringApplication.run(SpringAiOllamaApplication.class, args);
}
}
6.2.4 创建 Controller
package com.atguigu.ai.ollama.controller;
import jakarta.annotation.Resource;
import org.springframework.ai.ollama.OllamaChatModel;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/ollama")
public class SpringAiOllamaController {
@Resource
private OllamaChatModel ollamaChatModel;
@GetMapping("/test")
public String generate(@RequestParam(value = "message", defaultValue = "hello") String message) {
String response = this.ollamaChatModel.call(message);
System.out.println("response: " + response);
return response;
}
}
7. Spring AI Alibaba
7.1 概述
随着生成式 AI 的快速发展,涌现出了包括 LangChain、LlamaIndex 等开发框架,但大部分框架只提供了 Python 语言的实现。因此,我们基于 Spring AI 发布并快速演进 Spring AI Alibaba,是阿里云通义系列模型及服务在 Java AI 应用开发领域的最佳实践。
Spring AI Alibaba 已完整提供 Model、Prompt、RAG、Tools 等 AI 应用开发所需的必备能力。
7.2 快速入门
7.2.1 申请阿里云 API Key
访问阿里云百炼页面并登录账号:https://www.aliyun.com/product/bailian,开通'百炼大模型推理'服务,获取 API Key。
点击【密钥管理】,创建 API-KEY 即可。
7.2.2 引入依赖
创建一个名为 springai_alibaba 的子模块,引入如下依赖:
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<spring-ai.version>1.0.0-M5</spring-ai.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.alibaba.cloud.ai</groupId>
<artifactId>spring-ai-alibaba-starter</artifactId>
<version>1.0.0-M5.1
spring-milestones
Spring Milestones
https://repo.spring.io/milestone
false
7.2.3 创建配置文件
创建配置文件 application.properties:
server.port=8893
spring.application.name=spring-ai-deepseek-demo
spring.ai.dashscope.api-key=sk-*****cf
# 排除父模块中 Spring AI 的自动配置,否则当前子模块启动时会提示冲突
spring.autoconfigure.exclude=org.springframework.ai.autoconfigure.openai.OpenAiAutoConfiguration
7.2.4 编写 Controller
package com.atguigu.controller;
import com.alibaba.cloud.ai.dashscope.chat.DashScopeChatOptions;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.MessageChatMemoryAdvisor;
import org.springframework.ai.chat.client.advisor.SimpleLoggerAdvisor;
import org.springframework.ai.chat.memory.InMemoryChatMemory;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class SpringAiAlibabaController {
private static final String DEFAULT_PROMPT = "你是一个博学的智能聊天助手,请根据用户提问回答!";
private ChatClient dashScopeChatClient;
public SpringAiAlibabaController(ChatClient.Builder chatClientBuilder) {
this.dashScopeChatClient = chatClientBuilder
.defaultSystem(DEFAULT_PROMPT)
.defaultAdvisors(new MessageChatMemoryAdvisor(new InMemoryChatMemory()))
.defaultAdvisors(new SimpleLoggerAdvisor())
.defaultOptions(DashScopeChatOptions.builder().withTopP(0.7).build())
.build();
}
@GetMapping("/simple/chat")
public String simpleChat(@RequestParam("query") String query) {
dashScopeChatClient.prompt(query).call().content();
}
}
7.2.5 测试
在接口测试工具中输入 localhost:8893/simple/chat?query=你是谁?,响应结果如下。
8. Spring AI 的其他模型
8.1 图像模型
8.1.1 Image Model API 概述
在 Spring AI 框架中,Image Model API 旨在为与专注于图像生成的各种 AI 模型进行交互提供一个简单且可移植的接口。
8.1.2 Image Model API 接口及相关类
- ImageModel(图像模型):
@FunctionalInterface public interface ImageModel extends Model<ImagePrompt, ImageResponse>
- ImagePrompt(图像提示):封装了 ImageMessage 对象列表及可选模型请求选项。
- ImageMessage(图像消息):封装了用于影响生成图像的文本及其权重。
- ImageOptions(图像选项):表示可以传递给图像生成模型的选项。
- ImageResponse(图像响应):持有 AI 模型的输出。
- ImageGeneration(图像生成):代表输出响应及有关此结果的元数据。
8.1.3 Spring AI 实现生成图像
下面的示例使用 Spring Ai Alibaba 开源框架,spring-ai-alibaba-starter AutoConfiguration 默认初始化了 ImageModel 实例。
package com.atguigu.controller;
import com.alibaba.cloud.ai.dashscope.api.DashScopeImageApi;
import com.alibaba.cloud.ai.dashscope.image.DashScopeImageModel;
import com.alibaba.cloud.ai.dashscope.image.DashScopeImageOptions;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.ai.image.ImagePrompt;
import org.springframework.ai.image.ImageResponse;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.io.InputStream;
import java.net.URI;
import java.net.URL;
@RestController
public class ImageModelController {
@Resource
private DashScopeImageModel imageModel;
@GetMapping("/generate-image")
public void getImage(@RequestParam(value = "msg", defaultValue = "生成一直小猫") String msg, HttpServletResponse res) {
ImageResponse response = imageModel.call(new ImagePrompt(
msg,
DashScopeImageOptions.builder()
.withModel(DashScopeImageApi.DEFAULT_IMAGE_MODEL)
.withN(1)
.withHeight(1024)
.withWidth(1024)
.build()));
String imageUrl response.getResult().getOutput().getUrl();
{
URI.create(imageUrl).toURL();
url.openStream();
res.setHeader(, MediaType.IMAGE_PNG_VALUE);
res.getOutputStream().write(in.readAllBytes());
res.getOutputStream().flush();
} (Exception e) {
System.err.println(e.getMessage());
}
}
}
在接口测试工具中输入 localhost:8894/generate-image?msg=生成一直小猫,响应结果如下。
上述示例在新建的子模块 springai_other 中,配置与 6.2 中的类似,只是端口号变为 8894。
8.2 语音模型
8.2.1 Text-to-Speech API 概述
在 Spring AI 框架中,Text-to-Speech API 提供了一个基于 OpenAI 的 TTS(Text-To-Speech,文本转语音)模型的语音端点。
8.2.2 Spring AI 实现文本转语音
本示例基于 Spring AI Alibaba 框架。
package com.atguigu.controller;
import com.alibaba.cloud.ai.dashscope.audio.DashScopeSpeechSynthesisModel;
import com.alibaba.cloud.ai.dashscope.audio.DashScopeSpeechSynthesisOptions;
import com.alibaba.cloud.ai.dashscope.audio.synthesis.SpeechSynthesisPrompt;
import com.alibaba.cloud.ai.dashscope.audio.synthesis.SpeechSynthesisResponse;
import jakarta.annotation.Resource;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
@RestController
public class AudioModelController {
@Resource
private DashScopeSpeechSynthesisModel speechSynthesisModel;
private static final String TEXT = "床前明月光,疑是地上霜。举头望明月,低头思故乡。";
private static final String FILE_PATH = "E:\\testData\\tts";
@GetMapping("/tts")
public void tts() throws IOException {
DashScopeSpeechSynthesisOptions options = DashScopeSpeechSynthesisOptions.builder()
.withSpeed(1.0)
.withPitch()
.withVolume()
.build();
speechSynthesisModel.call( (TEXT, options));
(FILE_PATH + );
( (file)) {
response.getResult().getOutput().getAudio();
fos.write(byteBuffer.array());
} (IOException e) {
(e.getMessage());
}
}
}
在接口测试工具中输入 localhost:8894/tts,在 E:\testData\tts 目录下则会生成一条音频。
9. Spring AI 实现 RAG
9.1 概述
9.1.1 向量化
向量数据库 (Vector Database) 是一种以数学向量的形式存储数据集合的数据库,通过一个数字列表来表示维度空间中的一个位置。
嵌入模型 (Embedding Model) 和向量数据库是一对亲密无间的合作伙伴,也是 AI 技术栈中紧密关联的两大核心组件。
9.1.2 RAG
RAG 的基本概念
RAG 的全称是 Retrieval-Augmented Generation,中文叫做检索增强生成。RAG 是一种结合了检索系统和生成模型的新型技术框架。
通过使用 RAG,解决了传统 LLM(Large Language Model,大语言模型)存在的两个主要问题:
- 知识局限性:LLM 的知识被固定在训练数据中,无法知道最新消息。
- 幻觉现象:LLM 有时候会编造出并不存在的答案。
RAG 的使用场景
- 企业内部知识问答:员工需要查询公司规章制度、流程文档、技术手册。
- 金融/法律领域应用:解答合规、财税、法律问题,要求答案严谨。
- 电商/客服智能助理:自动回答用户关于商品、物流、售后等问题。
- 医疗健康领域:为患者或医生提供疾病知识、药物信息、医院信息、诊疗方案。
RAG 工作流程概述
- 用户输入问题:用户在输入窗口输入自己的问题。
- 问题向量化:根据用户初始输入的问题,调用 Embedding 模型,将问题转换为高维向量。
- 向量数据库检索:系统会连接到一个向量数据库,然后用刚才生成的问题向量,检索知识库中与之最相似的文档片段。
- 构建上下文:这一阶段需要组织提示词 (Prompt),让 LLM 更好地理解背景信息。
- 调用 LLM:将构造好的 Prompt 提交给 LLM。
- 返回最终回答给用户:最终系统将生成的回答返回前端,展示给用户。
9.2 Spring AI 实现基本 RAG 流程
9.2.1 创建子模块
先创建子模块 springai_rag,依赖和配置文件与 springai_alibaba 中的一样,只不过端口号改为 8895。
9.2.2 创建配置类
package com.atguigu.ai.rag.config;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.document.Document;
import org.springframework.ai.embedding.EmbeddingModel;
import org.springframework.ai.vectorstore.SimpleVectorStore;
import org.springframework.ai.vectorstore.VectorStore;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.List;
@Configuration
public class RagConfig {
@Bean
ChatClient chatClient(ChatClient.Builder builder) {
return builder.defaultSystem("你将作为一名 Java 开发语言的专家,对于用户的使用需求作出解答").build();
}
@Bean
VectorStore vectorStore(@Qualifier("dashscopeEmbeddingModel") EmbeddingModel embeddingModel) {
SimpleVectorStore simpleVectorStore = SimpleVectorStore.builder(embeddingModel).build();
List<Document> documents = List.of(new Document("产品说明:名称:Java 开发语言\n" +
"产品描述:Java 是一种面向对象开发语言。\n" +
"特性:\n" +
"1. 封装\n" +
"2. 继承\n" +
"3. 多态\n"));
simpleVectorStore.add(documents);
return simpleVectorStore;
}
}
通过这个配置类,完成以下内容:
- 配置 ChatClient 作为 Bean,其中设置系统默认角色为 Java 开发语言专家。
- 初始化 SimpleVectorStore,加载 Java 开发语言说明文档,将文档转换为向量形式存储。
9.2.3 编写 Controller
package com.atguigu.ai.rag.controller;
import jakarta.annotation.Resource;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.QuestionAnswerAdvisor;
import org.springframework.ai.vectorstore.VectorStore;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/rag")
public class RagController {
@Resource
private ChatClient dashScopeChatClient;
@Resource
private VectorStore vectorStore;
@GetMapping(value = "/chat", produces = "text/plain; charset=UTF-8")
public String generation(@RequestParam("userInput") String userInput) {
return dashScopeChatClient.prompt().user(userInput).advisors(new QuestionAnswerAdvisor(vectorStore)).call().content();
}
}
通过添加 QuestionAnswerAdvisor 并提供对应的向量存储,可以将之前放入的文档作为参考资料,并生成增强回答。
9.2.4 测试
在接口测试工具中输入 localhost:8895/rag/chat?userInput=java 语言有哪些特性,响应结果如下。
10. Spring AI 综合案例
智能简历筛选助手:该助手借助 Spring AI 的特性结合人工智能技术,为企业提供快速查看应聘候选人的信息及与候选人岗位的匹配度的服务。
10.1 搭建环境
创建名为 springai_all 的子模块,依赖和配置文件与 springai_alibaba 中的一样,只不过端口号改为 8896。
10.2 创建 RAG 知识库
用全部候选人的简历构建一个简历知识库。
10.2.1 创建 txt 文本
命名'张三简历.txt',放到 resource 目录下:
教育经历 北京大学 软件工程 本科 2005.09 - 2009.06 主修课程:Java 语言开发、C 语言开发、操作系统、编译原理、计算机网络、算法导论、电商商务、电子基础、高等数学、概率论与统计、离散数学。
工作经验 阿里巴巴有限公司 算法工程师 2009-7-1 - 2015-7-10 拥有五年以上的算法工程师经验,熟悉各种开发语言的使用,比如 Java、C++、C#等,熟练使用各种主流深度学习框架,能独立开发出高质量、高性能的算法模型,精通数据结构、算法及机器学习模型的实现与优化,在多个项目中负责算法模型的设计与开发,包括基于深度学习的图像识别、语音识别及自然语言处理等方向。。
小米科技有限公司 算法工程师 2015-8-1 - 2020-3-1 担任小米科技有限公司算法工程师,负责参与开发高性能机器学习算法。在项目中,我使用 Python 和 MATLAB 编写了多种算法模型,并且实现了 GPU 加速计算,使得算法在处理大规模复杂数据时表现优异。
10.2.2 添加配置类
package com.atguigu.all.config;
import org.springframework.ai.document.Document;
import org.springframework.ai.embedding.EmbeddingModel;
import org.springframework.ai.reader.TextReader;
import org.springframework.ai.transformer.splitter.TokenTextSplitter;
import org.springframework.ai.vectorstore.SimpleVectorStore;
import org.springframework.ai.vectorstore.VectorStore;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.List;
@Configuration
public class RagConfig {
@Bean
VectorStore vectorStore(@Qualifier("dashscopeEmbeddingModel") EmbeddingModel embeddingModel) {
SimpleVectorStore simpleVectorStore = SimpleVectorStore.builder(embeddingModel).build();
String filePath = "张三简历.txt";
TextReader textReader = new TextReader(filePath);
textReader.getCustomMetadata().put("filePath", filePath);
List<Document> documents = textReader.get();
TokenTextSplitter splitter = new TokenTextSplitter(1200, 350, 5, 100, );
splitter.apply(documents);
simpleVectorStore;
}
}
通过以上过程,一个简单的 RAG 知识库就创建完成了,使用时直接在向量库中检索即可。
10.3 创建工具类
10.3.1 创建工具
创建一个工具 (Function),可以用来查询候选人应聘的岗位。
package com.atguigu.all.function;
import java.util.function.Function;
public class RecruitServiceFunction implements Function<RecruitServiceFunction.Request, RecruitServiceFunction.Response> {
@Override
public Response apply(Request request) {
String position = "未知";
if (request.name.contains("张三")) {
position = "算法工程师";
}
return new Response(position);
}
public record Request(String name) {}
public record Response(String position) {}
}
10.3.2 添加配置类
在 RagConfig.java 中添加如下配置:
@Bean
@Description("某某是否有资格面试")
public Function<RecruitServiceFunction.Request, RecruitServiceFunction.Response> recruitServiceFunction() {
return new RecruitServiceFunction();
}
10.4 编写应用的人设
角色与目标:你是一个招聘助手,会针对用户的问题,结合候选人经历,岗位匹配度等专业知识,给用户提供指导。
指导原则:你需要确保给出的建议合理科学,不会对候选人的表现有言论侮辱。
限制:在提供建议时,需要强调在个性建议方面用户仍然需要线下寻求专业咨询。
澄清:在与用户交互过程中,你需要明确回答用户关于招聘方面的问题,对于非招聘方面的问题,你的回应是'我只是一个招聘助手,不能回答这个问题哦'。
个性化:在回答时,你需要以专业可靠的预期回答,偶尔可以带点幽默感。调节气氛。
10.5 编写 Controller
将人设、知识库、工具通过 Spring AI 框架串联起了,搭建成应用。
package com.atguigu.ai.all.controller;
import com.alibaba.cloud.ai.dashscope.chat.DashScopeChatOptions;
import jakarta.annotation.Resource;
import org.springframework.ai.chat.messages.Message;
import org.springframework.ai.chat.messages.SystemMessage;
import org.springframework.ai.chat.model.ChatModel;
import org.springframework.ai.chat.model.Generation;
import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.ai.chat.prompt.PromptTemplate;
import org.springframework.ai.document.Document;
import org.springframework.ai.vectorstore.VectorStore;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
@RestController
public class ChatController {
@Resource
private ChatModel chatModel;
@Resource
private VectorStore vectorStore;
@GetMapping("/ai/agent")
public String agent(@RequestParam("query") String query) {
List<Document> documents = vectorStore.similaritySearch(query);
String info = "";
if (documents.size() > 0) {
info = documents.get(0).getContent();
}
;
;
(systemPrompt);
(userPrompt);
promptTemplate.createMessage(Map.of(, info, , query));
(List.of(userMessage, systemMessage), DashScopeChatOptions.builder().withFunctions(Set.of()).build());
List<Generation> results = chatModel.call(prompt).getResults();
results.stream().map(x -> x.getOutput().getContent()).collect(Collectors.joining());
content;
}
}
10.6 测试
在接口测试工具中输入 localhost:8896/ai/agent?query=java 语言有哪些特性,响应结果如下。