掘金 人工智能 9小时前
Spring AI 聊天记忆
index_new5.html
../../../zaker_core/zaker_tpl_static/wap/tpl_guoji1.html

 

Spring AI 提供了灵活的聊天内存管理机制,支持多种内存类型和存储库,以适应不同的应用场景。默认情况下,它使用内存中的 MessageWindowChatMemory 来存储对话历史,并可配置为使用 JDBC 等持久化存储。通过 ChatClient 和 Advisor,可以轻松地将对话上下文集成到 AI 交互中,实现多轮对话。文章还介绍了如何自定义模板和扩展数据库支持,为开发者提供了强大的工具来构建智能对话应用。

✨ **Spring AI 聊天内存自动配置与默认行为**:Spring AI 默认会自动配置一个 ChatMemory bean,并使用内存中的存储库来管理对话历史,保留系统消息。如果已配置其他存储库(如 Cassandra、JDBC、Neo4j),则会优先使用。默认的内存类型是 MessageWindowChatMemory,它会将消息窗口保持在指定的最大大小,超出后会删除较旧的消息,保留系统消息。默认窗口大小为 20 条消息。

🗄️ **内存存储抽象与实现**:Spring AI 提供了 ChatMemoryRepository 抽象来存储聊天内存,并提供了 InMemoryChatMemoryRepository(使用 ConcurrentHashMap 存储在内存中)作为默认实现。此外,还支持 JdbcChatMemoryRepository,它使用 JDBC 在关系数据库中持久化存储消息,并支持 PostgreSQL、MySQL/MariaDB、SQL Server、HSQLDB 等多种数据库。Schema 初始化可以通过配置属性进行控制,也可以自定义脚本位置。

💬 **ChatClient 集成与 Advisor**:通过 ChatClient API,可以集成不同的 Advisor 来管理对话内存行为。MessageChatMemoryAdvisor 会将对话历史检索为消息集合并包含在提示中;PromptChatMemoryAdvisor 将对话历史附加到系统提示作为纯文本;VectorStoreChatMemoryAdvisor 则将对话历史检索为纯文本并追加到系统消息中。这些 Advisor 可以根据需要进行配置,例如使用 MessageWindowChatMemory 和 MessageChatMemoryAdvisor 来管理对话。

📝 **自定义模板与扩展性**:PromptChatMemoryAdvisor 支持自定义模板来扩充系统消息,用户可以通过提供自定义的 PromptTemplate 对象来控制对话内存的呈现方式。模板必须包含 'instructions'(接收原始系统消息)和 'memory'(接收对话内存)占位符。Spring AI 还提供了 StTemplateRenderer 和 NoOpTemplateRenderer,并允许用户通过实现 JdbcChatMemoryRepositoryDialect 接口来扩展对新数据库的支持。

💡 **直接使用 ChatModel 管理内存**:在不使用 ChatClient 的情况下,可以直接使用 ChatModel 来显式管理内存。开发者需要手动创建 ChatMemory 实例,并在每次与 ChatModel 交互后,将用户消息和模型响应添加到内存中,以维护对话上下文。这种方式提供了更精细的内存控制,适用于特定场景。

简绍

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

内存类型

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

消息窗口聊天记忆

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

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

这是 Spring AI 用于自动配置 bean 的默认消息类型。ChatMemory

内存存储

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

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

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

@AutowiredChatMemoryRepository chatMemoryRepository;

如果您更愿意手动创建 ,可以按如下方式创建:InMemoryChatMemoryRepository

ChatMemoryRepository repository = new InMemoryChatMemoryRepository();

JdbcChatMemory存储库

JdbcChatMemoryRepository是使用 JDBC 在关系数据库中存储消息的内置实现。它支持多个开箱即用的数据库,适用于需要持久存储聊天内存的应用程序。

<dependency>    <groupId>org.springframework.ai</groupId>    <artifactId>spring-ai-starter-model-chat-memory-repository-jdbc</artifactId></dependency>

Spring AI 为 提供了 的自动配置,您可以直接在应用程序中使用。JdbcChatMemoryRepository

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

如果您更愿意手动创建 ,可以通过提供实例和 :JdbcChatMemoryRepositoryJdbcTemplateJdbcChatMemoryRepositoryDialect

ChatMemoryRepository chatMemoryRepository = JdbcChatMemoryRepository.builder()    .jdbcTemplate(jdbcTemplate)    .dialect(new PostgresChatMemoryDialect())    .build();ChatMemory chatMemory = MessageWindowChatMemory.builder()    .chatMemoryRepository(chatMemoryRepository)    .maxMessages(10)    .build();
支持的数据库和 Dialect 抽象

Spring AI 通过 dialect 抽象支持多个关系数据库。以下数据库是开箱即用的:

Schema 初始化

自动配置将在启动时使用特定于供应商的数据库 SQL 脚本自动创建表。默认情况下,架构初始化仅针对嵌入式数据库(H2、HSQL、Derby 等)运行。SPRING_AI_CHAT_MEMORY您可以使用以下属性控制架构初始化:spring.ai.chat.memory.repository.jdbc.initialize-schema

# 控制何时初始化架构。值:(默认值)、、。embedded alway sneverspring.ai.chat.memory.repository.jdbc.initialize-schema=embedded # Only for embedded DBs (default)# 用于初始化的架构脚本的位置。支持 URL 和平台占位符。classpath:spring.ai.chat.memory.repository.jdbc.initialize-schema=always   # Always initialize# 在初始化脚本中使用的平台(如果使用@@platform@@占位符)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```java扩展方言要添加对新数据库的支持,请实现接口并提供用于选择、插入和删除消息的 SQL。然后,您可以将自定义方言传递给存储库构建器。JdbcChatMemoryRepositoryDialect

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

## 聊天客户端中的内存使用 ChatClient API 时,您可以提供一种实现来维护多个交互的对话上下文。ChatMemorySpring AI 提供了一些内置的 Advisor,您可以使用它们根据需要配置 的内存行为。ChatClient- MessageChatMemoryAdvisor.此顾问使用提供的实现来管理对话内存。在每次交互中,它都会从内存中检索对话历史记录,并将其作为消息集合包含在提示中。ChatMemory- PromptChatMemoryAdvisor.此顾问使用提供的实现来管理对话内存。在每次交互时,它都会从内存中检索对话历史记录,并将其作为纯文本附加到系统提示中。ChatMemory- VectorStoreChatMemoryAdvisor.此顾问使用提供的实现来管理对话内存。在每次交互时,它都会从矢量存储中检索对话历史记录,并将其作为纯文本追加到系统消息中。VectorStore例如,如果要与 一起使用,可以按如下方式配置:MessageWindowChatMemoryMessageChatMemoryAdvisor```javaChatMemory chatMemory = MessageWindowChatMemory.builder().build();ChatClient chatClient = ChatClient.builder(chatModel)    .defaultAdvisors(MessageChatMemoryAdvisor.builder(chatMemory).build())    .build();

当执行对 的调用时,内存将由 自动管理 。将根据指定的对话 ID 从内存中检索对话历史记录:ChatClientMessageChatMemoryAdvisor

String conversationId = "007";chatClient.prompt()    .user("Do I have license to code?")    .advisors(a -> a.param(ChatMemory.CONVERSATION_ID, conversationId))    .call()    .content();

演示案例

private final ZhiPuAiChatModel chatModel;private final  ChatClient chatClient;@Autowiredpublic ChatController(ZhiPuAiChatModel chatModel) {    this.chatModel = chatModel;    MessageWindowChatMemory chatMemory = MessageWindowChatMemory.builder()            .maxMessages(10)            .build();    chatClient = ChatClient.builder(chatModel)            .defaultAdvisors(MessageChatMemoryAdvisor.builder(chatMemory).build())            .build();}@GetMapping("/ai/generate")public Map generate(@RequestParam(value = "message", defaultValue = "Tell me a joke") String message) {    String conversationId = "007";    String content = chatClient.prompt().user(message)            .advisors(a -> a.param(ChatMemory.CONVERSATION_ID, conversationId))            .call()            .content();    return Map.of("generation", content);//        return Map.of("generation", chatModel.call(message));}

PromptChat记忆顾问

自定义模板它使用默认模板通过检索到的对话内存来扩充系统消息。您可以通过 builder 方法提供自己的对象来自定义此行为。PromptChatMemoryAdvisorPromptTemplate.promptTemplate()

自定义可以使用任何实现(默认情况下,它使用基于 StringTemplate 引擎)。重要的要求是模板必须包含以下两个占位符:PromptTemplateTemplateRendererStPromptTemplate

String answer = ChatClient.create(chatModel).prompt()    .user(u -> u            .text("Tell me the names of 5 movies whose soundtrack was composed by {composer}")            .param("composer", "John Williams"))    .call()    .content();

在内部,ChatClient 使用该类来处理用户和系统文本,并将变量替换为运行时提供的值,具体取决于给定的实现。 默认情况下,Spring AI 使用该实现,该实现基于 Terence Parr 开发的开源 StringTemplate 引擎。PromptTemplateTemplateRedererStTemplateRendererSpring AI 还为不需要模板处理的情况提供了一个。NoOpTemplateRendererSpring AI 还提供了一个 .NoOpTemplateRenderer如果您更愿意使用其他模板引擎,您可以直接向 ChatClient 提供界面的自定义实现。您也可以继续使用默认的 ,但使用自定义配置。TemplateRendererStTemplateRenderer例如,默认情况下,模板变量由语法标识。如果计划在提示中包含 JSON,则可能需要使用不同的语法来避免与 JSON 语法冲突。例如,您可以使用 和 分隔符。{}<>

String answer = ChatClient.create(chatModel).prompt()    .user(u -> u            .text("Tell me the names of 5 movies whose soundtrack was composed by <composer>")            .param("composer", "John Williams"))    .templateRenderer(StTemplateRenderer.builder().startDelimiterToken('<').endDelimiterToken('>').build())    .call()    .content();

聊天模型中的内存

如果直接使用 a 而不是 a ,则可以显式管理内存:ChatModelChatClient

// Create a memory instanceChatMemory chatMemory = MessageWindowChatMemory.builder().build();String conversationId = "007";// First interactionUserMessage 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 interactionUserMessage 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"

Fish AI Reader

Fish AI Reader

AI辅助创作,多种专业模板,深度分析,高质量内容生成。从观点提取到深度思考,FishAI为您提供全方位的创作支持。新版本引入自定义参数,让您的创作更加个性化和精准。

FishAI

FishAI

鱼阅,AI 时代的下一个智能信息助手,助你摆脱信息焦虑

联系邮箱 441953276@qq.com

相关标签

Spring AI 聊天内存 对话管理 AI开发 消息存储
相关文章