DOCS/journey/plans/251016_ontology_coldmail_implementation.md
Claude-51124 22557e7132 docs: 오래된 트러블슈팅 아카이브 및 구조 정리
- 7-8월 초기 구축 문서 12개를 _archive/troubleshooting/2025_07-08_initial_setup/로 이동
- book/300_architecture/390_human_in_the_loop_intent_learning.md를 journey/research/intent_classification/로 이동 (개발 여정 문서)
- 빈 폴더 제거 (journey/assets/*)
2025-11-17 14:06:05 +09:00

11 KiB

온톨로지 기반 Coldmail 필터 및 기억 시스템 구현 계획

날짜: 2025-10-16 작성자: Claude 관련 문서: 200_core_design/225_온톨로지_기반_지식_표현.md


목표

파인티처 메일 누락 같은 임베딩 한계(75% 정확도)를 온톨로지 추론으로 해결하고, 기억-감정-윤리 삼각형을 온톨로지로 구조화하여 로빙의 존재성 강화.


Phase 1: Coldmail 온톨로지 파일럿 (2주)

개념 계층 구축

파일: rb8001/app/ontology/coldmail_schema.owl

메일
└── 외부메일
    └── 제안메일
        └── coldmail (투자제안)
            ├── IR자료
            ├── 피칭덱
            └── 사업계획서

관계 정의

  • 발신자 -속한다→ 회사
  • 회사 -투자단계→ {시드, 시리즈A, ...}
  • 메일 -포함한다→ 첨부파일

추론 규칙 (10개)

파일: rb8001/app/services/coldmail_ontology_reasoner.py

Coldmail 판정 규칙 (6개)

  1. IF 제목 CONTAINS ["투자", "IR", "피칭", "사업계획"] AND 첨부 HAS PDF THEN coldmail (확률 0.9)
  2. IF 첨부파일명 CONTAINS ["회사소개서", "IR_Deck", "Pitch", "사업계획서"] THEN coldmail (확률 0.85)
  3. IF 제목 CONTAINS "검토요청" AND 첨부 EXISTS THEN coldmail (확률 0.8)
  4. IF 발신자 NOT IN known_contacts AND 첨부 HAS PDF THEN coldmail (확률 0.7)
  5. IF 본문 CONTAINS ["투자 유치", "펀딩", "시리즈", "밸류에이션"] THEN coldmail (확률 0.75)
  6. IF 발신자.도메인 IN ["startup", "ventures", "capital"] THEN coldmail (확률 0.6)

Normal 판정 규칙 (4개)

  1. IF 제목 CONTAINS ["행사", "초대", "안내", "세미나"] THEN normal (확률 0.9)
  2. IF 제목 CONTAINS ["영수증", "발급", "세금계산서", "견적서"] THEN normal (확률 0.95)
  3. IF 제목 CONTAINS ["회의", "공지", "보고", "업무"] THEN normal (확률 0.85)
  4. IF 발신자 IN known_contacts AND NOT (규칙 1-6) THEN normal (확률 0.8)

최종 판단 로직

  • Coldmail 규칙 매칭: 가장 높은 확률 선택
  • Normal 규칙 매칭: 가장 높은 확률 선택
  • Coldmail 확률 > Normal 확률 → Coldmail
  • Threshold: 0.7 이상 시 확정, 0.4-0.7은 LLM fallback

검증

  • 파인티처 메일: coldmail 확률 0.9+ (현재 0.28)
  • 기존 17건 재테스트: 정확도 90%+

Phase 2: 기억 시스템 온톨로지 통합 (1개월)

Neo4j 도입

위치: 51123 서버 (192.168.219.45) 설치 상태: 이미 설치됨 (시스템 직접 설치, Docker 아님)

설치 정보:

  • 버전: Neo4j 2025.06.2 Community Edition
  • 서비스 상태: Active (running) since 2025-08-20
  • 가동 시간: 1개월 26일
  • HTTP 포트: 7474 (브라우저 접속)
  • Bolt 포트: 7687 (드라이버 연결)
  • 인증: 활성화 (비밀번호 변경됨)

연결 정보:

  • Bolt URI: neo4j://192.168.219.45:7687
  • HTTP API: http://192.168.219.45:7474
  • 데이터베이스: neo4j (기본 DB), system (시스템 DB)

스키마 (설계안):

(사건)-[:발생시각]->(시간)
(사건)-[:관련감정]->(감정)
(사건)-[:참여자]->(사용자)
(사건)-[:결과]->(결과)

ChromaDB + Neo4j 하이브리드 알고리즘

rb8001/app/services/memory_hybrid_retrieval.py

1단계: ChromaDB 벡터 검색 (빠른 필터링)

# 입력: 사용자 쿼리 (예: "작년 프레젠테이션 때 어떻게 했지?")
# 1. 쿼리 임베딩: skill-embedding (8515) /embed 호출
# 2. ChromaDB 유사도 검색: top_k=20 (충분한 후보)
# 3. 출력: 20개 후보 대화 (벡터 점수 포함)

2단계: Neo4j 그래프 추론 (의미적 연결)

# 입력: ChromaDB 후보 20개
# Cypher 쿼리:
MATCH (event:사건)-[:관련감정]->(emotion)
MATCH (event)-[:결과]->(result)
WHERE event.id IN [후보 20 ID]
RETURN event, emotion, result, event.시간
ORDER BY event.시간 DESC

# 우선순위:
# - [:결과]->(성공) 관계 있는 사건 우선 (가중치 1.5배)
# - [:관련감정]->(긴장) 매칭 시 가중치 1.3배
# - 시간적 근접성: 1년 전 > 2년 전 (거리 역수)

3단계: 점수 통합 및 순위 결정

최종점수 = (벡터점수 * 0.4) + (그래프점수 * 0.6)
# 그래프점수 = 관계가중치 * 시간가중치
# 출력: 상위 5개 사건 반환

API 설계

rb8001/app/router/memory_ontology.py:

  • POST /memory/event: 사건 저장 (자동 관계 추론)
  • GET /memory/recall: 쿼리 기반 회상 (3단계 하이브리드)

Phase 3: 감정-윤리 온톨로지 규칙화 (1개월)

감정-우도 온톨로지

파일: rb8001/app/ontology/emotion_likelihood.owl

불안 -조정→ 위험관련증거 (가중치 1.3)
흥분 -조정→ 긍정관련증거 (가중치 1.2)
슬픔 -조정→ 위로관련증거 (가중치 1.5)

윤리 제약 온톨로지

파일: rb8001/app/ontology/ethics_constraints.owl

정보수집 행동 -제약→ [개인정보보호, 투명성, 동의]
조언 행동 -제약→ [해악금지, 자율성존중]

추론 엔진 통합

rb8001/app/services/ontology_explainer.py

추론 과정 추적 (Jena Rules)

# 규칙 실행 시 추적 로그 생성
trace = []
for rule in matched_rules:
    trace.append({
        "rule_id": rule.id,
        "condition": rule.condition,  # "사용자.감정 = 불안"
        "action": rule.action,         # "위험관련증거.우도 *= 1.3"
        "matched_value": matched_value # "감정: 불안"
    })

설명 템플릿 (자연어 생성)

def generate_explanation(trace):
    explanation = []
    for step in trace:
        if step['rule_id'].startswith('emotion_'):
            template = "사용자의 {emotion} 감정 때문에 {evidence} 관련 증거의 중요도를 {weight}배 조정했습니다."
            explanation.append(template.format(...))
        elif step['rule_id'].startswith('ethics_'):
            template = "{action} 행동은 {constraint} 원칙에 위배되어 거부했습니다. 대안: {alternative}"
            explanation.append(template.format(...))
    return " ".join(explanation)

윤리 충돌 해결 우선순위 (OWL Ontology)

# ethics_constraints.owl
:해악금지 rdf:type :윤리원칙 ; :priority 1 .
:투명성 rdf:type :윤리원칙 ; :priority 2 .
:자율성존중 rdf:type :윤리원칙 ; :priority 3 .
:개인정보보호 rdf:type :윤리원칙 ; :priority 1 .

# 충돌 시 priority 높은 것 우선 (1 > 2 > 3)

HermiT 일관성 검사

  • 규칙 간 모순 자동 탐지 (예: "불안 → 우도 증가" vs "불안 → 우도 감소")
  • 배포 전 ontology validation 자동화

기술 스택

구분 도구 용도
온톨로지 편집 Protégé OWL 스키마 설계
그래프 DB Neo4j 사건-관계 저장
추론 엔진 HermiT 일관성 검사
벡터 DB ChromaDB 기존 유지 (하이브리드)
표준 RDF/OWL 온톨로지 표현

마일스톤

날짜 단계 목표
Week 1-2 Phase 1 Coldmail 정확도 90%+
Week 3-6 Phase 2 기억 회상 의미적 연결
Week 7-10 Phase 3 감정-윤리 규칙 투명화

체크리스트

Phase 1: 완료 (2025-10-16)

  • Coldmail 온톨로지 스키마 설계 (규칙 기반, Python 구현)
  • 추론 규칙 11개 구현 (coldmail_ontology_reasoner.py)
  • 파인티처 메일 재테스트 (0.90, 목표 0.9+ 달성)
  • Hybrid Filter 통합 (USE_ONTOLOGY_FILTER 환경변수, 롤백 가능)
  • Slack 피드백 → 관계 가중치 베이지안 업데이트 (Phase 1.5)

Phase 2:

  • Neo4j 설치 확인 (51123 서버) - 이미 설치됨 (2025.06.2)
  • Neo4j Python 드라이버 연동 (neo4j 패키지)
  • ChromaDB + Neo4j 하이브리드 쿼리 구현
  • "1년 전 비슷한 상황" 회상 테스트

Phase 3:

  • 감정-우도 온톨로지 7가지 감정
  • 윤리 제약 온톨로지 사랑 기반 원칙
  • HermiT 일관성 검사 자동화


Phase 1 구현 완료 (2025-10-16)

구현 파일

  • rb8001/app/services/coldmail_ontology_reasoner.py: 11개 추론 규칙
  • rb8001/app/services/coldmail_hybrid_filter.py: 온톨로지 통합 (환경변수 제어)
  • rb8001/tests/test_coldmail_ontology.py: 7개 테스트 케이스 (100% 통과)
  • rb8001/tests/test_hybrid_simple.py: 5개 통합 테스트 (100% 통과)

테스트 결과

파인티처 메일: 0.28 → 0.90 (4개 규칙 매칭)
- R1: 투자 키워드 + PDF (0.90)
- R2: 회사소개서 첨부명 (0.85)
- R3: 검토요청 + 첨부 (0.80)
- R3B: 투자검토 키워드 (0.65)
- R4: 신규 발신자 + PDF (0.70)

롤백 시나리오

시나리오 1: 환경변수 롤백 (즉시, 권장)

증상: 온톨로지 오판, 성능 저하 방법:

cd /home/admin/ivada_project/rb8001

# .env 파일 수정
USE_ONTOLOGY_FILTER=false

# Docker 재시작 (5초 소요)
docker compose down && docker compose up -d

결과: 기존 임베딩 필터로 즉시 복귀, 코드 변경 없음

시나리오 2: Git 부분 롤백 (온톨로지만 제거)

증상: 환경변수 롤백으로도 해결 안 될 때 방법:

cd /home/admin/ivada_project/rb8001

# 온톨로지 파일만 제거
git rm app/services/coldmail_ontology_reasoner.py
git rm tests/test_coldmail_ontology.py tests/test_hybrid_simple.py

# hybrid_filter.py를 온톨로지 통합 이전 버전으로 복구
git checkout 48aacfa^ -- app/services/coldmail_hybrid_filter.py

# 커밋 및 배포
git commit -m "Rollback: Remove ontology reasoner"
git push origin main
docker compose down && docker compose up -d --build

시나리오 3: 전체 롤백 (Phase 1 이전)

증상: 심각한 오류, 전체 되돌리기 필요 방법:

cd /home/admin/ivada_project/rb8001

# Phase 1 파일럿 직전 커밋으로 복귀
git checkout 28ef36c  # 48aacfa 이전 커밋
git push origin main --force

# Docker 재빌드
docker compose down && docker compose up -d --build

주의: force push는 최후 수단

롤백 포인트 커밋

  • 28ef36c: Phase 1 이전 (안전한 복귀 지점)
  • 48aacfa: Phase 1 파일럿 완료 (온톨로지 단독 동작)
  • 7a122f4: Hybrid Filter 통합
  • 88636cf: UnboundLocalError 핫픽스 (현재)

롤백 검증

# 롤백 후 확인
docker logs rb8001 --tail 50 | grep -i "ontology\|embedding"
# "Embedding" 메시지만 보이면 롤백 성공

실전 검증 계획

  • 일시: 2025-10-17 09:05 Coldmail Daily Briefing
  • 확인 사항:
    • 로그에서 "Stage 1 (Ontology)" 메시지 출력
    • 파인티처 유사 케이스 발생 시 온톨로지 판정 확인
    • 오류 없이 정상 동작 확인
    • 응답 속도 측정 (온톨로지 vs 기존 임베딩)

참고

  • 설계 원칙: 200_core_design/225_온톨로지_기반_지식_표현.md
  • 문제 배경: troubleshooting/251014_claude_coldmail_filter_tokenization_issue.md
  • 온톨로지 연구: research/ontology/
  • 구현 커밋: rb8001 88636cf (hotfix), 7a122f4 (통합), 48aacfa (파일럿)