본문으로 건너뛰기

AI CoT/ToT/GoT 자료

Mind-Log v5.0 | 최종 업데이트: 2026-04-17 10:15


1. Reasoning Agent (TIER 1) 개요

Mind-Log v5.0 TIER 구조에서 Podcast Reasoning Agent는 사용자 입력(팟캐스트 기획, 감정 분석, 마인드 온톨로지 생성)을 처리하는 핵심 추론 에이전트입니다. GoT(Graph of Thoughts), ToT(Tree of Thoughts), CoT(Chain of Thoughts)를 조합하여 복합 감정 구조를 분석하고 팟캐스트 에피소드를 생성합니다.

역할담당 영역입력출력
메타인지 구조 추론감정/상황 분석사용자 발화 + 감정 벡터추론 결과 (reasoning_result)
리더십 스토리 구성팟캐스트 콘텐츠 기획이야기 원본 + 컨텍스트구조화된 에피소드 인사이트
심리 구조화마인드 온톨로지감정 그래프 + 키워드관계 그래프 (Neo4j 저장)

2. GoT (Graph of Thoughts) - 감정 그래프 구조

2.1 복합 감정 분석

GoT는 사용자가 경험하는 복합적인 감정 구조를 그래프로 모델링합니다.

예시: 고립감 + 억울함 + 책임감

고립감 (Isolation)
↓ 상호작용
억울함 (Injustice) ↔ 책임감 (Responsibility)
↓ 강화
결정 불안감 (Decision Anxiety)
↓ 피드백
신뢰도 침식 (Trust Erosion)

2.2 Neo4j 기반 감정 관계 그래프

실제 구현(podcast_reasoning.py:701)은 LEADS_TO 단일 관계 타입만 MERGE합니다. 구체적인 관계 의미(amplifies, conflict_with, triggers 등)는 엣지 프로퍼티 relationship에 문자열로 저장됩니다.

# podcast_reasoning.py:701 실제 구현
MERGE (a:Emotion {name: '고립감'})
MERGE (b:Emotion {name: '책임감'})
MERGE (a)-[:LEADS_TO {relationship: 'amplifies'}]->(b)

MERGE (c:Emotion {name: '억울함'})
MERGE (c)-[:LEADS_TO {relationship: 'conflict_with'}]->(b)

MERGE (d:Emotion {name: '결정불안감'})
MERGE (b)-[:LEADS_TO {relationship: 'triggers'}]->(d)

AMPLIFIES, TRIGGERS, CONFLICT_WITH, EXACERBATES 등 별도 관계 타입 구현은 향후 계획 섹션에 기재되어 있습니다.

2.3 마인드 온톨로지 생성에 활용

GoT 출력 → 감정 그래프 → 심리 키워드 추출 및 관계 구조화

마인드 온톨로지 예시:

리더십 심리 온톨로지
├─ 리더의 감정
│ ├─ 고립감
│ │ └─ 하위요소: 조직 내 정서적 거리감, 의사결정 고독
│ ├─ 억울함
│ │ └─ 하위요소: 노력 대비 평가 불일치, 팀의 비이해
│ └─ 책임감
│ └─ 하위요소: 조직 성과 몫감, 팀원 개발 의무
├─ 감정 간 상호작용
│ └─ 고립감 ⟶ 억울함 ⟶ 책임감 (악순환)
└─ 행동 패턴
├─ 과도한 업무 부하 (책임감 과잉)
├─ 감정적 폐쇄 (고립감 심화)
└─ 팀과의 단절 (신뢰도 침식)

3. ToT (Tree of Thoughts) - 코칭 전략 탐색

3.1 세 가지 치료적 접근 경로

ToT는 GoT에서 도출된 복합 감정 상태에 대해 여러 코칭 전략을 병렬로 탐색합니다.

복합 감정 상태 (고립감 + 억울함 + 책임감)

├─ Branch A: 공감적 접근 (Empathetic)
│ ├─ 감정 수용: "사용자의 고민이 타당함을 인정"
│ ├─ 정규화: "많은 사람들이 경험하는 보편적 감정"
│ └─ 목표: 감정적 안정 달성

├─ Branch B: 인지행동적 접근 (CBT-based)
│ ├─ 왜곡된 생각 재구조화: "나는 혼자가 아니다"
│ ├─ 행동 변화: "정서적 연결 재구축"
│ └─ 목표: 인지 패턴 변화 및 행동 개선

└─ Branch C: 해결중심적 접근 (Solution-Focused)
├─ 예외 찾기: "상황이 나아진 순간들은?"
├─ 목표 설정: "2주 후 원하는 모습은?"
└─ 목표: 실질적 개선 행동 계획 수립

3.2 각 분기별 치료적 효과 평가

전략즉각적 효과장기적 효과위험도유형별 적합성
공감적높음중간낮음감정 표현형
인지행동중간높음중간분석형
해결중심중간높음낮음실행형

3.3 최적 전략 선택

**Batch Validator (TIER 3)**가 다음 요소들을 고려하여 최고 점수 전략을 선택합니다:

  • 사용자 성향 (감정 표현 능력)
  • 현재 정서 상태 (위기 수준)
  • 상황 (긴급성, 기대)
  • 과거 성공 사례

예시 점수 계산:

scores = {
"empathetic": (0.9 * user_emotional_state) + (0.6 * urgency),
"cbt": (0.8 * analytical_ability) + (0.7 * cognitive_distortion_level),
"solution_focused": (0.9 * action_orientation) + (0.8 * goal_clarity)
}
selected = max(scores, key=scores.get)

4. CoT (Chain of Thoughts) - 단계별 추론

4.1 추론 사이클

CoT는 선택된 ToT 전략을 단계별로 실행하는 논리적 흐름입니다.

상황 이해
↓ (입력 데이터 분석)
감정 추론
↓ (감정 강도, 원인 파악)
맥락 파악
↓ (컨텍스트 고려)
상담 전략 선택
↓ (ToT 출력 기반)
응답 생성
↓ (맥락 + 전략 + 인사이트)
최종 코칭 응답

4.2 입력 데이터 기반 추론

CoT 추론 예시:

Input:
- 상황: 팀 회의에서 부하직원이 의견을 제시하자, 즉각 반박
- 생각: "내 판단이 최고다. 저 사람은 경험이 부족하다"
- 행동: 회의 종료 후 1:1 지적
- 반응: 부하직원 위축, 팀 내 위축감 확산

CoT Step 1 (상황 이해):
"의사결정 권한을 강하게 유지하려는 시도로 보입니다"

CoT Step 2 (감정 추론):
"이 행동의 뒤에는 책임감(결정에 대한 거대한 책임),
고립감(의사결정의 고독)이 있을 수 있습니다"

CoT Step 3 (맥락 파악):
"이 패턴이 반복되면 팀의 창의성과 주인의식이 저해됩니다.
의도(책임감)와 결과(팀 위축)의 불일치 발생"

CoT Step 4 (전략 선택):
"공감적 접근으로 책임감의 타당성을 인정한 후,
위임(delegation)을 통한 성장을 제안"

CoT Step 5 (응답 생성):
"느끼시는 책임감이 매우 크신 것 같습니다.
그러한 책임감이 있기에 조직을 이끌 수 있는 거죠.
다만, 팀을 더 강하게 만들기 위해
일부 의사결정 권한을 팀과 나누어보시면 어떨까요?"

5. 동적 활성화 - complexity_score에 따른 추론 깊이 조절

5.1 복잡도 분류

Podcast Reasoning Agent는 입력 복잡도에 따라 어떤 추론 계층을 활성화할지 결정합니다. 아래 4-tier 임계값은 설계 기준이며, 코드 내 determine_reasoning_depth 등 실제 매핑은 재검증 예정입니다(src/agents/podcast/podcast_reasoning.py).

상황complexity_score활성화 추론목적처리 시간
일상 대화0.0–0.3CoT만빠른 응답1초 이하
감정 표현0.3–0.5CoT + GoT감정 맥락 파악2-3초
고민 상담0.5–0.8CoT + ToT + GoT깊이 있는 분석5–8초
위기 상황0.8–1.0Safety CRISIS 경로 (하드코딩 폴백)즉각적 안정화0.5초 이하

5.2 CRISIS 동작 (PR #159 이후 현황)

Safety Agent가 CRISIS를 감지해도 cancel_event는 발행하지 않습니다. TIER 2~4는 하드코딩 폴백 응답으로 정상 완료됩니다. cancel_event는 TIMEOUT 상황에서만 set됩니다(workflow.py:378). 따라서 파이프라인 전체 취소(선점)가 아닌 폴백 진행 방식으로 동작합니다.

5.3 동적 활성화 로직

def determine_reasoning_depth(user_input: str, intent_metadata: dict, complexity_score: float) -> dict:
"""
complexity_score 기반 추론 깊이 결정
complexity_score = (emotion_intensity * 0.6) + (context_entropy * 0.4)
"""
if complexity_score < 0.3:
return {"reasoning_path": "COT_ONLY", "agents": ["synthesizer"]}

elif 0.3 <= complexity_score < 0.5:
return {
"reasoning_path": "COT_GOT",
"agents": ["memory_agent", "graph_analyzer", "synthesizer"]
}

elif 0.5 <= complexity_score < 0.8:
return {
"reasoning_path": "COT_TOT_GOT",
"agents": ["memory_agent", "graph_analyzer", "strategy_evaluator", "validator", "synthesizer"]
}

else: # complexity_score >= 0.8
return {
"reasoning_path": "SAFETY_CRISIS",
"agents": ["safety_agent"],
"skip_reasoning": True
}

6. Reasoning Agent 입출력 명세

6.1 입력 (INPUT)

Podcast Reasoning Agent는 request_memory / request_knowledge 같은 명시적 플래그를 사용하지 않습니다. Memory Agent와 Knowledge Agent는 조건부로 직접 호출(DI 패턴)되며, 결과가 None이면 스킵하는 None fallback 방식으로 동작합니다.

class ReasoningAgentInput(BaseModel):
# 필수 입력
user_input: str # 사용자 발화
user_id: str # 사용자 식별자

# 메타데이터
intent_metadata: dict # {intent_type: 'coaching'|'story'|'insight', ...}
complexity_score: float # 0.0–1.0 (추론 깊이 결정 지표)

# 선택적 입력
greenroom_context: Optional[dict] # {상황, 생각, 행동, 반응}
podcast_context: Optional[dict] # {이야기 원본, 주제, 청취자 타입}
ontology_context: Optional[dict] # {감정_키워드, 상황}

# 예시
input_example = {
"user_input": "팀장으로서 팀과의 거리감이 느껴집니다. 어떻게 해야 할까요?",
"user_id": "leader_001",
"intent_metadata": {"intent_type": "coaching", "domain": "team_dynamics"},
"complexity_score": 0.72, # 고민 상담 영역
"greenroom_context": {
"situation": "팀원들이 내 의견에 잘 따르지 않음",
"thought": "나는 리더로서 부족한가?",
"action": "더 많은 지시를 하려고 함",
"reaction": "거리감이 더 커짐"
}
}

6.2 내부 처리 (INTERNAL)

Memory Agent와 Knowledge Agent는 결과가 None이면 빈 dict로 처리됩니다. 명시적 플래그 없이 reasoning_path가 SAFETY_CRISIS가 아닌 경우 조건부 호출합니다.

def reasoning_agent_process(input: ReasoningAgentInput) -> dict:
# Step 1: 복잡도에 따른 추론 경로 결정
reasoning_path = determine_reasoning_depth(input.complexity_score)

# Step 2: Memory Agent 조건부 호출 (None fallback)
memory_context = {}
if reasoning_path != "SAFETY_CRISIS":
result = memory_agent.retrieve(
user_id=input.user_id,
query=input.user_input,
relevance_threshold=0.6
)
memory_context = result if result is not None else {}

# Step 3: Knowledge Agent 조건부 호출 (None fallback)
knowledge_context = {}
if reasoning_path != "SAFETY_CRISIS":
result = knowledge_agent.retrieve(
query=input.user_input,
domain=input.intent_metadata.get("domain")
)
knowledge_context = result if result is not None else {}

# Step 4: 추론 실행
if reasoning_path == "COT_ONLY":
return cot_reasoning(input, memory_context, knowledge_context)
elif reasoning_path == "COT_GOT":
return cot_got_reasoning(input, memory_context, knowledge_context)
elif reasoning_path == "COT_TOT_GOT":
return cot_tot_got_reasoning(input, memory_context, knowledge_context)
else: # SAFETY_CRISIS → 하드코딩 폴백
return safety_crisis_handling(input)

6.3 출력 (OUTPUT)

class ReasoningAgentOutput(BaseModel):
# 핵심 추론 결과
reasoning_graph: dict # GoT 출력 (감정 그래프, 패턴)
strategies: List[dict] # ToT 출력 (여러 코칭 전략)
selected_strategy: str # 선택된 최적 전략

# 단계별 추론 과정
step_by_step: List[dict] # CoT 단계별 추론 로그

# 보조 정보 (None fallback — 미수신 시 빈 dict)
memory_context: dict # Memory Agent 결과
knowledge_context: dict # Knowledge Agent 결과

# 메타정보
confidence_scores: dict # 각 단계의 신뢰도 점수
reasoning_path: str # 실제 사용된 추론 경로
processing_time: float # 처리 시간

# 예시 출력
output_example = {
"reasoning_graph": {
"core_pattern": "Authority Paradox",
"emotion_nodes": [
{"id": "isolation", "label": "고립감", "intensity": 0.8},
{"id": "responsibility", "label": "책임감", "intensity": 0.9},
{"id": "doubt", "label": "자기 의심", "intensity": 0.6}
],
"edges": [
{"from": "doubt", "to": "isolation", "relation": "causes"},
{"from": "responsibility", "to": "isolation", "relation": "amplifies"}
]
},
"strategies": [
{"name": "empathetic_listening", "score": 0.88, "risk": "low"},
{"name": "cbt_reframe", "score": 0.72, "risk": "medium"},
{"name": "delegation_focus", "score": 0.85, "risk": "low"}
],
"selected_strategy": "empathetic_listening",
"step_by_step": [
{"step": 1, "action": "empathy", "output": "팀장님의 책임감이 느껴집니다"},
{"step": 2, "action": "pattern_insight", "output": "이는 과도한 통제로 이어질 수 있습니다"},
{"step": 3, "action": "solution", "output": "팀과의 신뢰 재구축을 위한 3가지 방법"}
],
"memory_context": {
"past_sessions": 12,
"recurring_pattern": "team_distance",
"successful_intervention": "delegation_practice"
},
"knowledge_context": {
"leadership_model": "Servant Leadership",
"similar_cases": 3,
"best_practices": ["active_listening", "one_on_one_meetings"]
},
"confidence_scores": {
"pattern_detection": 0.92,
"strategy_selection": 0.88,
"response_generation": 0.85
},
"reasoning_path": "COT_TOT_GOT",
"processing_time": 6.3
}

7. 환각(Hallucination) 방지

7.1 신뢰도 스코어링

Reasoning Agent의 각 단계에서 신뢰도 점수를 계산하여 신뢰할 수 있는 추론만 출력합니다.

def calculate_confidence_score(reasoning_step: dict, evidence: dict) -> float:
evidence_count = len(evidence.get("sources", []))
source_quality = average([s.get("reliability", 0) for s in evidence.get("sources", [])])
consistency_check = validate_consistency(reasoning_step, evidence)

confidence = (
(evidence_count / max_evidence) * 0.3 +
source_quality * 0.4 +
consistency_check * 0.3
)
return confidence

confidence_threshold = {
"high_confidence": 0.8, # 직접 포함
"medium_confidence": 0.6, # "~일 수 있습니다" 형태로 제시
"low_confidence": 0.4, # 제외 또는 불확실성 명시
}

7.2 Batch Validator (TIER 3) 최종 검증

Script Generator로 보내기 전에 Batch Validator가 최종 검증합니다.

def validator_agent_check(reasoning_output: ReasoningAgentOutput) -> dict:
issues = []

# 1. 감정 그래프 검증: 과도한 노드 연결 방지
if len(reasoning_output.reasoning_graph["edges"]) > 15:
issues.append({
"type": "over_connection",
"severity": "high",
"message": "감정 그래프가 과도하게 연결되었습니다 (hallucination 위험)"
})

# 2. 전략 점수 검증
max_strategy_score = max([s["score"] for s in reasoning_output.strategies])
selected_strategy_score = next(
s["score"] for s in reasoning_output.strategies
if s["name"] == reasoning_output.selected_strategy
)
if selected_strategy_score < max_strategy_score - 0.1:
issues.append({
"type": "strategy_inconsistency",
"severity": "medium",
"message": "선택된 전략이 최고 점수 전략이 아닙니다"
})

# 3. 신뢰도 검증
low_confidence_steps = sum(
1 for step in reasoning_output.step_by_step
if reasoning_output.confidence_scores.get(f"step_{step['step']}", 1.0) < 0.6
)
if low_confidence_steps > 2:
issues.append({
"type": "low_confidence",
"severity": "medium",
"message": f"{low_confidence_steps}개 단계의 신뢰도가 낮습니다"
})

return {
"is_valid": len([i for i in issues if i["severity"] == "high"]) == 0,
"issues": issues,
"recommendation": "pass" if len(issues) == 0 else "review_before_synthesis"
}

8. 시나리오별 추론 예시

시나리오 1: 감정 분석 (complexity_score: 0.75 → CoT + ToT + GoT)

사용자 입력:

상황: 팀 회의에서 나의 의견이 받아들여지지 않음
생각: 나는 존중받지 못하고 있다
행동: 더욱 강하게 지시하고 통제함
반응: 팀원들이 더 위축됨

처리:

  1. GoT 분석: 핵심 패턴 "Authority Paradox" / 감정 노드: 자존감 훼손, 책임감, 고립감
  2. ToT 평가: 공감적 접근 0.88 (선택) / CBT 접근 0.72 / 위임 중심 0.80
  3. CoT 응답: 책임감 인정 → "지시"가 아닌 "파트너십"으로 전환 → 실행 방안 제시

시나리오 2: 팟캐스트 콘텐츠 기획 (complexity_score: 0.65 → CoT + ToT + GoT)

원본 이야기: "승진 후 처음 주는 피드백이 팀원을 상처입혔고, 그 후로 관계가 어색해졌다"

처리:

  1. GoT: 의도(성장 촉구) vs 수용(거절감) 간 간극
  2. ToT: 피드백 방식 개선 전략 + 관계 복구 전략 제시
  3. CoT: 상황 설정 → 리더의 마음 → 팀원의 마음 → 해결 과정 → 배운 점

시나리오 3: 마인드 온톨로지 생성 (complexity_score: 0.80 → CoT + ToT + GoT)

복합 감정 입력: "외로움", "답답함", "무거움"

처리:

  1. GoT: 세 감정 간 관계 분석 (LEADS_TO 단일 타입, relationship 프로퍼티 활용)
외로움 (의사결정 고독)
↓ LEADS_TO {relationship: 'amplifies'}
무거움 (조직 책임)
↓ LEADS_TO {relationship: 'triggers'}
답답함 (개선 안 됨)
  1. 온톨로지 생성:
심리 패턴
├─ 고립
│ ├─ 의사결정 고독
│ ├─ 정서적 지지 부족
│ └─ 신뢰 관계 제한
├─ 조직 책임감
│ ├─ 성과 부담
│ └─ 팀원 개발 의무
└─ 개선 저항감
├─ 이전 시도의 실패
└─ 자신감 부족

9. 다음 계층과의 연계

Script Generator (TIER 2) 입력:

  • reasoning_result (GoT, ToT, CoT 결과)
  • memory_results (과거 세션 기억 — None fallback)
  • knowledge_results (지식 베이스 — None fallback)

Script Generator의 역할:

  • Reasoning Agent 출력을 팟캐스트 스크립트 초안으로 변환
  • 에피소드 구조 및 서사 구성

Batch Validator (TIER 3) 검증:

  • 최종 응답의 품질 및 안전성 확인
  • 환각 요소 제거
  • 가이드라인 준수 확인

10. 참고

  • 코드 위치: src/agents/podcast/podcast_reasoning.py
  • 공용 인프라: src/agents/shared/base_agent.py, src/agents/shared/llm_client.py
  • Neo4j 통합 명세: docs/architecture/NEO4J_INTEGRATION.md
  • 에이전트 역할 정의: docs/architecture/AGENT_ROLES.md
  • 관련 에이전트: Episode Memory Agent, Knowledge Agent, Safety Agent

향후 계획

  • Neo4j 관계 타입 확장: 현재 LEADS_TO 단일 타입에서 AMPLIFIES, TRIGGERS, CONFLICT_WITH, EXACERBATES 등 4종 별도 관계 타입으로 확장. 엣지 프로퍼티 relationship 문자열을 실제 Cypher 관계 타입으로 마이그레이션 (podcast_reasoning.py:701 수정 필요)
  • request_memory / request_knowledge 플래그 구현: 현재 None fallback 기반 암묵적 조건부 호출을 명시적 Boolean 플래그로 전환하여 호출 여부를 외부에서 제어 가능하게 구현
  • cancel_event 기반 CRISIS 선점 복원: PR #159에서 cancel_event 미발행으로 전환된 CRISIS 경로를 재검토하여 파이프라인 즉시 선점 취소 방식으로 복원 (현재는 TIMEOUT 전용)
  • complexity_score 코드 매핑 검증: determine_reasoning_depth 등 실제 구현에서 설계 기준 4-tier(0.0-0.3/0.3-0.5/0.5-0.8/0.8-1.0)와 코드 임계값 정합성 확인 및 문서 반영

변경 이력

날짜버전변경 내용작성자
2026-04-17 10:15v5.0코드 기준 전면 재작성: 상단 경고 박스 제거, LEADS_TO 단일 관계 직접 기재, request_memory/request_knowledge 미구현 명시, CRISIS cancel_event 미발행 직접 기재, complexity_score 설계 기준 4-tier + 코드 매핑 재검증 예정 인라인 기재, 향후 계획 섹션 분리Mind-Log 팀
2026-04-17 17:30v4.9코드 정합성 요약 테이블 추가, 각 섹션 코드 현황 박스 보완Mind-Log 팀