Spring AI 聊天记忆

简绍

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

内存类型

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

消息窗口聊天记忆

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

java 复制代码
MessageWindowChatMemory memory = MessageWindowChatMemory.builder()
    .maxMessages(10)
    .build();

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

内存存储

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

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

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

java 复制代码
@Autowired
ChatMemoryRepository chatMemoryRepository;

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

java 复制代码
ChatMemoryRepository repository = new InMemoryChatMemoryRepository();

JdbcChatMemory存储库

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

xml 复制代码
<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-starter-model-chat-memory-repository-jdbc</artifactId>
</dependency>

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

java 复制代码
@Autowired
JdbcChatMemoryRepository chatMemoryRepository;

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

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

java 复制代码
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

java 复制代码
# 控制何时初始化架构。值:(默认值)、、。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)

要覆盖架构脚本位置,请使用:

javascript 复制代码
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();

ini 复制代码
## 聊天客户端中的内存
使用 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

java 复制代码
String conversationId = "007";

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

演示案例

java 复制代码
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);
//        return Map.of("generation", chatModel.call(message));
}

PromptChat记忆顾问

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

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

  • 用于接收原始系统消息的占位符。instructions
  • 用于接收检索到的对话内存的占位符。memory
java 复制代码
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 语法冲突。例如,您可以使用 和 分隔符。{}<>

java 复制代码
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

ini 复制代码
// 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"
相关推荐
街霸星星8 分钟前
使用 vfox 高效配置 Java 开发环境:一份全面指南
java
用户15129054522013 分钟前
C 语言教程
前端·后端
♛暮辞13 分钟前
java程序远程写入字符串到hadoop伪分布式
java·hadoop·分布式
UestcXiye13 分钟前
Rust Web 全栈开发(十):编写服务器端 Web 应用
前端·后端·mysql·rust·actix
用户15129054522022 分钟前
基于YOLOv10算法的交通信号灯检测与识别
后端
用户15129054522023 分钟前
Netstat命令详解(windows下)
后端
用户15129054522027 分钟前
GetTickCount() 函数的作用和用法
后端
能活着就行29 分钟前
Java线程的三种创建方式
后端
巴拉巴巴巴拉41 分钟前
IDEA 2024.1 配置 MyBatis Generator 详细教程
java·intellij-idea·mybatis
努力的小郑44 分钟前
Spring Boot整合阿里云OSS企业级实践:高可用文件存储解决方案
spring boot·后端·阿里云