- M.2: ForgettingCurve, MemoryDecay, MemoryReinforcement (selective forgetting) - M.3: DailyDigestGenerator, ReminderScheduler, ProactiveInformer (proactive reminders) - M.4: MemoryExtractor with LLM-based memory extraction from conversations - M.5: MemoryRecallInjector with token budget control for prompt injection - All phases include comprehensive unit tests (109 tests passing) - Updated checklist.md to mark all tasks complete
82 lines
2.6 KiB
Python
82 lines
2.6 KiB
Python
"""
|
|
MemoryDecay
|
|
|
|
Handles memory archiving, deprioritization, and restoration.
|
|
"""
|
|
|
|
from datetime import UTC, datetime
|
|
from typing import TYPE_CHECKING
|
|
|
|
if TYPE_CHECKING:
|
|
from app.models.memory import UserMemory
|
|
|
|
|
|
class MemoryDecay:
|
|
"""Handle memory archiving and deprioritization decisions."""
|
|
|
|
ARCHIVE_THRESHOLD = 0.2
|
|
DEPRIORITIZE_THRESHOLD = 0.5
|
|
|
|
def evaluate(self, memory: "UserMemory") -> dict:
|
|
"""Evaluate memory and return action recommendation.
|
|
|
|
Returns:
|
|
dict with keys: decay_score, should_archive, should_deprioritize, action
|
|
"""
|
|
from app.services.memory.forgetting_curve import ForgettingCurve
|
|
|
|
curve = ForgettingCurve()
|
|
decay_score = curve.calculate_decay(memory)
|
|
archive = decay_score < self.ARCHIVE_THRESHOLD
|
|
deprioritize = decay_score < self.DEPRIORITIZE_THRESHOLD
|
|
|
|
if archive:
|
|
action = "archive"
|
|
elif deprioritize:
|
|
action = "deprioritize"
|
|
else:
|
|
action = "keep_active"
|
|
|
|
return {
|
|
"decay_score": decay_score,
|
|
"should_archive": archive,
|
|
"should_deprioritize": deprioritize,
|
|
"action": action,
|
|
}
|
|
|
|
def archive_memory(self, memory: "UserMemory") -> "UserMemory":
|
|
"""Archive a memory (set is_archived=True, reset decay_score to low value).
|
|
|
|
Archived memories are moved to cold storage and not included in
|
|
active reminders or context injection.
|
|
"""
|
|
memory.is_archived = True
|
|
memory.decay_score = 0.1 # Very low, will be restored on access
|
|
memory.archive_at = datetime.now(UTC)
|
|
return memory
|
|
|
|
def deprioritize_memory(self, memory: "UserMemory") -> "UserMemory":
|
|
"""Mark a memory as deprioritized (excluded from active reminders).
|
|
|
|
Unlike archival, the memory is still accessible and included in
|
|
context injection if relevant.
|
|
"""
|
|
# Just update decay_score, the importance_level already encodes priority
|
|
from app.services.memory.forgetting_curve import ForgettingCurve
|
|
|
|
curve = ForgettingCurve()
|
|
memory.decay_score = curve.calculate_decay(memory)
|
|
return memory
|
|
|
|
def restore_from_archive(self, memory: "UserMemory") -> "UserMemory":
|
|
"""Restore a memory from archive.
|
|
|
|
Resets is_archived=False and decay_score=0.8 (strong retention).
|
|
The memory is moved back to hot storage.
|
|
"""
|
|
memory.is_archived = False
|
|
memory.decay_score = 0.8 # Strong retention after restore
|
|
memory.last_accessed_at = datetime.now(UTC)
|
|
memory.archive_at = None
|
|
return memory
|