- 비전 및 철학: 존재형 AI 에이전트 개념 - 윤리 원칙과 안전 기준 - 사용자 시나리오 및 유즈케이스 - 게임화 요소 (레벨업, 스탯, 스킬) - 기술 아키텍처 (기억 시스템, 감정 모델, DB 설계) - 멀티 에이전트 협업 구조 - DID 기반 신원 체계 - 장기 로드맵 (1년, 3년 비전)
14 KiB
14 KiB
감정 임베딩 설계와 벡터 공간 정의
감정 벡터 공간 아키텍처
다차원 감정 모델
import numpy as np
from dataclasses import dataclass
@dataclass
class EmotionSpace:
"""Russell의 Circumplex Model + Plutchik의 감정 바퀴 통합"""
# 기본 차원 (3D)
valence: float # -1 (부정) to +1 (긍정)
arousal: float # 0 (차분) to 1 (흥분)
dominance: float # 0 (순종) to 1 (지배)
# 확장 차원 (추가 5D)
anticipation: float # 0 to 1 (기대감)
trust: float # 0 to 1 (신뢰)
surprise: float # 0 to 1 (놀람)
social_connection: float # -1 (고립) to +1 (연결)
certainty: float # 0 (불확실) to 1 (확신)
def to_vector(self):
"""8차원 감정 벡터 생성"""
return np.array([
self.valence, self.arousal, self.dominance,
self.anticipation, self.trust, self.surprise,
self.social_connection, self.certainty
])
기본 감정 임베딩
class BasicEmotionEmbeddings:
"""Ekman의 6가지 기본 감정 + 확장"""
EMOTIONS = {
'joy': {
'vector': [0.9, 0.7, 0.7, 0.6, 0.8, 0.1, 0.8, 0.8],
'color': '#FFD700', # Gold
'intensity_range': (0.3, 1.0)
},
'sadness': {
'vector': [-0.8, 0.2, 0.2, 0.1, 0.3, 0.0, -0.3, 0.4],
'color': '#4169E1', # Royal Blue
'intensity_range': (0.2, 0.9)
},
'anger': {
'vector': [-0.7, 0.9, 0.8, 0.2, 0.1, 0.2, -0.2, 0.7],
'color': '#DC143C', # Crimson
'intensity_range': (0.3, 1.0)
},
'fear': {
'vector': [-0.8, 0.8, 0.1, 0.7, 0.1, 0.7, -0.1, 0.1],
'color': '#8B008B', # Dark Magenta
'intensity_range': (0.4, 1.0)
},
'disgust': {
'vector': [-0.9, 0.5, 0.6, 0.0, 0.0, 0.3, -0.4, 0.8],
'color': '#556B2F', # Dark Olive Green
'intensity_range': (0.3, 0.9)
},
'surprise': {
'vector': [0.1, 0.8, 0.3, 0.1, 0.4, 1.0, 0.2, 0.0],
'color': '#FF69B4', # Hot Pink
'intensity_range': (0.5, 1.0)
},
'anticipation': {
'vector': [0.3, 0.6, 0.5, 1.0, 0.5, 0.4, 0.4, 0.3],
'color': '#FFA500', # Orange
'intensity_range': (0.2, 0.8)
},
'trust': {
'vector': [0.7, 0.3, 0.4, 0.3, 1.0, 0.0, 0.9, 0.9],
'color': '#32CD32', # Lime Green
'intensity_range': (0.1, 1.0)
}
}
def get_embedding(self, emotion_name, intensity=0.5):
"""감정 이름과 강도로 임베딩 벡터 생성"""
if emotion_name not in self.EMOTIONS:
return None
base_vector = np.array(self.EMOTIONS[emotion_name]['vector'])
min_int, max_int = self.EMOTIONS[emotion_name]['intensity_range']
# 강도 조정
adjusted_intensity = min_int + (max_int - min_int) * intensity
return base_vector * adjusted_intensity
복합 감정 모델링
감정 블렌딩 알고리즘
class EmotionBlending:
def __init__(self):
self.basic_emotions = BasicEmotionEmbeddings()
def blend_emotions(self, emotion_mix):
"""
여러 감정을 혼합하여 복합 감정 생성
emotion_mix: {'joy': 0.6, 'surprise': 0.4}
"""
blended_vector = np.zeros(8)
total_weight = sum(emotion_mix.values())
for emotion, weight in emotion_mix.items():
emotion_vector = self.basic_emotions.get_embedding(emotion, weight)
if emotion_vector is not None:
blended_vector += emotion_vector * (weight / total_weight)
# 정규화
return self.normalize_vector(blended_vector)
def create_complex_emotions(self):
"""복합 감정 정의"""
complex_emotions = {
'nostalgia': self.blend_emotions({'joy': 0.4, 'sadness': 0.6}),
'bittersweetness': self.blend_emotions({'joy': 0.5, 'sadness': 0.5}),
'anxiety': self.blend_emotions({'fear': 0.7, 'anticipation': 0.3}),
'contempt': self.blend_emotions({'disgust': 0.6, 'anger': 0.4}),
'awe': self.blend_emotions({'surprise': 0.5, 'fear': 0.2, 'joy': 0.3}),
'guilt': self.blend_emotions({'sadness': 0.5, 'fear': 0.3, 'disgust': 0.2}),
'pride': self.blend_emotions({'joy': 0.7, 'dominance': 0.3}),
'shame': self.blend_emotions({'sadness': 0.4, 'fear': 0.3, 'disgust': 0.3})
}
return complex_emotions
def normalize_vector(self, vector):
"""벡터 정규화"""
norm = np.linalg.norm(vector)
if norm == 0:
return vector
return vector / norm
시간적 감정 역학
감정 전이 모델
class EmotionDynamics:
def __init__(self):
self.emotion_history = []
self.transition_matrix = self.build_transition_matrix()
def build_transition_matrix(self):
"""감정 간 전이 확률 매트릭스"""
# 8x8 매트릭스 (8개 기본 감정)
# 행: 현재 감정, 열: 다음 감정
transitions = np.array([
# joy → [joy, sad, anger, fear, disgust, surprise, anticipation, trust]
[0.6, 0.1, 0.05, 0.05, 0.02, 0.08, 0.1, 0.1],
# sadness → ...
[0.15, 0.5, 0.1, 0.1, 0.05, 0.02, 0.03, 0.05],
# ... 나머지 감정들
])
return transitions
def predict_next_emotion(self, current_emotion, context_modifier=None):
"""현재 감정에서 다음 감정 예측"""
current_idx = self.emotion_to_index(current_emotion)
transition_probs = self.transition_matrix[current_idx]
if context_modifier:
# 컨텍스트에 따른 확률 조정
transition_probs = self.apply_context(transition_probs, context_modifier)
next_emotion_idx = np.random.choice(8, p=transition_probs)
return self.index_to_emotion(next_emotion_idx)
def emotion_trajectory(self, initial_emotion, steps=10):
"""감정 변화 궤적 시뮬레이션"""
trajectory = [initial_emotion]
current = initial_emotion
for _ in range(steps):
current = self.predict_next_emotion(current)
trajectory.append(current)
return trajectory
감정 반감기와 지속성
class EmotionPersistence:
def __init__(self):
# 각 감정의 반감기 (초 단위)
self.half_lives = {
'surprise': 30, # 빠르게 사라짐
'anger': 300, # 5분
'fear': 600, # 10분
'joy': 1800, # 30분
'sadness': 3600, # 1시간
'disgust': 1200, # 20분
'anticipation': 900, # 15분
'trust': 7200 # 2시간
}
def decay_function(self, emotion, time_elapsed):
"""지수 감쇠 함수"""
half_life = self.half_lives.get(emotion, 1800)
decay_rate = np.log(2) / half_life
intensity = np.exp(-decay_rate * time_elapsed)
return intensity
def emotional_residue(self, past_emotions, current_time):
"""과거 감정의 현재 영향"""
residue = np.zeros(8)
for emotion_event in past_emotions:
time_diff = current_time - emotion_event['timestamp']
intensity = self.decay_function(
emotion_event['emotion'],
time_diff
)
if intensity > 0.01: # 1% 이상만 고려
emotion_vector = emotion_event['vector']
residue += emotion_vector * intensity
return residue
감정-인지 상호작용
감정이 의사결정에 미치는 영향
class EmotionCognitionInterface:
def __init__(self):
self.emotion_weights = {
'risk_assessment': {
'fear': -0.8, # 위험 회피
'anger': 0.3, # 위험 감수
'joy': 0.2, # 낙관적 평가
'anticipation': 0.4 # 기회 추구
},
'creativity': {
'joy': 0.7,
'surprise': 0.6,
'sadness': 0.3, # 성찰적 창의성
'anger': -0.2
},
'attention_focus': {
'fear': 0.9, # 높은 집중
'anger': 0.7,
'joy': -0.1, # 분산된 주의
'sadness': 0.4 # 세부사항 집중
}
}
def modulate_decision(self, base_decision, emotional_state):
"""감정 상태에 따른 의사결정 조정"""
modulated = base_decision.copy()
for cognitive_function, emotion_effects in self.emotion_weights.items():
for emotion, weight in emotion_effects.items():
emotion_intensity = emotional_state.get(emotion, 0)
modulated[cognitive_function] *= (1 + weight * emotion_intensity)
return modulated
def emotional_bias_correction(self, decision, emotion_intensity):
"""감정 편향 보정"""
if emotion_intensity > 0.7:
# 강한 감정 상태에서는 합리성 체크 강화
return self.apply_rationality_filter(decision)
return decision
감정 임베딩 학습
자기지도 학습 모델
class EmotionEmbeddingLearning:
def __init__(self, embedding_dim=128):
self.embedding_dim = embedding_dim
self.emotion_encoder = self.build_encoder()
def build_encoder(self):
"""감정 인코더 네트워크"""
import tensorflow as tf
model = tf.keras.Sequential([
tf.keras.layers.Input(shape=(8,)), # 8D 기본 감정 벡터
tf.keras.layers.Dense(64, activation='relu'),
tf.keras.layers.Dense(128, activation='relu'),
tf.keras.layers.Dense(self.embedding_dim, activation='tanh'),
tf.keras.layers.Lambda(lambda x: tf.nn.l2_normalize(x, axis=1))
])
return model
def contrastive_learning(self, anchor, positive, negative):
"""대조 학습으로 감정 임베딩 개선"""
anchor_emb = self.emotion_encoder(anchor)
positive_emb = self.emotion_encoder(positive)
negative_emb = self.emotion_encoder(negative)
# Triplet loss
pos_dist = tf.reduce_sum(tf.square(anchor_emb - positive_emb), axis=1)
neg_dist = tf.reduce_sum(tf.square(anchor_emb - negative_emb), axis=1)
loss = tf.maximum(pos_dist - neg_dist + 0.2, 0)
return tf.reduce_mean(loss)
감정 시각화
감정 공간 매핑
class EmotionVisualization:
def __init__(self):
self.color_map = self.create_color_map()
def create_color_map(self):
"""감정을 색상으로 매핑"""
return {
'valence': {
'positive': '#FFD700', # 황금색
'negative': '#4B0082' # 인디고
},
'arousal': {
'high': '#FF0000', # 빨강
'low': '#0000FF' # 파랑
}
}
def emotion_to_color(self, emotion_vector):
"""감정 벡터를 RGB 색상으로 변환"""
valence = emotion_vector[0] # -1 to 1
arousal = emotion_vector[1] # 0 to 1
dominance = emotion_vector[2] # 0 to 1
# RGB 매핑
r = int(128 + valence * 127) # Valence → Red
g = int(arousal * 255) # Arousal → Green
b = int(dominance * 255) # Dominance → Blue
return f'#{r:02x}{g:02x}{b:02x}'
def plot_emotion_trajectory(self, emotion_sequence):
"""감정 변화를 2D/3D 공간에 플로팅"""
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
fig = plt.figure(figsize=(12, 5))
# 2D plot (Valence-Arousal)
ax1 = fig.add_subplot(121)
valences = [e[0] for e in emotion_sequence]
arousals = [e[1] for e in emotion_sequence]
ax1.plot(valences, arousals, 'o-', markersize=8)
ax1.set_xlabel('Valence')
ax1.set_ylabel('Arousal')
ax1.set_title('Emotion Trajectory (2D)')
ax1.grid(True, alpha=0.3)
# 3D plot (Valence-Arousal-Dominance)
ax2 = fig.add_subplot(122, projection='3d')
dominances = [e[2] for e in emotion_sequence]
ax2.plot(valences, arousals, dominances, 'o-', markersize=8)
ax2.set_xlabel('Valence')
ax2.set_ylabel('Arousal')
ax2.set_zlabel('Dominance')
ax2.set_title('Emotion Trajectory (3D)')
plt.tight_layout()
return fig
감정 메트릭
감정 다양성과 안정성 측정
class EmotionMetrics:
def emotional_entropy(self, emotion_distribution):
"""감정 분포의 엔트로피 (다양성 측정)"""
probs = np.array(list(emotion_distribution.values()))
probs = probs / probs.sum()
entropy = -np.sum(probs * np.log(probs + 1e-10))
return entropy
def emotional_stability(self, emotion_history):
"""감정 안정성 지수"""
if len(emotion_history) < 2:
return 1.0
changes = []
for i in range(1, len(emotion_history)):
prev = emotion_history[i-1]
curr = emotion_history[i]
distance = np.linalg.norm(prev - curr)
changes.append(distance)
# 변화량의 표준편차 (낮을수록 안정적)
stability = 1 / (1 + np.std(changes))
return stability
def emotional_valence_bias(self, emotion_history):
"""긍정/부정 편향 측정"""
valences = [e[0] for e in emotion_history]
mean_valence = np.mean(valences)
if mean_valence > 0.2:
return 'positive_bias', mean_valence
elif mean_valence < -0.2:
return 'negative_bias', mean_valence
else:
return 'neutral', mean_valence