rorshi's picture
Phase 3 ๊ตฌํ˜„ ์ค‘
ec95760
# 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