目录
1.创建一个基础项目
2.创建父子工程
2.1 父工程中引入spring boot
2.2 创建子工程
2.2.1 子工程引入spring ai
2.2.2 spring-ai-starter-model-openai
3. 构建API请求的原理
4. DeepSeek AI聊天实战(ChatModel)
5. ChatClient接口
6. DeepSeek AI聊天实战(ChatClient)
6.1 实战1(系统提示词)
6.2 实战2(结构化输出)
6.3 实战3(流式输出)
7. Advisors介绍
7.1 SimpleLoggleAdvisor
8. ChatModel和ChatClient的区别
8.1 分析ChatModel接口
8.2 分析ChatClient接口
8.3 区别介绍
文章代码:spring-ai-first-term-practice/spring-ai-demo · 巨蛇神/JavaEE进阶 - 码云 - 开源中国
1.创建一个基础项目
2.创建父子工程
2.1 父工程中引入spring boot
在父工程的pom文件中引入spring-boot-starter-parent。(也就是引入spring boot)
因为后续我引入的是spring-ai-bom 版本是2.0.1,所以我就引入4.1.1版本的spring boot。大家看完文章之后可以使用其他版本的spring ai看看有什么区别。
<!-- 加入spring boot -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>4.1.1</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
注意,我们后续将要引入spring-ai-bom,这个依赖的每个版本,可能需要的spring boot版本要求是不一样的。例:Spring AI 2.0.x与Spring AI 1.1.8 它们分别支持的spring boot版本区间
官方:Spring AI
2.2 创建子工程
2.2.1 子工程引入spring ai
(把spring-ai-bom引入父工程也行,这样所有的子工程就都相当于引入了这个依赖)
子工程引入依赖:
(你或许不知道“spring-ai-starter-model-openai”这个依赖是干什么的,但没关系,下面会讲解)
<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> <!-- 引入OpenAI API 协议 --> <dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-starter-model-openai</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-bom</artifactId> <version>2.0.1</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>
2.2.2 spring-ai-starter-model-openai
Spring AI 生态专门为OpenAI及兼容其API服务的大模型设计了“spring-ai-starter-model-openai”用于快速集成大语言模型能力到spring boot应用中。(如DeepSeek也兼容了OpenAI)
同一个文档页面往下话到底,就看到:
该依赖核心价值包括:
- 简化配置:自动封装OpenAI API的请求和响应
- 统一接口:提供ChatClient等标准化接口,支持无缝切换不同模型提供商
- Spring 生态集成:与Spring Boot的自动配置、依赖注入等特性深度整合
核心价值解释:
1.简化配置:兼容了OpenAI API格式的模型都可以引入“spring-ai-starter-model-openai”后,通过配置文件(如application.yml)或代码 组装成一个OpenAI API格式的API请求。
以发送DeepSeek API请求为例。DeepSeek兼容了OpenAI API格式,因此可以在application.yml文件中配置如下:
上图中,我申请的DeepSeek的api-key配置到了环境变量中,你也可以把api-key直接粘贴,例api-key: sk-123...321
3. 构建API请求的原理
上图配置操作非常简单,但是为什么如这样简单的配置就构建了一个API请求?——你猜的没错!引入的“spring-ai-starter-model-openai”依赖使用了OpenAI API请求模板:
nitice:以DeepSeek官方示例为例。DeepSeek官方提供了一些配置选项,选择后,API请求就会在带有哪些配置。
2.统一接口 和 3.Spring 生态集成 这两价值现在不好直接体现,请直接看实战。
4. DeepSeek AI聊天实战(ChatModel)
- 配置聊天大模型后,在需要使用时,直接注入ChatModel(OpenAiChatModel实现了ChatModel接口。也可以一个构造ChatClient,后面讲)
- call(String)方法,把用户输入的信息(用户提示词)传给聊天大模型,大模型通过自己已有的知识,回答你。它是对话式AI应用最核心的方法,通过call调用AI。
package com.jusheshen.ai.controller; import org.springframework.ai.openai.OpenAiChatModel; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RequestMapping("/deepseek") @RestController public class DeepSeekController { @Autowired private OpenAiChatModel dsChatModel; //注入DeepSeek的deepseek-v4-flash模型,因为yml配置的base-url是deepseek @RequestMapping("/chat") public String chat(String prompt){ //用户输入提示词 String call = dsChatModel.call(prompt); //用户提示词传给大模型,模型处理后返回处理结果 return call; } }1.notice:Spring AI给我们提供了许多可配置的选项:
2.notice:在Spring AI 1.0.0-M6及更早,starter 还叫“spring-ai-openai-spring-boot-starter”,Spring AI 1.0.0-M7及之后版本改名叫“spring-ai-starter-model-openai”
随着Spring AI版本的改变,有一些工件ID也发生了变化,如果哪天依赖用着用着出错了,就来Upgrade Notes :: Spring AI Reference 看看是否发生改变。
3.notice:Spring AI已经为主流的模型供应商提供了单独的适配器,如DeepSeek可引入“spring-ai-starter-model-deepseek”。但更提倡引用“spring-ai-starter-model-openai”,因为许多供应商兼容OpenAI API格式,在切换大模型时可以省掉部分替换依赖的时间。
如上述,如果想把DeepSeek的模型换成ChatGPT的话直接改base-url、model和api-key就行。(base-url不写都可以,ChatGPT本身就是OpenAI的模型,有默认的base-url)
5. ChatClient接口
- ChatModel和ChatClient是Spring AI框架构建对话式AI应用的两大核心接口,上面使用了ChatModel完成与AI模型的交互。接下来介绍ChatModel和ChatClient的区别。
- ChatClient对ChatModel进行了封装,ChatModel更接近底层(大模型),ChatClient提供给用户开箱即用的服务。ChatClient实现了Fluent API可链式调用,它还支持同步和异步调用大模型。
官方示例:Chat Client API :: Spring AI Reference
@RestController class MyController { private final ChatClient chatClient; //ChatClient.Builder就是ChatModel,替换成ChatModel 更直观 public MyController(ChatClient.Builder chatClientBuilder) { this.chatClient = chatClientBuilder.build(); } @GetMapping("/ai") String generation(String userInput) { return this.chatClient.prompt()//链式调用 .user(userInput) .call() .content(); } }下面我接着以DeepSeek模型为例,你也可以配置其他厂商的模型。
6. DeepSeek AI聊天实战(ChatClient)
6.1 实战1(系统提示词)
6.2 实战2(结构化输出)
上述AI返回信息没有固定格式,有时候信息冗余在一块。ChatClient允许自定义AI返回类型,以下面为例:
构建一个输入菜名,返回所需配料的AI。并且自定义菜谱类。
其实代码层面,我根本没和AI说食谱类的dish属性是什么意思,ingredients是什么意思,但AI就是知道把菜名赋给dish,配料赋给ingredients。可看出AI很聪明。
6.3 实战3(流式输出)
平时在其他平台与AI对话时,你可能注意注意到 AI回复的信息都是一个字一个字的往外蹦的。我上面与AI所有的交互都是等AI大模型处理、返回完,再全部信息返回给后端,接着再return给前端,这就导致在处理复杂问题时,用户在前端要面对一个白板很长时间,这体验感真是糟糕透了,所以下面实现流式输出。
notice:一定要设置编码,否则输出的就是中文乱码!
@RequestMapping(value = "/stream",produces = "text/html;charset=utf-8") public Flux<String> stream(String message){ return chatClient.prompt() .user(message) //调用AI 流式输出 .stream() //返回数据 .content(); }7. Advisors介绍
Spring AI中的Advisors是基于AOP思想实现的,Advisors类似于Spring中的拦截器。下图是Advisor的执行时机,这种链式处理机制确保了每个Advisor都会被执行。Advisor的核心功能在于对请求进行拦截过滤和增强, 帮助我们在API调用前后解决各种问题。
以SimpleLoggleAdvisor为例。
7.1 SimpleLoggleAdvisor
SimpleLoggleAdvisor是Spring AI内置的Advisor之一,主要用来打印日志。手动添加到Advisor链中,即可自动打印所有经过大模型的聊天请求和响应。
SimpleLoggleAdvisor效果展示:
对于SimpleLoggleAdvisor打印的日志级别,可以自定义,而且自定义的模板与spring boot一样。
logging: level: org.springframework.ai.chat.client.advisor: debug
8. ChatModel和ChatClient的区别
现知道ChatClient是ChatModel的高级封装,使用起来也更加方便,但要真正知道它们两者的区别,必须了解它们各自接口的实现。
8.1 分析ChatModel接口
都知道ChatClient是ChatModel的封装,那么ChatClient能实现的ChatModel也能实现,例:用ChatModel流式输出
8.2 分析ChatClient接口
ChatClient封装了很多API,让人少费劲。
8.3 区别介绍
ChatModel和ChatClient是Spring AI框架提供的与大语言模型(LLM)交互的两大核心接口,但两者设计理念和适用场景不太一样。
- ChatModel是Spring AI框架中的底层接口,直接与具体的大模型(如OpenAI、通义千问、通义万像)交互,提供基础的call和stream方法,开发者需手动处理提示词组装、参数配置和响应解析等细节,在使用上相对更加灵活。
- ChatClient对ChatModel进行了封装,相比较ChatModel原子类API,ChatClient屏蔽了与AI大模型的交互复杂性,它自动集成提示词管理、响应格式化、结构化输出映射等能力,提高了开发效率。
能力对比:
| 维度 | ChatModel | ChatClient |
| 交互方式 | 手动构建Prompt,解析响应 | 链式API,自动封装请求与响应 |
| 结构化输出 | 手动解析文本 | 支持.entity(Class)自动映射POJO |
| 扩张能力 | 依赖外部组件 | 内置Advisor机制,提供更高级的功能,如提供上下文记忆,RAG等功能 |
| 适合场景 | 适合需要精细控制模型参数的场景,比如模型实验,参数调优等定制需求 | 适合快速构建AI服务,如带记忆的客服系统 |