简绍 Spring AI 会自动配置一个 bean,您可以直接在应用程序中使用该 bean。默认情况下,它使用内存中的存储库来存储消息 () 和实现来管理对话历史记录。如果已经配置了不同的存储库(例如,Cassandra、JDBC 或 Neo4j),Spring AI 将改用它。
内存类型 该抽象允许您实现各种类型的内存以适应不同的用例。内存类型的选择会显着影响应用程序的性能和行为。本节介绍Spring AI提供的内置内存类型及其特点。ChatMemory
消息窗口聊天记忆 MessageWindowChatMemory将消息窗口保持到指定的最大大小。当消息数超过最大值时,将删除较旧的消息,同时保留系统消息。默认窗口大小为 20 封邮件。
1 2 3 MessageWindowChatMemory memory = MessageWindowChatMemory.builder() .maxMessages(10 ) .build();
这是 Spring AI 用于自动配置 bean 的默认消息类型。ChatMemory
内存存储 Spring AI 提供了用于存储聊天内存的抽象。本节描述了 Spring AI 提供的内置存储库及其使用方法,但如果需要,您也可以实现自己的存储库。ChatMemoryRepository
InMemoryChatMemoryRepository使用 将消息存储在内存中。ConcurrentHashMap
默认情况下,如果尚未配置其他存储库,则 Spring AI 会自动配置可以直接在应用程序中使用的 bean 类型。ChatMemoryRepositoryInMemoryChatMemoryRepository
1 2 @Autowired ChatMemoryRepository chatMemoryRepository;
如果您更愿意手动创建 ,可以按如下方式创建:InMemoryChatMemoryRepository
1 ChatMemoryRepository repository = new InMemoryChatMemoryRepository ();
JdbcChatMemory存储库 JdbcChatMemoryRepository是使用 JDBC 在关系数据库中存储消息的内置实现。它支持多个开箱即用的数据库,适用于需要持久存储聊天内存的应用程序。
1 2 3 4 <dependency > <groupId > org.springframework.ai</groupId > <artifactId > spring-ai-starter-model-chat-memory-repository-jdbc</artifactId > </dependency >
Spring AI 为 提供了 的自动配置,您可以直接在应用程序中使用。JdbcChatMemoryRepository
1 2 3 4 5 6 7 @Autowired JdbcChatMemoryRepository chatMemoryRepository; ChatMemory chatMemory = MessageWindowChatMemory.builder() .chatMemoryRepository(chatMemoryRepository) .maxMessages(10 ) .build();
如果您更愿意手动创建 ,可以通过提供实例和 :JdbcChatMemoryRepositoryJdbcTemplateJdbcChatMemoryRepositoryDialect
1 2 3 4 5 6 7 8 9 ChatMemoryRepository chatMemoryRepository = JdbcChatMemoryRepository.builder() .jdbcTemplate(jdbcTemplate) .dialect(new PostgresChatMemoryDialect ()) .build(); ChatMemory chatMemory = MessageWindowChatMemory.builder() .chatMemoryRepository(chatMemoryRepository) .maxMessages(10 ) .build();
支持的数据库和 Dialect 抽象 Spring AI 通过 dialect 抽象支持多个关系数据库。以下数据库是开箱即用的:
PostgreSQL 数据库
MySQL / MariaDB
SQL 服务器
HSQLDB 数据库
Schema 初始化 自动配置将在启动时使用特定于供应商的数据库 SQL 脚本自动创建表。默认情况下,架构初始化仅针对嵌入式数据库(H2、HSQL、Derby 等)运行。SPRING_AI_CHAT_MEMORY 您可以使用以下属性控制架构初始化:spring.ai.chat.memory.repository.jdbc.initialize-schema
1 2 3 4 5 6 # 控制何时初始化架构。值:(默认值)、、。embedded alway snever spring.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)
要覆盖架构脚本位置,请使用:
1 2 3 4 5 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();
1 2 3 4 5 6 7 8 9 10 11 12 13 14 ## 聊天客户端中的内存 使用 ChatClient API 时,您可以提供一种实现来维护多个交互的对话上下文。ChatMemory Spring AI 提供了一些内置的 Advisor,您可以使用它们根据需要配置 的内存行为。ChatClient - MessageChatMemoryAdvisor.此顾问使用提供的实现来管理对话内存。在每次交互中,它都会从内存中检索对话历史记录,并将其作为消息集合包含在提示中。ChatMemory - PromptChatMemoryAdvisor.此顾问使用提供的实现来管理对话内存。在每次交互时,它都会从内存中检索对话历史记录,并将其作为纯文本附加到系统提示中。ChatMemory - VectorStoreChatMemoryAdvisor.此顾问使用提供的实现来管理对话内存。在每次交互时,它都会从矢量存储中检索对话历史记录,并将其作为纯文本追加到系统消息中。VectorStore 例如,如果要与 一起使用,可以按如下方式配置:MessageWindowChatMemoryMessageChatMemoryAdvisor ```java ChatMemory chatMemory = MessageWindowChatMemory.builder().build(); ChatClient chatClient = ChatClient.builder(chatModel) .defaultAdvisors(MessageChatMemoryAdvisor.builder(chatMemory).build()) .build();
当执行对 的调用时,内存将由 自动管理 。将根据指定的对话 ID 从内存中检索对话历史记录:ChatClientMessageChatMemoryAdvisor
1 2 3 4 5 6 7 String conversationId = "007" ;chatClient.prompt() .user("Do I have license to code?" ) .advisors(a -> a.param(ChatMemory.CONVERSATION_ID, conversationId)) .call() .content();
演示案例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 private final ZhiPuAiChatModel chatModel;private final ChatClient chatClient;@Autowired public 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); }
PromptChat记忆顾问 自定义模板 它使用默认模板通过检索到的对话内存来扩充系统消息。您可以通过 builder 方法提供自己的对象来自定义此行为。PromptChatMemoryAdvisorPromptTemplate.promptTemplate()
自定义可以使用任何实现(默认情况下,它使用基于 StringTemplate 引擎)。重要的要求是模板必须包含以下两个占位符:PromptTemplateTemplateRendererStPromptTemplate
用于接收原始系统消息的占位符。instructions
用于接收检索到的对话内存的占位符。memory
1 2 3 4 5 6 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 引擎。PromptTemplateTemplateRedererStTemplateRenderer Spring AI 还为不需要模板处理的情况提供了一个。NoOpTemplateRenderer Spring AI 还提供了一个 .NoOpTemplateRenderer 如果您更愿意使用其他模板引擎,您可以直接向 ChatClient 提供界面的自定义实现。您也可以继续使用默认的 ,但使用自定义配置。TemplateRendererStTemplateRenderer 例如,默认情况下,模板变量由语法标识。如果计划在提示中包含 JSON,则可能需要使用不同的语法来避免与 JSON 语法冲突。例如,您可以使用 和 分隔符。{}<>
1 2 3 4 5 6 7 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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 // 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"