This commit is contained in:
@@ -0,0 +1,61 @@
|
||||
"""
|
||||
Per-user conversation history store.
|
||||
|
||||
Each Discord user gets their own isolated message list. Only the last
|
||||
`max_history` messages are kept — older ones are silently dropped so the
|
||||
LLM context stays small.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
from typing import Dict, List
|
||||
|
||||
logger = logging.getLogger("bot.conversation")
|
||||
|
||||
# role we assign to user messages inside the OpenAI-style message list
|
||||
_USER_ROLE = "user"
|
||||
# role we assign to bot responses
|
||||
_ASSISTANT_ROLE = "assistant"
|
||||
|
||||
|
||||
class ConversationStore:
|
||||
"""Thread-safe-ish in-memory store keyed by Discord user ID (int)."""
|
||||
|
||||
def __init__(self, max_history: int = 7) -> None:
|
||||
self._max = max_history
|
||||
self._store: Dict[int, List[dict]] = {}
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# public API
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
def get_history(self, user_id: int) -> list[dict]:
|
||||
"""Return the last *max_history* messages for *user_id*."""
|
||||
return list(self._store.get(user_id, []))
|
||||
|
||||
def append(self, user_id: int, user_msg: str, assistant_reply: str) -> None:
|
||||
"""Store the user message + assistant reply, then trim to max."""
|
||||
if user_id not in self._store:
|
||||
self._store[user_id] = []
|
||||
|
||||
history = self._store[user_id]
|
||||
history.append({"role": _USER_ROLE, "content": user_msg})
|
||||
history.append({"role": _ASSISTANT_ROLE, "content": assistant_reply})
|
||||
|
||||
# Trim oldest messages if we exceeded the limit
|
||||
while len(history) > self._max:
|
||||
history.pop(0)
|
||||
|
||||
def clear(self, user_id: int) -> None:
|
||||
"""Wipe the conversation for a user."""
|
||||
self._store.pop(user_id, None)
|
||||
logger.info("Cleared conversation for user %s", user_id)
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# debug / introspection
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
@property
|
||||
def user_count(self) -> int:
|
||||
return len(self._store)
|
||||
Reference in New Issue
Block a user