聊天记忆

大型语言模型 (LLM) 是无状态的,这意味着它们不会保留先前交互的信息。当您希望在多个交互之间维护上下文或状态时,这可能会造成限制。为了解决这个问题,Spring AI 提供了聊天记忆功能,允许您使用 LLM 跨多个交互存储和检索信息。

ChatMemory 抽象允许您实现各种类型的内存以支持不同的用例。消息的底层存储由 处理ChatMemoryRepository,其唯一职责是存储和检索消息。由ChatMemory实现决定保留哪些消息以及何时删除它们。策略示例包括保留最后 N 条消息、将消息保留一段时间或将消息保留到一定的令牌限制。

在选择记忆类型之前,必须了解聊天记忆和聊天历史之间的区别。

聊天记忆。大型语言模型保留并用于在整个对话过程中保持语境感知的信息。

聊天记录。整个对话历史记录,包括用户和模型之间交换的所有消息。

ChatMemory 抽象旨在管理聊天内存。它允许您存储和检索与当前对话上下文相关的消息。但是,它并非存储聊天历史记录的最佳选择。如果您需要维护所有交换消息的完整记录,则应考虑使用其他方法,例如依赖 Spring Data 来高效地存储和检索完整的聊天历史记录。

快速入门

Spring AI 会自动配置一个ChatMemoryBean,供您在应用程序中直接使用。默认情况下,它使用内存存储库来存储消息(InMemoryChatMemoryRepository),并使用一个MessageWindowChatMemory实现来管理对话历史记录。如果已配置其他存储库(例如 Cassandra、JDBC 或 Neo4j),Spring AI 将改用该存储库。

@Autowired
ChatMemory chatMemory;

以下部分将进一步描述 Spring AI 中可用的不同内存类型和存储库。

内存类型

这种ChatMemory抽象允许您实现各种类型的内存以适应不同的用例。内存类型的选择会显著影响应用程序的性能和行为。本节介绍 Spring AI 提供的内置内存类型及其特性。

消息窗口聊天记忆
MessageWindowChatMemory维护一个消息窗口,使其不超过指定的最大大小。当消息数量超过最大值时,较旧的消息将被删除,同时保留系统消息。默认窗口大小为 20 条消息。

MessageWindowChatMemory memory = MessageWindowChatMemory.builder()
.maxMessages(10)
.build();
这是 Spring AI 用于自动配置ChatMemorybean 的默认消息类型。

内存存储
Spring AI 提供了ChatMemoryRepository用于存储聊天记忆的抽象。本节介绍 Spring AI 提供的内置存储库及其使用方法,但您也可以根据需要实现自己的存储库。

内存存储库
InMemoryChatMemoryRepository使用 将消息存储在内存中ConcurrentHashMap。

默认情况下,如果尚未配置其他存储库,Spring AI 会自动配置一个您可以在应用程序中直接使用的ChatMemoryRepository类型的 bean 。InMemoryChatMemoryRepository

@Autowired
ChatMemoryRepository chatMemoryRepository;
如果您希望InMemoryChatMemoryRepository手动创建,可以按如下方式操作:

ChatMemoryRepository repository = new InMemoryChatMemoryRepository();
JdbcChatMemoryRepository
JdbcChatMemoryRepository是一个内置实现,使用 JDBC 将消息存储在关系数据库中。它开箱即用地支持多种数据库,适用于需要持久存储聊天记忆的应用程序。

首先,向您的项目添加以下依赖项:

Maven

Gradle

org.springframework.ai spring-ai-starter-model-chat-memory-repository-jdbc

@Autowired
JdbcChatMemoryRepository chatMemoryRepository;

ChatMemory chatMemory = MessageWindowChatMemory.builder()
.chatMemoryRepository(chatMemoryRepository)
.maxMessages(10)
.build();
如果您希望手动创建,您可以通过提供一个实例和一个JdbcChatMemoryRepository来实现:JdbcTemplateJdbcChatMemoryRepositoryDialect

ChatMemoryRepository chatMemoryRepository = JdbcChatMemoryRepository.builder()
.jdbcTemplate(jdbcTemplate)
.dialect(new PostgresChatMemoryDialect())
.build();

ChatMemory chatMemory = MessageWindowChatMemory.builder()
.chatMemoryRepository(chatMemoryRepository)
.maxMessages(10)
.build();
支持的数据库和方言抽象
Spring AI 通过方言抽象支持多种关系数据库。以下数据库是开箱即用的:

PostgreSQL

MySQL/MariaDB

SQL 服务器

数据库

使用时,可以从 JDBC URL 自动检测正确的方言JdbcChatMemoryRepositoryDialect.from(DataSource)。您可以通过实现JdbcChatMemoryRepositoryDialect接口来扩展对其他数据库的支持。

配置属性
财产

描述

默认值

spring.ai.chat.memory.repository.jdbc.initialize-schema

控制何时初始化架构。值:(embedded默认)always、、never。

embedded

spring.ai.chat.memory.repository.jdbc.schema

用于初始化的架构脚本的位置。支持classpath:URL 和平台占位符。

classpath:org/springframework/ai/chat/memory/repository/jdbc/schema-@@platform@@.sql

spring.ai.chat.memory.repository.jdbc.platform

如果使用 @@platform@@ 占位符,则在初始化脚本中使用的平台。

自动检测

模式初始化
自动配置将SPRING_AI_CHAT_MEMORY在启动时使用数据库供应商特定的 SQL 脚本自动创建表。默认情况下,模式初始化仅适用于嵌入式数据库(H2、HSQL、Derby 等)。

您可以使用以下属性控制架构初始化spring.ai.chat.memory.repository.jdbc.initialize-schema:

spring.ai.chat.memory.repository.jdbc.initialize-schema=embedded # Only for embedded DBs (default)
spring.ai.chat.memory.repository.jdbc.initialize-schema=always # Always initialize
spring.ai.chat.memory.repository.jdbc.initialize-schema=never # Never initialize (useful with Flyway/Liquibase)
要覆盖架构脚本位置,请使用:

spring.ai.chat.memory.repository.jdbc.schema=classpath:/custom/path/schema-mysql.sql
扩展方言
要添加对新数据库的支持,请实现JdbcChatMemoryRepositoryDialect接口并提供用于选择、插入和删除消息的 SQL。然后,您可以将自定义方言传递给存储库构建器。

ChatMemoryRepository chatMemoryRepository = JdbcChatMemoryRepository.builder()
.jdbcTemplate(jdbcTemplate)
.dialect(new MyCustomDbDialect())
.build();
CassandraChatMemory存储库
CassandraChatMemoryRepository使用 Apache Cassandra 存储消息。它适用于需要持久存储聊天内存的应用程序,尤其适用于需要高可用性、持久性、可扩展性以及利用生存时间 (TTL) 功能的应用程序。

CassandraChatMemoryRepository具有时间序列模式,记录所有过去的聊天窗口,这对于治理和审计非常有价值。建议将生存时间设置为某个值,例如三年。

首先使用CassandraChatMemoryRepository,将依赖项添加到您的项目中:

Maven

Gradle

org.springframework.ai spring-ai-starter-model-chat-memory-repository-cassandra

@Autowired
CassandraChatMemoryRepository chatMemoryRepository;

ChatMemory chatMemory = MessageWindowChatMemory.builder()
.chatMemoryRepository(chatMemoryRepository)
.maxMessages(10)
.build();
如果您希望CassandraChatMemoryRepository手动创建,则可以通过提供实例来实现CassandraChatMemoryRepositoryConfig:

ChatMemoryRepository chatMemoryRepository = CassandraChatMemoryRepository
.create(CassandraChatMemoryConfig.builder().withCqlSession(cqlSession));

ChatMemory chatMemory = MessageWindowChatMemory.builder()
.chatMemoryRepository(chatMemoryRepository)
.maxMessages(10)
.build();
配置属性
财产

描述

默认值

spring.cassandra.contactPoints

启动集群发现的主机

127.0.0.1

spring.cassandra.port

要连接的 Cassandra 本机协议端口

9042

spring.cassandra.localDatacenter

要连接的 Cassandra 数据中心

datacenter1

spring.ai.chat.memory.cassandra.time-to-live

Cassandra 中写入的消息的生存时间 (TTL)

spring.ai.chat.memory.cassandra.keyspace

Cassandra 键空间

springframework

spring.ai.chat.memory.cassandra.messages-column

Cassandra 消息的列名

springframework

spring.ai.chat.memory.cassandra.table

Cassandra 表

ai_chat_memory

spring.ai.chat.memory.cassandra.initialize-schema

是否在启动时初始化模式。

true

模式初始化
自动配置将自动创建ai_chat_memory表。

您可以通过将属性设置spring.ai.chat.memory.repository.cassandra.initialize-schema为来禁用架构初始化false。

Neo4j ChatMemoryRepository
Neo4jChatMemoryRepository是一个内置实现,使用 Neo4j 将聊天消息作为节点和关系存储在属性图数据库中。它适用于希望利用 Neo4j 的图功能实现聊天内存持久化的应用程序。

首先,向您的项目添加以下依赖项:

Maven

Gradle

org.springframework.ai spring-ai-starter-model-chat-memory-repository-neo4j

@Autowired
Neo4jChatMemoryRepository chatMemoryRepository;

ChatMemory chatMemory = MessageWindowChatMemory.builder()
.chatMemoryRepository(chatMemoryRepository)
.maxMessages(10)
.build();
如果您希望Neo4jChatMemoryRepository手动创建,则可以通过提供 Neo4j 实例来实现Driver:

ChatMemoryRepository chatMemoryRepository = Neo4jChatMemoryRepository.builder()
.driver(driver)
.build();

ChatMemory chatMemory = MessageWindowChatMemory.builder()
.chatMemoryRepository(chatMemoryRepository)
.maxMessages(10)
.build();
配置属性
财产

描述

默认值

spring.ai.chat.memory.repository.neo4j.sessionLabel

存储对话会话的节点的标签

Session

spring.ai.chat.memory.repository.neo4j.messageLabel

存储消息的节点的标签

Message

spring.ai.chat.memory.repository.neo4j.toolCallLabel

存储工具调用的节点的标签(例如在助手消息中)

ToolCall

spring.ai.chat.memory.repository.neo4j.metadataLabel

存储消息元数据的节点的标签

Metadata

spring.ai.chat.memory.repository.neo4j.toolResponseLabel

存储工具响应的节点的标签

ToolResponse

spring.ai.chat.memory.repository.neo4j.mediaLabel

存储与消息相关的媒体的节点的标签

Media

索引初始化
Neo4j 代码库将自动确保为对话 ID 和消息索引创建索引,以优化性能。如果您使用自定义标签,系统也会为这些标签创建索引。无需初始化架构,但您应确保您的应用程序可以访问 Neo4j 实例。

聊天客户端中的内存
使用 ChatClient API 时,您可以提供一个ChatMemory实现来在多个交互中维护对话上下文。

Spring AI 提供了一些内置的 Advisor,您可以ChatClient根据需要使用它们来配置的内存行为。

目前,执行工具调用时与大型语言模型交换的中间消息不会存储在内存中。这是当前实现的限制,将在未来的版本中解决。如果您需要存储这些消息,请参阅用户控制工具执行的说明。
MessageChatMemoryAdvisor此顾问程序使用提供的实现来管理对话内存ChatMemory。每次交互时,它都会从内存中检索对话历史记录,并将其作为消息集合包含在提示中。

PromptChatMemoryAdvisor此顾问程序使用提供的实现来管理对话内存ChatMemory。每次交互时,它都会从内存中检索对话历史记录,并将其以纯文本形式附加到系统提示中。

VectorStoreChatMemoryAdvisor此顾问使用提供的实现来管理对话内存VectorStore。每次交互时,它都会从向量存储中检索对话历史记录,并将其以纯文本形式附加到系统消息中。

例如,如果要MessageWindowChatMemory与一起使用MessageChatMemoryAdvisor,可以按如下方式配置:

ChatMemory chatMemory = MessageWindowChatMemory.builder().build();

ChatClient chatClient = ChatClient.builder(chatModel)
.defaultAdvisors(MessageChatMemoryAdvisor.builder(chatMemory).build())
.build();
当执行对 的调用时ChatClient,内存将由 自动管理MessageChatMemoryAdvisor。对话历史记录将根据指定的对话 ID 从内存中检索:

String conversationId = “007”;

chatClient.prompt()
.user(“Do I have license to code?”)
.advisors(a -> a.param(ChatMemory.CONVERSATION_ID, conversationId))
.call()
.content();
PromptChatMemoryAdvisor
自定义模板
使用PromptChatMemoryAdvisor默认模板,将检索到的对话记忆添加到系统消息中。您可以PromptTemplate通过构建器方法提供自己的对象来自定义此行为.promptTemplate()。

此处提供的 可自定义顾问程序PromptTemplate如何将检索到的内存与系统消息合并。这与TemplateRenderer在ChatClient本身上配置 (使用)不同,后者会影响顾问程序运行前.templateRenderer()初始用户/系统提示内容的渲染。有关客户端级模板渲染的更多详细信息, 请参阅ChatClient 提示模板。
自定义PromptTemplate可以使用任何TemplateRenderer实现(默认情况下,它使用StPromptTemplate基于StringTemplate引擎的实现)。重要的要求是模板必须包含以下两个占位符:

instructions接收原始系统消息的占位符。

memory用于接收检索到的对话记忆的占位符。

VectorStoreChatMemoryAdvisor
自定义模板
使用VectorStoreChatMemoryAdvisor默认模板,将检索到的对话记忆添加到系统消息中。您可以PromptTemplate通过构建器方法提供自己的对象来自定义此行为.promptTemplate()。

此处提供的 可自定义顾问程序PromptTemplate如何将检索到的内存与系统消息合并。这与TemplateRenderer在ChatClient本身上配置 (使用)不同,后者会影响顾问程序运行前.templateRenderer()初始用户/系统提示内容的渲染。有关客户端级模板渲染的更多详细信息, 请参阅ChatClient 提示模板。
自定义PromptTemplate可以使用任何TemplateRenderer实现(默认情况下,它使用StPromptTemplate基于StringTemplate引擎的实现)。重要的要求是模板必须包含以下两个占位符:

instructions接收原始系统消息的占位符。

long_term_memory用于接收检索到的对话记忆的占位符。

聊天模型中的内存
如果您直接使用ChatModel而不是ChatClient,则可以明确管理内存:

// Create a memory instance
ChatMemory chatMemory = MessageWindowChatMemory.builder().build();
String conversationId = “007”;

// First interaction
UserMessage userMessage1 = new UserMessage(“My name is James Bond”);
chatMemory.add(conversationId, userMessage1);
ChatResponse response1 = chatModel.call(new Prompt(chatMemory.get(conversationId)));
chatMemory.add(conversationId, response1.getResult().getOutput());

// Second interaction
UserMessage userMessage2 = new UserMessage(“What is my name?”);
chatMemory.add(conversationId, userMessage2);
ChatResponse response2 = chatModel.call(new Prompt(chatMemory.get(conversationId)));
chatMemory.add(conversationId, response2.getResult().getOutput());

// The response will contain “James Bond”

作者:Jeebiz  创建时间:2025-08-03 23:47
最后编辑:Jeebiz  更新时间:2025-08-08 00:47
Spring AI 为提供了自动配置JdbcChatMemoryRepository,您可以在应用程序中直接使用。 Spring AI 提供了自动配置,CassandraChatMemoryRepository您可以在应用程序中直接使用它。 Spring AI 为提供了自动配置Neo4jChatMemoryRepository,您可以在应用程序中直接使用它。