最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

使用SpringBoot3整合Spring AI實(shí)現(xiàn)具有記憶功能的AI助手

 更新時(shí)間:2026年04月12日 15:16:52   作者:Nhuanuary  
本文介紹了使用SpringBoot3整合SpringAI和Redis實(shí)現(xiàn)一個(gè)具有記憶功能的AI助手,項(xiàng)目使用Redis作為存儲(chǔ)介質(zhì),支持用戶級(jí)別的會(huì)話隔離和30天的對(duì)話歷史持久化,詳細(xì)介紹了環(huán)境準(zhǔn)備、項(xiàng)目初始化、核心配置、功能實(shí)現(xiàn)及測(cè)試驗(yàn)證步驟,需要的朋友可以參考下

1. 項(xiàng)目概述

本教程詳細(xì)介紹如何使用 Spring Boot 3 整合 Spring AI 實(shí)現(xiàn)一個(gè)具有記憶功能的 AI 助手。該實(shí)現(xiàn)使用 Redis 作為存儲(chǔ)介質(zhì),支持用戶級(jí)別的會(huì)話隔離和 30 天的對(duì)話歷史持久化。

技術(shù)棧

  • Spring Boot 3.3.0
  • Java 17
  • Spring AI
  • Redis 6.0+
  • MyBatis Plus
  • MySQL 8.0
  • Sa-Token(用戶認(rèn)證)

2. 環(huán)境準(zhǔn)備

2.1 安裝必要軟件

2.2 配置環(huán)境變量

確保 JAVA_HOMEMAVEN_HOME 已正確配置。

3. 項(xiàng)目初始化

3.1 創(chuàng)建 Spring Boot 項(xiàng)目

使用 Spring Initializr 創(chuàng)建項(xiàng)目:

  • 訪問(wèn) Spring Initializr
  • 選擇 Spring Boot 3.3.0
  • 選擇 Java 17
  • 添加依賴:Spring Web, Spring Data Redis, MyBatis Plus, MySQL Driver, Spring Boot DevTools

3.2 配置 Maven 依賴

pom.xml 文件中添加以下依賴:

<dependencies>
    <!-- Spring Boot 核心依賴 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <!-- Spring Data Redis -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-redis</artifactId>
    </dependency>
    <!-- MyBatis Plus -->
    <dependency>
        <groupId>com.baomidou</groupId>
        <artifactId>mybatis-plus-boot-starter</artifactId>
        <version>3.5.5</version>
    </dependency>
    <!-- MySQL 驅(qū)動(dòng) -->
    <dependency>
        <groupId>com.mysql</groupId>
        <artifactId>mysql-connector-j</artifactId>
        <scope>runtime</scope>
    </dependency>
    <!-- Spring AI -->
    <dependency>
        <groupId>org.springframework.ai</groupId>
        <artifactId>spring-ai-openai</artifactId>
        <version>1.0.0</version>
    </dependency>
    <!-- Sa-Token 認(rèn)證 -->
    <dependency>
        <groupId>cn.dev33</groupId>
        <artifactId>sa-token-spring-boot-starter</artifactId>
        <version>1.38.1</version>
    </dependency>
    <!-- Jackson 序列化 -->
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
    </dependency>
    <!-- Lombok -->
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>
    <!-- Spring Boot 測(cè)試 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
</dependencies>

4. 核心配置

4.1 應(yīng)用配置文件 (application.yml)

創(chuàng)建 src/main/resources/application.yml 文件,配置應(yīng)用信息:

server:
  port: 9527
  servlet:
    context-path: /api
spring:
  application:
    name: smart-pic-community-backend
  # Redis 配置
  data:
    redis:
      database: 2
      host: localhost
      port: 6379
      timeout: 5000
  # 數(shù)據(jù)庫(kù)配置
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/smart_pic_community
    username: root
    password: your_password
  # Spring AI 配置
  ai:
    openai:
      base-url: https://api.deepseek.com/  # 使用 DeepSeek API
      api-key: your_api_key
      chat:
        options:
          model: deepseek-chat

4.2 Redis 配置 (RedisConfiguration.java)

創(chuàng)建 Redis 配置類(lèi),確保正確序列化對(duì)象:

package com.spc.smartpiccommunitybackend.config;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
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;
@Configuration
@Slf4j
public class RedisConfiguration {
    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        log.info("開(kāi)始創(chuàng)建redis模板對(duì)象...");
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
        // 設(shè)置連接工廠
        redisTemplate.setConnectionFactory(redisConnectionFactory);
        // 使用 StringRedisSerializer 來(lái)序列化和反序列化 redis 的 key
        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
        // key 采用 String 的序列化方式
        redisTemplate.setKeySerializer(stringRedisSerializer);
        redisTemplate.setHashKeySerializer(stringRedisSerializer);
        // 使用 Jackson2JsonRedisSerializer 來(lái)序列化和反序列化 redis 的 value
        Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(objectMapper);
        // value 采用 JSON 的序列化方式
        redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
        redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);
        redisTemplate.afterPropertiesSet();
        return redisTemplate;
    }
}

注意事項(xiàng)

  • 使用 Jackson2JsonRedisSerializer 而不是 StringRedisSerializer 可以避免 ClassCastException
  • 啟用默認(rèn)類(lèi)型可以確保反序列化時(shí)能正確識(shí)別對(duì)象類(lèi)型

5. 核心功能實(shí)現(xiàn)

5.1 創(chuàng)建模型類(lèi)

5.1.1 創(chuàng)建 MessageVO.java

創(chuàng)建消息視圖對(duì)象,用于前端展示:

package com.spc.smartpiccommunitybackend.model.vo.ai;

import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.ai.chat.messages.Message;

@NoArgsConstructor
@Data
public class MessageVO {
    private String role;
    private String content;

    public MessageVO(Message message) {
        this.role = switch (message.getMessageType()) {
            case USER -> "user";
            case ASSISTANT -> "assistant";
            case SYSTEM -> "system";
            default -> "";
        };
        this.content = message.getText();
    }
}

功能說(shuō)明

  • 將 Spring AI 的 Message 對(duì)象轉(zhuǎn)換為前端可識(shí)別的格式
  • 根據(jù)消息類(lèi)型設(shè)置不同的角色
  • 提取消息內(nèi)容用于展示

5.1.2 創(chuàng)建 SerializableMessage.java

創(chuàng)建可序列化的消息對(duì)象,用于 Redis 存儲(chǔ):

package com.spc.smartpiccommunitybackend.model.entity.ai;

import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;

@Data
@NoArgsConstructor
public class SerializableMessage implements Serializable {
    private static final long serialVersionUID = 1L;

    private String role;
    private String content;
    private String messageType;
    private Long timestamp;

    public SerializableMessage(String role, String content, String messageType) {
        this.role = role;
        this.content = content;
        this.messageType = messageType;
        this.timestamp = System.currentTimeMillis();
    }

    public SerializableMessage(String role, String content) {
        this(role, content, "user");
    }
}

功能說(shuō)明

  • 實(shí)現(xiàn) Serializable 接口,支持 Redis 序列化
  • 包含角色、內(nèi)容、消息類(lèi)型和時(shí)間戳字段
  • 提供多個(gè)構(gòu)造方法,方便使用

5.2 定義倉(cāng)庫(kù)接口 (ChatHistoryRepository.java)

創(chuàng)建聊天歷史倉(cāng)庫(kù)接口:

package com.spc.smartpiccommunitybackend.repository;

import java.util.List;
import java.util.Map;

public interface ChatHistoryRepository {
    /**
     * 保存會(huì)話記錄
     */
    void save(String type, String chatId, Long userId);
    
    /**
     * 獲取用戶的會(huì)話ID列表
     */
    List<String> getChatIds(Long userId, String type);
    
    /**
     * 保存聊天消息
     */
    void saveMessage(String chatId, String message, String sender);
    
    /**
     * 獲取聊天消息歷史
     */
    List<String> getMessages(String chatId);
    
    /**
     * 刪除會(huì)話
     */
    void deleteChat(Long userId, String type, String chatId);
    
    /**
     * 獲取會(huì)話信息
     */
    Map<Object, Object> getSessionInfo(String chatId);
}

5.3 實(shí)現(xiàn) Redis 聊天歷史倉(cāng)庫(kù) (RedisChatHistoryRepository.java)

實(shí)現(xiàn)基于 Redis 的聊天歷史倉(cāng)庫(kù):

package com.spc.smartpiccommunitybackend.repository;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.core.JsonProcessingException;
import lombok.RequiredArgsConstructor;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Component
@RequiredArgsConstructor
public class RedisChatHistoryRepository implements ChatHistoryRepository {

    private final RedisTemplate<String, Object> redisTemplate;

    // Redis key前綴
    private static final String CHAT_HISTORY_PREFIX = "chat:history:";
    private static final String CHAT_SESSION_PREFIX = "chat:session:";
    private static final String CHAT_MESSAGES_PREFIX = "chat:messages:";

    /**
     * 保存會(huì)話記錄
     */
    @Override
    public void save(String type, String chatId, Long userId) {
        // 保存會(huì)話信息
        String sessionKey = CHAT_SESSION_PREFIX + chatId;
        Map<String, Object> sessionInfo = new HashMap<>();
        sessionInfo.put("userId", String.valueOf(userId));
        sessionInfo.put("type", type);
        sessionInfo.put("createTime", System.currentTimeMillis());
        sessionInfo.put("lastUpdateTime", System.currentTimeMillis());
        redisTemplate.opsForHash().putAll(sessionKey, sessionInfo);
        // 設(shè)置過(guò)期時(shí)間為30天
        redisTemplate.expire(sessionKey, 30, TimeUnit.DAYS);

        // 將chatId添加到用戶的聊天歷史列表中
        String historyKey = CHAT_HISTORY_PREFIX + userId + ":" + type;
        redisTemplate.opsForSet().add(historyKey, chatId);
        // 設(shè)置過(guò)期時(shí)間為30天
        redisTemplate.expire(historyKey, 30, TimeUnit.DAYS);
    }

    /**
     * 獲取用戶的會(huì)話ID列表
     */
    @Override
    public List<String> getChatIds(Long userId, String type) {
        String historyKey = CHAT_HISTORY_PREFIX + userId + ":" + type;
        Set<Object> chatIds = redisTemplate.opsForSet().members(historyKey);
        if (chatIds == null || chatIds.isEmpty()) {
            return Collections.emptyList();
        }
        return chatIds.stream()
                .map(Object::toString)
                .collect(Collectors.toList());
    }

    /**
     * 保存聊天消息
     */
    @Override
    public void saveMessage(String chatId, String message, String sender) {
        String messagesKey = CHAT_MESSAGES_PREFIX + chatId;
        // 創(chuàng)建消息對(duì)象
        Map<String, Object> messageInfo = new HashMap<>();
        messageInfo.put("content", message);
        messageInfo.put("sender", sender);
        messageInfo.put("timestamp", System.currentTimeMillis());
        // 使用JSON格式保存消息
        ObjectMapper objectMapper = new ObjectMapper();
        try {
            String jsonMessage = objectMapper.writeValueAsString(messageInfo);
            redisTemplate.opsForList().rightPush(messagesKey, jsonMessage);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
            // 如果JSON序列化失敗,使用原始消息
            redisTemplate.opsForList().rightPush(messagesKey, message);
        }
        // 設(shè)置過(guò)期時(shí)間為30天
        redisTemplate.expire(messagesKey, 30, TimeUnit.DAYS);

        // 更新會(huì)話的最后更新時(shí)間
        String sessionKey = CHAT_SESSION_PREFIX + chatId;
        redisTemplate.opsForHash().put(sessionKey, "lastUpdateTime", System.currentTimeMillis());
        // 確保會(huì)話信息也有過(guò)期時(shí)間
        redisTemplate.expire(sessionKey, 30, TimeUnit.DAYS);
    }

    /**
     * 獲取聊天消息歷史
     */
    @Override
    public List<String> getMessages(String chatId) {
        String messagesKey = CHAT_MESSAGES_PREFIX + chatId;
        List<Object> messages = redisTemplate.opsForList().range(messagesKey, 0, -1);
        if (messages == null || messages.isEmpty()) {
            return Collections.emptyList();
        }
        return messages.stream()
                .map(Object::toString)
                .collect(Collectors.toList());
    }

    /**
     * 刪除會(huì)話
     */
    @Override
    public void deleteChat(Long userId, String type, String chatId) {
        // 從用戶的聊天歷史列表中刪除
        String historyKey = CHAT_HISTORY_PREFIX + userId + ":" + type;
        redisTemplate.opsForSet().remove(historyKey, chatId);

        // 刪除會(huì)話信息
        String sessionKey = CHAT_SESSION_PREFIX + chatId;
        redisTemplate.delete(sessionKey);

        // 刪除聊天消息
        String messagesKey = CHAT_MESSAGES_PREFIX + chatId;
        redisTemplate.delete(messagesKey);
    }

    /**
     * 獲取會(huì)話信息
     */
    @Override
    public Map<Object, Object> getSessionInfo(String chatId) {
        String sessionKey = CHAT_SESSION_PREFIX + chatId;
        return redisTemplate.opsForHash().entries(sessionKey);
    }
}

注意事項(xiàng)

  • 使用不同的 Redis key 前綴區(qū)分不同類(lèi)型的數(shù)據(jù)
  • 為所有 Redis 鍵設(shè)置過(guò)期時(shí)間,避免內(nèi)存泄漏
  • 處理 JSON 序列化失敗的情況,提高系統(tǒng)健壯性

5.4 實(shí)現(xiàn)聊天記憶 (RedisChatMemory.java)

實(shí)現(xiàn)基于 Redis 的聊天記憶,支持 Spring AI 的 ChatMemory 接口:

package com.spc.smartpiccommunitybackend.config;

import org.springframework.ai.chat.messages.Message;
import org.springframework.ai.chat.memory.ChatMemory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Component
public class RedisChatMemory implements ChatMemory {

    private final RedisTemplate<String, Object> redisTemplate;
    private static final String MEMORY_KEY_PREFIX = "chat:memory:";
    private static final long EXPIRATION_DAYS = 30;

    public RedisChatMemory(RedisTemplate<String, Object> redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    @Override
    public void add(String key, List<Message> messages) {
        // 為特定會(huì)話添加多條消息
        for (Message message : messages) {
            addMessage(key, message);
        }
    }

    @Override
    public List<Message> get(String key, int maxCount) {
        // 實(shí)現(xiàn) get 方法,根據(jù) key 獲取消息
        List<Message> messages = getMessages(key);
        // 如果指定了最大數(shù)量,返回不超過(guò)該數(shù)量的消息
        if (maxCount > 0 && messages.size() > maxCount) {
            return messages.subList(messages.size() - maxCount, messages.size());
        }
        return messages;
    }

    @Override
    public void clear() {
        // 清理所有會(huì)話記憶
        // 注意:這個(gè)操作會(huì)刪除所有聊天記憶,謹(jǐn)慎使用
    }

    /**
     * 為特定會(huì)話添加消息
     */
    public void addMessage(String chatId, Message message) {
        String key = MEMORY_KEY_PREFIX + chatId;
        redisTemplate.opsForList().rightPush(key, message);
        redisTemplate.expire(key, EXPIRATION_DAYS, TimeUnit.DAYS);
    }

    /**
     * 獲取特定會(huì)話的消息
     */
    public List<Message> getMessages(String chatId) {
        String key = MEMORY_KEY_PREFIX + chatId;
        List<Object> objects = redisTemplate.opsForList().range(key, 0, -1);
        List<Message> messages = new ArrayList<>();
        if (objects != null) {
            for (Object obj : objects) {
                if (obj instanceof Message) {
                    messages.add((Message) obj);
                }
            }
        }
        return messages;
    }

    /**
     * 清理特定會(huì)話的記憶
     */
    public void clear(String chatId) {
        String key = MEMORY_KEY_PREFIX + chatId;
        redisTemplate.delete(key);
    }
}

注意事項(xiàng)

  • 實(shí)現(xiàn) ChatMemory 接口以支持 Spring AI 的消息記憶功能
  • 為每條消息設(shè)置過(guò)期時(shí)間,確保內(nèi)存使用合理
  • 提供批量添加和獲取消息的方法,提高性能

5.5 配置 ChatClient (CommonConfiguration.java)

配置 Spring AI 的 ChatClient

package com.spc.smartpiccommunitybackend.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.openai.OpenAiChatModel;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class CommonConfiguration {

    @Bean
    public ChatClient chatClient(OpenAiChatModel openAiChatModel, ChatMemory chatMemory) {
        return ChatClient.builder(openAiChatModel)
                .defaultAdvisors(
                        new SimpleLoggerAdvisor(),
                        new MessageChatMemoryAdvisor(chatMemory)
                )
                .build();
    }
}

注意事項(xiàng)

  • 使用 MessageChatMemoryAdvisor 來(lái)啟用聊天記憶功能
  • 使用 SimpleLoggerAdvisor 來(lái)記錄聊天交互,方便調(diào)試

5.6 實(shí)現(xiàn)聊天控制器 (ChatController.java)

實(shí)現(xiàn)聊天控制器,處理 AI 對(duì)話請(qǐng)求:

package com.spc.smartpiccommunitybackend.controller;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.spc.smartpiccommunitybackend.repository.RedisChatHistoryRepository;
import com.spc.smartpiccommunitybackend.service.UserService;
import com.spc.smartpiccommunitybackend.utils.ErrorCode;
import com.spc.smartpiccommunitybackend.utils.ThrowUtils;
import com.spc.smartpiccommunitybackend.pojo.User;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.messages.Message;
import org.springframework.ai.chat.messages.SystemMessage;
import org.springframework.ai.chat.messages.UserMessage;
import org.springframework.ai.chat.messages.AssistantMessage;
import org.springframework.beans.factory.annotation.Resource;
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Flux;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

@RestController
@RequestMapping("/ai")
public class ChatController {

    private final ChatClient chatClient;
    private final RedisChatHistoryRepository chatHistoryRepository;
    @Resource
    private UserService userService;

    public ChatController(ChatClient chatClient, RedisChatHistoryRepository chatHistoryRepository) {
        this.chatClient = chatClient;
        this.chatHistoryRepository = chatHistoryRepository;
    }

    @RequestMapping(value = "/chat", produces = "text/html;charset=UTF-8")
    public Flux<String> chat(@RequestParam(defaultValue = "講個(gè)笑話") String prompt,
                             String chatId,
                             HttpServletRequest request) {
        User loginUser = userService.getLoginUser(request);
        // 校驗(yàn)登錄用戶是否為空
        ThrowUtils.throwIf(loginUser == null, ErrorCode.NOT_LOGIN_ERROR);
        Long userId = loginUser.getId();
        
        // 保存會(huì)話信息
        chatHistoryRepository.save("chat", chatId, userId);

        // 獲取歷史對(duì)話消息作為上下文
        List<Message> messages = new ArrayList<>();
        
        // 添加系統(tǒng)消息
        SystemMessage systemMessage = new SystemMessage(
            "你是一個(gè)智能圖片社區(qū)的AI助手,名為虹小智。請(qǐng)用友好、專(zhuān)業(yè)的語(yǔ)氣回答用戶問(wèn)題," +
            "提供關(guān)于圖片社區(qū)的相關(guān)信息和幫助。"
        );
        messages.add(systemMessage);
        
        // 獲取并解析歷史消息
        List<String> historyMessages = chatHistoryRepository.getMessages(chatId);
        ObjectMapper objectMapper = new ObjectMapper();
        
        for (String messageStr : historyMessages) {
            try {
                JsonNode node = objectMapper.readTree(messageStr);
                String sender = node.get("sender").asText();
                String content = node.get("content").asText();
                
                if ("user".equals(sender)) {
                    messages.add(new UserMessage(content));
                } else if ("ai".equals(sender)) {
                    messages.add(new AssistantMessage(content));
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        
        // 添加用戶當(dāng)前消息
        messages.add(new UserMessage(prompt));
        
        // 保存用戶消息到歷史記錄
        chatHistoryRepository.saveMessage(chatId, prompt, "user");
        
        // 調(diào)用AI模型獲取響應(yīng)
        return chatClient.stream(messages)
                .doOnNext(response -> {
                    // 保存AI響應(yīng)到歷史記錄
                    chatHistoryRepository.saveMessage(chatId, response, "ai");
                });
    }
}

注意事項(xiàng)

  • 驗(yàn)證用戶登錄狀態(tài),確保會(huì)話隔離
  • 保存用戶消息和 AI 響應(yīng)到歷史記錄
  • 使用 Flux 實(shí)現(xiàn)流式響應(yīng),提高用戶體驗(yàn)
  • 處理歷史消息解析異常,提高系統(tǒng)健壯性

5.7 實(shí)現(xiàn)聊天歷史控制器 (ChatHistoryController.java)

實(shí)現(xiàn)聊天歷史控制器,處理聊天歷史的獲取和刪除:

package com.spc.smartpiccommunitybackend.controller;

import com.spc.smartpiccommunitybackend.repository.RedisChatHistoryRepository;
import com.spc.smartpiccommunitybackend.service.UserService;
import com.spc.smartpiccommunitybackend.utils.ErrorCode;
import com.spc.smartpiccommunitybackend.utils.ThrowUtils;
import com.spc.smartpiccommunitybackend.pojo.User;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.util.List;

@RestController
@RequestMapping("/ai/history")
public class ChatHistoryController {

    private final RedisChatHistoryRepository chatHistoryRepository;
    private final UserService userService;

    public ChatHistoryController(RedisChatHistoryRepository chatHistoryRepository, UserService userService) {
        this.chatHistoryRepository = chatHistoryRepository;
        this.userService = userService;
    }

    /**
     * 獲取用戶的聊天歷史ID列表
     */
    @GetMapping("/{type}")
    public List<String> getChatHistory(@PathVariable String type, HttpServletRequest request) {
        User loginUser = userService.getLoginUser(request);
        ThrowUtils.throwIf(loginUser == null, ErrorCode.NOT_LOGIN_ERROR);
        Long userId = loginUser.getId();
        
        return chatHistoryRepository.getChatIds(userId, type);
    }

    /**
     * 刪除指定聊天歷史
     */
    @DeleteMapping("/{type}/{chatId}")
    public boolean deleteChatHistory(@PathVariable String type, 
                                    @PathVariable String chatId, 
                                    HttpServletRequest request) {
        User loginUser = userService.getLoginUser(request);
        ThrowUtils.throwIf(loginUser == null, ErrorCode.NOT_LOGIN_ERROR);
        Long userId = loginUser.getId();
        
        chatHistoryRepository.deleteChat(userId, type, chatId);
        return true;
    }
}

注意事項(xiàng)

  • 驗(yàn)證用戶登錄狀態(tài),確保只能操作自己的聊天歷史
  • 提供獲取和刪除聊天歷史的接口,方便前端管理

6. 測(cè)試和驗(yàn)證

6.1 啟動(dòng)服務(wù)

  1. 確保 Redis 和 MySQL 服務(wù)已啟動(dòng)
  2. 運(yùn)行 Spring Boot 應(yīng)用
  3. 訪問(wèn) http://localhost:9527/api/ai/chat?prompt=你好&chatId=test123 測(cè)試 AI 響應(yīng)

6.2 測(cè)試聊天記憶功能

  1. 發(fā)送第一條消息:http://localhost:9527/api/ai/chat?prompt=你好,我叫張三&chatId=test123
  2. 發(fā)送第二條消息:http://localhost:9527/api/ai/chat?prompt=你知道我叫什么名字嗎?&chatId=test123
  3. 驗(yàn)證 AI 能否正確回答你的名字

6.3 測(cè)試用戶隔離功能

  1. 使用不同用戶登錄
  2. 驗(yàn)證不同用戶的聊天歷史是否相互隔離

6.4 測(cè)試歷史記錄持久化

  1. 發(fā)送多條消息
  2. 重啟服務(wù)
  3. 驗(yàn)證聊天歷史是否仍然存在

6.5 測(cè)試歷史記錄管理

  1. 獲取用戶的聊天歷史列表:GET http://localhost:9527/api/ai/history/chat
  2. 刪除指定聊天歷史:DELETE http://localhost:9527/api/ai/history/chat/test123
  3. 驗(yàn)證聊天歷史是否已刪除

以上就是使用SpringBoot3整合Spring AI實(shí)現(xiàn)具有記憶功能的AI助手的詳細(xì)內(nèi)容,更多關(guān)于SpringBoot3 Spring AI實(shí)現(xiàn)AI助手的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 詳解Java中的final關(guān)鍵字的使用

    詳解Java中的final關(guān)鍵字的使用

    這篇文章主要介紹了詳解Java中的final關(guān)鍵字的使用,是Java入門(mén)學(xué)習(xí)中的基礎(chǔ)知識(shí),需要的朋友可以參考下
    2015-07-07
  • 淺談Java代理(jdk靜態(tài)代理、動(dòng)態(tài)代理和cglib動(dòng)態(tài)代理)

    淺談Java代理(jdk靜態(tài)代理、動(dòng)態(tài)代理和cglib動(dòng)態(tài)代理)

    下面小編就為大家?guī)?lái)一篇淺談Java代理(jdk靜態(tài)代理、動(dòng)態(tài)代理和cglib動(dòng)態(tài)代理)。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-01-01
  • 3分鐘純 Java 注解搭個(gè)管理系統(tǒng)的示例代碼

    3分鐘純 Java 注解搭個(gè)管理系統(tǒng)的示例代碼

    這篇文章主要介紹了3分鐘純 Java 注解搭個(gè)管理系統(tǒng)的示例代碼,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-03-03
  • MyBatis找不到mapper文件的實(shí)現(xiàn)

    MyBatis找不到mapper文件的實(shí)現(xiàn)

    這篇文章主要介紹了MyBatis找不到mapper文件的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-10-10
  • 一文詳解MyBatis中動(dòng)態(tài)SQL的封裝原理與常用標(biāo)簽實(shí)戰(zhàn)應(yīng)用

    一文詳解MyBatis中動(dòng)態(tài)SQL的封裝原理與常用標(biāo)簽實(shí)戰(zhàn)應(yīng)用

    這篇文章主要為大家詳細(xì)介紹了MyBatis中動(dòng)態(tài)SQL的核心技術(shù)與及常用標(biāo)簽的應(yīng)用,同時(shí)提供了最佳實(shí)踐和常見(jiàn)問(wèn)題解決方案,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2026-04-04
  • 基于SpringBoot生成二維碼的幾種實(shí)現(xiàn)方式

    基于SpringBoot生成二維碼的幾種實(shí)現(xiàn)方式

    本文將基于Spring Boot介紹兩種生成二維碼的實(shí)現(xiàn)方式,一種是基于Google開(kāi)發(fā)工具包,另一種是基于Hutool來(lái)實(shí)現(xiàn),具有一定的參考價(jià)值,感興趣的可以了解一下
    2022-03-03
  • RocketMQ消息發(fā)送流程源碼剖析

    RocketMQ消息發(fā)送流程源碼剖析

    這篇文章主要為大家介紹了RocketMQ消息發(fā)送流程源碼剖析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-08-08
  • MapStruct處理Java中實(shí)體與模型間不匹配屬性轉(zhuǎn)換的方法

    MapStruct處理Java中實(shí)體與模型間不匹配屬性轉(zhuǎn)換的方法

    今天小編就為大家分享一篇關(guān)于MapStruct處理Java中實(shí)體與模型間不匹配屬性轉(zhuǎn)換的方法,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧
    2019-03-03
  • SpringBoot的pom.xml文件中設(shè)置多環(huán)境配置信息方法詳解

    SpringBoot的pom.xml文件中設(shè)置多環(huán)境配置信息方法詳解

    這篇文章主要給大家介紹了關(guān)于SpringBoot的pom.xml文件中設(shè)置多環(huán)境配置信息的相關(guān)資料,Java項(xiàng)目通過(guò)pom.xml管理多中間件和多環(huán)境配置,結(jié)合application.yml動(dòng)態(tài)替換配置文件,利用Maven切換不同環(huán)境配置,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2025-05-05
  • java大話之創(chuàng)建型設(shè)計(jì)模式教程示例

    java大話之創(chuàng)建型設(shè)計(jì)模式教程示例

    這篇文章主要為大家介紹了java大話之創(chuàng)建型設(shè)計(jì)模式教程示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-02-02

最新評(píng)論

象州县| 叶城县| 高青县| 积石山| 正定县| 玉门市| 航空| 昭苏县| 昌宁县| 台北市| 阿坝县| 万载县| 望奎县| 大港区| 柳州市| 拜泉县| 阿拉善盟| 玉山县| 仪征市| 石嘴山市| 文昌市| 太湖县| 昌平区| 茂名市| 涞水县| 柳江县| 巴楚县| 宁远县| 图片| 红安县| 印江| 宁安市| 金川县| 梓潼县| 宁蒗| 宁阳县| 新兴县| 麦盖提县| 江山市| 石阡县| 留坝县|