@@ -476,6 +476,141 @@ ChatMemory chatMemory = MessageWindowChatMemory.builder()
476476==== Collection Initialization
477477The auto-configuration will automatically create the `ai_chat_memory` collection on startup if it does not already exist.
478478
479+ === RedisChatMemoryRepository
480+
481+ `RedisChatMemoryRepository` is a built-in implementation that uses Redis Stack (with Redis Query Engine and RedisJSON) to store chat messages.
482+ It is suitable for applications that require high-performance, low-latency chat memory persistence with optional TTL (time-to-live) support and advanced querying capabilities.
483+
484+ The repository stores messages as JSON documents and creates a search index for efficient querying.
485+ It also provides extended query capabilities through the `AdvancedRedisChatMemoryRepository` interface for searching messages by content, type, time range, and metadata.
486+
487+ First, add the following dependency to your project:
488+
489+ [tabs]
490+ ======
491+ Maven::
492+ +
493+ [source, xml]
494+ ----
495+ <dependency>
496+ <groupId>org.springframework.ai</groupId>
497+ <artifactId>spring-ai-starter-model-chat-memory-repository-redis</artifactId>
498+ </dependency>
499+ ----
500+
501+ Gradle::
502+ +
503+ [source,groovy]
504+ ----
505+ dependencies {
506+ implementation 'org.springframework.ai:spring-ai-starter-model-chat-memory-repository-redis'
507+ }
508+ ----
509+ ======
510+
511+ Spring AI provides auto-configuration for the `RedisChatMemoryRepository`, which you can use directly in your application.
512+
513+ [source,java]
514+ ----
515+ @Autowired
516+ RedisChatMemoryRepository chatMemoryRepository;
517+
518+ ChatMemory chatMemory = MessageWindowChatMemory.builder()
519+ .chatMemoryRepository(chatMemoryRepository)
520+ .maxMessages(10)
521+ .build();
522+ ----
523+
524+ If you'd rather create the `RedisChatMemoryRepository` manually, you can do so by providing a `JedisPooled` client:
525+
526+ [source,java]
527+ ----
528+ JedisPooled jedisClient = new JedisPooled("localhost", 6379);
529+
530+ ChatMemoryRepository chatMemoryRepository = RedisChatMemoryRepository.builder()
531+ .jedisClient(jedisClient)
532+ .indexName("my-chat-index")
533+ .keyPrefix("my-chat:")
534+ .timeToLive(Duration.ofHours(24))
535+ .build();
536+
537+ ChatMemory chatMemory = MessageWindowChatMemory.builder()
538+ .chatMemoryRepository(chatMemoryRepository)
539+ .maxMessages(10)
540+ .build();
541+ ----
542+
543+ ==== Configuration Properties
544+
545+ [cols="2,5,1",stripes=even]
546+ |===
547+ |Property | Description | Default Value
548+ | `spring.ai.chat.memory.redis.host` | Redis server host | `localhost`
549+ | `spring.ai.chat.memory.redis.port` | Redis server port | `6379`
550+ | `spring.ai.chat.memory.redis.index-name` | Name of the Redis search index | `chat-memory-idx`
551+ | `spring.ai.chat.memory.redis.key-prefix` | Key prefix for chat memory entries | `chat-memory:`
552+ | `spring.ai.chat.memory.redis.time-to-live` | Time to live for chat memory entries (e.g., `24h`, `30d`) | _no expiration_
553+ | `spring.ai.chat.memory.redis.initialize-schema` | Whether to initialize the Redis schema on startup | `true`
554+ | `spring.ai.chat.memory.redis.max-conversation-ids` | Maximum number of conversation IDs to return | `1000`
555+ | `spring.ai.chat.memory.redis.max-messages-per-conversation` | Maximum number of messages to return per conversation | `1000`
556+ |===
557+
558+ ==== Advanced Querying
559+
560+ The `RedisChatMemoryRepository` also implements `AdvancedRedisChatMemoryRepository`, which provides extended query capabilities:
561+
562+ [source,java]
563+ ----
564+ // Cast to access advanced features
565+ AdvancedRedisChatMemoryRepository advancedRepo = (AdvancedRedisChatMemoryRepository) chatMemoryRepository;
566+
567+ // Find messages by type across all conversations
568+ List<MessageWithConversation> userMessages = advancedRepo.findByType(MessageType.USER, 100);
569+
570+ // Find messages containing specific content
571+ List<MessageWithConversation> results = advancedRepo.findByContent("Spring AI", 50);
572+
573+ // Find messages within a time range
574+ List<MessageWithConversation> recentMessages = advancedRepo.findByTimeRange(
575+ conversationId,
576+ Instant.now().minus(Duration.ofHours(1)),
577+ Instant.now(),
578+ 100
579+ );
580+
581+ // Find messages by metadata
582+ List<MessageWithConversation> priorityMessages = advancedRepo.findByMetadata("priority", "high", 50);
583+
584+ // Execute custom Redis queries
585+ List<MessageWithConversation> customResults = advancedRepo.executeQuery("@type:USER @content:Redis", 100);
586+ ----
587+
588+ ==== Metadata Field Indexing
589+
590+ To enable efficient querying on custom metadata fields, you can configure metadata field definitions:
591+
592+ [source,properties]
593+ ----
594+ spring.ai.chat.memory.redis.metadata-fields[0].name=priority
595+ spring.ai.chat.memory.redis.metadata-fields[0].type=tag
596+ spring.ai.chat.memory.redis.metadata-fields[1].name=score
597+ spring.ai.chat.memory.redis.metadata-fields[1].type=numeric
598+ spring.ai.chat.memory.redis.metadata-fields[2].name=category
599+ spring.ai.chat.memory.redis.metadata-fields[2].type=tag
600+ ----
601+
602+ Supported field types are: `tag` (for exact match filtering), `text` (for full-text search), and `numeric` (for range queries).
603+
604+ ==== Schema Initialization
605+
606+ The auto-configuration will automatically create the Redis search index on startup if it does not already exist.
607+ You can disable this behavior by setting `spring.ai.chat.memory.redis.initialize-schema=false`.
608+
609+ ==== Requirements
610+
611+ * Redis Stack 7.0 or higher (includes Redis Query Engine and RedisJSON modules)
612+ * Jedis client library (included as a dependency)
613+
479614== Memory in Chat Client
480615
481616When using the ChatClient API, you can provide a `ChatMemory` implementation to maintain conversation context across multiple interactions.
0 commit comments