聊天记忆
大型语言模型 (LLMs) 是无状态的,这意味着它们不保留关于之前交互的信息。当您希望在多次交互中保持上下文或状态时,这可能是一个限制。为了解决这个问题,Spring AI 提供了一个 ChatMemory
抽象,允许您在与 LLM 的多次交互中存储和检索信息。
快速入门
Spring AI 会自动配置一个 ChatMemory
bean,您可以直接在应用程序中使用它。默认情况下,它使用内存存储库 (InMemoryChatMemoryRepository
) 来存储消息,并使用 MessageWindowChatMemory
实现来管理对话历史。如果已经配置了不同的存储库(例如 Cassandra、JDBC 或 Neo4j),Spring AI 将会使用它。
@Autowired
ChatMemory chatMemory;
以下章节将进一步描述 Spring AI 中可用的不同内存类型和存储库。
内存存储
Spring AI 提供了 ChatMemoryRepository
抽象用于存储聊天记忆。本节描述了 Spring AI 提供的内置存储库以及如何使用它们,但如果需要,您也可以实现自己的存储库。
内存存储库
InMemoryChatMemoryRepository
使用 ConcurrentHashMap
将消息存储在内存中。
默认情况下,如果尚未配置其他存储库,Spring AI 会自动配置一个类型为 InMemoryChatMemoryRepository
的 ChatMemoryRepository
bean,您可以直接在应用程序中使用它。
@Autowired
ChatMemoryRepository chatMemoryRepository;
如果您更愿意手动创建 InMemoryChatMemoryRepository
,可以按照以下方式进行
ChatMemoryRepository repository = new InMemoryChatMemoryRepository();
JDBC 存储库
JdbcChatMemoryRepository
是一个内置实现,它使用 JDBC 将消息存储在关系数据库中。它适用于需要持久存储聊天记忆的应用程序。
首先,向您的项目添加以下依赖项
-
Maven
-
Gradle
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-model-chat-memory-jdbc</artifactId>
</dependency>
dependencies {
implementation 'org.springframework.ai:spring-ai-starter-model-chat-memory-jdbc'
}
Spring AI 为 JdbcChatMemoryRepository
提供了自动配置,您可以直接在应用程序中使用它。
@Autowired
JdbcChatMemoryRepository chatMemoryRepository;
ChatMemory chatMemory = MessageWindowChatMemory.builder()
.chatMemoryRepository(chatMemoryRepository)
.maxMessages(10)
.build();
如果您更愿意手动创建 JdbcChatMemoryRepository
,可以通过提供一个 JdbcTemplate
实例来完成
ChatMemoryRepository chatMemoryRepository = JdbcChatMemoryRepository.builder()
.jdbcTemplate(jdbcTemplate)
.build();
ChatMemory chatMemory = MessageWindowChatMemory.builder()
.chatMemoryRepository(chatMemoryRepository)
.maxMessages(10)
.build();
Schema 初始化
自动配置将使用 JDBC 驱动程序自动创建 ai_chat_memory
表。目前,仅支持 PostgreSQL 和 MariaDB。
您可以通过将属性 spring.ai.chat.memory.repository.jdbc.initialize-schema
设置为 false
来禁用 schema 初始化。
如果您的项目使用 Flyway 或 Liquibase 等工具来管理数据库 schema,您可以禁用 schema 初始化,并参考 这些 SQL 脚本 来配置这些工具以创建 ai_chat_memory
表。
在聊天客户端中使用记忆
使用 ChatClient API 时,您可以提供一个 ChatMemory
实现,以便在多次交互中保持对话上下文。
Spring AI 提供了几个内置的 Advisors,您可以根据需要使用它们来配置 ChatClient
的记忆行为。
当前,与大型语言模型进行工具调用时交换的中间消息不会存储在记忆中。这是当前实现的一个限制,将在未来的版本中解决。如果您需要存储这些消息,请参考 用户控制的工具执行 的说明。 |
-
MessageChatMemoryAdvisor
. 此 Advisor 使用提供的ChatMemory
实现来管理对话记忆。在每次交互时,它会从记忆中检索对话历史,并将其作为消息集合包含在 prompt 中。 -
PromptChatMemoryAdvisor
. 此 Advisor 使用提供的ChatMemory
实现来管理对话记忆。在每次交互时,它会从记忆中检索对话历史,并将其作为纯文本附加到系统 prompt 中。 -
VectorStoreChatMemoryAdvisor
. 此 Advisor 使用提供的VectorStore
实现来管理对话记忆。在每次交互时,它会从向量存储中检索对话历史,并将其作为纯文本附加到系统消息中。
例如,如果您想将 MessageWindowChatMemory
与 MessageChatMemoryAdvisor
一起使用,可以按如下方式配置它
ChatMemory chatMemory = MessageChatMemoryAdvisor.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(AbstractChatMemoryAdvisor.CHAT_MEMORY_CONVERSATION_ID_KEY, conversationId))
.call()
.content();
结构化输出 工具调用
如果您直接使用 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"