Chat Memory连续对话保存和持久化

1. 什么是Chat Memory

"大模型的对话记忆"这一概念,根植于人工智能与自然语言处理领域,特别是针对具有深度学习能力的大型语言模型而言,它指的是模型在与用户进行交互式对话过程中,能够追踪、理解并利用先前对话上下文的能力。 此机制使得大模型不仅能够响应即时的输入请求,还能基于之前的交流内容能够在对话中记住先前的对话内容,并根据这些信息进行后续的响应。这种记忆机制使得模型能够在对话中持续跟踪和理解用户的意图和上下文,从而实现更自然和连贯的对话添加链接描述

Spring AI Alibaba中的聊天记忆提供了维护 AI 聊天应用程序的对话上下文和历史的机制。

2.前置知识

2.1.ChatMemoryRepository接口


2.2.ChatMemoryRepository接口实现类

2.3.RedisChatMemoryRepository类

2.4.MessageWindowChatMemory 消息窗口聊天记忆



添加链接描述

2.5.Advisors顾问


添加链接描述

3. 新建子模块SAA-08Persistent

本文使用Redis方式进行上下文内容的存储和记录

3.1. pom文件

redis坐标使用jedis详情见2.3

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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>com.hf.hong</groupId>
        <artifactId>SpringAIAlibaba-v1</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>

    <artifactId>SAA-08Persistent</artifactId>

    <properties>
        <maven.compiler.source>21</maven.compiler.source>
        <maven.compiler.target>21</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!-- 引入 springai alibaba DashScope 模型适配的 Starter -->
        <dependency>
            <groupId>com.alibaba.cloud.ai</groupId>
            <artifactId>spring-ai-alibaba-starter-dashscope</artifactId>
        </dependency>
        <!--lombok-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.38</version>
        </dependency>
        <!--hutool-->
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.8.22</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <!--spring-ai-alibaba memory-redis-->
        <dependency>
            <groupId>com.alibaba.cloud.ai</groupId>
            <artifactId>spring-ai-alibaba-starter-memory-redis</artifactId>
        </dependency>
        <!--jedis-->
        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.11.0</version>
                <configuration>
                    <compilerArgs>
                        <arg>-parameters</arg>
                    </compilerArgs>
                    <source>21</source>
                    <target>21</target>
                </configuration>
            </plugin>
        </plugins>
    </build>

    <repositories>
        <repository>
            <id>spring-milestones</id>
            <name>Spring Milestones</name>
            <url>https://repo.spring.io/milestone</url>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </repository>
    </repositories>

</project>

3.2. application.properties

yaml 复制代码
server.port=8008

#大模型对话中文乱码UTF8编码处理
server.servlet.encoding.enabled=true
server.servlet.encoding.force=true
server.servlet.encoding.charset=UTF-8

spring.application.name=SAA-08Persistent

# ====SpringAIAlibaba Config=============
spring.ai.dashscope.api-key=${aliQwen-api}


# ==========redis config ===============
spring.data.redis.host=localhost
spring.data.redis.port=6379
spring.data.redis.database=0
spring.data.redis.connect-timeout=3
spring.data.redis.timeout=2

3.3. 配置文件类

3.3.1.Redis配置类RedisMemoryConfig生成RedisChatMemoryRepository

java 复制代码
package com.hf.hong.config;

import com.alibaba.cloud.ai.memory.redis.RedisChatMemoryRepository;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 *
 * @author admin
 * @date 2026/3/17 21:23
 * @description: redis配置类生成RedisChatMemoryRepository
 */

@Configuration
public class RedisMemoryConfig {
    @Value("${spring.data.redis.host}")
    private String host;

    @Value("${spring.data.redis.port}")
    private int port;

    @Bean
    public RedisChatMemoryRepository redisChatMemoryRepository() {
        return RedisChatMemoryRepository.builder()
                .host(host)
                .port(port)
                .build();
    }
}

3.3.2.多模型并存配置类SAAChatModelConfig(与之前子模块中相比有改动)

java 复制代码
package com.hf.hong.config;

import com.alibaba.cloud.ai.dashscope.api.DashScopeApi;
import com.alibaba.cloud.ai.dashscope.chat.DashScopeChatModel;
import com.alibaba.cloud.ai.dashscope.chat.DashScopeChatOptions;
import com.alibaba.cloud.ai.memory.redis.RedisChatMemoryRepository;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.MessageChatMemoryAdvisor;
import org.springframework.ai.chat.memory.MessageWindowChatMemory;
import org.springframework.ai.chat.model.ChatModel;
import org.springframework.ai.chat.prompt.ChatOptions;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 *
 * @author admin
 * @date 2026/2/9 20:13
 * @description: 多模型并存配置类
 */

@Configuration
public class SAAChatModelConfig {
    private final String DEEPSEEK_MODEL = "deepseek-v3";
    private final String QWEN_MODEL = "qwen-plus";

    @Bean(name = "deepSeekChatModel")
    public ChatModel deepSeekChatModel() {

        return DashScopeChatModel.builder()
                .dashScopeApi(DashScopeApi.builder()
                        .apiKey(System.getenv("aliQwen-api"))
                        .build())
                .defaultOptions(
                        DashScopeChatOptions.builder().withModel(DEEPSEEK_MODEL).build()
                )
                .build();
    }

    @Bean(name = "qwenChatModel")
    public ChatModel qwenChatModel() {
        return DashScopeChatModel.builder().dashScopeApi(DashScopeApi.builder()
                        .apiKey(System.getenv("aliQwen-api"))
                        .build())
                .defaultOptions(
                        DashScopeChatOptions.builder()
                                .withModel(QWEN_MODEL)
                                .build()
                )
                .build();
    }

    @Bean(name = "deepseekChatClient")
    public ChatClient deepseekChatClient(@Qualifier("deepSeekChatModel") ChatModel deepSeekChatModel, RedisChatMemoryRepository redisChatMemoryRepository) {
        MessageWindowChatMemory messageWindowChatMemory = MessageWindowChatMemory.builder()
                .chatMemoryRepository(redisChatMemoryRepository)
                .maxMessages(10)
                .build();
        return ChatClient.builder(deepSeekChatModel)
                .defaultOptions(ChatOptions.builder()
                        .model(DEEPSEEK_MODEL)
                        .build())
                .defaultAdvisors(MessageChatMemoryAdvisor.builder(messageWindowChatMemory).build())
                .build();
    }


    @Bean(name = "qwenChatClient")
    public ChatClient qwenChatClient(@Qualifier("qwenChatModel") ChatModel qwenChatModel, RedisChatMemoryRepository redisChatMemoryRepository) {
        MessageWindowChatMemory messageWindowChatMemory = MessageWindowChatMemory.builder()
                .chatMemoryRepository(redisChatMemoryRepository)
                .maxMessages(10)
                .build();
        return ChatClient.builder(qwenChatModel)
                .defaultOptions(ChatOptions.builder()
                        .model(QWEN_MODEL)
                        .build())
                .defaultAdvisors(MessageChatMemoryAdvisor.builder(messageWindowChatMemory).build())
                .build();
    }
}

4.RedisChatMemoryController

java 复制代码
package com.hf.hong.controller;

import jakarta.annotation.Resource;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.function.Consumer;

import static org.springframework.ai.chat.memory.ChatMemory.CONVERSATION_ID;

/**
 *
 * @author admin
 * @date 2026/3/17 21:30
 * @description: redis实现chatMemory存储
 */


@RestController
@RequestMapping("/redis/chatMemory")
public class RedisChatMemoryController {
    @Resource(name = "qwenChatClient")
    private ChatClient qwenChatClient;


    /**
     * redis实现聊天记忆存储(匿名内部类)
     * @param msg
     * @param userId
     * @return
     */
    @GetMapping("/chat")
    public String chat(String msg, String userId) {
        return qwenChatClient.prompt(msg).advisors(new Consumer<ChatClient.AdvisorSpec>()
        {
            @Override
            public void accept(ChatClient.AdvisorSpec advisorSpec)
            {
                advisorSpec.param(CONVERSATION_ID, userId);
            }
        }).call().content();

    }


    /**
     * redis实现聊天记忆存储(lambda)
     * @param msg
     * @param userId
     * @return
     */
    @GetMapping("/chat2")
    public String chat2(String msg, String userId) {
        return qwenChatClient.prompt(msg)
                .advisors(advisorSpec -> advisorSpec.param(CONVERSATION_ID, userId))
                .call()
                .content();
    }
}

5. 测试

bash 复制代码
http://localhost:8008/redis/chatMemory/chat?msg=%E5%86%8D%E5%8A%A05&userId=1

切换chat2

相关推荐
java1234_小锋4 小时前
Spring AI 2.0 开发Java Agent智能体 - Spring AI 2.0简介
java·人工智能·spring·spring ai
yyk的萌2 天前
Spring AI + 智谱大模型实战:打造有记忆功能的智能天气助手
java·人工智能·spring·agent·spring ai
少许极端3 天前
AI修炼记1-Tool Calling
人工智能·ai·spring ai·tool calling
中间件XL3 天前
spring ai alibaba原理源码分析(一)-架构
人工智能·ai·alibaba·spring ai·agent框架
QC·Rex6 天前
Spring AI MCP Apps 实战:打造聊天与富 UI 融合的智能化应用
人工智能·spring·ui·spring ai·mcp
梵得儿SHI6 天前
(第一篇)Spring AI 架构设计与优化:从单实例到万级 QPS 分布式服务的演进之路
人工智能·分布式架构·spring ai·万级 qps·ai 服务高并发·模型 / 向量 / 业务·qps分布式服务
一叶飘零_sweeeet7 天前
Spring AI 与 Spring AI Alibaba怎么选?
java·spring·spring ai
海兰8 天前
【第3篇-续】多模型多模态项目实现示例(增加OpenAI通用适配)附源代码
java·人工智能·spring boot·alibaba·spring ai
海兰8 天前
【第2篇-续】从零开始helloworld使用openAI通用模型的完整实现示例附源代码
java·人工智能·spring boot·alibaba·spring ai