핵심은 한 문장을 보고 “감정 하나만 고르는 것”이 아니라, 여러 감정을 점수로 계산하는 구조로 가는 게 좋아.
네 서비스에서는 감정이 캐릭터 진화에도 쓰이고, 상담 반응에도 쓰이니까
다음처럼 2단 구조로 보는 게 제일 현실적이야.
1-1. 감정점수 종류를 분리해야 함
A. 현재 감정 점수
지금 이 메시지에서 드러나는 감정
예시 라벨:
sadness(슬픔)
anxiety(불안)
loneliness(외로움)
anger(분노)
joy(기쁨)
lethargy(무기력)
confusion(혼란)
calm(안정)
B. 상담 의도 점수
지금 이 사용자가 원하는 반응 방식
예시 라벨:
comfort_need(위로 원함)
advice_need(조언 원함)
listening_need(그냥 들어주길 원함)
empathy_need(공감 원함)
casual_talk(잡담 원함)
C. 장기 성격 축 점수
이건 진화용이고, 한 턴마다 아주 조금씩만 누적
E / I
S / N
T / F
J / P
즉 한 메시지에서 뽑는 건 사실상:
감정 + 상담의도 + MBTI축 힌트
이 3개야.
1-2. 실제 계산 방식
가장 현실적인 건 하이브리드 구조야.
1단계: 분류 모델 or LLM 분류
사용자 메시지를 넣고 이런 JSON을 받음.
{
"emotion": {
"sadness": 0.72,
"anxiety": 0.81,
"loneliness": 0.34,
"anger": 0.08,
"joy": 0.02,
"lethargy": 0.61,
"confusion": 0.55,
"calm": 0.04
},
"intent": {
"comfort_need": 0.87,
"advice_need": 0.29,
"listening_need": 0.76,
"empathy_need": 0.84,
"casual_talk": 0.05
},
"mbti_signal": {
"E": 0.18,
"I": 0.82,
"S": 0.36,
"N": 0.64,
"T": 0.21,
"F": 0.79,
"J": 0.58,
"P": 0.42
}
}
1-3. 이 점수는 어떻게 나오냐
모델 내부적으로는 보통 이런 흐름이야.
방식 A. softmax
여러 감정 중 대표 하나를 뽑는 방식
합이 1이 됨
단점:
사람 감정은 동시에 여러 개가 있을 수 있어서 상담에는 좀 아쉬움
방식 B. sigmoid
감정마다 독립 점수를 내는 방식
합이 1이 안 되어도 됨
이게 네 프로젝트에 더 적합함.
예:
슬픔 0.82
불안 0.77
외로움 0.54
이렇게 동시에 높아질 수 있음.
상담형 서비스에서는 sigmoid 기반 multi-label 방식이 더 자연스러움.
1-4. 점수를 바로 쓰지 말고 안정화해야 함
한 문장만 보고 진화 방향을 바꾸면 너무 출렁여.
그래서 매 턴 점수를 바로 확정값으로 쓰지 말고, 가중 평균으로 누적해야 함.
예를 들면:
현재 감정 점수
최근 5~10턴 평균
최신 메시지에 가중치 더 크게
공식 느낌:
최종감정점수 = (이전누적점수 0.7) + (현재메시지점수 0.3)
예:
이전 슬픔 누적: 0.40
현재 메시지 슬픔: 0.80
→ 새 슬픔 점수 = 0.40×0.7 + 0.80×0.3 = 0.52
이러면 갑자기 한 번 우울한 말 했다고 바로 캐릭터 전체가 바뀌지 않음.
1-5. MBTI 점수는 더 천천히 누적해야 함
감정은 빠르게 바뀌지만, 성격 축은 천천히 쌓여야 함.
예:
새로운 I 점수 = 기존 I 점수 0.9 + 현재 메시지의 I signal 0.1
즉,
감정은 빠르게 반응
성격은 느리게 축적
이렇게 나눠야 함.
여기서 제일 중요한 건
감정점수만으로 진화시키면 안 되고, 성격축 점수 + 상호작용량 + 안정도를 같이 봐야 한다는 거야.
왜냐하면 감정은 순간값이라서
“오늘 우울함” 때문에 INFJ가 되는 건 이상하거든.
2-1. 추천 진화 기준 3개
진화는 아래 3개 조건을 동시에 보자.
A. 대화량 조건
최소 몇 턴 이상 대화했는지
예:
1단계 → 2단계: 누적 20턴 이상
2단계 → 3단계: 누적 60턴 이상
B. 성격축 확신도 조건
MBTI 4축 중 어느 정도 한쪽으로 기울었는지
예:
E 0.72 / I 0.28 이면 E 확신도 높음
T 0.51 / F 0.49 이면 확정 애매함
확신도 계산 예시:
축확신도 = |E - I|
이 값이 클수록 확실함
예:
E 0.72 / I 0.28 → 확신도 0.44
E 0.55 / I 0.45 → 확신도 0.10
C. 관계 형성 조건
단순 턴 수 말고, 실제 meaningful interaction이 있는지
예:
고민 상담 메시지 횟수
일정 길이 이상 대화 수
며칠 이상 재방문
감정 공유 빈도
2-2. 추천 3단 진화 구조
1단계: 초기 몬스터
아직 성격 미정
감정에 따라 표정만 조금 변함
대화 시작 단계
조건:
기본 상태
2단계: 중간 진화
MBTI 전체 확정은 아니고 큰 갈래만 반영
예: 내향형 / 외향형 / 공감형 / 사고형
진화 조건 예시:
누적 대화 20턴 이상
최근 3일 이상 상호작용
4축 평균 확신도 0.20 이상
중간 진화 예:
I/F 쪽 높음 → 차분하고 다정한 중간형
E/T 쪽 높음 → 활발하고 직설적인 중간형
3단계: 최종 진화
16가지 MBTI 중 하나 확정
외형 + 말투 + 반응 스타일 고정
진화 조건 예시:
누적 대화 60턴 이상
7일 이상 재방문
4축 각각 확신도 0.25 이상
관계 친밀도 일정 이상
2-3. 분기점 예시
각 축을 0~1로 관리한다고 하면:
E > 0.60 이면 E 우세
I > 0.60 이면 I 우세
0.40~0.60이면 보류
MBTI 확정은 이런 식:
E/I
S/N
T/F
J/P
각 축이 다 0.60 넘는 쪽이 있으면 최종 확정
예:
I = 0.71
N = 0.67
F = 0.80
J = 0.62
→ INFJ
2-4. 진화가 너무 빨라지지 않게 하는 장치
이건 꼭 필요해.
추천 장치
최소 대화 턴 수
최소 일수
최근 점수만이 아니라 전체 누적 평균 사용
진화 직전 “안정도 체크” 수행
안정도 예:
최근 10턴의 MBTI 축 변동 폭이 너무 크면 진화 보류
즉,
“충분히 오래 대화했고, 성격 방향이 안정적으로 보일 때만 진화”
시키는 게 맞아.
이건 진짜 중요해.
결론부터 말하면 세션을 브라우저 연결로 보면 안 되고, 캐릭터별 장기 메모리 시스템으로 봐야 해.
3-1. 저장 구조를 4개로 나눠야 함
A. 사용자 고정 프로필
처음 입력한 것
성격 소개
강점
고민 스타일
선호 말투
피하고 싶은 주제
이건 거의 안 바뀜
B. 최근 대화 메모리
최근 10~20턴 정도 원문 저장
이건 모델에 바로 넣는 용도
C. 장기 요약 메모리
오래된 대화는 통째로 넣지 않고 요약
예:
사용자는 취업 스트레스를 반복적으로 언급
위로보다 먼저 공감받는 걸 선호
INFJ 캐릭터와는 진지한 고민 대화가 많음
이건 매 N턴마다 갱신
D. 캐릭터별 관계 메모리
캐릭터마다 따로 저장
예:
친밀도
신뢰도
호칭
함께 겪은 이벤트
최근 분위기
진화 단계
최종 MBTI 타입
대화 스타일 파라미터
즉, 같은 사용자라도 캐릭터 A와의 관계, 캐릭터 B와의 관계는 अलग으로 감
3-2. 응답 생성 시 실제로 넣는 정보
모델에 매번 전체 대화를 넣지 말고 아래만 넣는다.
시스템 프롬프트
캐릭터 최종 성격
사용자 고정 프로필
캐릭터별 관계 요약
최근 대화 N턴
현재 사용자 메시지
이렇게 해야 렉이 안 걸리고 비용도 덜 듦.