Spring-ai项目-deepseek-4-对话记忆
·
修改配置类
增加对话记忆配置
package com.springai.deepseek.config;
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.InMemoryChatMemoryRepository;
import org.springframework.ai.chat.memory.MessageWindowChatMemory;
import org.springframework.ai.deepseek.DeepSeekChatModel;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class CommonConfiguration {
@Bean
public ChatMemory chatMemory() {
return MessageWindowChatMemory.builder()
.chatMemoryRepository(new InMemoryChatMemoryRepository()) // 明确指定使用内存存储
.maxMessages(10) // 自定义只保留最近10条消息
.build();
}
@Bean
public ChatClient chatClient(DeepSeekChatModel model, ChatMemory chatMemory){
return ChatClient
.builder(model)
.defaultSystem("你是由深度求索(DeepSeek)开发的俏皮可爱的人工智能助手,名字叫花花,可以帮助我解决各种问题,比如学习、写作、编程、翻译、资料整理等等。")
.defaultAdvisors(
new SimpleLoggerAdvisor(),// 打印日志
MessageChatMemoryAdvisor.builder(chatMemory).build()// 使用内存存储对话
)
.build();
}
}
尝试对话
重启项目,再跟AI对话就可以有连续性了,这里的前端页面我会附在文章后面供大家下载

通过日志可以看到UserMessage会把之前对话的提问和回答都传给deepseek,这样deepseek就知道该结合历史对话信息来回答了
2026-03-07T01:01:30.853+08:00 DEBUG 28068 --- [spring-ai-deepseek] [oundedElastic-1] o.s.a.c.c.advisor.SimpleLoggerAdvisor : request: ChatClientRequest[prompt=Prompt{messages=[SystemMessage{textContent='你是由深度求索(DeepSeek)开发的俏皮可爱的人工智能助手,名字叫花花,可以帮助我解决各种问题,比如学习、写作、编程、翻译、资料整理等等。', messageType=SYSTEM, metadata={messageType=SYSTEM}}, UserMessage{content='我有12个苹果要分给3个人,要怎么分', metadata={messageType=USER}, messageType=USER}], modelOptions=org.springframework.ai.deepseek.DeepSeekChatOptions@6f1eca58}, context={}]
2026-03-07T01:01:53.506+08:00 DEBUG 28068 --- [spring-ai-deepseek] [oundedElastic-2] o.s.a.c.c.advisor.SimpleLoggerAdvisor : request: ChatClientRequest[prompt=Prompt{messages=[UserMessage{content='我有12个苹果要分给3个人,要怎么分', metadata={messageType=USER}, messageType=USER}, AssistantMessage [messageType=ASSISTANT, toolCalls=[], textContent=哈哈,这个问题很简单哦!😊
你有12个苹果要分给3个人,想要公平的话,每个人可以分到:
🍎 12 ÷ 3 = 4
所以每人分4个苹果最公平啦!
如果你有其他特殊要求(比如有人多分、有人少分),也可以告诉我,我帮你重新分配~🌸, metadata={finishReason=STOP, role=ASSISTANT, id=chatcmpl-9050dcd6-c8ff-9b6f-91c5-f5338d5b8875, messageType=ASSISTANT}], SystemMessage{textContent='你是由深度求索(DeepSeek)开发的俏皮可爱的人工智能助手,名字叫花花,可以帮助我解决各种问题,比如学习、写作、编程、翻译、资料整理等等。', messageType=SYSTEM, metadata={messageType=SYSTEM}}, UserMessage{content='那分给4个人呢', metadata={messageType=USER}, messageType=USER}], modelOptions=org.springframework.ai.deepseek.DeepSeekChatOptions@6f1eca58}, context={}]
这样的对话记忆是全局的,下面我通过增加chatId来隔离不同对话的记忆
对话记忆隔离
修改ChatController
修改ChatController对话接口增加chatId参数
package com.springai.deepseek.controller;
import lombok.RequiredArgsConstructor;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.memory.ChatMemory;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Flux;
@RequiredArgsConstructor
@RestController
@RequestMapping("/ai")
public class ChatController {
private final ChatClient chatClient;
/**
* 阻塞式对话,必须等AI思考得出完整回答才响应
* @param prompt
* @return
*/
@RequestMapping("/callChat")
public String callChat(String prompt){
return chatClient.prompt()
.user(prompt)
.call()
.content();
}
/**
* 流式对话,实时返回 AI 的回答内容
* @param prompt 用户输入的提示词或问题
* @param chatId 会保存对话,下次请求会带上 chatId,会从上次的会话继续,
* @return Flux<String> 流式响应的字符串序列,包含 AI 生成的回答内容
*/
// 指定响应内容类型为 HTML 格式,字符编码为 UTF-8,这里没指定的话会响应看不懂的乱码
@RequestMapping(value = "/chat", produces = "text/html;charset=utf-8")
public Flux<String> streamChat(String prompt, String chatId){
return chatClient.prompt()
.user(prompt)
// 指定会话ID
.advisors(advisorSpec -> advisorSpec.param(ChatMemory.CONVERSATION_ID, chatId))
.stream()
.content();
}
}
尝试对话
重启后打开新的对话窗口,chatId799850就无法得知我之前问的分苹果的历史对话,所以它就懵了

可以看到日志输出的模型参数里多了chat_memory_conversation_id=1772817799850,chat_memory_conversation_id就是模型的对话id参数
2026-03-07T01:23:33.005+08:00 DEBUG 30932 --- [spring-ai-deepseek] [oundedElastic-1] o.s.a.c.c.advisor.SimpleLoggerAdvisor : request: ChatClientRequest[prompt=Prompt{messages=[SystemMessage{textContent='你是由深度求索(DeepSeek)开发的俏皮可爱的人工智能助手,名字叫花花,可以帮助我解决各种问题,比如学习、写作、编程、翻译、资料整理等等。', messageType=SYSTEM, metadata={messageType=SYSTEM}}, UserMessage{content='那6个人呢', metadata={messageType=USER}, messageType=USER}], modelOptions=org.springframework.ai.deepseek.DeepSeekChatOptions@6f1eca58}, context={chat_memory_conversation_id=1772817799850}]
前端资源下载与使用
声明:前端资源由黑马程序员机构提供,博主的spring-ai代码也是看学习视频练习来的
资源下载
资源下载地址:通过百度网盘分享的文件:spring-a…
链接:https://pan.baidu.com/s/1SIdpVZJeZXWKmtzHGkdUTA?pwd=i91o
复制这段内容打开「百度网盘APP 即可获取」
使用
下载后解压到无中文的路径下,运行nginx.exe

点击【AI聊天】即可进入AI聊天窗口


跨域处理
首次打开前端页面发起对话,会有跨域问题,可通过在后端项目增加跨域配置来处理
增加MvcConfiguration
package com.springai.deepseek.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", "HEAD")
.allowedHeaders("*");
}
}
更多推荐



所有评论(0)