-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathmemory.py
93 lines (73 loc) · 2.82 KB
/
memory.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
import os
import redis
import structlog
import tiktoken
from msgpack import packb, unpackb
logger = structlog.get_logger()
class Memory:
def __init__(self):
self.redis_client = redis.from_url(os.environ.get("REDIS_URL"))
self.max_tokens = os.environ.get("MAX_TOKENS", 4096)
self.enc = tiktoken.encoding_for_model("gpt-4")
def get_messages(self, chat_id: str) -> list:
"""
Get messages from redis
Older messages will be removed if total_tokens length is greater than max_tokens
This does not remove the system messages as they are not part of the total_tokens length
max_tokens should be set accordingly, depending on the model and system messages length
:param chat_id: Chat ID
:return: List of messages
"""
messages = self.redis_client.get(chat_id)
if messages:
messages = unpackb(messages)
# If total_tokens length is greater than max_tokens, remove the
# oldest messages until it's not
total_tokens = sum([message["content_tokens"] for message in messages])
while total_tokens > self.max_tokens:
logger.debug(
"Removing oldest message",
chat_id=chat_id,
total_tokens=total_tokens,
max_tokens=self.max_tokens,
message=messages[0],
)
messages.pop(0)
total_tokens = sum([message["content_tokens"] for message in messages])
# Update redis
self.redis_client.set(chat_id, packb(messages))
return messages
return []
def add_message(self, chat_id: str, message: dict) -> None:
"""
Add message to chat_id in redis
:param chat_id: Chat ID
:param message: Message to add
"""
messages = self.get_messages(chat_id)
message["content_tokens"] = len(self.enc.encode(message["content"]))
messages.append(message)
self.redis_client.set(chat_id, packb(messages))
def delete_messages(self, chat_id: str) -> None:
"""
Delete messages from chat_id in redis
:param chat_id: Chat ID
"""
self.redis_client.delete(chat_id)
def get_profile(self, user_id: str) -> dict:
"""
Get user profile from redis
:param user_id: User ID
:return: User profile
"""
profile = self.redis_client.get(f"profile_{user_id}")
if profile:
return unpackb(profile)
return {}
def set_profile(self, user_id: str, profile: dict) -> None:
"""
Set user profile in redis
:param user_id: User ID
:param profile: User profile
"""
self.redis_client.set(f"profile_{user_id}", packb(profile))