""" ImpactEvaluator Evaluates the breadth of impact a memory has based on associated topics. """ from typing import TYPE_CHECKING if TYPE_CHECKING: from app.models.memory import UserMemory class ImpactEvaluator: """Evaluate the impact breadth of a memory""" # Threshold for maximum impact score IMPACT_THRESHOLD = 5 # Number of associated topics for max impact def evaluate(self, memory: "UserMemory") -> float: """Calculate impact score (0.0 - 1.0) The more associated topics a memory has, the higher its impact. Topics represent "what this memory is about" — if it touches many aspects of the user's life, it has high impact. """ associated_topics = memory.associated_topics or [] if not associated_topics: return 0.0 # Normalize: IMPACT_THRESHOLD topics = full impact (1.0) raw_score = len(associated_topics) / self.IMPACT_THRESHOLD return min(1.0, raw_score) def get_topic_overlap(self, memory_a: "UserMemory", memory_b: "UserMemory") -> float: """Calculate topic overlap between two memories (0.0 - 1.0) Used for finding related memories. """ topics_a = set(memory_a.associated_topics or []) topics_b = set(memory_b.associated_topics or []) if not topics_a or not topics_b: return 0.0 intersection = topics_a & topics_b union = topics_a | topics_b return len(intersection) / len(union) if union else 0.0 def rank_by_impact(self, memories: list["UserMemory"]) -> list["UserMemory"]: """Rank memories by impact score (descending)""" return sorted(memories, key=lambda m: self.evaluate(m), reverse=True)