チャットメモリ
大規模言語モデル(LLM)は状態を持たないため、以前のインタラクションに関する情報を保持しません。これは、複数のインタラクションにわたってコンテキストや状態を維持したい場合に制約となる可能性があります。この問題に対処するため、Spring AI は、LLM との複数のインタラクションにわたって情報を保存および取得できるチャットメモリ機能を提供します。
ChatMemory
抽象化により、様々なユースケースに対応するために様々な型のメモリを実装できます。メッセージの基盤となるストレージは ChatMemoryRepository
によって処理され、メッセージの保存と取得のみを担います。どのメッセージを保持し、いつ削除するかは ChatMemory
実装によって決定されます。戦略の例としては、最後の N 個のメッセージを保持する、一定期間メッセージを保持する、一定のトークン制限までメッセージを保持するなどが挙げられます。
メモリの種類を選択する前に、チャットメモリとチャット履歴の違いを理解することが重要です。
チャットメモリ。大規模言語モデルが保持し、会話全体を通じてコンテキスト認識を維持するために使用する情報。
Chat History。ユーザーとモデル間で交換されたすべてのメッセージを含む、会話履歴全体。
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 は、アプリケーションで直接使用できる型 InMemoryChatMemoryRepository
の ChatMemoryRepository
Bean を自動構成します。
@Autowired
ChatMemoryRepository chatMemoryRepository;
InMemoryChatMemoryRepository
を手動で作成する場合は、次のようにします。
ChatMemoryRepository repository = new InMemoryChatMemoryRepository();
JdbcChatMemoryRepository
JdbcChatMemoryRepository
は、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 PostgresChatMemoryDialect())
.build();
ChatMemory chatMemory = MessageWindowChatMemory.builder()
.chatMemoryRepository(chatMemoryRepository)
.maxMessages(10)
.build();
サポートされているデータベースとダイアレクトの抽象化
Spring AI は、ダイアレクト抽象化により複数のリレーショナルデータベースをサポートします。以下のデータベースは標準でサポートされています。
PostgreSQL
MySQL/MariaDB
SQL Server
HSQLDB
JdbcChatMemoryRepositoryDialect.from(DataSource)
を使用すると、JDBC URL から適切なダイアレクトが自動検出されます。JdbcChatMemoryRepositoryDialect
インターフェースを実装することで、他のデータベースのサポートを継承できます。
プロパティの構成
プロパティ | 説明 | デフォルト値 |
| スキーマを初期化するタイミングを制御します。値: |
|
| 初期化に使用するスキーマスクリプトの場所。 |
|
| @@platform@@ プレースホルダーが使用されている場合に初期化スクリプトで使用するプラットフォーム。 | 自動検出 |
スキーマの初期化
自動構成により、起動時にデータベースのベンダー固有の SQL スクリプトを使用して SPRING_AI_CHAT_MEMORY
テーブルが自動的に作成されます。デフォルトでは、スキーマの初期化は組み込みデータベース(H2、HSQL、Derby など)に対してのみ実行されます。
spring.ai.chat.memory.repository.jdbc.initialize-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)
スキーマスクリプトの場所をオーバーライドするには、次を使用します。
spring.ai.chat.memory.repository.jdbc.schema=classpath:/custom/path/schema-mysql.sql
CassandraChatMemoryRepository
CassandraChatMemoryRepository
は Apache Cassandra を使用してメッセージを保存します。これは、特に可用性、耐久性、拡張性、Time-to-Live(TTL)機能を活用するために、チャットメモリの永続的な保存を必要とするアプリケーションに適しています。
CassandraChatMemoryRepository
は時系列スキーマを備えており、過去のすべてのチャットウィンドウの記録を保持します。これはガバノンスと監査に役立ちます。有効期限(TTL)を 3 年など、適切な値に設定することをお勧めします。
まず 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(CassandraChatMemoryConfig.builder().withCqlSession(cqlSession));
ChatMemory chatMemory = MessageWindowChatMemory.builder()
.chatMemoryRepository(chatMemoryRepository)
.maxMessages(10)
.build();
プロパティの構成
プロパティ | 説明 | デフォルト値 |
| クラスタ検出を開始するホスト |
|
| 接続する Cassandra ネイティブプロトコルポート |
|
| Cassandra データセンターに接続する |
|
| Cassandra で書き込まれたメッセージの存続時間 (TTL) | |
| Cassandra キースペース |
|
| メッセージの Cassandra 列名 |
|
| Cassandra テーブル |
|
| 起動時にスキーマを初期化するかどうか。 |
|
ネオ 4j 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 provides auto-configuration for the Neo4jChatMemoryRepository
, which you can use directly in your application.
@Autowired
Neo4jChatMemoryRepository chatMemoryRepository;
ChatMemory chatMemory = MessageWindowChatMemory.builder()
.chatMemoryRepository(chatMemoryRepository)
.maxMessages(10)
.build();
If you’d rather create the Neo4jChatMemoryRepository
manually, you can do so by providing a Neo4j Driver
instance:
ChatMemoryRepository chatMemoryRepository = Neo4jChatMemoryRepository.builder()
.driver(driver)
.build();
ChatMemory chatMemory = MessageWindowChatMemory.builder()
.chatMemoryRepository(chatMemoryRepository)
.maxMessages(10)
.build();
プロパティの構成
プロパティ | 説明 | デフォルト値 |
| 会話セッションを保存するノードのラベル |
|
| メッセージを保存するノードのラベル |
|
| The label for nodes that store tool calls (e.g. in Assistant Messages) |
|
| The label for nodes that store message metadata |
|
| ツールのレスポンスを保存するノードのラベル |
|
| The label for the nodes that store media associated with a message |
|
Index Initialization
The Neo4j repository will automatically ensure that indexes are created for conversation IDs and message indices to optimize performance. If you use custom labels, indexes will be created for those labels as well. No schema initialization is required, but you should ensure your Neo4j instance is accessible to your application.
Memory in Chat Client
When using the ChatClient API, you can provide a ChatMemory
implementation to maintain conversation context across multiple interactions.
Spring AI provides a few built-in Advisors that you can use to configure the memory behavior of the ChatClient
, based on your needs.
Currently, the intermediate messages exchanged with a large-language model when performing tool calls are not stored in the memory. This is a limitation of the current implementation and will be addressed in future releases. If you need to store these messages, refer to the instructions for the User Controlled Tool Execution. |
MessageChatMemoryAdvisor
。This advisor manages the conversation memory using the providedChatMemory
implementation. On each interaction, it retrieves the conversation history from the memory and includes it in the prompt as a collection of messages.PromptChatMemoryAdvisor
。This advisor manages the conversation memory using the providedChatMemory
implementation. On each interaction, it retrieves the conversation history from the memory and appends it to the system prompt as plain text.VectorStoreChatMemoryAdvisor
。This advisor manages the conversation memory using the providedVectorStore
implementation. On each interaction, it retrieves the conversation history from the vector store and appends it to the system message as plain text.
For example, if you want to use MessageWindowChatMemory
with the MessageChatMemoryAdvisor
, you can configure it as follows:
ChatMemory chatMemory = MessageWindowChatMemory.builder().build();
ChatClient chatClient = ChatClient.builder(chatModel)
.defaultAdvisors(MessageChatMemoryAdvisor.builder(chatMemory).build())
.build();
When performing a call to the ChatClient
, the memory will be automatically managed by the MessageChatMemoryAdvisor
. The conversation history will be retrieved from the memory based on the specified conversation ID:
String conversationId = "007";
chatClient.prompt()
.user("Do I have license to code?")
.advisors(a -> a.param(ChatMemory.CONVERSATION_ID, conversationId))
.call()
.content();
PromptChatMemoryAdvisor
カスタムテンプレート
The PromptChatMemoryAdvisor
uses a default template to augment the system message with the retrieved conversation memory. You can customize this behavior by providing your own PromptTemplate
object via the .promptTemplate()
builder method.
The PromptTemplate provided here customizes how the advisor merges retrieved memory with the system message. This is distinct from configuring a TemplateRenderer on the ChatClient itself (using .templateRenderer() ), which affects the rendering of the initial user/system prompt content before the advisor runs. See ChatClient プロンプトテンプレート for more details on client-level template rendering. |
カスタム PromptTemplate
では、任意の TemplateRenderer
実装を使用できます(デフォルトでは、StringTemplate (英語) エンジンに基づく StPromptTemplate
を使用します)。重要な要件として、テンプレートには以下の 2 つのプレースホルダが含まれている必要があります。
元のシステムメッセージを受信するための
instructions
プレースホルダー。取得した会話メモリを受け取るための
memory
プレースホルダー。
VectorStoreChatMemoryAdvisor
カスタムテンプレート
The VectorStoreChatMemoryAdvisor
uses a default template to augment the system message with the retrieved conversation memory. You can customize this behavior by providing your own PromptTemplate
object via the .promptTemplate()
builder method.
The PromptTemplate provided here customizes how the advisor merges retrieved memory with the system message. This is distinct from configuring a TemplateRenderer on the ChatClient itself (using .templateRenderer() ), which affects the rendering of the initial user/system prompt content before the advisor runs. See ChatClient プロンプトテンプレート for more details on client-level template rendering. |
カスタム PromptTemplate
では、任意の TemplateRenderer
実装を使用できます(デフォルトでは、StringTemplate (英語) エンジンに基づく StPromptTemplate
を使用します)。重要な要件として、テンプレートには以下の 2 つのプレースホルダが含まれている必要があります。
元のシステムメッセージを受信するための
instructions
プレースホルダー。取得した会話メモリを受け取るための
long_term_memory
プレースホルダー。
Memory in Chat Model
If you’re working directly with a ChatModel
instead of a ChatClient
, you can manage the memory explicitly:
// 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"