原文网址:Spring AI--快速入门2:上下文记忆+会话隔离-CSDN博客

简介

上篇文章:Spring Ai--快速入门1:对话实战-CSDN博客 实现了简单对话功能,但不支持上下文。

对话记忆的核心是:上下文的存储(发送请求时会附带)。本文实现上下文记忆和会话隔离。

会话记忆

代码

详述

SpringAI 对话记忆核心类是ChatMemory。

  1. ChatMemory提供的方法:添加消息到对话、从对话中检索消息、清除对话历史。
  2. 目前有一个内置实现:MessageWindowChatMemory,可配置最大消息数量(默认20),当消息数量超过时,较旧的消息会被移除。
  3. Spring AI 用 ChatMemoryRepository 来读写上下文,其默认实现是:用InMemoryChatMemoryRepository(存储在内存中)。

代码

下边自定义ChatMemory的Bean,并将其绑定到ChatClient的增强器。(实际上,Spring Ai有默认的ChatMemory的Bean,其实现就是InMemoryChatMemoryRepository,最大消息数是20,这里不自定义Bean也可以,本处写出来主要是为了了解如何自定义配置。)

package com.knife.example.ai.chat.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.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 AiCustomConfiguration {
    /**
     * 聊天对话记忆的存储
     */
    @Bean
    public ChatMemory chatMemory() {
        // 当前版本下 MessageWindowChatMemory 是 ChatMemory 的唯一内置实现类
        // 并且构造器私有化,只提供Builder模式来创建实例(这点与之前的版本不一样)
        return MessageWindowChatMemory.builder()
                // 对话存储的repository存储库层的实现方式。默认是 Spring 提供的 InMemoryChatMemoryRepository
                .chatMemoryRepository(new InMemoryChatMemoryRepository())
                .maxMessages(20) // 最大消息数
                .build();
    }

    /**
     * 会话客户端
     */
    @Bean
    public ChatClient chatClient(ChatClient.Builder chatClientBuilder,
                                 ChatMemory chatMemory) {
        return chatClientBuilder
                .defaultSystem("你是一个博学的智能聊天助手,请根据用户提问回答!")
                .defaultAdvisors(
                        new SimpleLoggerAdvisor(), // 日志记录器
                        MessageChatMemoryAdvisor.builder(chatMemory).build() // 添加聊天记录记忆的环绕增强器
                )
                .build();
    }
}

测试

访问:http://localhost:8080/doc.html

如下图所示,可发现:有上下文记忆功能了!

后台日志(可以发现:请求会带着之前的会话问题和结果)

第一次:

第二次:

第三次:

详细日志(这里只贴出请求日志)

2025-12-07T11:45:49.079+08:00 DEBUG 19168 --- [1_chat] [nio-8080-exec-2] o.s.a.c.c.advisor.SimpleLoggerAdvisor    : request: ChatClientRequest[prompt=Prompt{messages=[SystemMessage{textContent='你是一个博学的智能聊天助手,请根据用户提问回答!', messageType=SYSTEM, metadata={messageType=SYSTEM}}, UserMessage{content='一加一等于几?', metadata={messageType=USER}, messageType=USER}], modelOptions=OpenAiChatOptions: {"streamUsage":false,"model":"qwen-plus","temperature":0.8,"top_p":0.7}}, context={}]
2025-12-07T11:46:24.627+08:00 DEBUG 19168 --- [1_chat] [nio-8080-exec-1] o.s.a.c.c.advisor.SimpleLoggerAdvisor    : request: ChatClientRequest[prompt=Prompt{messages=[UserMessage{content='一加一等于几?', metadata={messageType=USER}, messageType=USER}, AssistantMessage [messageType=ASSISTANT, toolCalls=[], textContent=一加一等于二。, metadata={role=ASSISTANT, messageType=ASSISTANT, refusal=, finishReason=STOP, annotations=[{}], index=0, id=chatcmpl-6e39b8f1-2bc8-437b-8c04-8d03e8cb2e46}], SystemMessage{textContent='你是一个博学的智能聊天助手,请根据用户提问回答!', messageType=SYSTEM, metadata={messageType=SYSTEM}}, UserMessage{content='再加一呢?', metadata={messageType=USER}, messageType=USER}], modelOptions=OpenAiChatOptions: {"streamUsage":false,"model":"qwen-plus","temperature":0.8,"top_p":0.7}}, context={}]
2025-12-07T11:48:28.010+08:00 DEBUG 19168 --- [1_chat] [nio-8080-exec-4] o.s.a.c.c.advisor.SimpleLoggerAdvisor    : request: ChatClientRequest[prompt=Prompt{messages=[UserMessage{content='一加一等于几?', metadata={messageType=USER}, messageType=USER}, AssistantMessage [messageType=ASSISTANT, toolCalls=[], textContent=一加一等于二。, metadata={role=ASSISTANT, messageType=ASSISTANT, refusal=, finishReason=STOP, annotations=[{}], index=0, id=chatcmpl-6e39b8f1-2bc8-437b-8c04-8d03e8cb2e46}], UserMessage{content='再加一呢?', metadata={messageType=USER}, messageType=USER}, AssistantMessage [messageType=ASSISTANT, toolCalls=[], textContent=如果在一加一(即2)的基础上再加一,那么结果就是3。, metadata={role=ASSISTANT, messageType=ASSISTANT, refusal=, finishReason=STOP, annotations=[{}], index=0, id=chatcmpl-f604d8f7-60f0-42b3-b1f4-ede325ad52fb}], SystemMessage{textContent='你是一个博学的智能聊天助手,请根据用户提问回答!', messageType=SYSTEM, metadata={messageType=SYSTEM}}, UserMessage{content='再次加一呢?', metadata={messageType=USER}, messageType=USER}], modelOptions=OpenAiChatOptions: {"streamUsage":false,"model":"qwen-plus","temperature":0.8,"top_p":0.7}}, context={}]

会话隔离

现在已经实现记忆,但是还有问题:所有会话共享一个记忆,没有进行隔离!

会话隔离的方法是:在请求发送前,调用 advisor() 方法配置一个 Consumer

为便于维护,全文已转移到此网址:Spring AI-快速入门2:上下文记忆+会话隔离 - 自学精灵

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐