Chat Memory
大型语言模型 (LLM) 是无状态的,这意味着它们不会保留以前交互的信息。当您希望在多次交互中保持上下文或状态时,这可能是一个限制。为了解决这个问题,Spring AI 提供了聊天记忆功能,允许您在与 LLM 的多次交互中存储和检索信息。
Large language models (LLMs) are stateless, meaning they do not retain information about previous interactions. This can be a limitation when you want to maintain context or state across multiple interactions. To address this, Spring AI provides chat memory features that allow you to store and retrieve information across multiple interactions with the LLM.
ChatMemory
抽象允许您实现各种类型的记忆以支持不同的用例。消息的底层存储由 ChatMemoryRepository
处理,其唯一职责是存储和检索消息。由 ChatMemory
实现来决定要保留哪些消息以及何时删除它们。策略示例可以包括保留最后 N 条消息、在一定时间段内保留消息,或将消息保留到一定令牌限制。
The ChatMemory
abstraction allows you to implement various types of memory to support different use cases. The underlying storage of the messages is handled by the ChatMemoryRepository
, whose sole responsibility is to store and retrieve messages. It’s up to the ChatMemory
implementation to decide which messages to keep and when to remove them. Examples of strategies could include keeping the last N messages, keeping messages for a certain time period, or keeping messages up to a certain token limit.
在选择记忆类型之前,了解聊天记忆和聊天历史之间的区别至关重要。
Before choosing a memory type, it’s essential to understand the difference between chat memory and chat history.
-
Chat Memory 。大型语言模型保留并用于在整个对话中保持上下文意识的信息。
-
Chat Memory. The information that a large-language model retains and uses to maintain contextual awareness throughout a conversation.
-
Chat History 。完整的对话历史,包括用户和模型之间交换的所有消息。
-
Chat History. The entire conversation history, including all messages exchanged between the user and the model.
ChatMemory
抽象旨在管理 chat memory 。它允许您存储和检索与当前对话上下文相关的消息。但是,它不最适合存储 chat history 。如果您需要维护所有交换消息的完整记录,您应该考虑使用不同的方法,例如依赖 Spring Data 来高效存储和检索完整的聊天历史。
The ChatMemory
abstraction is designed to manage the chat memory. It allows you to store and retrieve messages that are relevant to the current conversation context. However, it is not the best fit for storing the chat history. If you need to maintain a complete record of all the messages exchanged, you should consider using a different approach, such as relying on Spring Data for efficient storage and retrieval of the complete chat history.
Quick Start
Spring AI 自动配置一个 ChatMemory
bean,您可以直接在应用程序中使用。默认情况下,它使用内存存储库来存储消息 ( InMemoryChatMemoryRepository
) 和 MessageWindowChatMemory
实现来管理对话历史。如果已配置不同的存储库(例如,Cassandra、JDBC 或 Neo4j),Spring AI 将使用该存储库。
Spring AI auto-configures a ChatMemory
bean that you can use directly in your application. By default, it uses an in-memory repository to store messages (InMemoryChatMemoryRepository
) and a MessageWindowChatMemory
implementation to manage the conversation history. If a different repository is already configured (e.g., Cassandra, JDBC, or Neo4j), Spring AI will use that instead.
@Autowired
ChatMemory chatMemory;
以下部分将进一步描述 Spring AI 中可用的不同记忆类型和存储库。
The following sections will describe further the different memory types and repositories available in Spring AI.
Memory Types
ChatMemory
抽象允许您实现各种类型的记忆以适应不同的用例。记忆类型的选择可以显著影响应用程序的性能和行为。本节描述了 Spring AI 提供的内置记忆类型及其特性。
The ChatMemory
abstraction allows you to implement various types of memory to suit different use cases. The choice of memory type can significantly impact the performance and behavior of your application. This section describes the built-in memory types provided by Spring AI and their characteristics.
Message Window Chat Memory
MessageWindowChatMemory
维护一个消息窗口,最大大小可达指定值。当消息数量超过最大值时,较旧的消息将被删除,同时保留系统消息。默认窗口大小为 20 条消息。
MessageWindowChatMemory
maintains a window of messages up to a specified maximum size. When the number of messages exceeds the maximum, older messages are removed while preserving system messages. The default window size is 20 messages.
MessageWindowChatMemory memory = MessageWindowChatMemory.builder()
.maxMessages(10)
.build();
这是 Spring AI 用于自动配置 ChatMemory
bean 的默认消息类型。
This is the default message type used by Spring AI to auto-configure a ChatMemory
bean.
Memory Storage
Spring AI 提供了 ChatMemoryRepository
抽象用于存储聊天记忆。本节描述了 Spring AI 提供的内置存储库以及如何使用它们,但您也可以根据需要实现自己的存储库。
Spring AI offers the ChatMemoryRepository
abstraction for storing chat memory. This section describes the built-in repositories provided by Spring AI and how to use them, but you can also implement your own repository if needed.
In-Memory Repository
InMemoryChatMemoryRepository
使用 ConcurrentHashMap
将消息存储在内存中。
InMemoryChatMemoryRepository
stores messages in memory using a ConcurrentHashMap
.
默认情况下,如果没有配置其他存储库,Spring AI 会自动配置一个类型为 InMemoryChatMemoryRepository
的 ChatMemoryRepository
bean,您可以直接在应用程序中使用。
By default, if no other repository is already configured, Spring AI auto-configures a ChatMemoryRepository
bean of type InMemoryChatMemoryRepository
that you can use directly in your application.
@Autowired
ChatMemoryRepository chatMemoryRepository;
如果您更喜欢手动创建 InMemoryChatMemoryRepository
,可以按如下方式操作:
If you’d rather create the InMemoryChatMemoryRepository
manually, you can do so as follows:
ChatMemoryRepository repository = new InMemoryChatMemoryRepository();
JdbcChatMemoryRepository
JdbcChatMemoryRepository
是一个内置实现,它使用 JDBC 将消息存储在关系数据库中。它开箱即用地支持多种数据库,适用于需要持久存储聊天记忆的应用程序。
JdbcChatMemoryRepository
is a built-in implementation that uses JDBC to store messages in a relational database. It supports multiple databases out-of-the-box and is suitable for applications that require persistent storage of chat memory.
首先,将以下依赖项添加到您的项目中:
First, add the following dependency to your project:
-
Maven
-
Gradle
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-model-chat-memory-repository-jdbc</artifactId>
</dependency>
dependencies {
implementation 'org.springframework.ai:spring-ai-starter-model-chat-memory-repository-jdbc'
}
Spring AI 为 JdbcChatMemoryRepository
提供自动配置,您可以直接在应用程序中使用。
Spring AI provides auto-configuration for the JdbcChatMemoryRepository
, that you can use directly in your application.
@Autowired
JdbcChatMemoryRepository chatMemoryRepository;
ChatMemory chatMemory = MessageWindowChatMemory.builder()
.chatMemoryRepository(chatMemoryRepository)
.maxMessages(10)
.build();
如果您更喜欢手动创建 JdbcChatMemoryRepository
,可以通过提供 JdbcTemplate
实例和 JdbcChatMemoryRepositoryDialect
来实现:
If you’d rather create the JdbcChatMemoryRepository
manually, you can do so by providing a JdbcTemplate
instance and a JdbcChatMemoryRepositoryDialect
:
ChatMemoryRepository chatMemoryRepository = JdbcChatMemoryRepository.builder()
.jdbcTemplate(jdbcTemplate)
.dialect(new PostgresChatMemoryDialect())
.build();
ChatMemory chatMemory = MessageWindowChatMemory.builder()
.chatMemoryRepository(chatMemoryRepository)
.maxMessages(10)
.build();
Supported Databases and Dialect Abstraction
Spring AI 通过方言抽象支持多种关系数据库。以下数据库开箱即用:
Spring AI supports multiple relational databases via a dialect abstraction. The following databases are supported out-of-the-box:
-
PostgreSQL
-
MySQL / MariaDB
-
SQL Server
-
HSQLDB
使用 JdbcChatMemoryRepositoryDialect.from(DataSource)
时,可以从 JDBC URL 自动检测正确的方言。您可以通过实现 JdbcChatMemoryRepositoryDialect
接口来扩展对其他数据库的支持。
The correct dialect can be auto-detected from the JDBC URL when using JdbcChatMemoryRepositoryDialect.from(DataSource)
. You can extend support for other databases by implementing the JdbcChatMemoryRepositoryDialect
interface.
Configuration Properties
Property |
Description |
Default Value |
|
Controls when to initialize the schema. Values: |
|
|
Location of the schema script to use for initialization. Supports |
|
|
Platform to use in initialization scripts if the @@platform@@ placeholder is used. |
auto-detected |
Schema Initialization
自动配置会在启动时自动创建 SPRING_AI_CHAT_MEMORY
表,使用特定于供应商的 SQL 脚本来创建数据库。默认情况下,模式初始化仅针对嵌入式数据库(H2、HSQL、Derby 等)运行。
The auto-configuration will automatically create the SPRING_AI_CHAT_MEMORY
table on startup, using a vendor-specific SQL script for your database. By default, schema initialization runs only for embedded databases (H2, HSQL, Derby, etc.).
您可以使用 spring.ai.chat.memory.repository.jdbc.initialize-schema
属性控制模式初始化:
You can control schema initialization using the spring.ai.chat.memory.repository.jdbc.initialize-schema
property:
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)
要覆盖模式脚本位置,请使用:
To override the schema script location, use:
spring.ai.chat.memory.repository.jdbc.schema=classpath:/custom/path/schema-mysql.sql
Extending Dialects
要添加对新数据库的支持,请实现 JdbcChatMemoryRepositoryDialect
接口并提供用于选择、插入和删除消息的 SQL。然后可以将自定义方言传递给存储库构建器。
To add support for a new database, implement the JdbcChatMemoryRepositoryDialect
interface and provide SQL for selecting, inserting, and deleting messages. You can then pass your custom dialect to the repository builder.
ChatMemoryRepository chatMemoryRepository = JdbcChatMemoryRepository.builder()
.jdbcTemplate(jdbcTemplate)
.dialect(new MyCustomDbDialect())
.build();
CassandraChatMemoryRepository
CassandraChatMemoryRepository
使用 Apache Cassandra 存储消息。它适用于需要持久存储聊天记忆的应用程序,特别是在可用性、持久性、扩展性以及利用生存时间 (TTL) 功能方面。
CassandraChatMemoryRepository
uses Apache Cassandra to store messages. It is suitable for applications that require persistent storage of chat memory, especially for availability, durability, scale, and when taking advantage of time-to-live (TTL) feature.
CassandraChatMemoryRepository
具有时间序列模式,记录所有过去的聊天窗口,这对于治理和审计很有价值。建议将生存时间设置为某个值,例如三年。
CassandraChatMemoryRepository
has a time-series schema, keeping record of all past chat windows, valuable for governance and auditing. Setting time-to-live to some value, for example three years, is recommended.
要使用 CassandraChatMemoryRepository
,首先将依赖项添加到您的项目中:
To use CassandraChatMemoryRepository
first, add the dependency to your project:
-
Maven
-
Gradle
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-model-chat-memory-repository-cassandra</artifactId>
</dependency>
dependencies {
implementation 'org.springframework.ai:spring-ai-starter-model-chat-memory-repository-cassandra'
}
Spring AI 为 CassandraChatMemoryRepository
提供自动配置,您可以直接在应用程序中使用。
Spring AI provides auto-configuration for the CassandraChatMemoryRepository
that you can use directly in your application.
@Autowired
CassandraChatMemoryRepository chatMemoryRepository;
ChatMemory chatMemory = MessageWindowChatMemory.builder()
.chatMemoryRepository(chatMemoryRepository)
.maxMessages(10)
.build();
如果您更喜欢手动创建 CassandraChatMemoryRepository
,可以通过提供 CassandraChatMemoryRepositoryConfig
实例来创建:
If you’d rather create the CassandraChatMemoryRepository
manually, you can do so by providing a CassandraChatMemoryRepositoryConfig
instance:
ChatMemoryRepository chatMemoryRepository = CassandraChatMemoryRepository
.create(CassandraChatMemoryConfig.builder().withCqlSession(cqlSession));
ChatMemory chatMemory = MessageWindowChatMemory.builder()
.chatMemoryRepository(chatMemoryRepository)
.maxMessages(10)
.build();
Configuration Properties
Property |
Description |
Default Value |
|
Host(s) to initiate cluster discovery |
|
|
Cassandra native protocol port to connect to |
|
|
Cassandra datacenter to connect to |
|
|
Time to live (TTL) for messages written in Cassandra |
|
|
Cassandra keyspace |
|
|
Cassandra column name for messages |
|
|
Cassandra table |
|
|
Whether to initialize the schema on startup. |
|
Schema Initialization
自动配置将自动创建 ai_chat_memory
表。
The auto-configuration will automatically create the ai_chat_memory
table.
您可以通过将属性 spring.ai.chat.memory.repository.cassandra.initialize-schema
设置为 false
来禁用模式初始化。
You can disable the schema initialization by setting the property spring.ai.chat.memory.repository.cassandra.initialize-schema
to false
.
Neo4j ChatMemoryRepository
Neo4jChatMemoryRepository
是一个内置实现,它使用 Neo4j 将聊天消息作为节点和关系存储在属性图数据库中。它适用于希望利用 Neo4j 图功能进行聊天记忆持久化的应用程序。
Neo4jChatMemoryRepository
is a built-in implementation that uses Neo4j to store chat messages as nodes and relationships in a property graph database. It is suitable for applications that want to leverage Neo4j’s graph capabilities for chat memory persistence.
首先,将以下依赖项添加到您的项目中:
First, add the following dependency to your project:
-
Maven
-
Gradle
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-model-chat-memory-repository-neo4j</artifactId>
</dependency>
dependencies {
implementation 'org.springframework.ai:spring-ai-starter-model-chat-memory-repository-neo4j'
}
Spring AI 为 Neo4jChatMemoryRepository
提供自动配置,您可以直接在应用程序中使用。
Spring AI provides auto-configuration for the Neo4jChatMemoryRepository
, which you can use directly in your application.
@Autowired
Neo4jChatMemoryRepository chatMemoryRepository;
ChatMemory chatMemory = MessageWindowChatMemory.builder()
.chatMemoryRepository(chatMemoryRepository)
.maxMessages(10)
.build();
如果您更倾向于手动创建 Neo4jChatMemoryRepository
,可以通过提供一个 Neo4j Driver
实例来实现:
If you’d rather create the Neo4jChatMemoryRepository
manually, you can do so by providing a Neo4j Driver
instance:
ChatMemoryRepository chatMemoryRepository = Neo4jChatMemoryRepository.builder()
.driver(driver)
.build();
ChatMemory chatMemory = MessageWindowChatMemory.builder()
.chatMemoryRepository(chatMemoryRepository)
.maxMessages(10)
.build();
Configuration Properties
Property |
Description |
Default Value |
|
The label for the nodes that store conversation sessions |
|
|
The label for the nodes that store messages |
|
|
The label for nodes that store tool calls (e.g. in Assistant Messages) |
|
|
The label for nodes that store message metadata |
|
|
The label for the nodes that store tool responses |
|
|
The label for the nodes that store media associated with a message |
|
Index Initialization
Neo4j 存储库将自动确保为对话 ID 和消息索引创建索引,以优化性能。如果您使用自定义标签,也将为这些标签创建索引。无需进行模式初始化,但您应确保您的 Neo4j 实例可供您的应用程序访问。
The Neo4j repository will automatically ensure that indexes are created for conversation IDs and message indices to optimize performance. If you use custom labels, indexes will be created for those labels as well. No schema initialization is required, but you should ensure your Neo4j instance is accessible to your application.
Memory in Chat Client
当使用 ChatClient API 时,您可以提供一个 ChatMemory
实现,以在多次交互中保持对话上下文。
When using the ChatClient API, you can provide a ChatMemory
implementation to maintain conversation context across multiple interactions.
Spring AI 提供了一些内置的 Advisor,您可以根据需要使用它们来配置 ChatClient
的内存行为。
Spring AI provides a few built-in Advisors that you can use to configure the memory behavior of the ChatClient
, based on your needs.
目前,执行工具调用时与大型语言模型交换的中间消息未存储在内存中。这是当前实现的一个限制,将在未来版本中解决。如果您需要存储这些消息,请参阅 User Controlled Tool Execution 的说明。
Currently, the intermediate messages exchanged with a large-language model when performing tool calls are not stored in the memory. This is a limitation of the current implementation and will be addressed in future releases. If you need to store these messages, refer to the instructions for the User Controlled Tool Execution.
-
MessageChatMemoryAdvisor
。此 Advisor 使用提供的ChatMemory
实现管理对话内存。在每次交互中,它从内存中检索对话历史记录,并将其作为消息集合包含在提示中。 -
MessageChatMemoryAdvisor
. This advisor manages the conversation memory using the providedChatMemory
implementation. On each interaction, it retrieves the conversation history from the memory and includes it in the prompt as a collection of messages. -
PromptChatMemoryAdvisor
。此 Advisor 使用提供的ChatMemory
实现管理对话内存。在每次交互中,它从内存中检索对话历史记录,并将其作为纯文本附加到系统提示中。 -
PromptChatMemoryAdvisor
. This advisor manages the conversation memory using the providedChatMemory
implementation. On each interaction, it retrieves the conversation history from the memory and appends it to the system prompt as plain text. -
VectorStoreChatMemoryAdvisor
。此 Advisor 使用提供的VectorStore
实现管理对话内存。在每次交互中,它从向量存储中检索对话历史记录,并将其作为纯文本附加到系统消息中。 -
VectorStoreChatMemoryAdvisor
. This advisor manages the conversation memory using the providedVectorStore
implementation. On each interaction, it retrieves the conversation history from the vector store and appends it to the system message as plain text.
例如,如果您想将 MessageWindowChatMemory
与 MessageChatMemoryAdvisor
一起使用,可以按如下方式进行配置:
For example, if you want to use MessageWindowChatMemory
with the MessageChatMemoryAdvisor
, you can configure it as follows:
ChatMemory chatMemory = MessageWindowChatMemory.builder().build();
ChatClient chatClient = ChatClient.builder(chatModel)
.defaultAdvisors(MessageChatMemoryAdvisor.builder(chatMemory).build())
.build();
当对 ChatClient
进行调用时,内存将由 MessageChatMemoryAdvisor
自动管理。对话历史记录将根据指定的对话 ID 从内存中检索:
When performing a call to the ChatClient
, the memory will be automatically managed by the MessageChatMemoryAdvisor
. The conversation history will be retrieved from the memory based on the specified conversation ID:
String conversationId = "007";
chatClient.prompt()
.user("Do I have license to code?")
.advisors(a -> a.param(ChatMemory.CONVERSATION_ID, conversationId))
.call()
.content();
PromptChatMemoryAdvisor
Custom Template
PromptChatMemoryAdvisor
使用默认模板通过检索到的对话内存来增强系统消息。您可以通过 .promptTemplate()
构建器方法提供自己的 PromptTemplate
对象来自定义此行为。
The PromptChatMemoryAdvisor
uses a default template to augment the system message with the retrieved conversation memory. You can customize this behavior by providing your own PromptTemplate
object via the .promptTemplate()
builder method.
此处提供的 |
The |
自定义 PromptTemplate
可以使用任何 TemplateRenderer
实现(默认情况下,它基于 StringTemplate 引擎使用 StPromptTemplate
)。重要的要求是模板必须包含以下两个占位符:
The custom PromptTemplate
can use any TemplateRenderer
implementation (by default, it uses StPromptTemplate
based on the StringTemplate engine). The important requirement is that the template must contain the following two placeholders:
-
* 一个
instructions
占位符,用于接收原始系统消息。 -
an
instructions
placeholder to receive the original system message. -
* 一个
memory
占位符,用于接收检索到的对话记忆。 -
a
memory
placeholder to receive the retrieved conversation memory.
VectorStoreChatMemoryAdvisor
Custom Template
VectorStoreChatMemoryAdvisor
使用默认模板通过检索到的对话内存来增强系统消息。您可以通过 .promptTemplate()
构建器方法提供自己的 PromptTemplate
对象来自定义此行为。
The VectorStoreChatMemoryAdvisor
uses a default template to augment the system message with the retrieved conversation memory. You can customize this behavior by providing your own PromptTemplate
object via the .promptTemplate()
builder method.
此处提供的 |
The |
自定义 PromptTemplate
可以使用任何 TemplateRenderer
实现(默认情况下,它基于 StringTemplate 引擎使用 StPromptTemplate
)。重要的要求是模板必须包含以下两个占位符:
The custom PromptTemplate
can use any TemplateRenderer
implementation (by default, it uses StPromptTemplate
based on the StringTemplate engine). The important requirement is that the template must contain the following two placeholders:
-
* 一个
instructions
占位符,用于接收原始系统消息。 -
an
instructions
placeholder to receive the original system message. -
* 一个
long_term_memory
占位符,用于接收检索到的对话记忆。 -
a
long_term_memory
placeholder to receive the retrieved conversation memory.
Memory in Chat Model
如果您直接使用 ChatModel
而不是 ChatClient
,您可以显式管理内存:
If you’re working directly with a ChatModel
instead of a ChatClient
, you can manage the memory explicitly:
// 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"