目录

一、Spring AI ChatMemory:让大模型"记住"你

1.1 核心组件

1.2 使用 Advisor 简化操作

1.3 配置最大消息数

1.4 多用户隔离记忆

二、存储持久化:从内存到数据库

2.1 JDBC 存储(MySQL)

2.2 Redis 存储

三、多层次记忆架构(模仿人类记忆)

3.1 痛点分析

四、架构总览

五、总结


一、Spring AI ChatMemory:让大模型"记住"你

Spring AI 提供了 ChatMemory 组件,专门用于存储聊天记录。它允许你在跨多个交互时维护上下文或状态。

1.1 核心组件

@AutoConfiguration
@ConditionalOnClass({ ChatMemory.class, ChatMemoryRepository.class })
public class ChatMemoryAutoConfiguration {

    @Bean
    @ConditionalOnMissingBean
    ChatMemoryRepository chatMemoryRepository() {
        return new InMemoryChatMemoryRepository();
    }

    @Bean
    @ConditionalOnMissingBean
    ChatMemory chatMemory(ChatMemoryRepository chatMemoryRepository) {
        return MessageWindowChatMemory.builder()
                .chatMemoryRepository(chatMemoryRepository)
                .build();
    }
}

1.2 使用 Advisor 简化操作

Spring AI 提供了 PromptChatMemoryAdvisor,专门用于对话记忆的拦截,无需手动维护

@SpringBootTest
public class ChatMemoryTest {
    private ChatClient chatClient;

    @BeforeEach
    public void init(@Autowired DeepSeekChatModel chatModel,
                     @Autowired ChatMemory chatMemory) {
        chatClient = ChatClient.builder(chatModel)
                .defaultAdvisors(
                    PromptChatMemoryAdvisor.builder(chatMemory).build()
                )
                .build();
    }

    @Test
    public void testChatOptions() {
        // 第一次对话 → 存入记忆
        String content = chatClient.prompt()
                .user("我叫xx")
                .advisors(advisorSpec -> advisorSpec.param(ChatMemory.CONVERSATION_ID, "1"))
                .call()
                .content();

        // 第二次对话 → 从记忆读取上下文
        content = chatClient.prompt()
                .user("我叫什么?")
                .advisors(advisorSpec -> advisorSpec.param(ChatMemory.CONVERSATION_ID, "1"))
                .call()
                .content();
        // 输出:"你叫xx"
    }
}

1.3 配置最大消息数

对话记录发送给大模型都是按 Token 计费的,过多的记录会导致:

  • Token 超限

  • 成本增加

  • 响应变慢

@Bean
ChatMemory chatMemory(ChatMemoryRepository chatMemoryRepository) {
    return MessageWindowChatMemory.builder()
            .maxMessages(10)  // 默认20条(10轮对话),先进先出
            .chatMemoryRepository(chatMemoryRepository)
            .build();
}

1.4 多用户隔离记忆

不同用户的对话记录需要隔离:

@Test
public void testMultiUser() {
    // 用户1的对话
    chatClient.prompt()
        .user("我叫xx")
        .advisors(advisorSpec -> advisorSpec.param(ChatMemory.CONVERSATION_ID, "1"))
        .call();

    // 用户2的对话(独立记忆)
    chatClient.prompt()
        .user("我叫什么?")
        .advisors(advisorSpec -> advisorSpec.param(ChatMemory.CONVERSATION_ID, "2"))
        .call();
    // 用户2不知道xx是谁 ✅
}

二、存储持久化:从内存到数据库

默认情况下,ChatMemory 存储在 JVM 内存中,存在两个问题:

  1. 内存溢出(OOM)

  2. 重启后数据丢失

Spring AI 内置了多种持久化方案:Cassandra、JDBC、Neo4j、MongoDB 等。

2.1 JDBC 存储(MySQL)

添加依赖:

<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-starter-model-chat-memory-repository-jdbc</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
    <groupId>com.mysql</groupId>
    <artifactId>mysql-connector-j</artifactId>
    <scope>runtime</scope>
</dependency>

配置 application.yml:

spring:
  datasource:
    username: root
    password: 123456
    url: jdbc:mysql://localhost:3306/springai?characterEncoding=utf8&useSSL=false&serverTimezone=UTC
    driver-class-name: com.mysql.cj.jdbc.Driver

spring.ai.chat.memory.repository.jdbc.initialize-schema=always
spring.ai.chat.memory.repository.jdbc.schema=classpath:/schema-mysql.sql

建表脚本 schema-mysql.sql:

CREATE TABLE IF NOT EXISTS SPRING_AI_CHAT_MEMORY (
    `conversation_id` VARCHAR(36) NOT NULL,
    `content` TEXT NOT NULL,
    `type` VARCHAR(10) NOT NULL,
    `timestamp` TIMESTAMP NOT NULL,
    INDEX `SPRING_AI_CHAT_MEMORY_CONVERSATION_ID_TIMESTAMP_IDX` (`conversation_id`, `timestamp`)
);

配置类:

@Configuration
public class ChatMemoryConfig {
    @Bean
    ChatMemory chatMemory(JdbcChatMemoryRepository chatMemoryRepository) {
        return MessageWindowChatMemory.builder()
                .maxMessages(10)
                .chatMemoryRepository(chatMemoryRepository)
                .build();
    }
}

2.2 Redis 存储

Alibaba 提供了现成的 Redis 实现(GitHub 地址):

<properties>
    <jedis.version>5.2.0</jedis.version>
</properties>

<dependency>
    <groupId>com.alibaba.cloud.ai</groupId>
    <artifactId>spring-ai-alibaba-starter-memory-redis</artifactId>
</dependency>
<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
    <version>${jedis.version}</version>
</dependency>
spring:
  ai:
    memory:
      redis:
        host: localhost
        port: 6379
        timeout: 5000
        password:
@Configuration
public class RedisMemoryConfig {
    @Value("${spring.ai.memory.redis.host:localhost}")
    private String redisHost;
    
    @Value("${spring.ai.memory.redis.port:6379}")
    private int redisPort;
    
    @Value("${spring.ai.memory.redis.password:}")
    private String redisPassword;
    
    @Value("${spring.ai.memory.redis.timeout:5000}")
    private int redisTimeout;

    @Bean
    public RedisChatMemoryRepository redisChatMemoryRepository() {
        return RedisChatMemoryRepository.builder()
                .host(redisHost)
                .port(redisPort)
                // .password(redisPassword)
                .timeout(redisTimeout)
                .build();
    }
}

//数据库测试
    @Test
    public void testChatOptions3() {
        String content = chatClient.prompt()
                .user("你好,我叫搜搜!")
                .advisors(new BeReadingAdvisor())
                .advisors(advisorSpec -> advisorSpec.param(ChatMemory.CONVERSATION_ID,"1"))
                .call()
                .content();
        System.out.println(content);
        System.out.println("--------------------------------------------------------------------------");

        content = chatClient.prompt()
                .user("我叫什么 ?")
                .advisors(new BeReadingAdvisor())
                .advisors(advisorSpec -> advisorSpec.param(ChatMemory.CONVERSATION_ID,"1"))
                .call()
                .content();
        System.out.println(content);
    }

三、多层次记忆架构(模仿人类记忆)

3.1 痛点分析

记忆多 = 更聪明,但会触发 Token 上限。如何在有限窗口内保留更多有用信息?

人类记忆分为三种:瞬时记忆、短时记忆、长时记忆。我们可以借鉴这个模型:

text

┌─────────────────────────────────────────────────────────────┐
│                    多层次记忆架构                            │
├─────────────────────────────────────────────────────────────┤
│  📍 近期记忆(短期)   │  最近 10 条对话,直接上下文窗口      │
├─────────────────────────────────────────────────────────────┤
│  📍 中期记忆(中期)   │  RAG 检索相关历史(Top-K ≈ 5条)    │
├─────────────────────────────────────────────────────────────┤
│  📍 长期记忆(长期)   │  定时批处理 / 关键点实时提取         │
└─────────────────────────────────────────────────────────────┘

四、架构总览

┌────────────────────────────────────────────────────────────────┐
│                        用户交互                                │
└────────────────────┬───────────────────────────────────────────┘
                     ▼
┌────────────────────────────────────────────────────────────────┐
│              PromptChatMemoryAdvisor (拦截器)                   │
│  ┌─────────────┐  ┌─────────────┐  ┌────────────────────────┐ │
│  │ 近期记忆    │  │ 中期记忆    │  │ 长期记忆               │ │
│  │ (最近10条)  │ + │ (RAG Top5)  │ + │ (总结/关键点)          │ │
│  └─────────────┘  └─────────────┘  └────────────────────────┘ │
└────────────────────┬───────────────────────────────────────────┘
                     ▼
┌────────────────────────────────────────────────────────────────┐
│                    大模型 API 调用                             │
└────────────────────────────────────────────────────────────────┘

五、总结

层级技术方案特点
近期记忆ChatMemory + JDBC/Redis实时、高频、低延迟
中期记忆RAG + 向量数据库检索相关历史、按需加载
长期记忆批处理/实时提取沉淀知识、精炼存储

这种多层次记忆架构,能够在有限的 Token 窗口内最大化保留有用信息,让 AI 对话更接近"人"的自然交互体验。

Logo

中国智能体开发者社区,聚焦智能体与大模型开发,提供前沿资讯、实用工具链、开源项目及行业案例。通过技术沙龙、开发者大赛等活动,促进经验交流与协作,助力开发者快速构建创新智能应用。

更多推荐