Spring AI 项目实战(五):Spring Boot + AI + DeepSeek + Redis 实现聊天应用上下文记忆功能(附完整源码)
系列文章
序号 | 文章名称 |
---|---|
1 | Spring AI 项目实战(一):Spring AI 核心模块入门 |
2 | Spring AI 项目实战(二):Spring Boot + AI + DeepSeek 深度实战(附完整源码) |
3 | Spring AI 项目实战(三):Spring Boot + AI + DeepSeek 打造智能客服系统(附完整源码) |
4 | Spring AI 项目实战(四):Spring Boot + AI + DeepSeek 超参数优化——智能化机器学习平台(附完整源码) |
5 | Spring AI 项目实战(五):Spring Boot + AI + DeepSeek + Redis 实现聊天应用上下文记忆功能(附完整源码) |
一、引言
在当今数字化时代,智能聊天应用的需求日益增长。为了开发出功能强大且具备上下文记忆功能的智能聊天应用,我们可以结合 Spring AI、DeepSeek API 和 Redis 等技术。本文将详细介绍如何基于 Spring Boot 3.2、Spring AI 1.0.0 - M4、DeepSeek API 和 Redis 实现一个完整的智能聊天应用,包括环境搭建、核心组件实现、REST API 控制器编写、Web 界面设计以及部署与测试等方面。
二、项目概述
本项目是一个完整的智能聊天应用,它展示了如何使用最新的 Spring AI 框架集成 DeepSeek API,并通过 Redis 实现对话上下文记忆功能。项目包含完整的前后端实现,提供了美观的 Web 界面和完善的 API 接口。其核心特性包括智能对话、上下文记忆、现代化界面、系统监控、会话管理、异常处理和智能路由等。
2.1 技术栈
本项目使用的技术栈如下:
- Spring Boot: 3.2.0,用于快速搭建项目框架。
- Spring AI: 1.0.0 - M4,最新里程碑版本,用于集成 AI 对话服务。
- Java: 17,作为项目的开发语言。
- Redis: 用于数据存储和缓存,实现对话上下文记忆。
- DeepSeek API: 提供 AI 对话服务。
- Maven: 进行项目管理。
- Lombok: 简化代码编写。
- Jackson: 用于 JSON 序列化。
- HTML/CSS/JavaScript: 实现前端界面。
2.2 项目结构
项目的主要结构如下:
src/main/java/com/yyvb/springai/
├── SpringAiDeepSeekChatApplication.java # 主启动类
├── client/
│ └── DeepSeekClient.java # DeepSeek API客户端
├── config/
│ └── AppConfig.java # Spring AI和Redis配置
├── controller/
│ └── ChatController.java # REST API控制器
├── dto/
│ ├── ChatRequest.java # 请求数据传输对象
│ └── ChatResponse.java # 响应数据传输对象
├── exception/
│ └── GlobalExceptionHandler.java # 全局异常处理器
├── model/
│ └── ChatMessage.java # 聊天消息实体
└── service/├── ChatService.java # 聊天业务服务└── ChatContextService.java # 上下文管理服务src/main/resources/
├── application.yml # 应用配置文件
└── static/└── index.html # Web界面 (27KB, 854行)
三、环境搭建与配置
3.1 基础环境要求
在开始项目开发之前,需要确保以下基础环境已经安装和配置好:
- Java 17+,本项目使用 Java 17。
- Maven 3.6+,用于项目依赖管理。
- Redis 服务器,用于数据存储和缓存。
- DeepSeek API Key,用于调用 DeepSeek API。
3.2 项目依赖配置
在 pom.xml
中添加核心依赖,代码如下:
<properties><java.version>17</java.version><spring-ai.version>1.0.0-M4</spring-ai.version>
</properties><dependencies><!-- Spring Boot Web --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- Spring Boot Data Redis --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><!-- Spring AI OpenAI依赖(支持DeepSeek) --><dependency><groupId>org.springframework.ai</groupId><artifactId>spring-ai-openai-spring-boot-starter</artifactId><version>${spring-ai.version}</version></dependency><!-- Lombok --><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><!-- Validation --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-validation</artifactId></dependency>
</dependencies>
上述代码中,我们添加了 Spring Boot Web、Spring Boot Data Redis、Spring AI OpenAI 依赖、Lombok 和 Validation 等依赖。
3.3 应用配置
在 application.yml
中进行完整的应用配置,代码如下:
spring:application:name: springai-deepseek-chat-redis# Redis配置data:redis:host: localhostport: 6379password: database: 12lettuce:pool:max-active: 20max-idle: 10min-idle: 2max-wait: -1ms# AI配置 (DeepSeek兼容OpenAI API)ai:openai:api-key: ${DEEPSEEK_API_KEY:sk-your-deepseek-api-key}base-url: https://api.deepseek.comchat:options:model: deepseek-chattemperature: 0.7max-tokens: 2000# 服务器配置
server:port: 8080servlet:encoding:charset: UTF-8enabled: trueforce: true# 日志配置
logging:level:com.yyvb: DEBUGorg.springframework.ai: DEBUG# 应用配置
app:chat:max-context-size: 20context-expire-seconds: 3600
在这个配置文件中,我们配置了应用的名称、Redis 的连接信息、AI 的相关配置(包括 API Key、基础 URL、模型、温度和最大令牌数等)、服务器的端口和编码信息、日志级别以及应用的聊天上下文配置。
四、核心组件实现
4.1 消息实体设计
ChatMessage.java
是一个增强的消息实体类,代码如下:
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;import java.io.Serializable;
import java.time.LocalDateTime;/*** 聊天消息实体类*/
@Data
@AllArgsConstructor
@NoArgsConstructor
@JsonIgnoreProperties(ignoreUnknown = true)
public class ChatMessage implements Serializable {private static final long serialVersionUID = 1L;/*** 用户或助手角色*/@JsonProperty("role")private String role;/*** 消息内容*/@JsonProperty("content")private String content;/*** 消息时间戳*/@JsonProperty("timestamp")@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")private LocalDateTime timestamp;/*** 构造函数,初始化角色和内容,并设置当前时间戳* @param role 角色* @param content 内容*/public ChatMessage(String role, String content) {this.role = role;this.content = content;this.timestamp = LocalDateTime.now();}/*** 判断消息是否有效* @return 如果角色和内容都不为空,则返回 true,否则返回 false*/public boolean isValid() {return role != null && !role.trim().isEmpty() && content != null && !content.trim().isEmpty();}
}
这个类使用了 Lombok 的注解来简化代码,包含了角色、内容和时间戳等属性,并且提供了判断消息是否有效的方法。
4.2 Spring AI 配置
AppConfig.java
是完整的 Spring AI 配置类,代码如下:
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import org.springframework.ai.openai.api.OpenAiApi;
import org.springframework.ai.openai.client.OpenAiChatModel;
import org.springframework.ai.openai.support.OpenAiChatOptions;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;import java.util.Objects;/*** Spring AI 和 Redis 配置类*/
@Configuration
public class AppConfig {/*** DeepSeek API Key*/@Value("${spring.ai.openai.api-key:}")private String apiKey;/*** DeepSeek API 基础 URL*/@Value("${spring.ai.openai.base-url:https://api.deepseek.com}")private String baseUrl;/*** OpenAI API 配置 - 用于 DeepSeek* @return OpenAiApi 实例*/@Beanpublic OpenAiApi openAiApi() {return new OpenAiApi(baseUrl, apiKey);}/*** ChatModel 配置 - 使用 DeepSeek API* @param openAiApi OpenAiApi 实例* @return ChatModel 实例*/@Beanpublic ChatModel chatModel(OpenAiApi openAiApi) {OpenAiChatOptions options = OpenAiChatOptions.builder().withModel("deepseek-chat").withTemperature(0.7).withMaxTokens(2000).build();return new OpenAiChatModel(openAiApi, options);}/*** Redis Template 配置 - 修复 JSON 序列化问题* @param connectionFactory Redis 连接工厂* @return RedisTemplate 实例*/@Beanpublic RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) {RedisTemplate<String, Object> template = new RedisTemplate<>();template.setConnectionFactory(connectionFactory);ObjectMapper mapper = new ObjectMapper();mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);mapper.registerModule(new JavaTimeModule());Jackson2JsonRedisSerializer<Object> serializer = new Jackson2JsonRedisSerializer<>(mapper, Object.class);template.setKeySerializer(new StringRedisSerializer());template.setValueSerializer(serializer);template.setDefaultSerializer(serializer);template.setEnableDefaultSerializer(true);template.afterPropertiesSet();return template;}
}
在这个配置类中,我们配置了 OpenAI API(用于 DeepSeek)、ChatModel 和 Redis Template。其中,Redis Template 的配置解决了 JSON 序列化的问题。
4.3 DeepSeek 客户端实现
DeepSeekClient.java
是使用 Spring AI 的客户端类,代码如下:
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.ai.client.ChatModel;
import org.springframework.ai.client.Prompt;
import org.springframework.ai.client.chat.AssistantMessage;
import org.springframework.ai.client.chat.ChatResponse;
import org.springframework.ai.client.chat.UserMessage;
import org.springframework.stereotype.Component;import java.util.ArrayList;
import java.util.List;/*** DeepSeek API 客户端类*/
@Component
public class DeepSeekClient {private static final Logger log = LoggerFactory.getLogger(DeepSeekClient.class);private final ChatModel chatModel;/*** 构造函数,注入 ChatModel* @param chatModel ChatModel 实例*/public DeepSeekClient(ChatModel chatModel) {this.chatModel = chatModel;}/*** 发送单条消息到 DeepSeek* @param message 消息内容* @return 响应内容*/public String sendMessage(String message) {try {Prompt prompt = new Prompt(new UserMessage(message));ChatResponse response = chatModel.call(prompt);return response.getResult().getOutput().getContent();} catch (Exception e) {log.error("调用 DeepSeek API 失败: {}", e.getMessage(), e);return "抱歉,我现在无法回答您的问题,请稍后再试。";}}/*** 带上下文的消息发送* @param context 对话上下文* @return 响应内容*/public String sendMessageWithContext(List<ChatMessage> context) {try {List<Message> messages = new ArrayList<>();for (ChatMessage chatMessage : context) {if (chatMessage == null || !chatMessage.isValid()) {continue;}String role = chatMessage.getRole().trim();String content = chatMessage.getContent().trim();if ("user".equals(role)) {messages.add(new UserMessage(content));} else if ("assistant".equals(role)) {messages.add(new AssistantMessage(content));}}if (messages.isEmpty()) {return "没有有效的对话历史";}// 限制消息数量if (messages.size() > 10) {messages = messages.subList(messages.size() - 10, messages.size());}Prompt prompt = new Prompt(messages);ChatResponse response = chatModel.call(prompt);return response.getResult().getOutput().getContent();} catch (Exception e) {log.error("调用 DeepSeek API 失败: {}", e.getMessage(), e);throw e;}}
}
这个类封装了与 DeepSeek API 的交互,提供了发送单条消息和带上下文消息的方法。
4.4 上下文管理服务
ChatContextService.java
是 Redis 上下文管理服务类,代码如下:
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.ListOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;/*** 聊天上下文管理服务类*/
@Service
public class ChatContextService {private static final Logger log = LoggerFactory.getLogger(ChatContextService.class);private static final String CHAT_CONTEXT_KEY_PREFIX = "chat_context:";private final RedisTemplate<String, Object> redisTemplate;private final int maxContextSize;private final int contextExpireSeconds;/*** 构造函数,注入 RedisTemplate 和配置参数* @param redisTemplate RedisTemplate 实例* @param maxContextSize 最大上下文大小* @param contextExpireSeconds 上下文过期时间(秒)*/public ChatContextService(RedisTemplate<String, Object> redisTemplate,@Value("${app.chat.max-context-size:20}") int maxContextSize,@Value("${app.chat.context-expire-seconds:3600}") int contextExpireSeconds) {this.redisTemplate = redisTemplate;this.maxContextSize = maxContextSize;this.contextExpireSeconds = contextExpireSeconds;}/*** 将对话消息添加到 Redis 中* @param userId 用户 ID* @param message 聊天消息*/public void addMessageToContext(String userId, ChatMessage message) {try {if (message == null || !message.isValid()) {log.warn("尝试添加无效消息到上下文,用户 ID: {}", userId);return;}String key = getContextKey(userId);ListOperations<String, Object> listOperations = redisTemplate.opsForList();listOperations.rightPush(key, message);redisTemplate.expire(key, contextExpireSeconds, TimeUnit.SECONDS);// 限制上下文大小Long size = listOperations.size(key);if (size != null && size > maxContextSize) {long deleteCount = size - maxContextSize;for (int i = 0; i < deleteCount; i++) {listOperations.leftPop(key);}}log.info("用户 {} 的消息已成功添加到上下文", userId);} catch (Exception e) {log.error("添加消息到上下文失败,用户 ID: {}, 错误: {}", userId, e.getMessage(), e);}}/*** 从 Redis 中获取对话历史* @param userId 用户 ID* @return 对话历史列表*/@SuppressWarnings("unchecked")public List<ChatMessage> getChatContext(String userId) {try {String key = getContextKey(userId);ListOperations<String, Object> listOperations = redisTemplate.opsForList();Long size = listOperations.size(key);if (size != null && size > 0) {List<Object> objects = listOperations.range(key, 0, size - 1);if (objects != null && !objects.isEmpty()) {List<ChatMessage> validMessages = new ArrayList<>();for (Object obj : objects) {ChatMessage message = null;if (obj instanceof ChatMessage) {message = (ChatMessage) obj;} else if (obj instanceof Map) {// 处理从 Redis 反序列化的 Map 对象Map<?, ?> map = (Map<?, ?>) obj;String role = map.get("role") != null ? map.get("role").toString() : null;String content = map.get("content") != null ? map.get("content").toString() : null;if (role != null && content != null) {message = new ChatMessage(role, content);}}if (message != null && message.isValid()) {validMessages.add(message);}}return validMessages;}}return List.of();} catch (Exception e) {log.error("获取用户上下文失败,用户 ID: {}, 错误: {}", userId, e.getMessage(), e);return List.of();}}/*** 获取上下文的 Redis Key* @param userId 用户 ID* @return Redis Key*/private String getContextKey(String userId) {return CHAT_CONTEXT_KEY_PREFIX + userId;}
}
这个服务类负责将对话消息添加到 Redis 中,并从 Redis 中获取对话历史,同时对上下文的大小进行了限制。
4.5 聊天业务服务
ChatService.java
是核心业务逻辑类,代码如下:
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;import java.util.List;
import java.util.UUID;/*** 聊天业务服务类*/
@Service
public class ChatService {private static final Logger log = LoggerFactory.getLogger(ChatService.class);private final DeepSeekClient deepSeekClient;private final ChatContextService chatContextService;/*** 构造函数,注入 DeepSeekClient 和 ChatContextService* @param deepSeekClient DeepSeekClient 实例* @param chatContextService ChatContextService 实例*/public ChatService(DeepSeekClient deepSeekClient, ChatContextService chatContextService) {this.deepSeekClient = deepSeekClient;this.chatContextService = chatContextService;}/*** 发送消息并获取回复* @param userId 用户 ID* @param userMessage 用户消息* @return 回复内容*/public String sendMessage(String userId, String userMessage) {try {String requestId = UUID.randomUUID().toString().substring(0, 8);log.info("开始处理聊天请求,用户 ID: {}, 请求 ID: {}", userId, requestId);// 创建用户消息对象ChatMessage userChatMessage = new ChatMessage("user", userMessage);// 将用户消息添加到上下文chatContextService.addMessageToContext(userId, userChatMessage);// 从 Redis 获取对话历史List<ChatMessage> chatContext = chatContextService.getChatContext(userId);log.info("获取到用户 {} 的上下文,消息数量: {}", userId, chatContext.size());// 调用 DeepSeek API 获取回复String response;if (chatContext.isEmpty() || chatContext.size() == 1) {response = deepSeekClient.sendMessage(userMessage);} else {try {response = deepSeekClient.sendMessageWithContext(chatContext);} catch (Exception e) {log.warn("上下文模式发送失败,回退到单条消息模式: {}", e.getMessage());response = deepSeekClient.sendMessage(userMessage);}}// 创建 AI 回复消息对象ChatMessage assistantChatMessage = new ChatMessage("assistant", response);// 将 AI 回复添加到上下文chatContextService.addMessageToContext(userId, assistantChatMessage);log.info("聊天请求处理完成,用户 ID: {}, 请求 ID: {}", userId, requestId);return response;} catch (Exception e) {log.error("处理聊天消息失败,用户 ID: {}, 错误: {}", userId, e.getMessage(), e);return "抱歉,处理您的消息时出现了错误,请稍后再试。";}}
}
这个类处理用户的聊天请求,将用户消息添加到上下文,调用 DeepSeek API 获取回复,并将回复添加到上下文。
五、REST API 控制器
5.1 请求响应 DTO
ChatRequest.java
是请求数据传输对象类,代码如下:
import lombok.Data;
import javax.validation.constraints.NotBlank;/*** 聊天请求数据传输对象*/
@Data
public class ChatRequest {/*** 用户 ID,不能为空*/@NotBlank(message = "用户 ID 不能为空")private String userId;/*** 消息内容,不能为空*/@NotBlank(message = "消息内容不能为空")private String message;
}
ChatResponse.java
是响应数据传输对象类,代码如下:
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;import java.util.Map;/*** 聊天响应数据传输对象*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class ChatResponse {private int code;private String message;private String response;private String requestId;/*** 创建成功响应* @param response 响应内容* @return ChatResponse 实例*/public static ChatResponse success(String response) {return new ChatResponse(200, "成功", response, null);}/*** 创建错误响应* @param message 错误消息* @return ChatResponse 实例*/public static ChatResponse error(String message) {return new ChatResponse(500, message, null, null);}
}
这两个类分别用于封装请求和响应的数据。
5.2 控制器实现
ChatController.java
是完整的 REST API 控制器类,代码如下:
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;import javax.validation.Valid;
import java.util.List;
import java.util.Map;/*** 聊天 REST API 控制器*/
@RestController
@RequestMapping("/api/chat")
@Validated
@CrossOrigin(origins = "*")
public class ChatController {private static final Logger log = LoggerFactory.getLogger(ChatController.class);private final ChatService chatService;/*** 构造函数,注入 ChatService* @param chatService ChatService 实例*/public ChatController(ChatService chatService) {this.chatService = chatService;}/*** 发送聊天消息* @param request 聊天请求* @return 响应实体*/@PostMapping("/send")public ResponseEntity<ChatResponse> sendMessage(@Valid @RequestBody ChatRequest request) {try {log.info("收到聊天请求,用户 ID: {}", request.getUserId());String response = chatService.sendMessage(request.getUserId(), request.getMessage());return ResponseEntity.ok(ChatResponse.success(response));} catch (Exception e) {log.error("处理聊天请求失败: {}", e.getMessage(), e);return ResponseEntity.internalServerError().body(ChatResponse.error("处理消息时发生错误:" + e.getMessage()));}}/*** 获取用户的对话历史* @param userId 用户 ID* @return 响应实体*/@GetMapping("/history/{userId}")public ResponseEntity<List<ChatMessage>> getChatHistory(@PathVariable String userId) {try {List<ChatMessage> history = chatService.getChatHistory(userId);return ResponseEntity.ok(history);} catch (Exception e) {log.error("获取对话历史失败: {}", e.getMessage(), e);return ResponseEntity.internalServerError().build();}}/*** 清除用户的对话历史* @param userId 用户 ID* @return 响应实体*/@DeleteMapping("/history/{userId}")public ResponseEntity<Map<String, String>> clearChatHistory(@PathVariable String userId) {try {chatService.clearChatHistory(userId);return ResponseEntity.ok(Map.of("message", "对话历史已清除"));} catch (Exception e) {log.error("清除对话历史失败: {}", e.getMessage(), e);return ResponseEntity.internalServerError().body(Map.of("error", "清除对话历史时发生错误:" + e.getMessage()));}}/*** 健康检查接口* @return 响应实体*/@GetMapping("/health")public ResponseEntity<Map<String, String>> health() {return ResponseEntity.ok(Map.of("status", "UP","service", "SpringAI DeepSeek Chat","timestamp", String.valueOf(System.currentTimeMillis())));}
}
这个控制器类提供了发送聊天消息、获取对话历史、清除对话历史和健康检查等接口。
六、Web 界面实现
6.1 界面特性
项目包含一个完整的 Web 界面 (index.html
),具备以下特性:
- 现代化设计:采用渐变背景、圆角卡片和阴影效果,提升用户体验。
- 响应式布局:支持桌面和移动设备,适应不同屏幕尺寸。
- 实时聊天:支持实时消息发送和接收,让用户能够流畅地进行对话。
- 系统监控:实时显示 Redis 状态、DeepSeek API 状态,方便管理员进行监控。
- 上下文记忆:显示当前对话上下文数量,让用户了解对话的连续性。
- 功能完整:支持查看历史、清除历史、统计信息等功能,满足用户的多样化需求。
6.2 界面布局
- 顶部区域:显示系统标题和技术栈信息,让用户快速了解应用的基本情况。
- 主体区域:
- 左侧:为聊天界面,包含用户输入框和消息显示区域,方便用户输入和查看消息。
- 右侧:为系统监控面板,包含状态卡片和控制按钮,用于显示系统状态和进行相关操作。
- 底部区域:以网格布局展示核心特性,让用户直观地了解应用的主要功能。
6.3 核心功能
- 智能对话:支持连续对话,自动滚动消息列表,让用户能够持续与 AI 进行交流。
- 状态监控:实时显示系统状态,如 Redis 连接状态、DeepSeek API 响应时间等,帮助管理员及时发现和解决问题。
- 历史管理:用户可以查看和清除对话历史,方便管理自己的聊天记录。
- 错误处理:提供友好的错误提示,当出现异常情况时,让用户能够清楚地了解问题所在。
七、部署与测试
7.1 快速启动
按照以下步骤进行快速启动:
- 环境准备:
# 设置 DeepSeek API Key
export DEEPSEEK_API_KEY=sk-your-deepseek-api-key# 启动 Redis
redis-server
- 运行应用:
mvn clean spring-boot:run
- 访问应用:
- Web 界面: http://localhost:8080
7.2 API 测试
可以使用以下命令进行 API 测试:
# 健康检查
curl http://localhost:8080/api/chat/health# 发送消息
curl -X POST http://localhost:8080/api/chat/send \-H "Content-Type: application/json" \-d '{"userId": "test_user", "message": "你好"}'# 获取历史
curl http://localhost:8080/api/chat/history/test_user
八、总结
本项目成功实现了基于 Spring AI + DeepSeek + Redis 的智能聊天应用,具备完整的上下文记忆功能和现代化的 Web 界面。通过本项目,开发者可以学习到 Spring AI 框架的实际应用、DeepSeek API 的集成方法、Redis 上下文存储的实现、完整的 Web 应用开发流程以及生产级应用的最佳实践。
九、源码
百度云盘地址: 百度云盘 提取码: yyb8