SpringBoot 使用 Spring AI 构建简单智能助手
介绍基于 Spring Boot 和 Spring AI 框架快速搭建智能助手的完整流程。内容包括环境配置、依赖引入、模型参数设置(支持硅基流动/OpenAI)、ChatClient 核心 API 使用(同步/流式调用)、系统提示词设置、多轮对话上下文管理、日志集成、工具调用扩展以及前后端基础集成方案。通过 Advisor 机制实现会话记忆与功能增强,提供从零到一的开发实践指南。

介绍基于 Spring Boot 和 Spring AI 框架快速搭建智能助手的完整流程。内容包括环境配置、依赖引入、模型参数设置(支持硅基流动/OpenAI)、ChatClient 核心 API 使用(同步/流式调用)、系统提示词设置、多轮对话上下文管理、日志集成、工具调用扩展以及前后端基础集成方案。通过 Advisor 机制实现会话记忆与功能增强,提供从零到一的开发实践指南。

Java 领域实现大模型(LLM)开发的两大核心框架,核心差异如下:
| 框架 | 最低 JDK 版本 | 核心优势 |
|---|---|---|
| Spring AI | 17 | 深度适配 SpringBoot 生态,自动装配,开发成本低 |
| LangChain4J | 8 | 兼容性强,支持低版本 JDK,生态插件丰富 |
先带大家快速搭建一个基本功能项目,后面再依次拆分讲解
环境要求
JDK:17 及以上版本(Spring AI 强制要求);
SpringBoot:3.5.9 及以上(本文示例使用 3.5.9);
构建工具:Maven;
大模型 URL&API:可通过硅基流动获取(支持 DeepSeek、OpenAI 等多模型,需实名认证并获取 API-Key)。

首先,在项目 pom.xml 中添加 spring-ai 的版本信息:
<properties>
<java.version>17</java.version>
<spring-ai.version>1.0.0-SNAPSHOT</spring-ai.version><!-- Spring AI 版本 -->
</properties>
然后,添加 spring-ai 的依赖管理项:
<!-- 管理 Spring AI 所有依赖版本,避免版本冲突 -->
<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>
最后,引入 spring-ai-openai 的依赖:
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-model-openai</artifactId>
<version>${spring-ai.version}</version>
</dependency>
为了方便后续开发,我们再手动引入一个 Lombok 依赖:
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.22</version>
</dependency>
注意: 建议使用官方推荐的 lombok 版本,避免潜在 bug。
完整依赖 (复制注意修改项目信息)
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.5.9</version>
<relativePath/>
</parent>
<groupId>com.ai</groupId>
<artifactId>SpringAi</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>SpringAi</name>
<description>SpringAi</description>
<properties>
<java.version>17
1.0.0-SNAPSHOT
org.springframework.ai
spring-ai-bom
${spring-ai.version}
pom
import
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-starter-test
test
org.springframework.ai
spring-ai-starter-model-openai
${spring-ai.version}
org.projectlombok
lombok
1.18.22
org.springframework.boot
spring-boot-maven-plugin
首先需要使用 Ai 的对应 key。介绍一个网站,叫做硅基流动,可以从这里获取 API Key,后续也会介绍其他模型获取方式。
无论什么大模型网站我们都需要获取两个内容
API key

模型请求地址

接下来,我们在配置文件中配置模型的参数信息。
以 openai 为例,我们将application.properties修改为application.yaml,然后添加下面的内容:
spring:
# Spring AI 核心配置
ai:
openai:
api-key: fghjklfghjklsahdjksadasdsadasd # 硅基流动/OpenAI 的 API-Key(我瞎写的改成你自己的)
base-url: https://api.siliconflow.cn # 大模型接口地址(硅基流动/OpenAI 官方地址)
chat:
options:
model: deepseek-ai/DeepSeek-V3 # 模型名称(硅基流动/OpenAI 模型名,你选择模型的名字)
temperature: 0.7 # 随机性(0-1,值越大回答越灵活)
completions-path: /v1/chat/completions # 对话接口路径(上面截图 API 地址)
配置项说明:
import jakarta.annotation.Resource;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.openai.OpenAiChatModel;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class AiChatConfig {
@Resource
// 自动装配 OpenAiChatModel:由 spring-ai-starter-model-openai 自动配置
private OpenAiChatModel openAiChatModel;
/**
* 配置 ChatClient - OpenAI 兼容的聊天客户端
*
* @return ChatClient 实例
*/
@Bean("open-ai")
public ChatClient openAIChatClient() {
return ChatClient.builder(openAiChatModel).build();
}
}
import lombok.RequiredArgsConstructor;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RequiredArgsConstructor
@RestController
@RequestMapping("/ai")
public class AiChatController {
private final ChatClient chatClient;
// 请求方式和路径不要改动,将来要与前端联调
@RequestMapping("/chat")
public String chat(@RequestParam(defaultValue = "介绍一下你自己") String prompt) {
return chatClient
.prompt(prompt) // 传入用户提示词
.call() // 同步请求,会等待 AI 全部输出完才返回结果
.content(); // 返回响应内容
}
}
请求地址:http://localhost:8080/ai/chat

Spring AI 围绕 ChatClient 构建统一对话入口,核心相关 API 及作用如下:
| 核心 API | 所属包 | 核心作用 |
|---|---|---|
| ChatClient | org.springframework.ai.chat.client | 大模型对话统一入口,封装同步 / 流式调用 |
| ChatClient.Builder | org.springframework.ai.chat.client | 构建 ChatClient 实例,配置系统提示、增强器 |
| OpenAiChatModel | org.springframework.ai.openai | OpenAI 兼容的模型实现,由 Spring 自动装配 |
| ChatMemory | org.springframework.ai.chat.memory | 对话记忆接口,存储多轮对话上下文 |
| MessageWindowChatMemory | org.springframework.ai.chat.memory | ChatMemory 的实现类,基于消息窗口保留上下文 |
| MessageChatMemoryAdvisor | org.springframework.ai.chat.client.advisor | 会话记忆增强器,实现多轮对话上下文关联 |
| SimpleLoggerAdvisor | org.springframework.ai.chat.client.advisor | 日志增强器,打印 AI 交互全流程日志 |
| Flux | reactor.core.publisher | 流式返回结果类型,实现前端实时接收数据 |
同步调用是指等待大模型完整返回结果后,再将数据返回给前端,适用于短文本问答场景,
核心 API 为String ChatClient.prompt().call().content()。
快速开始中就是使用同步调用
流式调用是指大模型逐字 / 逐段返回结果,前端实时接收并展示,解决同步调用'等待时间长、用户体验差'的问题,核心基于 WebFlux 实现
核心 API 为Flux<String> ChatClient.prompt().stream().content()。
编写流式对话接口
在 ChatController 中添加流式调用接口 chat2:
/**
* 流式对话接口
*
* @param prompt 用户提问的提示词,默认值为'介绍一下你自己'
* @return Flux<String> 流式结果,前端实时接收
*/
@RequestMapping(value = "/chat2", produces = "text/html;charset=UTF-8")
public Flux<String> chat2(@RequestParam(defaultValue = "介绍一下你自己") String prompt) {
// 流式调用核心 API 链
return chatClient
.prompt(prompt) // 传入用户提示词
.stream() // 流式调用:非阻塞,逐段返回结果
.content(); // 提取流式的纯文本内容
}
重启测试,再次访问,会一点点生成数据展示在页面上。
可以发现,当我们询问 AI 你是谁的时候,它回答自己是 DeepSeek-R1,这是大模型底层的设定。如果我们希望 AI 按照新的设定工作,就需要给它设置 System 背景信息。
在 SpringAI 中,设置 System 信息非常方便,不需要在每次发送时封装到 Message,而是创建 ChatClient 时指定即可。
用于定义 AI 的角色、回答风格、业务规则,无需在每次调用时重复传递,由 ChatClient 自动附加到 Prompt 中,不同的项目可能需要设置不同的 System 信息,所以一般会定义对应的类保存。
创建 SystemManage 系统设置管理类
/**
* AI 服务 System 模板管理
* 职责:统一管理所有 AI 服务使用的 System 模板
*/
public class SystemManage {
// 提示词 Demo
public static final String DEMO_SYSTEM = """
你是一个专业的 AI 智能助手,你的名字叫小艾同学,请以友好、乐于助人和愉快的方式解答各种问题。
重要:当用户询问具体信息时,不要编造不存在的数据。
""";
}
修改 AiChatConfig 类
import jakarta.annotation.Resource;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.openai.OpenAiChatModel;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class AiChatConfig {
@Resource
// 自动装配 OpenAiChatModel:由 spring-ai-starter-model-openai 自动配置
private OpenAiChatModel openAiChatModel;
/**
* 配置 ChatClient - OpenAI 兼容的聊天客户端
*
* @return ChatClient 实例
*/
@Bean("open-ai")
public ChatClient openAIChatClient() {
return ChatClient.builder(openAiChatModel)
// 配置系统提示:定义 AI 的角色、回答风格
.defaultSystem(SystemManage.DEMO_SYSTEM)
.build();
}
}
重启测试,再次访问,会按照定义的内容生成。
多轮对话的核心是上下文关联,即 AI 能识别上一轮的提问和回答,例如:
用户:12 个苹果分给 2 个人,每人分几个?
AI:6 个;
用户:分给 3 个人呢?
AI:4 个(需识别'12 个苹果'的上下文)。
核心原理
Spring AI 通过 ChatMemory + MessageChatMemoryAdvisor 实现该能力,无需额外编写业务代码,只需在配置类中完成相关 Bean 配置。
Advisor 核心概念
Advisor 是 Spring AI 基于 AOP 切面机制实现的功能增强接口,用于在大模型对话的请求前、响应后进行无侵入式处理,核心执行流程:
用户请求 → AdvisedRequest(增强前请求)→ Advisor 增强(如添加上下文、记录日志)→ Prompt(最终请求)→ 大模型 → ChatResponse(模型响应)→ Advisor 增强(如存储上下文)→ AdvisedResponse(增强后响应)→ 返回给用户
Advisor API
| Advisor 类名 | 核心作用 | 配置方式 |
|---|---|---|
| MessageChatMemoryAdvisor | 实现多轮对话上下文关联,自动读写 ChatMemory | MessageChatMemoryAdvisor.builder(chatMemory).build() |
修改 AiChatConfig 类
import jakarta.annotation.Resource;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.openai.OpenAiChatModel;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class AiChatConfig {
@Resource
// 自动装配 OpenAiChatModel:由 spring-ai-starter-model-openai 自动配置
private OpenAiChatModel openAiChatModel;
/**
* 配置 ChatMemory - 内存存储的会话记忆
*
* @return ChatMemory 内存存储的会话记忆实例
*/
@Bean
public ChatMemory chatMemory() {
return MessageWindowChatMemory.builder()
.maxMessages(30) // 窗口最大消息数目,保留最近 30 条消息
.build();
}
/**
* 配置 ChatClient - OpenAI 兼容的聊天客户端
*
* @return ChatClient 实例
*/
@Bean("open-ai")
public ChatClient openAIChatClient() {
return ChatClient.builder(openAiChatModel)
// 配置系统提示:定义 AI 的角色、回答风格
.defaultSystem(SystemManage.DEMO_SYSTEM)
// 配置增强器:会话记忆(多轮对话)
.defaultAdvisors(
// 会话记忆增强器,实现多轮对话上下文关联
MessageChatMemoryAdvisor.builder(chatMemory).build(),
// 会话记忆增强器
new SimpleLoggerAdvisor()
).build();
}
}
测试多轮对话
默认情况下,应用于 AI 的交互时不记录日志的,我们无法得知 SpringAI 组织的提示词到底长什么样,有没有问题。这样不方便我们调试。
SpringAI 基于 AOP 机制实现与大模型对话过程的增强、拦截、修改等功能。所有的增强通知都需要实现 Advisor 接口。

Advisor API
| Advisor 类名 | 核心作用 | 配置方式 |
|---|---|---|
| SimpleLoggerAdvisor | 记录 AI 交互全流程日志(Prompt、响应、Token 等) | new SimpleLoggerAdvisor() |
修改 AiChatConfig 类
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.ChatMemory;
import org.springframework.ai.chat.memory.MessageWindowChatMemory;
import org.springframework.ai.openai.OpenAiChatModel;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class AiChatConfig {
@Resource
// 自动装配 OpenAiChatModel:由 spring-ai-starter-model-openai 自动配置
private OpenAiChatModel openAiChatModel;
/**
* 配置 ChatMemory - 内存存储的会话记忆
*
* @return ChatMemory 内存存储的会话记忆实例
*/
@Bean
public ChatMemory chatMemory() {
return MessageWindowChatMemory.builder()
.maxMessages(30) // 窗口最大消息数目,保留最近 30 条消息
.build();
}
/**
* 配置 ChatClient - OpenAI 兼容的聊天客户端
*
* @return ChatClient 实例
*/
@Bean("open-ai")
public ChatClient openAIChatClient() {
return ChatClient.builder(openAiChatModel)
// 配置系统提示:定义 AI 的角色、回答风格
.defaultSystem(SystemManage.DEMO_SYSTEM)
// 配置增强器:会话记忆(多轮对话)+ 日志记录(调试)
.defaultAdvisors(
MessageChatMemoryAdvisor.builder(chatMemory).build(), // 会话记忆增强器
new SimpleLoggerAdvisor()
).build();
}
}
修改日志级别
在 application.yaml 中添加日志配置,更新日志级别:
位置要顶格写,不要写在 spring 标签的下面
logging:
level:
org.springframework.ai: debug # AI 对话的日志级别
com.ruangong.springai: debug # 本项目的日志级别
重启项目,再次聊天就能看到 AI 对话的日志信息了~
工具调用是 Spring AI 核心扩展能力之一,允许大模型根据用户提问自动判断并调用自定义工具(如天气查询、数据库操作、计算器等),而非仅依赖模型自身知识回答问题,核心解决'大模型知识时效性差、无法执行实时 / 计算类操作'的问题。
工具调用流程

工具调用常用注解
| 核心组件 | 所属包 | 注解位置 | 作用 |
|---|---|---|---|
| @Tool | org.springframework.ai.annotation | 方法 | 标记方法为可被 AI 调用的工具 |
| @ToolParam | org.springframework.ai.annotation | 参数 | 标记被 AI 调用的工具方法参数 |
定义可被 AI 调用的工具类
import org.springframework.ai.tool.annotation.Tool;
import org.springframework.ai.tool.annotation.ToolParam;
import org.springframework.stereotype.Component;
/**
* 这里两个示例工具方法就直接返回字符串,实际项目中可以注入 mapper 实现数据库查询
* 工具 1:数学计算工具
* 工具 2:天气查询工具
*/
@Component
public class MyTool {
@Tool(
name = "calculator_tool",
description = "执行数学计算,参数:expression(数学表达式,如 10+20*3)",
returnDirect = true
)
public String calculator_tool(@ToolParam(description = "执行数学计算,如 10+20*3 等") String expression) {
System.out.println("------------------------------------------数学计算-----------------------------------------");
// 简单计算(实际可使用安全的表达式解析库,如 JEP)
return "自己拿计算器算去";
}
@Tool(
name = "weather_tool",
description = "查询指定城市的实时天气信息,入参:city(城市名称,如北京、上海)",
returnDirect = true
)
public String weather_tool(@ToolParam(description = "搜索关键词,如'北京'、'上海'等") String city) {
System.out.println("------------------------------------------天气查询-----------------------------------------");
String weatherInfo = switch (city) {
case "北京" -> "晴,气温 18~28℃,西南风 2 级";
case "上海" -> "多云,气温 22~30℃,东南风 3 级";
case "广州" -> "小雨,气温 25~32℃,东北风 1 级";
default -> "暂未查询到「" + city + "」的天气信息,请确认城市名称";
};
weatherInfo;
}
}
修改 AiChatConfig 类
import jakarta.annotation.Resource;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.openai.OpenAiChatModel;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class AiChatConfig {
@Resource
// 自动装配 OpenAiChatModel:由 spring-ai-starter-model-openai 自动配置
private OpenAiChatModel openAiChatModel;
@Resource
// 注入工具函数所在工具类 MyTool
private MyTool myTool;
/**
* 配置 ChatMemory - 内存存储的会话记忆
*
* @return ChatMemory 内存存储的会话记忆实例
*/
@Bean
public ChatMemory chatMemory() {
return MessageWindowChatMemory.builder()
.maxMessages(30) // 窗口最大消息数目,保留最近 30 条消息
.build();
}
/**
* 配置 ChatClient - OpenAI 兼容的聊天客户端
*
* @return ChatClient 实例
*/
@Bean("open-ai")
public ChatClient openAIChatClient() {
return ChatClient.builder(openAiChatModel)
// 配置系统提示:定义 AI 的角色、回答风格
.defaultSystem(SystemManage.DEMO_SYSTEM)
// 配置增强器:会话记忆(多轮对话)
.defaultAdvisors(
// 会话记忆增强器,实现多轮对话上下文关联
MessageChatMemoryAdvisor.builder(chatMemory).build(),
// 会话记忆增强器
new SimpleLoggerAdvisor()
)
// 配置自定义调用工具
.defaultTools(myTool)
.build();
}
}
这样就可以实现工具调用了,由大模型自动识别调用,当然为了提高工具调用的命中率可以修改系统设置
// 提示词 Demo
public static final String TEST_SYSTEM = """
你是一个专业的 AI 智能助手,你的名字叫小艾同学,请以友好、乐于助人和愉快的方式解答各种问题。
## 可用工具函数:
当用户询问具体信息时,你应该**优先使用工具函数**查询数据库中的实际数据,而不是凭空回答:
1. **calculator_tool(expression)** - 执行数学计算
- 用途:当用户询问'帮我算'、'帮我计算',如帮我算 10+20*3 等
- 示例:calculator_tool("10+20*3")
2. **weather_tool(city)** - 查询指定城市的实时天气信息
- 用途:当用户询问'今天北京天气怎么样'、'广州天气'等
- 示例:weather_tool("北京")
**重要**:当用户询问具体信息时,必须先调用相应工具查询,然后基于查询结果进行回答。不要编造不存在的数据。
""";
在浏览器通过地址访问,非常麻烦,也不够优雅。如果能有一个优美的前端页面就好了。
别着急,我提前给大家准备了一个前端页面。已经进行了资源绑定

前端启动流程
解决 CORS 问题
前后端在不同域名,存在跨域问题,因此我们需要在服务端解决 cors 问题。在 config 包中添加一个类:
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class MvcConfiguration implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
.allowedHeaders("*")
.exposedHeaders("Content-Disposition");
}
}
重启服务,如果你的服务端接口正确,那么应该就可以聊天了。
注意:前端访问服务端的默认路径是:http://localhost:8080
聊天对话的接口是:POST /ai/chat 如果想实现流式对话将后台请求路径修改
请确保你的服务端接口也是这样。

恭喜您,你的第一个 AI 对话机器人就简单完成了。
在实际项目中,不同用户会在不同会话进行提问,在上文的多轮对话上下文中,使用 MessageChatMemoryAdvisor 仅能实现上下文,无法实现会话隔离。
因为所有的请求都使用默认的记忆,所以要实现会话级别的记忆那么久需要为每一个会话都创建一个专属于会话的'记忆',例如前台案例请求携带的 chatId,就是会话的标识
修改 ChatController 对应方法
/**
* 流式对话接口
*
* @param prompt 用户提问的提示词,默认值为'介绍一下你自己'
* @return Flux<String> 流式结果,前端实时接收
*/
@RequestMapping(value = "/chat2", produces = "text/html;charset=UTF-8")
public Flux<String> chat2(@RequestParam(defaultValue = "介绍一下你自己") String prompt, String chatId) {
// 流式调用核心 API 链
return chatClient
.prompt(prompt) // 传入用户提示词
// 为当前请求设置对话记忆 (使用默认的会话 id 标识与前台生成的 chatId)
.advisors(advisorSpec -> advisorSpec.param(ChatMemory.CONVERSATION_ID, chatId))
.stream() // 流式调用:非阻塞,逐段返回结果
.content(); // 提取流式的纯文本内容
}
页面在进行会话切换时,会将会话的 Id 发送给后台,获取信息,所以后台需要保存对话信息
创建 AiChatMessage 类,保存对话信息
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.time.LocalDateTime;
/**
* AI 聊天消息实体类
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class AiChatMessage {
// 消息 ID
private Long id;
// 会话 ID
private String sessionId;
// 角色:user-用户,assistant-AI 助手
private String role;
// 消息内容
private String content;
// 创建时间
private LocalDateTime createTime;
}
数据实际应该存储到数据库,本文使用自定义数据类模拟
创建 MessageData 类,模拟存储对话数据
import java.util.ArrayList;
// 保存对话信息工具类,模拟数据库存储
public class MessageData {
public static ArrayList<AiChatMessage> messages = new ArrayList<>();
public static void addMessage(AiChatMessage message) {
messages.add(message);
}
}
修改 ChatController 类内容
/**
* 流式对话接口
*
* @param prompt 用户提问的提示词,默认值为'介绍一下你自己'
* @return Flux<String> 流式结果,前端实时接收
*/
@RequestMapping(value = "/chat2", produces = "text/html;charset=UTF-8")
public Flux<String> chat2(@RequestParam(defaultValue = "介绍一下你自己") String prompt, String chatId) {
// 流式调用核心 API 链 获取结果
Flux<String> content = chatClient
.prompt(prompt)
.advisors(advisorSpec -> advisorSpec.param(ChatMemory.CONVERSATION_ID, chatId))
.stream()
.content();
// 将用户信息存储
MessageData.addMessage(AiChatMessage.builder()
.role(MessageType.USER.getValue())
.content(prompt)
.sessionId(chatId)
.build());
StringBuilder fullResponse = new StringBuilder();
return content.doOnNext(fullResponse::append)
// 返回结束时执行
.doOnComplete(() -> {
// 获取会话结果存储
MessageData.addMessage(AiChatMessage.builder()
.role(MessageType.ASSISTANT.getValue())
.content(fullResponse.toString())
.sessionId(chatId)
.build());
});
}
@GetMapping("/history/chat/{chatId}")
public List<AiChatMessage> history(@PathVariable String chatId) {
// 获取指定会话的历史信息并返回
return MessageData.messages.stream()
.filter(msg -> msg.getSessionId().equals(chatId))
.toList();
}
因为只是一个案例,所以使用 session 存储会话 id,实际开发中创建会话可以存储到数据库中,然后通过数据库查询返回
修改 ChatController 类内容
/**
* 流式对话接口
*
* @param prompt 用户提问的提示词,默认值为'介绍一下你自己'
* @return Flux<String> 流式结果,前端实时接收
*/
@RequestMapping(value = "/chat", produces = "text/html;charset=UTF-8")
public Flux<String> chat2(@RequestParam(defaultValue = "介绍一下你自己") String prompt, String chatId, HttpSession session) {
// 获取当前会话中的 chatId 列表
HashSet<String> sessionIds = (HashSet<String>) session.getAttribute("sessionIds");
// 因为是 set 集合所以每次请求直接添加即可
sessionIds.add(chatId);
// 将最新的 chatId 列表存入 sessin
session.setAttribute("sessionIds", sessionIds);
// 流式调用核心 API 链 获取结果
Flux<String> content = chatClient
.prompt(prompt)
.advisors(advisorSpec -> advisorSpec.param(ChatMemory.CONVERSATION_ID, chatId))
.stream()
.content();
// 将用户信息存储
MessageData.addMessage(AiChatMessage.builder()
.role(MessageType.USER.getValue())
.content(prompt)
.sessionId(chatId)
.build());
StringBuilder fullResponse = new StringBuilder();
return content.doOnNext(fullResponse::append)
// 返回结束时执行
.doOnComplete(() -> {
// 获取会话结果存储
MessageData.addMessage(AiChatMessage.builder()
.role(MessageType.ASSISTANT.getValue())
.content(fullResponse.toString())
.sessionId(chatId)
.build());
});
}
@GetMapping("/history/chat/{chatId}")
public List<AiChatMessage> history(@PathVariable String chatId) {
return MessageData.messages.stream()
.filter(msg -> msg.getSessionId().equals(chatId))
.toList();
}
/**
* 获取历史会话列表方法
*
* @param session 当前会话对象 自动注入
* HashSet<String> 存储 ChatId 的集合
*/
HashSet<String> {
System.out.println();
HashSet<String> sessionIds = (HashSet<String>) session.getAttribute();
(sessionIds == ) {
sessionIds = <String>();
sessionIds.add();
sessionIds.add();
sessionIds.add();
}
sessionIds;
}

微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online
JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online
使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online
Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online
生成新的随机RSA私钥和公钥pem证书。 在线工具,RSA密钥对生成器在线工具,online
基于 Mermaid.js 实时预览流程图、时序图等图表,支持源码编辑与即时渲染。 在线工具,Mermaid 预览与可视化编辑在线工具,online