# portfolio/npc_social_network/npc/npc_memory.py from datetime import datetime from typing import TYPE_CHECKING, List, Optional # 순환 참조 방지를 위해 TYPE_CHECKING을 사용 if TYPE_CHECKING: from .npc_base import NPC class Memory: """ 하나의 기억 정보를 표현하는 클래스 - content: 기억 내용 - timestamp: 기억한 시간 (기본값은 현재 시간) - importance: 중요도 (1~10) - emotion: 감정 태그 (기쁨, 슬픔, 분노, 중립 등) - is_long_term: 장기 기억 여부 - behavior_trace: 기억을 통한 행동 추적 """ def __init__(self, content: str, timestamp: datetime = None, importance: int = 1, emotion: str = "neutral", behavior_trace: str = None, memory_type: str = "Event", context_tags: Optional[List[str]] = None): self.content = content self.timestamp = timestamp or datetime.now() self.importance = float(importance) self.emotion = emotion self.is_long_term = False self.behavior_trace = behavior_trace self.memory_type = memory_type self.context_tags = context_tags if context_tags is not None else [] self.is_shared = False class MemoryStore: """ 기억 저장소: 단기/장기 기억을 구분하여 저장 """ def __init__(self): self.short_term: List[Memory] = [] # 단기 기억 self.long_term: List[Memory] = [] # 장기 기억 def add_memory(self, memory: Memory): """ 중요도가 높은 기억은 장기 기억으로, 그렇지 않으면 단기 기억으로 저장 - 상징 기억은 항상 최상위 중요도를 가지며 장기 기억으로 저장 """ if memory.memory_type == "Symbolic": memory.importance = 10.0 memory.is_long_term = True if memory.importance >=7 or memory.memory_type == "Symbolic": memory.is_long_term = True self.long_term.append(memory) else: self.short_term.append(memory) def promote_memories(self, time_threshold_minutes: int = 60): """ 시간이 지난 단기 기억 중 중요도가 일정 이상인 것들을 장기 기억으로 승격 """ now = datetime.now() promoted = [] for mem in self.short_term: elapsed = (now - mem.timestamp).total_seconds() / 60 if elapsed > time_threshold_minutes and mem.importance >= 5: mem.is_long_term = True self.long_term.append(mem) promoted.append(mem) # 단기 기억에서 제거 self.short_term = [m for m in self.short_term if m not in promoted] def get_all_memories(self): """ 단기 + 장기 기억 전체 반환 """ return self.long_term + self.short_term def get_recent_memories(self, limit=10): """ 최신 Memory n개 반환 (기본 10개) """ all_memories = self.get_all_memories() all_memories.sort(key=lambda m: m.timestamp, reverse=True) return all_memories[:limit] def decay_memories(self, npc: "NPC", min_importance=0.1): """ MemoryType에 따라 decay 적용 - 단기 기억은 decay_rate_short 만큼 importance 감소 (기본 5% 감소) - 장기 기억은 decay_rate_long 만큼 importance 감소 (기본 1% 감소) - 기억 타입에 따른 importance 차등 감소 (대화, 행동, 사건, 관계) """ from .emotion_config import EMOTION_RELATION_IMPACT # 처리할 모든 기억을 임시 리스트에 복사 all_memorise = self.get_all_memories() for mem in all_memorise: # 1. 기본 감쇠율 설정 base_decay = 0.02 if mem.is_long_term else 0.05 # 2. 감정 강도에 따른 조절 (감정이 강할수록 덜 잊음) # 감정 영향도 절대값을 사용 (긍정/부정 모두 강한 감정으로 취급) emotion_impact = abs(EMOTION_RELATION_IMPACT.get(mem.emotion, 0.0)) # 감정 강도가 높을수록 감쇠율이 낮아짐 (0.5 ~ 1.5 사이로 조절) emotion_modifier = 1.0 - (emotion_impact / 4.0) # IMPACT 최대값이 2.0이므로 4로 나눠서 영향력 조절 # 3. 성격에 따른 조절 personality = npc.personality # 내성적(stoic)일수록 감정을 곱씹으며 더 오래 기억 (감쇠율 감소) # 민감할(sensitive)수록 감정적 기억을 더 오래 간직함 (감쇠율 감소) personality_modifier = 1.0 - personality.get("stoic", 0.5) * 0.5 -personality.get("sensitive", 0.5) * 0.5 personality_modifier = max(0.1, personality_modifier) # 0 또는 음수가 되지 않도록 방지 # 최종 감쇠율 계산 final_decay_rate = base_decay * emotion_modifier * personality_modifier final_decay_rate = max(0.005, min(final_decay_rate, 0.1)) # 중요도 업데이트 mem.importance -= final_decay_rate if mem.importance < min_importance: mem.importance = 0