Spring AI ChatMemory 对话记忆配置指南:概念、实战与常见问题

场景

Spring AI Advisor 完全指南:拦截器机制与实战全解:

https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/161018652

上述学习advisor时已基本实现会话记忆功能。

下面进行扩展学习。

大语言模型(LLM)本质上是无状态的------每次调用都是独立的。

如果在第一轮告诉模型"我叫小明",第二轮再问"我叫什么?",模型不会记得之前的对话。

要实现连贯的多轮对话,核心思路是在每次请求时把完整的对话历史一起发送给模型。

Spring AI 通过 ChatMemory 和 Advisor 机制将这一流程深度封装,开发者只需少量配置即可实现记忆、会话隔离甚至持久化。

本文聚焦于 ChatMemory 的核心知识点,基于 Spring AI 1.1.2 版本提供完整的示例代码,

并汇总实践中高频遇到的问题和解决方案。

核心概念

Spring AI 将对话记忆的管理拆分为三个层次,各司其职:

组件 角色 职责

ChatMemory 记忆策略层 决定保留哪些消息、何时裁剪(如只保留最近 N 条)

ChatMemoryRepository 存储层 纯粹负责消息的增删查改(内存、JDBC、Redis 等)

MessageChatMemoryAdvisor 拦截器层 自动在每次请求中注入对话历史,并在响应后保存新消息

MessageWindowChatMemory:滑动窗口记忆

MessageWindowChatMemory 是 Spring AI 目前推荐的核心记忆实现。

它维护一个固定大小的消息窗口(默认 20 条),超过上限时自动移除旧消息,但会保留 系统消息 (SystemMessage)。

这种设计使你能精确控制每次发送给模型的上下文长度,避免 Token 爆炸。

两种 Advisor 注册方式

方式 代码 适用场景

构建时注册(全局) ChatClient.builder().defaultAdvisors(...) 对所有请求生效

请求时指定(按需) prompt().advisors(a -> a.param(...)) 传递运行时参数(如 conversationId)

因为记忆需要根据会话 ID 动态加载不同用户的历史,所以 MessageChatMemoryAdvisor 必须采用请求时传参的方式。

注:

博客:
https://blog.csdn.net/badao_liumang_qizhi

实现

pom.xml

复制代码
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.3.3</version> <!-- 降级为稳定版,解决冲突 -->
    </parent>

    <groupId>com.example</groupId>
    <artifactId>spring-ai-ollama-demo</artifactId>
    <version>1.0</version>

    <properties>
        <java.version>17</java.version>
        <spring-ai.version>1.1.2</spring-ai.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!-- Spring AI Ollama 核心 -->
        <dependency>
            <groupId>org.springframework.ai</groupId>
            <artifactId>spring-ai-starter-model-ollama</artifactId>
            <version>${spring-ai.version}</version>
        </dependency>


    </dependencies>

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

application.yml

复制代码
​
server:
  port: 886

spring:
  ai:
    ollama:
      base-url: http://localhost:11434
      chat:
        model: qwen2.5:7b-instruct
        options:
          temperature: 0.7
          num-ctx: 4096     # Ollama 上下文窗口大小

logging:
  level:
    org.springframework.ai.chat.client.advisor: DEBUG   # 观察记忆注入日志

​

MemoryConfig ------ 创建 ChatMemory

复制代码
package com.badao.ai.config;

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

import org.springframework.ai.chat.memory.InMemoryChatMemoryRepository;
import org.springframework.ai.chat.memory.MessageWindowChatMemory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class MemoryConfig {

    @Bean
    public ChatMemory chatMemory() {
        // 1. 创建底层存储仓库(内存实现)
        InMemoryChatMemoryRepository repository = new InMemoryChatMemoryRepository();

        // 2. 用滑动窗口策略包装,限制每次最多注入 10 条最近消息
        return MessageWindowChatMemory.builder()
                .chatMemoryRepository(repository)
                .maxMessages(10)
                .build();
    }
}

ChatConfig ------ 注册记忆 Advisor

复制代码
package com.badao.ai.config;

import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.MessageChatMemoryAdvisor;
import org.springframework.ai.chat.memory.ChatMemory;
import org.springframework.ai.chat.model.ChatModel;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class ChatConfig {

    @Bean
    public ChatClient chatClient(ChatModel chatModel, ChatMemory chatMemory) {
        return ChatClient.builder(chatModel)
                .defaultAdvisors(
                        MessageChatMemoryAdvisor.builder(chatMemory).build()
                )
                .build();
    }
}

控制器 ------ 多轮对话接口

复制代码
package com.badao.ai.controller;

import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.memory.ChatMemory; // 导入 ChatMemory 接口
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/api")
public class MemoryChatController {

    private final ChatClient chatClient;

    public MemoryChatController(ChatClient chatClient) {
        this.chatClient = chatClient;
    }

    @PostMapping("/chat/memory")
    public ChatResponse chatWithMemory(@RequestBody MemoryChatRequest request) {
        String result = chatClient.prompt()
                .user(request.message())
                .advisors(advisor -> advisor.param(
                        ChatMemory.CONVERSATION_ID,
                        request.conversationId()
                ))
                .call()
                .content();
        return new ChatResponse(200, "success", result);
    }

    public record MemoryChatRequest(String message, String conversationId) {}
    public record ChatResponse(int code, String msg, String data) {}
}

测试验证

测试会话记忆,传递001,告诉名字,再询问名字

传递002询问名字

相关推荐
我是大卫4 小时前
从零到答辩全链路:花1小时用TRAE Work搞定100页案例报告+40页答辩PPT
人工智能·trae
Jul1en_4 小时前
【Java 脚手架】封装通用工具类-1
java·spring boot·分布式·spring·spring cloud
极序时代GEO品牌优化4 小时前
杭州极序时代|面向地域、设备与用户画像的动态GEO
人工智能·python·算法·极序时代geo
崔高杰4 小时前
【自动阅读笔记】Inference-Time Scaling for Generalist Reward Modeling
人工智能·笔记·机器学习
风途科技~4 小时前
隧道氮氧化物检测仪|实时监测 NO、NO₂浓度,助力公路隧道通风智能调控
大数据·人工智能
senmuleishi4 小时前
持续发力嵌入式AI IDE,攻坚大科学装置电源解决方案
ide·人工智能
刘婉晴4 小时前
【大模型安全】OWASP 大语言模型十大风险
人工智能·安全·语言模型
mlidongfeng4 小时前
[AI][C++26] SIMD 编程模型思考
开发语言·c++·人工智能
关于不上作者榜就原神启动那件事4 小时前
从 MDC 到 Agent:我手搓的文档路由协议,在 Spring AI Alibaba 里找到了正式实现
java·人工智能·spring·ai·agent
大模型真好玩5 小时前
LangChain DeepAgents 速通指南(十二)——一文详解生产级智能体的命令体系和工程设计
人工智能·langchain·agent