此版本仍在开发中,尚未被视为稳定版本。最新的快照版本请使用 Spring AI 1.0.0-SNAPSHOT!spring-doc.cadn.net.cn

聊天记忆

大型语言模型 (LLM) 是无状态的,这意味着它们不会保留有关以前交互的信息。当您希望在多个交互中维护上下文或状态时,这可能是一个限制。为了解决这个问题,Spring AI 提供了一个ChatMemory抽象,允许您在与 LLM 的多次交互中存储和检索信息。spring-doc.cadn.net.cn

快速开始

Spring AI 会自动配置ChatMemory可以直接在应用程序中使用的 bean。默认情况下,它使用内存中存储库来存储消息 (InMemoryChatMemoryRepository) 和MessageWindowChatMemoryimplementation 来管理对话历史记录。如果已经配置了不同的存储库(例如,Cassandra、JDBC 或 Neo4j),Spring AI 将改用该存储库。spring-doc.cadn.net.cn

@Autowired
ChatMemory chatMemory;

以下部分将进一步描述 Spring AI 中可用的不同内存类型和存储库。spring-doc.cadn.net.cn

内存类型

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

消息窗口聊天内存

MessageWindowChatMemory将消息窗口保持到指定的最大大小。当消息数超过最大值时,将删除较旧的消息,同时保留系统消息。默认窗口大小为 20 封邮件。spring-doc.cadn.net.cn

MessageWindowChatMemory memory = MessageWindowChatMemory.builder()
    .maxMessages(10)
    .build();

这是 Spring AI 用于自动配置ChatMemory豆。spring-doc.cadn.net.cn

内存存储

Spring AI 提供了ChatMemoryRepository用于存储聊天内存的抽象。本节描述了 Spring AI 提供的内置存储库及其使用方法,但如果需要,您也可以实现自己的存储库。spring-doc.cadn.net.cn

内存存储库

InMemoryChatMemoryRepository使用ConcurrentHashMap.spring-doc.cadn.net.cn

默认情况下,如果尚未配置其他存储库,则 Spring AI 会自动配置ChatMemoryRepository类型的 beanInMemoryChatMemoryRepository可以直接在应用程序中使用。spring-doc.cadn.net.cn

@Autowired
ChatMemoryRepository chatMemoryRepository;

如果您更愿意创建InMemoryChatMemoryRepository手动,您可以按如下方式执行此作:spring-doc.cadn.net.cn

ChatMemoryRepository repository = new InMemoryChatMemoryRepository();

JDBC 存储库

JdbcChatMemoryRepository是使用 JDBC 在关系数据库中存储消息的内置实现。它适用于需要持久存储聊天内存的应用程序。spring-doc.cadn.net.cn

首先,将以下依赖项添加到您的项目中:spring-doc.cadn.net.cn

<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,您可以直接在应用程序中使用。spring-doc.cadn.net.cn

@Autowired
JdbcChatMemoryRepository chatMemoryRepository;

ChatMemory chatMemory = MessageWindowChatMemory.builder()
    .chatMemoryRepository(chatMemoryRepository)
    .maxMessages(10)
    .build();

如果您更愿意创建JdbcChatMemoryRepository手动执行此作,您可以通过提供JdbcTemplate实例:spring-doc.cadn.net.cn

ChatMemoryRepository chatMemoryRepository = JdbcChatMemoryRepository.builder()
    .jdbcTemplate(jdbcTemplate)
    .build();

ChatMemory chatMemory = MessageWindowChatMemory.builder()
    .chatMemoryRepository(chatMemoryRepository)
    .maxMessages(10)
    .build();

配置属性

属性spring-doc.cadn.net.cn

描述spring-doc.cadn.net.cn

默认值spring-doc.cadn.net.cn

spring.ai.chat.memory.repository.jdbc.initialize-schemaspring-doc.cadn.net.cn

是否在启动时初始化 Schema。spring-doc.cadn.net.cn

truespring-doc.cadn.net.cn

Schema 初始化

自动配置将自动创建ai_chat_memory表目前仅支持 PostgreSQL 和 MariaDB。spring-doc.cadn.net.cn

您可以通过设置属性spring.ai.chat.memory.repository.jdbc.initialize-schemafalse.spring-doc.cadn.net.cn

如果您的项目使用 Flyway 或 Liquibase 等工具来管理数据库架构,则可以禁用架构初始化,并参考这些 SQL 脚本来配置这些工具以创建ai_chat_memory桌子。spring-doc.cadn.net.cn

聊天客户端中的内存

使用 ChatClient API 时,您可以提供ChatMemory实现以在多个交互中维护对话上下文。spring-doc.cadn.net.cn

Spring AI 提供了一些内置的 Advisor,你可以使用它们来配置ChatClient,具体取决于您的需求。spring-doc.cadn.net.cn

目前,在执行工具调用时与大型语言模型交换的中间消息不存储在内存中。这是当前实施的限制,将在将来的版本中得到解决。如果需要存储这些消息,请参阅 User Controlled Tool Execution 的说明。
  • MessageChatMemoryAdvisor.此顾问使用提供的ChatMemory实现。在每次交互时,它都会从内存中检索对话历史记录,并将其作为消息集合包含在提示中。spring-doc.cadn.net.cn

  • PromptChatMemoryAdvisor.此顾问使用提供的ChatMemory实现。在每次交互时,它都会从内存中检索对话历史记录,并将其作为纯文本附加到系统提示符中。spring-doc.cadn.net.cn

  • VectorStoreChatMemoryAdvisor.此顾问使用提供的VectorStore实现。在每次交互时,它都会从向量存储中检索对话历史记录,并将其作为纯文本附加到系统消息中。spring-doc.cadn.net.cn

例如,如果要使用MessageWindowChatMemory使用MessageChatMemoryAdvisor,您可以按如下方式对其进行配置:spring-doc.cadn.net.cn

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

ChatClient chatClient = ChatClient.builder(chatModel)
    .defaultAdvisors(MessageChatMemoryAdvisor.builder(chatMemory).build())
    .build();

当调用ChatClient,内存将由MessageChatMemoryAdvisor.将根据指定的对话 ID 从内存中检索对话历史记录:spring-doc.cadn.net.cn

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中,您可以显式管理内存:spring-doc.cadn.net.cn

// 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"