Spring AI Alibaba 入门开发1-环境搭建、ollama部署、Chat和ChatModel、流式输出
目录
一、准备工作
二、HelloWorld
2.1 项目结构
2.2 创建父工程
2.3 创建子模块——ssa-01-HelloWorld
三、微服务调用本地大模型-本章可跳过
3.1 准备工作
系统与硬件要求
本地部署大模型配置推荐列表
3.2 开发调用本地大模型
四、ChatModel和ChatClient
4.1 ChatModel
4.2 ChatClient
4.3 使用ChatClient调用大模型
4.4 两者对比
五、同时使用多个模型实现流式输出
5.1 流式输出介绍
5.2 SSE(Server-Sent Events)服务器发送事件
5.3 多模型共存开发
5.4 Flux介绍
5.5 新增前端交互
一、准备工作
1、到阿里百炼平台申请API KEY、然后获取base_url、模型code。具体请自行百度。
2、我的相关配置
JDK 21
maven 建议3.9.5
SpringBoot : 3.5.5
spring-ai: 1.0.0
SpringAIAlibaba:1.0.2
二、HelloWorld
2.1 项目结构
2.2 创建父工程
只需修改父工程pom.xml即可,代码如下:
<properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <maven.compiler.source>21</maven.compiler.source> <maven.compiler.target>21</maven.compiler.target> <java.version>21</java.version> <spring-boot.version>3.5.5</spring-boot.version> <spring-ai.version>1.0.0</spring-ai.version> <SpringAIAlibaba.version>1.0.0.2</SpringAIAlibaba.version> </properties> <dependencyManagement> <dependencies> <!-- Spring Boot --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>${spring-boot.version}</version> <type>pom</type> <scope>import</scope> </dependency> <!-- Spring AI Alibaba --> <dependency> <groupId>com.alibaba.cloud.ai</groupId> <artifactId>spring-ai-alibaba-bom</artifactId> <version>${SpringAIAlibaba.version}</version> <type>pom</type> <scope>import</scope> </dependency> <!-- Spring AI --> <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> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <version>${spring-boot.version}</version> </plugin> </plugins> </build> <repositories> <repository> <id>spring-milestones</id> <name>Spring Milestones</name> <url>https://repo.spring.io/milestone</url> <snapshots> <enabled>false</enabled> </snapshots> </repository> </repositories>2.3 创建子模块——ssa-01-HelloWorld
1、pom.xml
<properties> <maven.compiler.source>21</maven.compiler.source> <maven.compiler.target>21</maven.compiler.target> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>com.alibaba.cloud.ai</groupId> <artifactId>spring-ai-alibaba-starter-dashscope</artifactId> </dependency> <!--lombok--> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <!--hutool--> <dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>5.8.22</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.11.0</version> <configuration> <compilerArgs> <arg>-parameters</arg> </compilerArgs> <source>21</source> <target>21</target> </configuration> </plugin> </plugins> </build> <repositories> <repository> <id>spring-milestones</id> <name>Spring Milestones</name> <url>https://repo.spring.io/milestone</url> <snapshots> <enabled>false</enabled> </snapshots> </repository> </repositories>2、配置文件
application.properties
server.port=8888 #解决中文乱码 server.servlet.encoding.charset=UTF-8 server.servlet.encoding.enabled=true server.servlet.encoding.force=true spring.application.name=ssa-01-HelloWorld #Sprig AI Alibaba 相关配置 spring.ai.dashscope.api-key=${qianwen-api} spring.ai.dashscope.base-url=https://ws-6tq01jo6mtthlhoq.cn-beijing.maas.aliyuncs.com/compatible-mode/v1 spring.ai.dashscope.chat.options.model=qwen-max注意:配置api-key时,不能使用明文,需要先配置环境变量,然后在properties中使用${环境变量}
3、创建配置类
有两种方式获取api-key,一种是读取application.properties的内容,一种是读取环境变量的值。具体实现如下:
@Configuration public class LLMConfig { //方式1:读取配置文件信息 @Value("${spring.ai.dashscope.api-key}") private String apiKey; @Bean public DashScopeApi dashScopeApi() { return DashScopeApi.builder().apiKey(apiKey).build(); } //方式2:读取环境变量 // @Bean // public DashScopeApi dashScopeApi2() { // return DashScopeApi.builder().apiKey(System.getenv("qianwen-api")).build(); // } }4、对话模型-Chat Model
对话模型(Chat Model)接收一系列消息(Message)作为输入,与模型 LLM 服务进行交互,并接收返回的聊天消息(Chat Message)作为输出。相比于普通的程序输入,模型的输入与输出消息(Message)不止支持纯字符文本,还支持包括语音、图片、视频等作为输入输出。同时,在 Spring AI Alibaba 中,消息中还支持包含不同的角色,帮助底层模型区分来自模型、用户和系统指令等的不同消息。
Spring AI Alibaba 复用了 Spring AI 抽象的 Model API,并与通义系列大模型服务进行适配(如通义千问、通义万相等),目前支持纯文本聊天、文生图、文生语音、语音转文本等。以下是框架定义的几个核心 API:
- ChatModel,文本聊天交互模型,支持纯文本格式作为输入,并将模型的输出以格式化文本形式返回。
- ImageModel,接收用户文本输入,并将模型生成的图片作为输出返回。
- AudioModel,接收用户文本输入,并将模型合成的语音作为输出返回。
Spring AI Alibaba 支持以上 Model 抽象与通义系列模型的适配,并通过spring-ai-alibaba-starterAutoConfiguration 自动初始化了默认实例,因此我们可以在应用程序中直接注入 ChatModel、ImageModel 等 bean,当然在需要的时候也可以自定义 Model 实例。
5、创建controller
使用两种方式与大模型进行交互,一种是.call():此方式是一次响应所有的内容;一种是.stream():文字逐个返回。
@RestController public class ChatHelloWorldController { @Resource private ChatModel chatModel; @GetMapping("/hello/call") public String doCall(@RequestParam(value = "msg" , defaultValue = "高欢") String msg) { String result = chatModel.call(msg); return result; } @GetMapping("/hello/stream") public Flux<String> doStream(@RequestParam(value = "msg" , defaultValue = "宇文泰") String msg) { return chatModel.stream(msg); } }三、微服务调用本地大模型-本章可跳过
3.1 准备工作
1、本地安装Ollama。注意:默认安装C盘,建议更换其他位置。安装方法请百度。
系统与硬件要求
| 项目 | 最低要求 | 特别说明 |
|---|---|---|
| 操作系统 | Windows 10 22H2 或更新版本(家庭版/专业版均可) | 版本过旧可能导致兼容性问题,建议更新。 |
| 处理器 (CPU) | 4核及以上(推荐Intel i7或AMD Ryzen 5以上) | 若没有独立显卡,将完全依赖CPU进行推理,速度会慢很多。 |
| 内存 (RAM) | 16GB 或更高 | 运行大模型时,内存是保证系统不崩溃的关键。 |
| 显卡 (GPU) | 强烈推荐NVIDIA或AMD独立显卡 | Ollama支持NVIDIA、AMD Radeon GPU加速。 |
| NVIDIA显卡驱动 | 551.61 或更新版本 | 这是官方文档的要求,驱动太旧可能无法识别显卡。 |
| AMD显卡驱动 | 安装最新版AMD Radeon驱动,或支持ROCm/Vulkan的驱动 | 部分RDNA2架构显卡(如RX 6000系列)可能推荐使用Vulkan加速。 |
| 存储空间 | 安装程序本身约需4GB,另需为模型文件预留几十到上百GB | 模型文件体积很大,强烈建议安装在SSD上以提升加载速度。 |
本地部署大模型配置推荐列表
| 推荐级别 | 模型系列 | 具体推荐模型 (Ollama命令) | 模型大小 (量化后) | 显存占用 | 预期速度 (tokens/秒) | 适用场景 |
|---|---|---|---|---|---|---|
| 🏆 首选推荐 | Qwen3 (4B) | ollama run qwen3:4b-q4_K_M | ~2.9 GB | ~3.2 GB | 30 - 50 | 日常聊天、问答、编程辅助、文本总结,体验流畅 |
| 🥈 次选推荐 | Qwen2.5 (3B) | ollama run qwen2.5:3b-q4_K_M | ~2.0 GB | ~2.2 GB | 40 - 60 | 轻量级任务,响应极快,适合资源敏感场景 |
| 🤔 进阶挑战 | DeepSeek-R1 (7B) | ollama run deepseek-r1:7b-q4_K_M | ~4.4 GB | ~4.6 GB (略超显存) | 8 - 15 | 复杂推理、代码生成,需要部分CPU+GPU混合运行,速度较慢 |
确认好模型后,可以使用pull命令拉去,使用run命令运行,具体与docker类似。
3.2 开发调用本地大模型
1、新建子模块,项目结构如下:
2、修改pom.xml文件
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!--spring-ai-alibaba dashscope--> <dependency> <groupId>com.alibaba.cloud.ai</groupId> <artifactId>spring-ai-alibaba-starter-dashscope</artifactId> </dependency> <!--ollama--> <dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-starter-model-ollama</artifactId> <version>1.0.0</version> </dependency> <!--lombok--> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <!--hutool--> <dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>5.8.22</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.11.0</version> <configuration> <compilerArgs> <arg>-parameters</arg> </compilerArgs> <source>21</source> <target>21</target> </configuration> </plugin> </plugins> </build> <repositories> <repository> <id>spring-milestones</id> <name>Spring Milestones</name> <url>https://repo.spring.io/milestone</url> <snapshots> <enabled>false</enabled> </snapshots> </repository> </repositories>3、application.properties
server.port=8888 #解决中文乱码 server.servlet.encoding.charset=UTF-8 server.servlet.encoding.enabled=true server.servlet.encoding.force=true spring.application.name=ssa-02-ollama #Sprig AI Alibaba 相关配置 spring.ai.dashscope.api-key=${qianwen-api} spring.ai.ollama.base-url=http://localhost:11434 spring.ai.ollama.chat.options.model=qwen3:4b4、新建controller
@RestController public class OllamaController { @Resource(name = "ollamaChatModel") private ChatModel chatModel; @GetMapping("/ollama") private Flux<String> ollama(@RequestParam(value = "msg" ,defaultValue = "高欢") String msg){ return chatModel.stream(msg); } }5、新建启动类
public class SSA_02_OllamaApplication { public static void main(String[] args) { SpringApplication.run(SSA_02_OllamaApplication.class, args); } }6、运行如下:
四、ChatModel和ChatClient
4.1 ChatModel
对话模型(Chat Model)接收一系列消息(Message)作为输入,与模型 LLM 服务进行交互,并接收返回的聊天消息(Chat Message)作为输出。相比于普通的程序输入,模型的输入与输出消息(Message)不止支持纯字符文本,还支持包括语音、图片、视频等作为输入输出。同时,在 Spring AI Alibaba 中,消息中还支持包含不同的角色,帮助底层模型区分来自模型、用户和系统指令等的不同消息。
Spring AI Alibaba 复用了 Spring AI 抽象的 Model API,并与通义系列大模型服务进行适配(如通义千问、通义万相等),目前支持纯文本聊天、文生图、文生语音、语音转文本等。以下是框架定义的几个核心 API:
- ChatModel,文本聊天交互模型,支持纯文本格式作为输入,并将模型的输出以格式化文本形式返回。
- ImageModel,接收用户文本输入,并将模型生成的图片作为输出返回。
- AudioModel,接收用户文本输入,并将模型合成的语音作为输出返回。
Spring AI Alibaba 支持以上 Model 抽象与通义系列模型的适配,并通过spring-ai-alibaba-starterAutoConfiguration 自动初始化了默认实例,因此我们可以在应用程序中直接注入 ChatModel、ImageModel 等 bean,当然在需要的时候也可以自定义 Model 实例。
ChatModel适合简单大模型交互场景。
4.2 ChatClient
ChatClient提供了与 AI 模型通信的 Fluent API,它支持同步和反应式(Reactive)编程模型。与ChatModel、Message、ChatMemory等原子 API 相比,使用ChatClient可以将与 LLM 及其他组件交互的复杂性隐藏在背后,因为基于 LLM 的应用程序通常要多个组件协同工作(例如,提示词模板、聊天记忆、LLM Model、输出解析器、RAG 组件:嵌入模型和存储),并且通常涉及多个交互,因此协调它们会让编码变得繁琐。当然使用ChatModel等原子 API 可以为应用程序带来更多的灵活性,成本就是您需要编写大量样板代码。
ChatClient 类似于应用程序开发中的服务层,它为应用程序直接提供AI 服务,开发者可以使用 ChatClient Fluent API 快速完成一整套 AI 交互流程的组装。
包括一些基础功能,如:
- 定制和组装模型的输入(Prompt)
- 格式化解析模型的输出(Structured Output)
- 调整模型交互参数(ChatOptions)
还支持更多高级功能:
- 聊天记忆(Chat Memory)
- 工具/函数调用(Function Calling)
- RAG
ChatClient是高级封装,基于ChatModel创建,适合快速构建保准化复杂AI服务,支持同步和流式交互,集成多种高级功能。
4.3 使用ChatClient调用大模型
1、项目结构
2、创建子模块,修改pom.xml
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!--spring-ai-alibaba dashscope--> <dependency> <groupId>com.alibaba.cloud.ai</groupId> <artifactId>spring-ai-alibaba-starter-dashscope</artifactId> </dependency> <!--lombok--> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <!--hutool--> <dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>5.8.22</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.11.0</version> <configuration> <compilerArgs> <arg>-parameters</arg> </compilerArgs> <source>21</source> <target>21</target> </configuration> </plugin> </plugins> </build> <repositories> <repository> <id>spring-milestones</id> <name>Spring Milestones</name> <url>https://repo.spring.io/milestone</url> <snapshots> <enabled>false</enabled> </snapshots> </repository> </repositories>创建启动类
@SpringBootApplication public class SSA_03_ChatModel_ChatClient_Application { public static void main(String[] args) { SpringApplication.run(SSA_03_ChatModel_ChatClient_Application.class, args); } }创建配置文件
server.port=8888 #解决中文乱码 server.servlet.encoding.charset=UTF-8 server.servlet.encoding.enabled=true server.servlet.encoding.force=true spring.application.name=ssa-02-ChatModel-ChatClient #Sprig AI Alibaba 相关配置 spring.ai.dashscope.api-key=${qianwen-api} spring.ai.ollama.base-url=http://localhost:11434 spring.ai.ollama.chat.options.model=goekdenizguelmez/JOSIEFIED-Qwen2.5:7b-q4_k_m创建controller,注意:下面通过两种方式创建ChatClient对象。
方式一:在config里通过@Bean注解创建——推荐
@Configuration public class LLMConfig { @Value("${spring.ai.dashscope.api-key}") private String apiKey; @Bean public DashScopeApi dashScopeApi() { return DashScopeApi.builder().apiKey(apiKey).build(); } @Bean public ChatClient chatClient(ChatModel dashScopeChatModel) { return ChatClient.builder(dashScopeChatModel).build(); } }@RestController public class ChatClient_V2_Controller { @Resource private ChatClient chatClient; @GetMapping("/client1") public String doClient1(@RequestParam(value = "msg" ,defaultValue = "请简单介绍侯莫陈崇") String msg) { return chatClient.prompt().user(msg).call().content(); } }第二种方式:在controller里通过构造方法创建——不推荐
@RestController public class ChatClientController { private final ChatClient chatClient; public ChatClientController(ChatModel dashScopeChatModel) { this.chatClient = ChatClient.builder(dashScopeChatModel).build(); } @GetMapping("/client") public String doClient(@RequestParam(value = "msg" ,defaultValue = "南北朝时期最勇猛的将领是谁?") String msg) { return chatClient.prompt().user(msg).call().content(); } }4.4 两者对比
五、同时使用多个模型实现流式输出
5.1 流式输出介绍
1、流式输出(StreamingOutput)
是一种逐步返回大模型生成结果的技术,生成一点返回一点,允许服务器将响应内容
分批次实时传输给客户端,而不是等待全部内容生成完毕后再一次性返回。
这种机制能显著提升用户体验,尤其适用于大模型响应较慢的场景(如生成长文本或复杂推理结果)
2、实现方式
Spring AI Alibaba两种流式输出:分别为ChatModel和ChatClient。
5.2 SSE(Server-Sent Events)服务器发送事件
Server-Sent:由服务器发送。
Events:事件,指服务器主动推送给客户端的数据或消息。
Server-SentEvents(SSE)服务器发送事件实现流式输出。
Server-Sent Events (SSE) 是一种允许服务端可以持续推送数据片段(如逐词或逐句)到前端的 Web 技术。通过单向的HTTP长连接,使用一个长期存在的连接,让服务器可以主动将数据"推"给客户端,SSE是轻量级的单向通信协议,适合AI对话这类服务端主导的场景
核心概念
SSE 的核心思想是:客户端发起一个请求,服务器保持这个连接打开并在有新数据时,通过这个连接将数据发送给客户端。这与传统的请求-响应模式(客户端请求一次,服务器响应一次,连接关闭)有本质区别。SSE下一代(Stream able Http)。
总结:一种让服务器能够主动、持续地向客户端(比如你的网页浏览器)推送数据的技术。
SSE适用场景:
5.3 多模型共存开发
1、创建子模块,项目结构
2、修改pom.xml
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!--spring-ai-alibaba dashscope--> <dependency> <groupId>com.alibaba.cloud.ai</groupId> <artifactId>spring-ai-alibaba-starter-dashscope</artifactId> </dependency> <!--lombok--> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.38</version> </dependency> <!--hutool--> <dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>5.8.22</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.11.0</version> <configuration> <compilerArgs> <arg>-parameters</arg> </compilerArgs> <source>21</source> <target>21</target> </configuration> </plugin> </plugins> </build> <repositories> <repository> <id>spring-milestones</id> <name>Spring Milestones</name> <url>https://repo.spring.io/milestone</url> <snapshots> <enabled>false</enabled> </snapshots> </repository> </repositories>3、新增配置文件
server.port=8888 #解决中文乱码 server.servlet.encoding.charset=UTF-8 server.servlet.encoding.enabled=true server.servlet.encoding.force=true spring.application.name=ssa-01-HelloWorld #Sprig AI Alibaba 相关配置 spring.ai.dashscope.api-key=${qianwen-api} spring.ai.dashscope.base-url=https://ws-6tq01jo6mtthlhoq.cn-beijing.maas.aliyuncs.com/compatible-mode/v1 #spring.ai.dashscope.chat.options.model=qwen-max4、创建启动类
@SpringBootApplication public class SSA_04_Stream_OutputApplication { public static void main(String[] args) { SpringApplication.run(SSA_04_Stream_OutputApplication.class, args); } }5、新增配置类-创建ChatModel对象
@Configuration public class LLMConfig { //定义各个模型名称 private final String DEEPSEEK_MODEL = "deepseek-v4-pro"; private final String QWEN_MODEL = "qwen-max"; //创建deepseek的ChatModel @Bean(name = "deepseek") public ChatModel deepseek() { return DashScopeChatModel.builder().dashScopeApi( DashScopeApi.builder().apiKey(System.getenv("qianwen-api")).build()) .defaultOptions(DashScopeChatOptions.builder().withModel(DEEPSEEK_MODEL).build()) .build(); } //创建qwen的ChatModel @Bean(name = "qwen") public ChatModel qwen() { return DashScopeChatModel.builder().dashScopeApi( DashScopeApi.builder().apiKey(System.getenv("qianwen-api")).build() ).defaultOptions(DashScopeChatOptions.builder().withModel(QWEN_MODEL).build()) .build(); } }6、新增controller-使用ChatModel调用大模型
@RestController public class ChatModelController { @Resource(name = "deepseek") private ChatModel deepseekChatModel; @Resource(name = "qwen") private ChatModel qwenChatModel; @GetMapping("/model/deepseek") public Flux<String> doDeepSeekModel(@RequestParam(value = "msg",defaultValue = "你是谁") String msg) { return deepseekChatModel.stream(msg); } @GetMapping("/model/qwen") public Flux<String> doQwenModel(@RequestParam(value = "msg",defaultValue = "你是谁") String msg) { return qwenChatModel.stream(msg); } }7、新增配置类-创建ChatClient对象
@Configuration public class LLMConfig { //定义各个模型名称 private final String DEEPSEEK_MODEL = "deepseek-v4-pro"; private final String QWEN_MODEL = "qwen-max"; //创建deepseek的ChatModel @Bean(name = "deepseek") public ChatModel deepseek() { return DashScopeChatModel.builder().dashScopeApi( DashScopeApi.builder().apiKey(System.getenv("qianwen-api")).build()) .defaultOptions(DashScopeChatOptions.builder().withModel(DEEPSEEK_MODEL).build()) .build(); } //创建qwen的ChatModel @Bean(name = "qwen") public ChatModel qwen() { return DashScopeChatModel.builder().dashScopeApi( DashScopeApi.builder().apiKey(System.getenv("qianwen-api")).build() ).defaultOptions(DashScopeChatOptions.builder().withModel(QWEN_MODEL).build()) .build(); } @Bean(name = "deepseekChatClient") public ChatClient deepseekChatClient(@Qualifier("deepseek") ChatModel deepseek) { return ChatClient.builder(deepseek) .defaultOptions(ChatOptions.builder().model(DEEPSEEK_MODEL).build()).build(); } @Bean(name = "qwenChatClient") public ChatClient qwenChatClient(@Qualifier("qwen") ChatModel qwen) { return ChatClient.builder(qwen).defaultOptions(ChatOptions.builder().model(QWEN_MODEL).build()).build(); } }8、创建controller-使用ChatClientdiaoyong 调用大模型
@RestController public class ChatModelController { @Resource(name = "deepseek") private ChatModel deepseekChatModel; @Resource(name = "qwen") private ChatModel qwenChatModel; @Resource(name = "deepseekChatClient") private ChatClient deepseekChatClient; @Resource(name = "qwenChatClient") private ChatClient qwenChatClient; @GetMapping("/model/deepseek") public Flux<String> doDeepSeekModel(@RequestParam(value = "msg",defaultValue = "你是谁") String msg) { return deepseekChatModel.stream(msg); } @GetMapping("/model/qwen") public Flux<String> doQwenModel(@RequestParam(value = "msg",defaultValue = "你是谁") String msg) { return qwenChatModel.stream(msg); } @GetMapping("/client/deepseek") public Flux<String> deDeepSeekClient(@RequestParam(value = "msg",defaultValue = "你是谁") String msg) { return deepseekChatClient.prompt(msg).stream().content(); } @GetMapping("/client/qwen") public Flux<String> doQwenClient(@RequestParam(value = "msg",defaultValue = "你是谁") String msg){ return qwenChatClient.prompt(msg).stream().content(); } }5.4 Flux介绍
Flux是SpringWebFlux中的一个核心组件,属于响应式编程模型的一部分。它主要用于处理异步、非阻塞的流式数据,能够高效地处理高并发场景。Flux可以生成和处理一系列的事件或数据如流式输出等。
看类注释和类所在的jar包我们就明白:
SAA中的流式输出是通过ReactorStreams技术实现的和SpringWebFlux的底层实现是一样的技术。
具体执行流程:
ReactorStreams会订阅数据源,当有数据时,ReactorStreams以分块流的方式发送给客户端用户。
5.5 新增前端交互
在/resoure/static添加index.html
<!DOCTYPE html> <html> <head> <title>SSE流式chat</title> <style> body { font-family: Arial, sans-serif; background-color: #f4f4f4; margin: 0; padding: 20px; } #messageInput { width: 90%; padding: 10px; font-size: 16px; border: 1px solid #ccc; border-radius: 4px; margin-bottom: 10px; } button { padding: 10px 20px; font-size: 16px; background-color: #007bff; color: white; border: none; border-radius: 4px; cursor: pointer; } button:hover { background-color: #0056b3; } #messages { margin-top: 20px; padding: 15px; background-color: #f9f9f9; border: 1px solid #ddd; border-radius: 8px; max-height: 300px; overflow-y: auto; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); } #messages div { padding: 8px 0; border-bottom: 1px solid #eee; font-size: 14px; color: #333; } #messages div:last-child { border-bottom: none; } </style> </head> <body> <textarea id="messageInput" rows="4" cols="50" placeholder="请输入你的问题..."></textarea><br> <button onclick="sendMsg()">发送提问</button> <div id="messages"></div> <script> function sendMsg() { // 获取用户输入的消息 const message = document.getElementById('messageInput').value; if (message == "") return false; //1 客户端使用 JavaScript 的 EventSource 对象连接到服务器上的一个特定端点(URL) const eventSource = new EventSource('client/qwen?question=' + message); //2 监听消息事件 eventSource.onmessage = function (event) { // 获取流式返回的数据 const data = event.data; // 将接收到的数据展示到页面上 const messagesDiv = document.getElementById('messages'); messagesDiv.innerHTML += event.data; }; //3 监听错误事件 eventSource.onerror = function (error) { console.error('EventSource 发生错误:', error); eventSource.close(); // 关闭连接 }; } </script> </body> </html>修改对应的controller
@GetMapping("/client/qwen") public Flux<String> doQwenClient(@RequestParam(value = "question") String msg){ return qwenChatClient.prompt(msg).stream().content(); }启动后,输入:http://localhost:8888/index.html
