ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Spring AI Alibaba 入门开发1-环境搭建、ollama部署、Chat和ChatModel、流式输出

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 GB30 - 50日常聊天、问答、编程辅助、文本总结,体验流畅
🥈 次选推荐Qwen2.5 (3B)ollama run qwen2.5:3b-q4_K_M~2.0 GB~2.2 GB40 - 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:4b

4、新建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)编程模型。与ChatModelMessageChatMemory等原子 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-max

4、创建启动类

@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

返回列表