humanda5
[ν…ŒμŠ€νŠΈμ€‘]μ‚¬μš©μž κ°œμž… κ΅¬ν˜„
2cd8c90
# NPC κ°„μ˜ 관계λ₯Ό 감정 μƒνƒœμ™€ μƒν˜Έμž‘μš©μ„ 기반으둜 동적 ν˜•μ„± 및 λ³€ν™”
# portfolio/npc_social_network/npc/npc_relationship.py
from typing import List, Optional, TYPE_CHECKING
from .npc_manager import get_korean_postposition
if TYPE_CHECKING:
from .npc_memory import Memory
from .npc_base import NPC
from .npc_manager import NPCManager
class SocialProfile:
"""νŠΉμ • λŒ€μƒκ³Όμ˜ μ‚¬νšŒμ  관계λ₯Ό μ’…ν•©μ μœΌλ‘œ κ΄€λ¦¬ν•˜λŠ” 클래슀"""
def __init__(self, target_name:str):
self.target_name = target_name
self.score: float = 0.0 # 관계 점수 (-100 ~ 100)
self.type: str = "stranger" # 관계 μœ ν˜• (e.g., "friend", "rival", "colleague")
self.summary: str = f"{target_name}에 λŒ€ν•΄ 아직 잘 λͺ¨λ¦…λ‹ˆλ‹€." # LLM이 μƒμ„±ν•œ 관계 μš”μ•½
self.key_memories: List["Memory"] = [] # 관계에 영ν–₯을 μ€€ 핡심 κΈ°μ–΅
class RelationshipManager:
"""SocialProfile 객체λ₯Ό μ‚¬μš©ν•˜μ—¬ λͺ¨λ“  관계λ₯Ό 관리"""
def __init__(self, owner_npc: "NPC"):
self.owner_npc = owner_npc
# 관계 사전: {μƒλŒ€λ°© 이름: SocialProfile 객체}
self.relationships: dict[str, SocialProfile] = {}
def _get_or_create_profile(self, target_name: str) -> SocialProfile:
"""λŒ€μƒμ˜ ν”„λ‘œν•„μ΄ μ—†μœΌλ©΄ μƒˆλ‘œ μƒμ„±ν•˜κ³  λ°˜ν™˜"""
if target_name not in self.relationships:
self.relationships[target_name] = SocialProfile(target_name)
return self.relationships[target_name]
def update_relationship(self, target_name: str, emotion: str, strength: float=1.0,
memory: Optional["Memory"]=None):
"""
νŠΉμ • 감정 기반으둜 관계 수치 μ‘°μ •
- 긍정/λΆ€μ •λ§Œμ΄ μ•„λ‹ˆλΌ 감정 μœ ν˜•μ— λ”°λ₯Έ 영ν–₯ 차별화
- 감정, 강도, 그리고 κ΄€λ ¨ 기얡을 λ°”νƒ•μœΌλ‘œ 관계 점수 및 ν”„λ‘œν•„ μ—…λ°μ΄νŠΈ
"""
from .emotion_config import EMOTION_RELATION_IMPACT
profile = self._get_or_create_profile(target_name)
impact = EMOTION_RELATION_IMPACT.get(emotion, 0.0)
delta = impact * strength
# 관계 점수 μ—…λ°μ΄νŠΈ 및 클리핑
profile.score = max(-100, min(100, profile.score + delta))
# 관계 μœ ν˜• μ—…λ°μ΄νŠΈ
self.update_relationship_type(profile)
# 핡심 κΈ°μ–΅ μΆ”κ°€
if memory and memory.importance >= 6:
if memory not in profile.key_memories:
profile.key_memories.append(memory)
profile.key_memories = profile.key_memories[-5:] # 졜근 5개만 μœ μ§€
target_npc = self.owner_npc.manager.get_npc_by_name(target_name)
target_korean_name = target_npc.korean_name if target_npc else target_name
print(f"[{self.owner_npc.korean_name}] '{target_korean_name}'μ™€μ˜ μƒˆλ‘œμš΄ 핡심 κΈ°μ–΅ μΆ”κ°€: {memory.content[:30]}...")
def update_relationship_type(self, profile:SocialProfile):
"""
μ μˆ˜μ— 따라 관계 μœ ν˜•μ„ μ—…λ°μ΄νŠΈ
- 관계 μœ ν˜• μ •μ˜
"""
if profile.score > 70: profile.type = "best friend"
elif profile.score > 30: profile.type = "friend"
elif profile.score > 5: profile.type = "acquaintance"
elif profile.score < -5: profile.type = "nuisance"
elif profile.score < -30: profile.type = "rival"
elif profile.score < -70: profile.type = "enemy"
else: profile.type = "stranger"
def get_relationship_score(self, target_name:str) -> float:
"""ν˜„μž¬ 관계 점수λ₯Ό λ°˜ν™˜"""
profile = self._get_or_create_profile(target_name)
return profile.score
def get_relationship_summary(self, target_name: str) -> str:
"""LLM이 μƒμ„±ν•œ 관계 μš”μ•½ λ°˜ν™˜"""
profile = self._get_or_create_profile(target_name)
return profile.summary
def set_relationship(self, target_name: str, relationship_type: str):
"""ν”Œλ ˆμ΄μ–΄ κ°œμž… λ“±μœΌλ‘œ 관계 μœ ν˜•κ³Ό 점수λ₯Ό 직접 μ„€μ •"""
from .. import simulation_core
profile = self._get_or_create_profile(target_name)
# μ„€μ •λœ νƒ€μž…μ— 따라 점수λ₯Ό λΆ€μ—¬ (κ°’ 쑰절 κ°€λŠ₯)
score_map = {
"best friend": 80.0,
"friend": 50.0,
"acquaintance": 10.0,
"stranger": 0.0,
"nuisance": -10.0,
"rival": -50.0,
"enemy": -80.0
}
profile.type = relationship_type
profile.score = score_map.get(relationship_type, 0.0)
target_npc = self.owner_npc.manager.get_npc_by_korean_name(target_name)
target_korean_name = target_npc.korean_name if target_npc else target_name
self_postposition = get_korean_postposition(self.owner_npc.korean_name, "은", "λŠ”")
target_postposition = get_korean_postposition(target_korean_name, "κ³Ό", "와")
# 관계 μš”μ•½λ„ κ°„λ‹¨ν•˜κ²Œ μ—…λ°μ΄νŠΈ
profile.summary = f"{target_korean_name}{target_postposition} {self.owner_npc.korean_name}{self_postposition} {relationship_type} 관계이닀."
simulation_core.add_log(f"[관계 μ„€μ •] {self.owner_npc.korean_name} -> {target_korean_name} 관계가 '{relationship_type}'(으)둜 μ„€μ •λ˜μ—ˆμŠ΅λ‹ˆλ‹€.")
def summarize_relationship(self, target_name: str, npc_manager: "NPCManager"):
""" LLM을 μ‚¬μš©ν•˜μ—¬ νŠΉμ • λŒ€μƒκ³Όμ˜ 관계λ₯Ό 주기적으둜 μš”μ•½ν•˜κ³  μ—…λ°μ΄νŠΈ"""
from ..models.llm_helper import query_llm_with_prompt
from .. import simulation_core
profile = self._get_or_create_profile(target_name)
if not profile.key_memories:
return # μš”μ•½ν•  기얡이 μ—†μœΌλ©΄ μ‹€ν–‰ μ•ˆν•¨
target_npc = npc_manager.get_npc_by_name(target_name)
target_korean_name = target_npc.korean_name if target_npc else target_name
memory_details = "\n".join([f"- {mem.content} (감정: {mem.emotion})" for mem in profile.key_memories])
prompt = f"""
# μ§€μ‹œμ‚¬ν•­
λ‚˜μ€ '{self.owner_npc.korean_name}'μž…λ‹ˆλ‹€. λ‚˜μ˜ 기얡을 λ°”νƒ•μœΌλ‘œ '{target_korean_name}'에 λŒ€ν•œ λ‚˜μ˜ 생각과 감정을 ν•œλ‘ λ¬Έμž₯으둜 μ†”μ§ν•˜κ²Œ μš”μ•½ν•΄μ£Όμ„Έμš”.
# '{target_korean_name}'와(κ³Ό)의 핡심 κΈ°μ–΅λ“€
{memory_details}
β†’ '{target_korean_name}'에 λŒ€ν•œ {self.owner_npc.korean_name}의 생각:
"""
summary = query_llm_with_prompt(prompt).replace("'", "").strip()
if summary and "[LLM Error]" not in summary:
profile.summary = summary
simulation_core.add_log(f"[{self.owner_npc.korean_name}의 관계 μš”μ•½ μ—…λ°μ΄νŠΈ] {profile.summary}")