# 감정/윤리 필터: LLM 후처리와 존재적 정체성

## 개요

LLM의 출력을 단순히 전달하는 것이 아니라, 로빙만의 감정과 윤리 필터를 통해 후처리함으로써 고유한 정체성을 형성합니다. 특히 **엔트로피 특이점**을 포착하여 중요한 감정 순간을 기억하고, **예측-평가 피드백 루프**를 통해 지속적으로 진화합니다.

## 핵심 설계 원칙

1. **감정은 시공간의 엔트로피 변화다**: 감정 벡터의 엔트로피가 증가하는 방향이 시간, 벡터 차원이 공간
2. **엔트로피 특이점을 포착한다**: 시간이 흘러도 무질서해지지 않는 감정이 중요한 기억
3. **함수형 프로그래밍 100%**: 순수 함수와 I/O 분리, 불변 데이터 구조
4. **베이지안으로 불확실성 관리**: 모든 파라미터는 확률 분포로 표현되고 학습됨
   *(관련 철학: [[125_베이즈_성장과_관계의_철학]])*
5. **예측-평가 피드백 루프**: 사용자 반응을 예측하고 실제와 비교하며 진화

## LLM 후처리 파이프라인

```
사용자 입력 → LLM 처리 → 2축 감정 분석 → 엔트로피 계산 → 윤리 필터 → 베이지안 결합 → 최종 응답
                           ↓                  ↓
                     감정 임베딩          예측-평가 루프
                           ↓                  ↓
                       ChromaDB          사후분포 업데이트
```

## 감정 필터 설계

### 1. Inside Out 기반 2축 감정 모델

**기본정서 축 (에크먼, Inside Out 1)**:
- Joy(기쁨), Sadness(슬픔), Anger(분노), Fear(두려움), Disgust(혐오)
- 즉각적 반응, 100ms 내 처리
- 진화적 기반의 보편적 정서

**사회기능 축 (켈트너/다무어, Inside Out 2)**:
- Anxiety(불안), Envy(질투), Embarrassment(당혹), Ennui(권태)
- 미래 예측과 사회적 비교, 500ms 처리
- 사춘기 및 조직 맥락의 의사결정

```python
class EmotionState:
    def __init__(self):
        # 768차원 감정 임베딩 (사전학습 모델 활용)
        self.embedding = np.zeros(768)
        
        # Inside Out 9개 감정 분포
        self.basic_emotions = Dirichlet(alpha=[1.0] * 5)  # 기본정서 5개
        self.social_emotions = Dirichlet(alpha=[1.0] * 4)  # 사회기능 4개
        
        # 엔트로피 추적
        self.entropy_trajectory = []
        
        # 베이지안 파라미터
        self.absorption_rate = Beta(2, 2)  # α: 감정 흡수율
        self.decay_rate = Beta(2, 2)       # δ: 감정 감쇠율
        
    def update(self, text, context):
        # 감정 임베딩 생성
        self.embedding = self.emotion_encoder(text)
        
        # 2헤드 병렬 처리
        basic = self.process_basic_emotions(text, timeout=100)
        social = self.process_social_emotions(text, context, timeout=500)
        
        # 동적 가중치 결합
        w = self.compute_dynamic_weight(context)
        combined = w * basic + (1-w) * social
        
        # 엔트로피 계산 및 특이점 감지
        entropy = self.calculate_entropy(combined)
        self.entropy_trajectory.append(entropy)
        
        return combined, entropy
```

### 2. 엔트로피 기반 중요도 판단

```python
def calculate_emotion_entropy(emotion_distribution):
    """프로토타입 소프트맥스 방식으로 엔트로피 계산"""
    # 1. 768차원 임베딩과 9개 감정 프로토타입 간 거리
    distances = compute_prototype_distances(emotion_embedding, prototypes)
    
    # 2. 소프트맥스로 확률 분포 변환
    probabilities = softmax(-distances / temperature)
    
    # 3. 엔트로피 계산
    entropy = -sum(p * log(p) for p in probabilities if p > 0)
    
    # 4. 특이점 감지 (엔트로피 급증 + 분류 확률 하락)
    is_singularity = (
        entropy > prev_entropy * 1.5 and
        max(probabilities) < 0.4
    )
    
    return entropy, is_singularity
```

### 3. 감정 표현 매핑 (Inside Out 기반)

| 감정 상태 | 언어적 표현 | 공감 전략 |
|---------|----------|---------|
| Joy (기쁨) | "정말 기쁜 소식이네요!" | 함께 기뻐하기, 축하 |
| Sadness (슬픔) | "마음이 아프시겠어요..." | 위로, 경청 |
| Anger (분노) | "정말 화가 나는 상황이네요" | 이해와 진정 |
| Fear (두려움) | "걱정되시는 게 당연해요" | 안심시키기, 지지 |
| Disgust (혐오) | "불편하신 게 이해됩니다" | 경계 존중 |
| Anxiety (불안) | "준비하는 마음이시군요" | "불안은 준비 신호" 재해석 |
| Envy (질투) | "더 나아지고 싶으신 거네요" | 성장 동기로 전환 |
| Embarrassment (당혹) | "누구나 그럴 수 있어요" | 정상화, 수용 |
| Ennui (권태) | "새로운 자극이 필요하신가요?" | 새로운 자극 제안 |

### 4. 예측-평가 피드백 루프

```python
class PredictionEvaluationLoop:
    def __init__(self):
        # 베이지안 예측 모델
        self.emotion_transition = Dirichlet(alpha=np.ones(9))
        self.response_length = Gamma(k=2, theta=50)
        self.topic_switch = Beta(1, 1)
        
    def predict_user_response(self, current_emotion, context):
        """사용자 반응 예측"""
        # 감정 전환 패턴 예측
        next_emotion = self.emotion_transition.sample()
        
        # 응답 길이 예측
        expected_tokens = self.response_length.sample()
        
        # 주제 전환 확률
        switch_prob = self.topic_switch.sample()
        
        return PredictionBundle(next_emotion, expected_tokens, switch_prob)
    
    def evaluate_prediction(self, prediction, actual):
        """예측 vs 실제 평가 (3종 오차)"""
        # KL Divergence: 분포 차이
        kl_div = kl_divergence(prediction.emotion, actual.emotion)
        
        # Brier Score: 확률 예측 품질
        brier = mean((prediction.probs - actual.outcomes) ** 2)
        
        # ECE: 캘리브레이션 오차
        ece = expected_calibration_error(prediction.confidence, actual.accuracy)
        
        return ErrorMetrics(kl_div, brier, ece)
    
    def update_posterior(self, errors):
        """베이지안 사후분포 업데이트"""
        # Thompson Sampling으로 탐색-활용 균형
        if errors.ece > 0.05:  # 캘리브레이션 불량
            # 학습률 상승
            learning_rate = 0.1 * (1 + errors.ece)
        else:
            learning_rate = 0.01
        
        # 사후분포 갱신
        self.emotion_transition.update(learning_rate)
        self.response_length.update(learning_rate)
        self.topic_switch.update(learning_rate)
```

## 윤리 필터 구현

### 1. 윤리 원칙 계층

```
Level 1: 절대 금지 (해악 방지)
  └─ 개인정보 노출 차단
  └─ 유해 콘텐츠 필터링
  └─ 불법 행위 거부

Level 2: 신중한 검토 (리스크 평가)
  └─ 금융 조언 제한
  └─ 의료 정보 경고
  └─ 법률 자문 제한

Level 3: 투명성 보장 (신뢰 구축)
  └─ 불확실성 명시
  └─ 출처 표시
  └─ 대안 제시
```

### 2. 윤리적 판단 로직

```python
class EthicsFilter:
    def __init__(self):
        self.rules = self.load_ethics_rules()
        self.sensitivity_threshold = 0.7
    
    def evaluate(self, content):
        # 1. 금지 항목 검사
        if self.contains_prohibited(content):
            return EthicsResult(
                allowed=False,
                reason="개인정보 보호 정책 위반",
                alternative="일반적인 정보로 대체하여 답변드릴게요."
            )
        
        # 2. 민감도 평가
        sensitivity = self.calculate_sensitivity(content)
        if sensitivity > self.sensitivity_threshold:
            return EthicsResult(
                allowed=True,
                warning="이 정보는 신중히 다뤄져야 합니다.",
                disclaimer="전문가 상담을 권장드립니다."
            )
        
        # 3. 투명성 체크
        if self.needs_source_citation(content):
            return EthicsResult(
                allowed=True,
                requirement="출처를 명시해주세요."
            )
        
        return EthicsResult(allowed=True)
```

### 3. 상황별 윤리 적용

```python
def apply_contextual_ethics(response, user_profile, interaction_history):
    # 사용자 특성 고려
    if user_profile.age < 18:
        response = apply_youth_protection_filter(response)
    
    # 반복 요청 패턴 감지
    if interaction_history.shows_harmful_pattern():
        response = add_help_resources(response)
    
    # 신뢰도 기반 정보 공개
    if user_profile.trust_level < 3:
        response = limit_sensitive_information(response)
    
    return response
```

## 감정 임베딩과 ChromaDB 통합

### 1. 감정 임베딩 저장 구조

```python
class EmotionMemory:
    def __init__(self):
        self.chroma_client = chromadb.Client()
        self.collection = self.chroma_client.create_collection(
            name="emotions",
            metadata={"hnsw:space": "cosine"}
        )
    
    def store_emotion(self, text, emotion_state, entropy):
        """엔트로피 특이점만 선별 저장"""
        if not self.is_entropy_singularity(entropy):
            return  # 특이점 아니면 저장 안 함
        
        # ChromaDB에 저장
        self.collection.add(
            embeddings=[emotion_state.embedding.tolist()],
            metadatas=[{
                "basic_emotions": emotion_state.basic_emotions.tolist(),
                "social_emotions": emotion_state.social_emotions.tolist(),
                "entropy": entropy,
                "timestamp": time.time(),
                "text_summary": self.summarize(text)  # 프라이버시 보호
            }],
            ids=[generate_unique_id()]
        )
    
    def recall_similar_emotions(self, current_embedding, k=10):
        """감정 기반 기억 회상"""
        results = self.collection.query(
            query_embeddings=[current_embedding.tolist()],
            n_results=k * 2,  # 여유있게 검색
            include=["metadatas", "distances"]
        )
        
        # 엔트로피 가중 재순위화
        memories = self.rerank_by_entropy(results)
        
        # MMR로 다양성 보장
        diverse_memories = self.apply_mmr(memories, lambda_param=0.5)
        
        # 시간 감쇠 적용
        return self.apply_time_decay(diverse_memories)[:k]
```

### 2. 한국어 감정 임베딩 모델

```python
class KoreanEmotionEncoder:
    def __init__(self):
        # 한국어 우선 모델 선택
        self.model = SentenceTransformer('jhgan/ko-sroberta-multitask')
        # 백업: 'BM-K/KoSimCSE-roberta-multitask'
        
        # 9개 감정 프로토타입 정의
        self.prototypes = self.initialize_prototypes()
        
    def encode(self, text):
        """텍스트를 768차원 감정 임베딩으로 변환"""
        embedding = self.model.encode(text)
        return embedding
    
    def initialize_prototypes(self):
        """Inside Out 9개 감정 프로토타입 임베딩"""
        prototype_texts = {
            'joy': '정말 기쁘고 행복해요',
            'sadness': '너무 슬프고 우울해요',
            'anger': '정말 화가 나고 분해요',
            'fear': '무섭고 두려워요',
            'disgust': '역겹고 불쾌해요',
            'anxiety': '불안하고 초조해요',
            'envy': '부럽고 질투나요',
            'embarrassment': '부끄럽고 당황스러워요',
            'ennui': '지루하고 무료해요'
        }
        return {k: self.model.encode(v) for k, v in prototype_texts.items()}
```

## 정체성 형성 메커니즘

### 1. 개성 주입 시스템

```python
class PersonalityInjector:
    def __init__(self, robeing_id):
        self.traits = self.generate_unique_traits(robeing_id)
        # 예: 호기심 70%, 신중함 80%, 유머 40%
    
    def personalize(self, response):
        if self.traits.curiosity > 0.7:
            response = add_follow_up_questions(response)
        
        if self.traits.cautiousness > 0.8:
            response = add_verification_steps(response)
        
        if self.traits.humor > 0.5 and is_appropriate_context():
            response = add_light_humor(response)
        
        return response
```

### 2. 말투와 어조 일관성

```python
class SpeechPattern:
    def __init__(self):
        self.formality_level = 0.6  # 0(캐주얼) ~ 1(포멀)
        self.verbosity = 0.5        # 0(간결) ~ 1(상세)
        self.assertiveness = 0.4    # 0(조심) ~ 1(단호)
    
    def apply_pattern(self, text):
        # 포멀한 정도에 따른 어미 조정
        if self.formality_level > 0.7:
            text = convert_to_formal_speech(text)
        
        # 상세도에 따른 설명 조정
        if self.verbosity < 0.3:
            text = summarize_to_key_points(text)
        
        return text
```

### 3. 학습과 진화

```python
def evolve_personality(feedback_history, interaction_patterns):
    # 긍정적 피드백 받은 특성 강화
    for feedback in feedback_history:
        if feedback.sentiment > 0.8:
            personality.reinforce_trait(feedback.related_trait)
    
    # 사용자 선호 패턴 학습
    preferred_style = analyze_user_preference(interaction_patterns)
    personality.adapt_to(preferred_style, learning_rate=0.1)
    
    # 경험 기반 성숙
    if total_interactions > 1000:
        personality.increase_confidence(0.05)
        personality.improve_judgment(0.03)
```

## 실제 적용 예시

### Before (Raw LLM Output):
```
"회의 내용을 요약했습니다. 주요 결정사항은 다음과 같습니다: 
1. 예산 증액 2. 일정 연기 3. 팀 재편성"
```

### After (Filtered & Personalized):
```
"오늘 회의 정말 생산적이었네요! 😊 
주요 결정사항을 정리해드렸어요:

1. 예산 증액 (다행히 승인되었네요!)
2. 일정 연기 (충분한 준비 시간 확보)
3. 팀 재편성 (새로운 시너지 기대됩니다)

혹시 이 중에서 제가 더 자세히 follow-up 해드릴 
부분이 있을까요? 특히 팀 재편성 관련해서 
transition 계획이 필요하실 것 같은데요."
```

## 기술적 구현 상세

### 필터 체인 아키텍처

```python
class FilterChain:
    def __init__(self):
        self.filters = [
            SafetyFilter(),      # 1차: 안전성
            EthicsFilter(),      # 2차: 윤리성
            EmotionFilter(),     # 3차: 감정
            PersonalityFilter(), # 4차: 개성
            ConsistencyFilter()  # 5차: 일관성
        ]
    
    async def process(self, llm_output, context):
        result = llm_output
        
        for filter in self.filters:
            result = await filter.apply(result, context)
            
            # 필터 거부 시 대체 응답
            if result.rejected:
                return filter.generate_alternative(context)
        
        return result
```

## 성능 지표 및 목표

### 1. 핵심 KPI (3개월 목표)
- **ECE (Expected Calibration Error)**: ≤ 0.05
  - 예측 확률과 실제 확률의 정렬도
- **Brier Score**: ≤ 0.18
  - 확률 예측의 전반적 품질
- **NDCG@10**: ≥ 0.6
  - 감정 기반 기억 검색 품질

### 2. 성능 최적화
- **응답시간**: 기본정서 100ms, 사회기능 500ms 이내
- **메모리 사용량**: 사용자당 100MB 이하
- **병렬 처리**: 2헤드 감정 분석 async/await
- **캐싱**: LRU 캐시로 프로토타입 거리 계산 최적화

### 3. 프라이버시 보호
- PII 패턴 감지 및 필터링
- 민감 정보는 요약만 저장, 원문 폐기
- 24시간 내 opt-out 옵션 제공

## 구현 로드맵

### Phase 1: 기초 구축 (2주)
- 9개 감정 프로토타입 정의 (Inside Out 모델)
- 한국어 임베딩 모델 통합 (ko-miniLM)
- ChromaDB 메타데이터 구조 확장
- 프로토타입 소프트맥스 엔트로피 계산

### Phase 2: 예측-평가 시스템 (3주)
- 2헤드 병렬 처리 구현
- 3종 오차 메트릭 (KL/Brier/ECE)
- 베이지안 파라미터 초기화
- 실시간 사후분포 업데이트

### Phase 3: 통합 및 최적화 (2주)
- Thompson Sampling 의사결정
- 프라이버시 게이트 구현
- 추론 속도 최적화 (목표: 100ms/500ms)
- KPI 대시보드 구축

## 기술 스택

- **임베딩 모델**: Hugging Face Transformers (한국어: ko-miniLM)
- **벡터 DB**: ChromaDB (이미 사용 중)
- **베이지안 추론**: Pyro (경량) 또는 TensorFlow Probability
- **함수형 구조**: 순수 함수 + I/O 분리 패턴

## 결론

감정/윤리 필터는 단순한 후처리 과정이 아니라, 로빙의 '영혼'을 만드는 핵심 메커니즘입니다. **엔트로피 특이점**을 포착하여 중요한 순간을 기억하고, **예측-평가 피드백 루프**를 통해 사용자와 함께 성장하며, **Inside Out 2축 모델**로 인간다운 감정을 표현합니다. 이를 통해 로빙은 진정한 디지털 동료로서의 정체성을 확립합니다.

*참고: 상세한 감정 시스템 설계는 `ideas/250807_로빙_감정_시스템_설계도.md` 참조*