文章目录
- SpringBoot使用SpringAi完成简单智能助手
- [一、Spring AI 基础认知](#一、Spring AI 基础认知)
-
- [1.1 主流大模型开发框架对比](#1.1 主流大模型开发框架对比)
- [1.2 Spring AI 核心特性](#1.2 Spring AI 核心特性)
- [1.3 快速开始](#1.3 快速开始)
- [1.4 Spring AI 核心 API](#1.4 Spring AI 核心 API)
- [1.5 流式结果](#1.5 流式结果)
- [1.6 系统(角色)设置](#1.6 系统(角色)设置)
- [1.7 多轮对话上下文](#1.7 多轮对话上下文)
- [1.8 日志集成](#1.8 日志集成)
- [1.9 工具调用](#1.9 工具调用)
- [1.10 前端集成](#1.10 前端集成)
- [1.11 会话隔离](#1.11 会话隔离)
- [1.12 前端界面功能简单实现](#1.12 前端界面功能简单实现)

SpringBoot使用SpringAi完成简单智能助手
一、Spring AI 基础认知
1.1 主流大模型开发框架对比
Java 领域实现大模型(LLM)开发的两大核心框架,核心差异如下:
表格
| 框架 | 最低JDK版本 | 核心优势 |
|---|---|---|
| Spring AI | 17 | 深度适配 SpringBoot 生态,自动装配,开发成本低 |
| LangChain4J | 8 | 兼容性强,支持低版本 JDK,生态插件丰富 |
1.2 Spring AI 核心特性
- 完全适配 SpringBoot 自动装配,提供各主流大模型的 starter 依赖,快速集成;
- 封装 ChatClient 统一对话 API,支持同步调用和流式调用两种交互方式;
- 基于 Advisor 切面机制实现功能增强,支持会话记忆、日志记录、RAG 等能力;
- 自动扫描 @Tool 注解实现工具调用,无需手动注册;
- 支持自定义 System 系统提示、对话上下文记忆,适配多轮对话场景。
1.3 快速开始
先带大家快速搭建一个基本功能项目,后面再依次拆分讲解
环境要求JDK:17 及以上版本(Spring AI 强制要求);
SpringBoot:3.5.9 及以上(本文示例使用 3.5.9);
构建工具:Maven;
大模型 URL&API:可通过硅基流动(https://www.siliconflow.cn/) 获取(支持 DeepSeek、OpenAI 等多模型,需实名认证并获取 API-Key)。
①创建SpringBoot项目

②引入依赖
首先,在项目pom.xml中添加spring-ai的版本信息:
xml
<properties>
<java.version>17</java.version>
<spring-ai.version>1.0.0-SNAPSHOT</spring-ai.version> <!-- Spring AI 版本 -->
</properties>
然后,添加spring-ai的依赖管理项:
xml
<!-- 管理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 的依赖:
xml
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-model-openai</artifactId>
<version>${spring-ai.version}</version>
</dependency>
为了方便后续开发,我们再手动引入一个Lombok依赖:
xml
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.22</version>
</dependency>
注意: 千万不要用start.spring.io提供的lombok,有bug!!
完整依赖(复制注意修改项目信息)
xml
<?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/> <!-- lookup parent from repository -->
</parent>
<groupId>com.ai</groupId>
<artifactId>SpringAi</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>SpringAi</name>
<description>SpringAi</description>
<properties>
<java.version>17</java.version>
<spring-ai.version>1.0.0-SNAPSHOT</spring-ai.version>
</properties>
<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>
<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>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-model-openai</artifactId>
<version>${spring-ai.version}</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.22</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
③配置模型信息
首先需要使用Ai的对应key
介绍一个网站,叫做硅基流动 https://www.siliconflow.cn/,可以从这获取,当然后面也会介绍其他的模型获取网站ps:点击链接会默认填写推荐码,谢谢大家

无论什么大模型网站我们都需要获取两个内容
-
模型请求地址

-
API key

接下来,我们在配置文件中配置模型的参数信息。
以 openai 为例,我们将
application.properties修改为application.yaml,然后添加下面的内容:
yml
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地址)
配置项说明:
- api-key:大模型平台的访问密钥,需从硅基流动 / OpenAI 等平台获取;
- base-url:大模型的接口根地址,硅基流动为https://api.siliconflow.cn,OpenAI 官方为-https://api.openai.com/v1;
- model:指定调用的大模型名称,需与平台提供的模型名完全一致;
- temperature:回答的随机性,0 为完全固定回答,1 为最大随机性,推荐 0.5-0.7;
- completions-path:对话接口的固定路径,主流大模型均为/v1/chat/completions。
④创建AiChatConfig工具类
java
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自动配置
OpenAiChatModel openAiChatModel;
/**
* 配置 ChatClient - OpenAI兼容的聊天客户端
* @return ChatClient 实例
*/
@Bean("open-ai")
public ChatClient openAIChatClient() {
return ChatClient.builder(openAiChatModel)
.build();
}
}
⑤创建AiChatController控制类
java
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

1.4 Spring AI 核心 API
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 | 流式返回结果类型,实现前端实时接收数据 |
1.5 流式结果
同步调用是指等待大模型完整返回结果后,再将数据返回给前端,适用于短文本问答场景,
核心API 为
String ChatClient.prompt().call().content()。快速开始中就是使用同步调用
流式调用是指大模型逐字 / 逐段返回结果,前端实时接收并展示,解决同步调用 "等待时间长、用户体验差" 的问题,核心基于WebFlux实现核心 API 为
Flux<String> ChatClient.prompt().stream().content()。
编写流式对话接口
在ChatController中添加流式调用接口chat2:
java
/**
* 流式对话接口
* @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(); // 提取流式的纯文本内容
}
重启测试,再次访问,会一点点生成数据展示在页面上。

1.6 系统(角色)设置
可以发现,当我们询问AI你是谁的时候,它回答自己是DeepSeek-R1,这是大模型底层的设定。如果我们希望AI按照新的设定工作,就需要给它设置System背景信息。
在SpringAI中,设置System信息非常方便,不需要在每次发送时封装到Message,而是创建ChatClient时指定即可。用于定义 AI 的角色、回答风格、业务规则,无需在每次调用时重复传递,由 ChatClient 自动附加到 Prompt 中,不同的项目可能需要设置不同的System信息,所以一般会定义对应的类保存。
创建SystemManage系统设置管理类
java
/**
* AI服务System模板管理
* 职责:统一管理所有AI服务使用的System模板
*/
public class SystemManage {
//提示词Demo
public static final String DEMO_SYSTEM= """
你是一个专业的AI智能助手,你的名字叫小艾同学,请以友好、乐于助人和愉快的方式解答各种问题。
重要:当用户询问具体信息时,不要编造不存在的数据。
""";
}
修改AiChatConfig类
java
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自动配置
OpenAiChatModel openAiChatModel;
/**
* 配置 ChatClient - OpenAI兼容的聊天客户端
* @return ChatClient 实例
*/
@Bean("open-ai")
public ChatClient openAIChatClient() {
return ChatClient.builder(openAiChatModel)
// 配置系统提示:定义AI的角色、回答风格
.defaultSystem(SystemManage.DEMO_SYSTEM)
.build();
}
}
重启测试,再次访问,会按照定义的内容生成。

1.7 多轮对话上下文
多轮对话的核心是上下文关联,即 AI 能识别上一轮的提问和回答,例如:
用户:12 个苹果分给 2 个人,每人分几个?
AI:6 个;
用户:分给 3 个人呢?
AI:4 个(需识别 "12 个苹果" 的上下文)。
核心原理
- MessageChatMemoryAdvisor会在每次调用大模型时,自动从 ChatMemory 中读取历史对话消息,并附加到当前 Prompt 中;
- 大模型基于历史消息 + 当前提问生成回答,实现上下文关联;
- 回答生成后,MessageChatMemoryAdvisor会自动将当前用户消息和 AI 回答存入 ChatMemory,更新上下文。
Spring AI 通过ChatMemory + MessageChatMemoryAdvisor实现该能力,无需额外编写业务代码,只需在配置类中完成相关 Bean 配置。
Advisor 核心概念
Advisor 是 Spring AI 基于AOP 切面机制实现的功能增强接口,用于在大模型对话的请求前、响应后进行无侵入式处理,核心执行流程:
java
用户请求 → AdvisedRequest(增强前请求)→ Advisor增强(如添加上下文、记录日志)→ Prompt(最终请求)→ 大模型 → ChatResponse(模型响应)→ Advisor增强(如存储上下文)→ AdvisedResponse(增强后响应)→ 返回给用户
Advisor API
| Advisor 类名 | 核心作用 | 配置方式 |
|---|---|---|
| MessageChatMemoryAdvisor | 实现多轮对话上下文关联,自动读写 ChatMemory | MessageChatMemoryAdvisor.builder(chatMemory).build() |
修改AiChatConfig类
java
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自动配置
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(), // 会话记忆增强器
)
.build();
}
}
测试多轮对话
- 第一次访问:http://localhost:8080/ai/chat?prompt=12个苹果分给2个人,每人分几个?
返回:6 个; - 第二次访问:http://localhost:8080/ai/chat?prompt=分给3个人呢?
返回:4 个(成功识别上下文 "12 个苹果")。

1.8 日志集成
默认情况下,应用于AI的交互时不记录日志的,我们无法得知SpringAI组织的提示词到底长什么样,有没有问题。这样不方便我们调试。
SpringAI基于AOP机制实现与大模型对话过程的增强、拦截、修改等功能。所有的增强通知都需要实现Advisor接口。

Advisor API
| Advisor 类名 | 核心作用 | 配置方式 |
|---|---|---|
| SimpleLoggerAdvisor | 记录 AI 交互全流程日志(Prompt、响应、Token 等) | new SimpleLoggerAdvisor() |
修改AiChatConfig类
java
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自动配置
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 标签的下面
yml
logging:
level:
org.springframework.ai: debug # AI对话的日志级别
com.ruangong.springai: debug # 本项目的日志级别
重启项目,再次聊天就能看到AI对话的日志信息了~

1.9 工具调用
工具调用是 Spring AI 核心扩展能力之一,允许大模型根据用户提问自动判断并调用自定义工具(如天气查询、数据库操作、计算器等),而非仅依赖模型自身知识回答问题,核心解决 "大模型知识时效性差、无法执行实时 / 计算类操作" 的问题。
工具调用流程

工具调用常用注解
| 核心组件 | 所属包 | 注解位置 | 作用 |
|---|---|---|---|
| @Tool | org.springframework.ai.annotation | 方法 | 标记方法为可被 AI 调用的工具 |
| @ToolParam | org.springframework.ai.annotation | 参数 | 标记被 AI 调用的工具方法参数 |
定义可被 AI 调用的工具类
java
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 + "」的天气信息,请确认城市名称";
};
return weatherInfo;
}
}
修改AiChatConfig类
java
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自动配置
OpenAiChatModel openAiChatModel;
@Resource
//注入工具函数所在工具类
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(), // 会话记忆增强器
)
// 配置自定义调用工具
.defaultTools(myTool)
.build();
}
}
这样就可以实现工具调用了,由大模型自动识别调用,当然为了提高工具调用的命中率可以修改系统设置
java
//提示词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("北京")
**重要**:当用户询问具体信息时,必须先调用相应工具查询,然后基于查询结果进行回答。不要编造不存在的数据。
""";
1.10 前端集成
在浏览器通过地址访问,非常麻烦,也不够优雅。如果能有一个优美的前端页面就好了。
别着急,我提前给大家准备了一个前端页面。已经进行了资源绑定

前端启动流程
- 删除node_modules,pakage-lock.json文件
- 执行 npm install --registry=https://registry.npmmirror.com
- 执行 npm run dev 就可以启动了
解决CORS问题
前后端在不同域名,存在跨域问题,因此我们需要在服务端解决cors问题。在 config 包中添加一个类:
java
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对话机器人就简单完成了。
1.11 会话隔离
在实际项目中,不同用户会在不同会话进行提问,在上文的多轮对话上下文中,使用MessageChatMemoryAdvisor仅能实现上下文,无法实现会话隔离。
因为所有的请求都使用默认的记忆,所以要实现会话级别的记忆那么久需要为每一个会话都创建一个专属于会话的"记忆",例如前台案例请求携带的chatId,就是会话的标识
修改ChatController 对应方法
java
/**
* 流式对话接口
* @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(); // 提取流式的纯文本内容
}
1.12 前端界面功能简单实现
多会话切换历史查询
页面在进行会话切换时,会将会话的Id发送给后台,获取信息,所以后台需要保存对话信息
创建AiChatMessage类,保存对话信息
java
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.time.LocalDateTime;
/**
* AI聊天消息实体类
* @author system
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
//AI聊天消息实体类
public class AiChatMessage {
//消息ID
private Long id;
//会话ID
private String sessionId;
//角色:user-用户,assistant-AI助手
private String role;
//消息内容")
private String content;
//创建时间
private LocalDateTime createTime;
}
数据实际应该存储到数据库,本文使用自定义数据类模拟
创建MessageData类,模拟存储对话数据
java
import java.util.ArrayList;
//保存对话信息工具类,模拟数据库存储
public class MessageData {
public static ArrayList<AiChatMessage> messages=new ArrayList<>();
public static void addMessage(AiChatMessage message){
messages.add(message);
}
}
修改ChatController类内容
java
/**
* 流式对话接口
* @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类内容
java
/**
* 流式对话接口
* @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 当前会话对象 自动注入
* @return HashSet<String> 存储ChatId的集合
*/
@GetMapping("/history/chat")
public HashSet<String> history1(HttpSession session){
System.out.println("----------------------------------------------");
HashSet<String> sessionIds= (HashSet<String>) session.getAttribute("sessionIds");
if(sessionIds==null){
sessionIds=new HashSet<String>();
//加几个模拟数据 要不需要手动点击
sessionIds.add("1773648154863");
sessionIds.add("1773648154864");
sessionIds.add("1773648154865");
}
return sessionIds;
}