Implement performance improvements for memory caching, HTTP client reuse, and regex optimization
Co-authored-by: Kenearos <86194771+Kenearos@users.noreply.github.com>
This commit is contained in:
parent
860e4d5027
commit
b72cd9db1c
5 changed files with 451 additions and 246 deletions
106
memory.py
106
memory.py
|
|
@ -27,6 +27,8 @@ class ConversationMemory:
|
|||
self.max_messages = max_messages
|
||||
self.retention_hours = retention_hours
|
||||
self.logger = logger or logging.getLogger(__name__)
|
||||
# In-memory cache to reduce file I/O for frequently accessed users
|
||||
self._cache: Dict[str, List[Dict]] = {}
|
||||
|
||||
def _get_user_file(self, username):
|
||||
"""Get the file path for a user's conversation history"""
|
||||
|
|
@ -34,6 +36,59 @@ class ConversationMemory:
|
|||
safe_username = "".join(c for c in username.lower() if c.isalnum() or c in "._-")
|
||||
return self.data_dir / f"{safe_username}.json"
|
||||
|
||||
def _load_user_history(self, username):
|
||||
"""
|
||||
Load user history from cache or file
|
||||
|
||||
Args:
|
||||
username (str): Twitch username
|
||||
|
||||
Returns:
|
||||
list: List of message dicts or empty list
|
||||
"""
|
||||
safe_username = username.lower()
|
||||
|
||||
# Check cache first
|
||||
if safe_username in self._cache:
|
||||
return self._cache[safe_username]
|
||||
|
||||
file_path = self._get_user_file(username)
|
||||
|
||||
if not file_path.exists():
|
||||
self._cache[safe_username] = []
|
||||
return []
|
||||
|
||||
try:
|
||||
with open(file_path, 'r', encoding='utf-8') as f:
|
||||
history = json.load(f)
|
||||
self._cache[safe_username] = history
|
||||
return history
|
||||
except Exception as e:
|
||||
self.logger.error(f"Error loading history for {username}: {e}")
|
||||
self._cache[safe_username] = []
|
||||
return []
|
||||
|
||||
def _save_user_history(self, username, history):
|
||||
"""
|
||||
Save user history to file and update cache
|
||||
|
||||
Args:
|
||||
username (str): Twitch username
|
||||
history (list): List of message dicts
|
||||
"""
|
||||
safe_username = username.lower()
|
||||
file_path = self._get_user_file(username)
|
||||
|
||||
# Update cache
|
||||
self._cache[safe_username] = history
|
||||
|
||||
# Save to file
|
||||
try:
|
||||
with open(file_path, 'w', encoding='utf-8') as f:
|
||||
json.dump(history, f, ensure_ascii=False, indent=2)
|
||||
except Exception as e:
|
||||
self.logger.error(f"Error saving history for {username}: {e}")
|
||||
|
||||
def get_user_history(self, username, limit=5):
|
||||
"""
|
||||
Load recent chat history for a user
|
||||
|
|
@ -45,29 +100,22 @@ class ConversationMemory:
|
|||
Returns:
|
||||
list: List of message dicts with role, content, timestamp
|
||||
"""
|
||||
file_path = self._get_user_file(username)
|
||||
history = self._load_user_history(username)
|
||||
|
||||
if not file_path.exists():
|
||||
if not history:
|
||||
return []
|
||||
|
||||
try:
|
||||
with open(file_path, 'r', encoding='utf-8') as f:
|
||||
history = json.load(f)
|
||||
except Exception as e:
|
||||
self.logger.error(f"Error loading history for {username}: {e}")
|
||||
return []
|
||||
|
||||
# Filter by retention time
|
||||
# Filter by retention time using list comprehension for better performance
|
||||
cutoff_time = datetime.now() - timedelta(hours=self.retention_hours)
|
||||
recent = []
|
||||
|
||||
for msg in history:
|
||||
def is_recent(msg):
|
||||
try:
|
||||
msg_time = datetime.fromisoformat(msg['timestamp'])
|
||||
if msg_time > cutoff_time:
|
||||
recent.append(msg)
|
||||
return msg_time > cutoff_time
|
||||
except (KeyError, ValueError):
|
||||
continue
|
||||
return False
|
||||
|
||||
recent = [msg for msg in history if is_recent(msg)]
|
||||
|
||||
# Return only the most recent messages up to limit
|
||||
return recent[-limit:] if recent else []
|
||||
|
|
@ -81,17 +129,8 @@ class ConversationMemory:
|
|||
role (str): 'user' or 'assistant'
|
||||
content (str): Message content
|
||||
"""
|
||||
file_path = self._get_user_file(username)
|
||||
|
||||
# Load existing history
|
||||
history = []
|
||||
if file_path.exists():
|
||||
try:
|
||||
with open(file_path, 'r', encoding='utf-8') as f:
|
||||
history = json.load(f)
|
||||
except Exception as e:
|
||||
self.logger.error(f"Error loading history for {username}: {e}")
|
||||
history = []
|
||||
# Load existing history (uses cache if available)
|
||||
history = self._load_user_history(username)
|
||||
|
||||
# Add new message
|
||||
history.append({
|
||||
|
|
@ -104,12 +143,8 @@ class ConversationMemory:
|
|||
if len(history) > self.max_messages:
|
||||
history = history[-self.max_messages:]
|
||||
|
||||
# Save back to file
|
||||
try:
|
||||
with open(file_path, 'w', encoding='utf-8') as f:
|
||||
json.dump(history, f, ensure_ascii=False, indent=2)
|
||||
except Exception as e:
|
||||
self.logger.error(f"Error saving history for {username}: {e}")
|
||||
# Save back to file and update cache
|
||||
self._save_user_history(username, history)
|
||||
|
||||
def format_for_prompt(self, history):
|
||||
"""
|
||||
|
|
@ -136,6 +171,13 @@ class ConversationMemory:
|
|||
Args:
|
||||
username (str): Twitch username
|
||||
"""
|
||||
safe_username = username.lower()
|
||||
|
||||
# Clear from cache
|
||||
if safe_username in self._cache:
|
||||
del self._cache[safe_username]
|
||||
|
||||
# Clear from disk
|
||||
file_path = self._get_user_file(username)
|
||||
if file_path.exists():
|
||||
try:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue