|
1 |
| -Build a production-ready AI assistant that remembers conversations semantically and auto-cleans using Redis 8’s new features. |
2 |
| - |
3 |
| -This smart AI assistant offers: |
4 |
| - - **Ephemeral Memory**: Messages expire automatically at different intervals |
5 |
| - - **Semantic Recall**: Search past chats by meaning, not just keywords |
6 |
| - - **Zero Maintenance**: No cleanup scripts or cron jobs needed |
7 |
| - - **Multi-User Support**: Memory isolated by user and session |
8 |
| - - **Hybrid Search**: Combine text and vector search for better results |
9 |
| - |
10 |
| -**Note**: [Redis 8](https://hub.docker.com/_/redis/tags) is required for this tutorial Redis 8 since it introduces `HSETEX`, which lets you set TTL per hash field, ideal for ephemeral chat memory without complex expiration logic. |
11 |
| - |
12 |
| -### Hierarchical Memory Structure |
13 |
| -Store chat sessions as Redis hashes. Each message is a field with its own TTL. |
14 |
| - |
15 |
| -```redis:[run_confirmation=true] Upload Session Data |
16 |
| -// User-scoped sessions for isolation |
17 |
| -// Pattern: user:{user_id}:session:{session_id} |
18 |
| -HSETEX user:alice:session:morning EX 3600 FIELDS 1 msg:1717935301 "Good morning! What's my schedule today?" |
19 |
| -HSETEX user:alice:session:morning EX 1800 FIELDS 1 msg:1717935361 "Remind me about the team meeting at 2 PM" |
20 |
| -HSETEX user:alice:session:morning EX 900 FIELDS 1 msg:1717935420 "What's the weather forecast?" |
21 |
| -HSETEX user:alice:session:morning EX 300 FIELDS 1 msg:1717935480 "Thanks, that's all for now" |
22 |
| -
|
23 |
| -// Different user, same session pattern |
24 |
| -HSETEX user:bob:session:work EX 7200 FIELDS 1 msg:1717935500 "I need to prepare for the client presentation" |
25 |
| -HSETEX user:bob:session:work EX 3600 FIELDS 1 msg:1717935560 "What are the key points I should cover?" |
| 1 | +This intelligent AI assistant is designed to support real-world, multi-session use with Redis as its memory core. |
| 2 | + |
| 3 | +What you get: |
| 4 | + - **Smart Memory**: Ephemeral context that expires automatically, long-term facts retained forever |
| 5 | + - **Semantic Search**: Recall relevant info by meaning using vector search |
| 6 | + - **Zero Maintenance**: Auto-expiring short-term memory without a need to track timestamps manually |
| 7 | + - **Multi-User**: Isolated memory per user |
| 8 | + - **Learning**: Assistant can "understand" each user better the more it's used |
| 9 | + |
| 10 | +**Note**: Requires [Redis 8](https://hub.docker.com/_/redis/tags) for `HSETEX`, which adds per-field TTL for hashes, which is ideal for managing short-term memory with precision. |
| 11 | + |
| 12 | +### Architecture Overview |
| 13 | +| Layer | Description | |
| 14 | +| ---------- | ---------- | |
| 15 | +| `Working Memory`| `Short-term chat context (ephemeral)` | |
| 16 | +| `Knowledge Base` | `Persistent facts, user preferences` | |
| 17 | +| `Vector Search` | `Unified semantic recall across both layers` | |
| 18 | + |
| 19 | +### Working Memory (Ephemeral) |
| 20 | +Stores recent user messages with TTL based on importance. Automatically expires to prevent bloat. |
| 21 | +This uses `HSETEX`, a Redis 8 command that adds field-level expiration to hashes. It allows storing all temporary messages in a single key while managing TTLs per message, simplifying short-term memory management without needing multiple keys. |
| 22 | + |
| 23 | +```redis:[run_confirmation=true] Recent Conversations with TTL Based on Importance. |
| 24 | +// Quick exchanges (5 min) |
| 25 | +HSETEX user:alice:session:001 EX 300 FIELDS 1 msg:001 "What's the weather?" |
| 26 | +// Session context (30 min) |
| 27 | +HSETEX user:alice:session:001 EX 1800 FIELDS 1 msg:002 "I need a dentist appointment" |
| 28 | +// Important decisions (2 hours) |
| 29 | +HSETEX user:alice:session:001 EX 7200 FIELDS 1 msg:003 "Book it for Tuesday 2 PM" |
26 | 30 | ```
|
27 | 31 |
|
28 |
| -### Memory Tiers for Different Lifetimes |
29 |
| -Control how long messages last depending on their importance. |
30 |
| - |
31 |
| -```redis:[run_confirmation=true] Memory Tiers Strategy |
32 |
| -// Short-term (5 minutes) - Immediate context |
33 |
| -HSETEX user:alice:session:current EX 300 FIELDS 1 msg:1717935301 "Current conversation context" |
34 |
| -
|
35 |
| -// Medium-term (30 minutes) - Session memory |
36 |
| -HSETEX user:alice:session:current EX 1800 FIELDS 1 msg:1717935302 "Important session details" |
37 |
| -
|
38 |
| -// Long-term (2 hours) - Cross-session context |
39 |
| -HSETEX user:alice:session:current EX 7200 FIELDS 1 msg:1717935303 "Key user preferences and facts" |
| 32 | +### Knowledge Base (Persistent) |
| 33 | +Long-term memory: stores important facts, user preferences, and context across sessions. These never expire. |
| 34 | +`embedding` is a binary-encoded `FLOAT32[]` used for vector similarity that can be generated using sentence-transformers or similar libraries. Demo uses 8-dim vectors; production models typically use 128–1536 dimensions. |
| 35 | + |
| 36 | +```redis:[run_confirmation=true] Important User Information That Never Expires. |
| 37 | +// User preferences - need vector fields for search |
| 38 | +HSET user:alice:knowledge:pref:001 user_id "alice" memory_type "knowledge" content "prefers mornings before 10 AM" importance 9 timestamp 1717935000 embedding "\x40\x20\x00\x00\x3f\x80\x00\x00\x40\x40\x00\x00\x3f\x40\x00\x00\x40\x60\x00\x00\x40\x00\x00\x00\x3f\x00\x00\x00\x40\x80\x00\x00" |
| 39 | +HSET user:alice:knowledge:pref:002 user_id "alice" memory_type "knowledge" content "likes detailed explanations" importance 8 timestamp 1717935000 embedding "\x3f\x40\x00\x00\x40\x60\x00\x00\x40\x00\x00\x00\x40\x20\x00\x00\x3f\x80\x00\x00\x40\x40\x00\x00\x40\x80\x00\x00\x3f\x00\x00\x00" |
| 40 | +// Personal facts |
| 41 | +HSET user:alice:knowledge:personal:001 user_id "alice" memory_type "knowledge" content "allergic to shellfish" importance 10 timestamp 1717935000 embedding "\x40\x00\x00\x00\x40\x20\x00\x00\x3f\x80\x00\x00\x40\x40\x00\x00\x40\x60\x00\x00\x3f\x40\x00\x00\x40\x80\x00\x00\x3f\x00\x00\x00" |
| 42 | +HSET user:alice:knowledge:personal:002 user_id "alice" memory_type "knowledge" content "golden retriever named Max" importance 7 timestamp 1717935000 embedding "\x3f\x80\x00\x00\x40\x40\x00\x00\x40\x00\x00\x00\x3f\x40\x00\x00\x40\x80\x00\x00\x40\x20\x00\x00\x3f\x00\x00\x00\x40\x60\x00\x00" |
| 43 | +// Work context |
| 44 | +HSET user:alice:knowledge:work:001 user_id "alice" memory_type "knowledge" content "Senior PM at TechCorp" importance 8 timestamp 1717935000 embedding "\x40\x40\x00\x00\x3f\x00\x00\x00\x40\x80\x00\x00\x40\x20\x00\x00\x3f\x80\x00\x00\x40\x60\x00\x00\x40\x00\x00\x00\x3f\x40\x00\x00" |
| 45 | +HSET user:alice:knowledge:work:002 user_id "alice" memory_type "knowledge" content "leading Project Apollo" importance 9 timestamp 1717935000 embedding "\x40\x60\x00\x00\x40\x80\x00\x00\x3f\x40\x00\x00\x40\x00\x00\x00\x40\x20\x00\x00\x3f\x80\x00\x00\x40\x40\x00\x00\x3f\x00\x00\x00" |
40 | 46 | ```
|
41 | 47 |
|
42 |
| -### Check Current Session Memory |
43 |
| -No manual cleanup needed; expired messages vanish automatically. |
44 |
| - |
45 |
| -```redis:[run_confirmation=true] Monitor Session State Over Time |
46 |
| -// After a few minutes, run this command to see what's left. |
47 |
| -HGETALL user:alice:session:morning |
48 |
| -``` |
49 |
| - |
50 |
| -### Vector Search Setup for Semantic Recall |
51 |
| -Create an index to store messages as vectors for semantic search. |
| 48 | +### Vector Search: Semantic Memory Recall |
| 49 | +Unify working + knowledge memory into a vector index for semantically meaningful search. |
52 | 50 |
|
53 | 51 | ```redis:[run_confirmation=true] Create a Vector Index
|
54 |
| -FT.CREATE idx:ai_memory |
| 52 | +FT.CREATE idx:memory |
55 | 53 | ON HASH
|
56 |
| - PREFIX 1 memory: |
| 54 | + PREFIX 2 vmemory: user: |
57 | 55 | SCHEMA
|
58 |
| - user_id TAG SORTABLE |
59 |
| - session_id TAG SORTABLE |
60 |
| - message TEXT |
61 |
| - context TEXT |
62 |
| - timestamp NUMERIC SORTABLE |
| 56 | + user_id TAG |
| 57 | + memory_type TAG |
| 58 | + content TEXT |
| 59 | + importance NUMERIC |
| 60 | + timestamp NUMERIC |
63 | 61 | embedding VECTOR HNSW 6
|
64 | 62 | TYPE FLOAT32
|
65 |
| - DIM 8 // DIM = embedding size, DIM 8 is just for demo purposes. In real use, embeddings are usually 128–1536 |
| 63 | + DIM 8 // DIM = embedding size; 8 used here for simplicity — in production, use 128 to 1536 |
66 | 64 | DISTANCE_METRIC COSINE // COSINE = measures semantic closeness
|
67 | 65 | ```
|
68 | 66 |
|
69 |
| -Add sample vectorized messages (embedding dims are demo-sized): |
| 67 | +### Add Indexed Memory |
| 68 | +Populate the vector index with memory items from both ephemeral and persistent layers. |
70 | 69 |
|
71 | 70 | ```redis:[run_confirmation=true] Add entries for the chatbot
|
72 |
| -HSET memory:alice:1 user_id "alice" session_id "morning" message "I have a dentist appointment at 3 PM today" context "healthcare scheduling appointment" timestamp 1717935301 embedding "\x3f\x00\x00\x00\x40\x00\x00\x00\x40\x40\x00\x00\x40\x80\x00\x00\x40\x00\x00\x00\x40\x00\x00\x00" |
73 |
| -HSET memory:alice:2 user_id "alice" session_id "morning" message "Remind me to water the plants in my office" context "task reminder plants office" timestamp 1717935361 embedding "\x40\x00\x00\x00\x40\x00\x00\x00\x40\x00\x00\x00\x3f\x00\x00\x00\x3f\x00\x00\x00\x40\x00\x00\x00" |
74 |
| -HSET memory:alice:3 user_id "alice" session_id "work" message "Schedule a meeting with the engineering team" context "work scheduling meeting team" timestamp 1717935420 embedding "\x40\x40\x00\x00\x40\x00\x00\x00\x40\x00\x00\x00\x40\x00\x00\x00\x3f\x00\x00\x00\x3f\x00\x00\x00" |
75 |
| -HSET memory:bob:1 user_id "bob" session_id "work" message "I need to review the quarterly sales report" context "business analysis quarterly report" timestamp 1717935480 embedding "\x40\x40\x00\x00\x40\x00\x00\x00\x3f\x00\x00\x00\x40\x00\x00\x00\x40\x00\x00\x00\x00\x00\x00\x00" |
| 71 | +// Working memory (expires from Redis, stays in search until rebuild) |
| 72 | +HSET vmemory:alice:001 user_id "alice" memory_type "working" content "Book dentist for Tuesday 2 PM" importance 8 timestamp 1717935310 embedding "\x3f\x80\x00\x00\x40\x00\x00\x00\x40\x40\x00\x00\x40\x80\x00\x00\x3f\x00\x00\x00\x40\x20\x00\x00\x40\x60\x00\x00\x3f\x40\x00\x00" |
| 73 | +
|
| 74 | +// Knowledge base (persistent) |
| 75 | +HSET vmemory:alice:kb:001 user_id "alice" memory_type "knowledge" content "allergic to shellfish" importance 10 timestamp 1717935000 embedding "\x40\x00\x00\x00\x40\x20\x00\x00\x3f\x80\x00\x00\x40\x40\x00\x00\x40\x60\x00\x00\x3f\x40\x00\x00\x40\x80\x00\x00\x3f\x00\x00\x00" |
76 | 76 | ```
|
77 | 77 |
|
78 |
| -### Let Chatbot Think – Semantic Search with Vectors |
79 |
| -When a user says something new, find all related past conversations across your entire system based on semantic meaning. |
| 78 | +### Full Memory Search |
| 79 | +Search across all memories to recall relevant data. |
80 | 80 |
|
81 | 81 | ```redis:[run_confirmation=false] Find Top 5 Related Messages By Meaning
|
82 |
| -FT.SEARCH idx:ai_memory |
83 |
| - "*=>[KNN 5 @embedding $vec AS score]" |
84 |
| - PARAMS 2 vec "\x00\x00@@\x00\x00\x80@\x00\x00\x00@\x00\x00\x80?\x00\x00@@\x00\x00\x00@" |
85 |
| - RETURN 4 user_id message context timestamp |
86 |
| - SORTBY score ASC |
87 |
| - DIALECT 2 |
| 82 | +FT.SEARCH idx:memory |
| 83 | + "(@user_id:{alice}) => [KNN 5 @embedding $vec AS score]" |
| 84 | + PARAMS 2 vec "\x40\x00\x00\x00\x40\x20\x00\x00\x3f\x80\x00\x00\x40\x40\x00\x00\x40\x60\x00\x00\x3f\x40\x00\x00\x40\x80\x00\x00\x3f\x00\x00\x00" |
| 85 | + RETURN 4 content memory_type importance score |
| 86 | + SORTBY score ASC |
| 87 | + DIALECT 2 |
88 | 88 | ```
|
89 | 89 |
|
90 |
| -Now your assistant “remembers” things it’s heard before - by meaning. |
91 |
| - |
92 |
| -### User-Scoped Semantic Search |
93 |
| -Your AI should only recall memories from the specific user it's talking to, not leak information between users. |
| 90 | +### Session-Only Search |
| 91 | +Limit results to current conversation context (ephemeral memory). |
94 | 92 |
|
95 |
| -```redis:[run_confirmation=false] Find Similar Memories For Specific User Only |
96 |
| -FT.SEARCH idx:ai_memory |
97 |
| - "(@user_id:{alice}) => [KNN 3 @embedding $query_vec AS vector_score]" |
98 |
| - PARAMS 2 query_vec "\x00\x00@@\x00\x00\x80@\x00\x00\x00@\x00\x00\x80?\x00\x00@@\x00\x00\x00@" |
99 |
| - RETURN 5 user_id message context vector_score session_id |
100 |
| - SORTBY vector_score ASC |
| 93 | +```redis:[run_confirmation=false] Session-Only Search |
| 94 | +FT.SEARCH idx:memory |
| 95 | + "(@user_id:{alice} @memory_type:{working}) => [KNN 5 @embedding $vec AS score]" |
| 96 | + PARAMS 2 vec "\x3f\x80\x00\x00\x40\x40\x00\x00\x40\x00\x00\x00\x3f\x40\x00\x00\x40\x80\x00\x00\x40\x20\x00\x00\x3f\x00\x00\x00\x40\x60\x00\x00" |
| 97 | + RETURN 4 content score timestamp memory_type |
| 98 | + SORTBY score ASC |
101 | 99 | DIALECT 2
|
102 | 100 | ```
|
103 | 101 |
|
104 |
| -### Time-Bounded Semantic Search |
105 |
| -When users ask about "recent" things, limit your search to a specific time window while still using semantic matching. |
| 102 | +### Knowledge-Only Search |
| 103 | +Focus only on persistent memory: facts, preferences, decisions. |
106 | 104 |
|
107 |
| -```redis:[run_confirmation=false] Find recent similar memories (last 24 hours) |
108 |
| -FT.SEARCH idx:ai_memory |
109 |
| - "(@timestamp:[1717849200 +inf]) => [KNN 3 @embedding $query_vec AS vector_score]" |
110 |
| - PARAMS 2 query_vec "\x00\x00@@\x00\x00\x80@\x00\x00\x00@\x00\x00\x80?\x00\x00@@\x00\x00\x00@" |
111 |
| - RETURN 6 message timestamp vector_score |
112 |
| - SORTBY timestamp DESC |
| 105 | +```redis:[run_confirmation=false] Knowledge-Only Search |
| 106 | +FT.SEARCH idx:memory |
| 107 | + "(@user_id:{alice} @memory_type:{knowledge}) => [KNN 8 @embedding $vec AS score]" |
| 108 | + PARAMS 2 vec "\x40\x40\x00\x00\x3f\x00\x00\x00\x40\x80\x00\x00\x40\x20\x00\x00\x3f\x80\x00\x00\x40\x60\x00\x00\x40\x00\x00\x00\x3f\x40\x00\x00" |
| 109 | + RETURN 4 content importance score timestamp |
| 110 | + SORTBY score ASC |
113 | 111 | DIALECT 2
|
114 | 112 | ```
|
115 | 113 |
|
116 |
| -### Session-Specific Recall |
117 |
| -When users refer to something from "earlier in our conversation," search only within the current session context. |
| 114 | +### Monitoring Memory State |
| 115 | +Use these queries to inspect what’s stored in memory. |
118 | 116 |
|
119 |
| -``` |
120 |
| -FT.SEARCH idx:ai_memory |
121 |
| - "(@user_id:{alice} @session_id:{morning}) => [KNN 10 @embedding $query_vec AS vector_score]" |
122 |
| - PARAMS 2 query_vec "\x00\x00@@\x00\x00\x80@\x00\x00\x00@\x00\x00\x80?\x00\x00@@\x00\x00\x00@" |
123 |
| - RETURN 4 message context vector_score timestamp |
124 |
| - SORTBY vector_score |
125 |
| - DIALECT 2 |
| 117 | +```redis:[run_confirmation=false] Check Memory State |
| 118 | +// Check active session memory |
| 119 | +HGETALL user:alice:knowledge:pref:001 // Example for one preference item |
| 120 | +
|
| 121 | +// View user knowledge |
| 122 | +HGETALL user:alice:knowledge:pref:001 |
| 123 | +
|
| 124 | +// Search user's memories |
| 125 | +FT.SEARCH idx:memory |
| 126 | + "@user_id:{alice}" |
| 127 | + RETURN 3 content memory_type importance |
126 | 128 | ```
|
127 | 129 |
|
128 |
| -### Want to check what's still in memory? |
| 130 | +### Data Cleanup |
129 | 131 |
|
130 |
| -Only unexpired fields remain. |
| 132 | +For privacy compliance, delete all user-related keys. |
131 | 133 |
|
132 |
| -```redis:[run_confirmation=false] Check Sessions |
133 |
| -HGETALL memory:alice:1 |
134 |
| -HGETALL memory:alice:2 |
135 |
| -HGETALL memory:alice:3 |
136 |
| -HGETALL memory:bob:1 |
| 134 | +```redis:[run_confirmation=true] Complete user removal |
| 135 | +DEL user:alice:knowledge:pref:001 |
| 136 | +DEL user:alice:knowledge:pref:002 |
| 137 | +DEL user:alice:knowledge:personal:001 |
| 138 | +DEL user:alice:knowledge:personal:002 |
| 139 | +DEL user:alice:knowledge:work:001 |
| 140 | +DEL user:alice:knowledge:work:002 |
| 141 | +DEL vmemory:alice:001 |
| 142 | +DEL vmemory:alice:kb:001 |
137 | 143 | ```
|
138 | 144 |
|
139 | 145 | ### Next Steps
|
140 | 146 | Now that your assistant has memory and meaning, you can:
|
141 |
| - - Combine Redis Vector Search with LLMs (RAG) |
142 |
| - - Use OpenAI or sentence-transformers for embeddings |
143 |
| - - Add fallback persistent storage with Redis Flex |
144 |
| - - Manage users with ACLs, quotas, and keyspace notifications |
| 147 | + - Combine with RAG Pipelines |
| 148 | + - Use sentence-transformers to generate high-dimensional vectors |
| 149 | + - Add [Redis Flex](https://redis.io/solutions/flex/?utm_source=redisinsight&utm_medium=app&utm_campaign=tutorials) for fallback persistence |
| 150 | + - Use Redis ACLs to isolate users, enforce quotas, and monitor usage |
0 commit comments