聊天記憶

大型語言模型(LLM)是無狀態的,這意味著它們不會保留先前互動的資訊。當您希望在多次互動中保持上下文或狀態時,這可能是一個限制。為了解決這個問題,Spring AI 提供了聊天記憶功能,允許您在與 LLM 的多次互動中儲存和檢索資訊。

ChatMemory 抽象允許您實現各種型別的記憶以支援不同的用例。訊息的底層儲存由 ChatMemoryRepository 處理,其唯一職責是儲存和檢索訊息。由 ChatMemory 實現來決定保留哪些訊息以及何時刪除它們。策略示例可以包括保留最後 N 條訊息,保留特定時間段內的訊息,或保留達到特定令牌限制的訊息。

在選擇記憶型別之前,理解聊天記憶和聊天曆史之間的區別至關重要。

  • 聊天記憶。大型語言模型保留並用於在整個對話中保持上下文感知的資訊。

  • 聊天曆史。整個對話歷史,包括使用者和模型之間交換的所有訊息。

ChatMemory 抽象旨在管理聊天記憶。它允許您儲存和檢索與當前對話上下文相關的訊息。然而,它不適用於儲存聊天曆史。如果您需要維護所有交換訊息的完整記錄,您應該考慮使用不同的方法,例如依靠 Spring Data 來高效儲存和檢索完整的聊天曆史。

快速入門

Spring AI 會自動配置一個 ChatMemory bean,您可以直接在應用程式中使用。預設情況下,它使用記憶體儲存庫來儲存訊息 (InMemoryChatMemoryRepository) 和 MessageWindowChatMemory 實現來管理對話歷史。如果已配置不同的儲存庫(例如 Cassandra、JDBC 或 Neo4j),Spring AI 將使用該儲存庫。

@Autowired
ChatMemory chatMemory;

以下部分將進一步描述 Spring AI 中可用的不同記憶型別和儲存庫。

記憶型別

ChatMemory 抽象允許您實現各種型別的記憶以適應不同的用例。記憶型別的選擇可以顯著影響應用程式的效能和行為。本節描述了 Spring AI 提供的內建記憶型別及其特性。

訊息視窗聊天記憶

MessageWindowChatMemory 維護一個訊息視窗,最大大小為指定值。當訊息數量超過最大值時,較舊的訊息將被刪除,同時保留系統訊息。預設視窗大小為 20 條訊息。

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

這是 Spring AI 自動配置 ChatMemory bean 時使用的預設訊息型別。

記憶儲存

Spring AI 提供了 ChatMemoryRepository 抽象來儲存聊天記憶。本節描述了 Spring AI 提供的內建儲存庫以及如何使用它們,但您也可以根據需要實現自己的儲存庫。

記憶體儲存庫

InMemoryChatMemoryRepository 使用 ConcurrentHashMap 將訊息儲存在記憶體中。

預設情況下,如果尚未配置其他儲存庫,Spring AI 會自動配置一個型別為 InMemoryChatMemoryRepositoryChatMemoryRepository bean,您可以直接在應用程式中使用。

@Autowired
ChatMemoryRepository chatMemoryRepository;

如果您希望手動建立 InMemoryChatMemoryRepository,可以按如下方式操作:

ChatMemoryRepository repository = new InMemoryChatMemoryRepository();

JdbcChatMemoryRepository

JdbcChatMemoryRepository 是一個內建實現,它使用 JDBC 將訊息儲存在關係資料庫中。它開箱即用支援多種資料庫,適用於需要持久儲存聊天記憶的應用程式。

首先,將以下依賴項新增到您的專案:

  • Maven

  • Gradle

<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-starter-model-chat-memory-repository-jdbc</artifactId>
</dependency>
dependencies {
    implementation 'org.springframework.ai:spring-ai-starter-model-chat-memory-repository-jdbc'
}

Spring AI 為 JdbcChatMemoryRepository 提供了自動配置,您可以直接在應用程式中使用。

@Autowired
JdbcChatMemoryRepository chatMemoryRepository;

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

如果您希望手動建立 JdbcChatMemoryRepository,可以透過提供 JdbcTemplate 例項和 JdbcChatMemoryRepositoryDialect 來實現:

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

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

支援的資料庫和方言抽象

Spring AI 透過方言抽象支援多種關係資料庫。以下資料庫開箱即用:

  • PostgreSQL

  • MySQL / MariaDB

  • SQL Server

  • HSQLDB

  • Oracle Database

使用 JdbcChatMemoryRepositoryDialect.from(DataSource) 時,可以從 JDBC URL 自動檢測到正確的方言。您可以透過實現 JdbcChatMemoryRepositoryDialect 介面來擴充套件對其他資料庫的支援。

配置屬性

財產

描述

預設值

spring.ai.chat.memory.repository.jdbc.initialize-schema

控制何時初始化 schema。值:embedded(預設)、alwaysnever

embedded

spring.ai.chat.memory.repository.jdbc.schema

用於初始化的 schema 指令碼的位置。支援 classpath: URL 和平臺佔位符。

classpath:org/springframework/ai/chat/memory/repository/jdbc/schema-@@platform@@.sql

spring.ai.chat.memory.repository.jdbc.platform

如果使用 @@platform@@ 佔位符,用於初始化指令碼的平臺。

auto-detected

Schema 初始化

自動配置將在啟動時自動建立 SPRING_AI_CHAT_MEMORY 表,使用特定於您的資料庫的供應商 SQL 指令碼。預設情況下,schema 初始化僅針對嵌入式資料庫(H2、HSQL、Derby 等)執行。

您可以使用 spring.ai.chat.memory.repository.jdbc.initialize-schema 屬性控制 schema 初始化:

spring.ai.chat.memory.repository.jdbc.initialize-schema=embedded # Only for embedded DBs (default)
spring.ai.chat.memory.repository.jdbc.initialize-schema=always   # Always initialize
spring.ai.chat.memory.repository.jdbc.initialize-schema=never    # Never initialize (useful with Flyway/Liquibase)

要覆蓋 schema 指令碼位置,請使用:

spring.ai.chat.memory.repository.jdbc.schema=classpath:/custom/path/schema-mysql.sql

擴充套件方言

要新增對新資料庫的支援,請實現 JdbcChatMemoryRepositoryDialect 介面並提供用於選擇、插入和刪除訊息的 SQL。然後,您可以將自定義方言傳遞給儲存庫構建器。

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

CassandraChatMemoryRepository

CassandraChatMemoryRepository 使用 Apache Cassandra 儲存訊息。它適用於需要持久儲存聊天記憶的應用程式,特別是為了可用性、永續性、可伸縮性以及利用生存時間(TTL)功能。

CassandraChatMemoryRepository 具有時間序列 schema,記錄所有過去的聊天視窗,這對於治理和審計很有價值。建議將生存時間設定為某個值,例如三年。

要使用 CassandraChatMemoryRepository,首先將依賴項新增到您的專案:

  • Maven

  • Gradle

<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-starter-model-chat-memory-repository-cassandra</artifactId>
</dependency>
dependencies {
    implementation 'org.springframework.ai:spring-ai-starter-model-chat-memory-repository-cassandra'
}

Spring AI 為 CassandraChatMemoryRepository 提供了自動配置,您可以直接在應用程式中使用。

@Autowired
CassandraChatMemoryRepository chatMemoryRepository;

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

如果您希望手動建立 CassandraChatMemoryRepository,可以透過提供 CassandraChatMemoryRepositoryConfig 例項來實現:

ChatMemoryRepository chatMemoryRepository = CassandraChatMemoryRepository
    .create(CassandraChatMemoryRepositoryConfig.builder().withCqlSession(cqlSession));

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

配置屬性

財產

描述

預設值

spring.cassandra.contactPoints

用於啟動叢集發現的主機

127.0.0.1

spring.cassandra.port

Cassandra 本機協議連線埠

9042

spring.cassandra.localDatacenter

要連線的 Cassandra 資料中心

datacenter1

spring.ai.chat.memory.cassandra.time-to-live

寫入 Cassandra 的訊息的生存時間(TTL)

spring.ai.chat.memory.cassandra.keyspace

Cassandra 鍵空間

springframework

spring.ai.chat.memory.cassandra.messages-column

Cassandra 訊息的列名

springframework

spring.ai.chat.memory.cassandra.table

Cassandra 表

ai_chat_memory

spring.ai.chat.memory.cassandra.initialize-schema

是否在啟動時初始化 schema。

true

Schema 初始化

自動配置將自動建立 ai_chat_memory 表。

您可以透過將屬性 spring.ai.chat.memory.repository.cassandra.initialize-schema 設定為 false 來停用 schema 初始化。

Neo4j ChatMemoryRepository

Neo4jChatMemoryRepository 是一個內建實現,它使用 Neo4j 將聊天訊息儲存為屬性圖資料庫中的節點和關係。它適用於希望利用 Neo4j 的圖功能進行聊天記憶持久化的應用程式。

首先,將以下依賴項新增到您的專案:

  • Maven

  • Gradle

<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-starter-model-chat-memory-repository-neo4j</artifactId>
</dependency>
dependencies {
    implementation 'org.springframework.ai:spring-ai-starter-model-chat-memory-repository-neo4j'
}

Spring AI 為 Neo4jChatMemoryRepository 提供了自動配置,您可以直接在應用程式中使用。

@Autowired
Neo4jChatMemoryRepository chatMemoryRepository;

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

如果您希望手動建立 Neo4jChatMemoryRepository,可以透過提供 Neo4j Driver 例項來實現:

ChatMemoryRepository chatMemoryRepository = Neo4jChatMemoryRepository.builder()
    .driver(driver)
    .build();

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

配置屬性

財產

描述

預設值

spring.ai.chat.memory.repository.neo4j.sessionLabel

儲存會話的節點的標籤

Session

spring.ai.chat.memory.repository.neo4j.messageLabel

儲存訊息的節點的標籤

Message

spring.ai.chat.memory.repository.neo4j.toolCallLabel

儲存工具呼叫(例如在助手訊息中)的節點的標籤

ToolCall

spring.ai.chat.memory.repository.neo4j.metadataLabel

儲存訊息元資料的節點的標籤

元資料

spring.ai.chat.memory.repository.neo4j.toolResponseLabel

儲存工具響應的節點的標籤

ToolResponse

spring.ai.chat.memory.repository.neo4j.mediaLabel

儲存與訊息關聯的媒體的節點的標籤

Media

索引初始化

Neo4j 儲存庫將自動確保為會話 ID 和訊息索引建立索引,以最佳化效能。如果您使用自定義標籤,也會為這些標籤建立索引。無需 schema 初始化,但您應確保您的 Neo4j 例項可供應用程式訪問。

CosmosDBChatMemoryRepository

CosmosDBChatMemoryRepository 是一個內建實現,它使用 Azure Cosmos DB NoSQL API 儲存訊息。它適用於需要全球分散式、高度可擴充套件的文件資料庫來持久化聊天記憶的應用程式。該儲存庫使用會話 ID 作為分割槽鍵,以確保高效的資料分發和快速檢索。

首先,將以下依賴項新增到您的專案:

  • Maven

  • Gradle

<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-starter-model-chat-memory-repository-cosmos-db</artifactId>
</dependency>
dependencies {
    implementation 'org.springframework.ai:spring-ai-starter-model-chat-memory-repository-cosmos-db'
}

Spring AI 為 CosmosDBChatMemoryRepository 提供了自動配置,您可以直接在應用程式中使用。

@Autowired
CosmosDBChatMemoryRepository chatMemoryRepository;

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

如果您希望手動建立 CosmosDBChatMemoryRepository,可以透過提供 CosmosDBChatMemoryRepositoryConfig 例項來實現:

ChatMemoryRepository chatMemoryRepository = CosmosDBChatMemoryRepository
    .create(CosmosDBChatMemoryRepositoryConfig.builder()
        .withCosmosClient(cosmosAsyncClient)
        .withDatabaseName("chat-memory-db")
        .withContainerName("conversations")
        .build());

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

配置屬性

財產

描述

預設值

spring.ai.chat.memory.repository.cosmosdb.endpoint

Azure Cosmos DB 端點 URI。自動配置所需。

spring.ai.chat.memory.repository.cosmosdb.key

Azure Cosmos DB 主金鑰或輔助金鑰。如果未提供,將使用 Azure Identity 身份驗證。

spring.ai.chat.memory.repository.cosmosdb.connection-mode

Cosmos DB 客戶端的連線模式(directgateway)。

gateway

spring.ai.chat.memory.repository.cosmosdb.database-name

Cosmos DB 資料庫名稱。

SpringAIChatMemory

spring.ai.chat.memory.repository.cosmosdb.container-name

Cosmos DB 容器名稱。

ChatMemory

spring.ai.chat.memory.repository.cosmosdb.partition-key-path

容器的分割槽鍵路徑。

/conversationId

身份驗證

Cosmos DB 聊天記憶儲存庫支援兩種身份驗證方法:

  1. 基於金鑰的身份驗證:提供 spring.ai.chat.memory.repository.cosmosdb.key 屬性以及您的 Cosmos DB 主金鑰或輔助金鑰。

  2. Azure Identity 身份驗證:如果未提供金鑰,儲存庫將使用 Azure Identity (DefaultAzureCredential) 透過託管標識、服務主體或其他 Azure 憑據源進行身份驗證。

Schema 初始化

自動配置將自動建立指定的資料庫和容器(如果它們不存在)。容器配置使用會話 ID 作為分割槽鍵(/conversationId),以確保聊天記憶操作的最佳效能。無需手動設定 schema。

您可以使用上述配置屬性自定義資料庫和容器名稱。

MongoChatMemoryRepository

MongoChatMemoryRepository 是一個內建實現,它使用 MongoDB 儲存訊息。它適用於需要靈活的、面向文件的資料庫來持久化聊天記憶的應用程式。

首先,將以下依賴項新增到您的專案:

  • Maven

  • Gradle

<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-starter-model-chat-memory-repository-mongodb</artifactId>
</dependency>
dependencies {
    implementation 'org.springframework.ai:spring-ai-starter-model-chat-memory-repository-mongodb'
}

Spring AI 為 MongoChatMemoryRepository 提供了自動配置,您可以直接在應用程式中使用。

@Autowired
MongoChatMemoryRepository chatMemoryRepository;

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

如果您希望手動建立 MongoChatMemoryRepository,可以透過提供 MongoTemplate 例項來實現:

ChatMemoryRepository chatMemoryRepository = MongoChatMemoryRepository.builder()
    .mongoTemplate(mongoTemplate)
    .build();

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

配置屬性

財產

描述

預設值

spring.ai.chat.memory.repository.mongo.create-indices

是否在啟動時自動建立或重新建立索引。注意:更改 TTL 值將刪除 TTL 索引並重新建立它。

spring.ai.chat.memory.repository.mongo.ttl

寫入 MongoDB 的訊息的生存時間(TTL),單位為秒。如果未設定,訊息將無限期儲存。

0

集合初始化

自動配置將在啟動時自動建立 ai_chat_memory 集合(如果它尚不存在)。

聊天客戶端中的記憶

使用 ChatClient API 時,您可以提供 ChatMemory 實現以在多次互動中維護對話上下文。

Spring AI 提供了一些內建的 Advisor,您可以根據需要使用它們來配置 ChatClient 的記憶行為。

目前,在執行工具呼叫時與大型語言模型交換的中間訊息不會儲存在記憶體中。這是當前實現的一個限制,將在未來版本中解決。如果您需要儲存這些訊息,請參閱 使用者控制的工具執行 的說明。
  • MessageChatMemoryAdvisor。此 Advisor 使用提供的 ChatMemory 實現管理對話記憶。在每次互動時,它從記憶中檢索對話歷史並將其作為訊息集合包含在提示中。

  • PromptChatMemoryAdvisor。此 Advisor 使用提供的 ChatMemory 實現管理對話記憶。在每次互動時,它從記憶中檢索對話歷史並將其作為純文字附加到系統提示中。

  • VectorStoreChatMemoryAdvisor。此 Advisor 使用提供的 VectorStore 實現管理對話記憶。在每次互動時,它從向量儲存中檢索對話歷史並將其作為純文字附加到系統訊息中。

例如,如果您想將 MessageWindowChatMemoryMessageChatMemoryAdvisor 一起使用,可以按如下方式配置它:

ChatMemory chatMemory = MessageWindowChatMemory.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(ChatMemory.CONVERSATION_ID, conversationId))
    .call()
    .content();

PromptChatMemoryAdvisor

自定義模板

PromptChatMemoryAdvisor 使用預設模板透過檢索到的對話記憶來增強系統訊息。您可以透過 .promptTemplate() 構建器方法提供自己的 PromptTemplate 物件來自定義此行為。

此處提供的 PromptTemplate 自定義了 Advisor 如何將檢索到的記憶與系統訊息合併。這與在 ChatClient 本身配置 TemplateRenderer(使用 .templateRenderer())是不同的,後者會影響 Advisor 執行之前初始使用者/系統提示內容的渲染。有關客戶端級別模板渲染的更多詳細資訊,請參閱 ChatClient 提示模板

自定義 PromptTemplate 可以使用任何 TemplateRenderer 實現(預設情況下,它使用基於 StringTemplate 引擎的 StPromptTemplate)。重要的要求是模板必須包含以下兩個佔位符:

  • 一個 instructions 佔位符用於接收原始系統訊息。

  • 一個 memory 佔位符用於接收檢索到的對話記憶。

VectorStoreChatMemoryAdvisor

自定義模板

VectorStoreChatMemoryAdvisor 使用預設模板透過檢索到的對話記憶來增強系統訊息。您可以透過 .promptTemplate() 構建器方法提供自己的 PromptTemplate 物件來自定義此行為。

此處提供的 PromptTemplate 自定義了 Advisor 如何將檢索到的記憶與系統訊息合併。這與在 ChatClient 本身配置 TemplateRenderer(使用 .templateRenderer())是不同的,後者會影響 Advisor 執行之前初始使用者/系統提示內容的渲染。有關客戶端級別模板渲染的更多詳細資訊,請參閱 ChatClient 提示模板

自定義 PromptTemplate 可以使用任何 TemplateRenderer 實現(預設情況下,它使用基於 StringTemplate 引擎的 StPromptTemplate)。重要的要求是模板必須包含以下兩個佔位符:

  • 一個 instructions 佔位符用於接收原始系統訊息。

  • 一個 long_term_memory 佔位符用於接收檢索到的對話記憶。

聊天模型中的記憶

如果您直接使用 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"
© . This site is unofficial and not affiliated with VMware.