# 온톨로지 기반 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개) 7. IF 제목 CONTAINS ["행사", "초대", "안내", "세미나"] THEN normal (확률 0.9) 8. IF 제목 CONTAINS ["영수증", "발급", "세금계산서", "견적서"] THEN normal (확률 0.95) 9. IF 제목 CONTAINS ["회의", "공지", "보고", "업무"] THEN normal (확률 0.85) 10. 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 서버 (별도 컨테이너) **스키마**: ``` (사건)-[:발생시각]->(시간) (사건)-[:관련감정]->(감정) (사건)-[:참여자]->(사용자) (사건)-[:결과]->(결과) ``` ### ChromaDB + Neo4j 하이브리드 알고리즘 **rb8001/app/services/memory_hybrid_retrieval.py** #### 1단계: ChromaDB 벡터 검색 (빠른 필터링) ```python # 입력: 사용자 쿼리 (예: "작년 프레젠테이션 때 어떻게 했지?") # 1. 쿼리 임베딩: skill-embedding (8515) /embed 호출 # 2. ChromaDB 유사도 검색: top_k=20 (충분한 후보) # 3. 출력: 20개 후보 대화 (벡터 점수 포함) ``` #### 2단계: Neo4j 그래프 추론 (의미적 연결) ```python # 입력: 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단계: 점수 통합 및 순위 결정 ```python 최종점수 = (벡터점수 * 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) ```python # 규칙 실행 시 추적 로그 생성 trace = [] for rule in matched_rules: trace.append({ "rule_id": rule.id, "condition": rule.condition, # "사용자.감정 = 불안" "action": rule.action, # "위험관련증거.우도 *= 1.3" "matched_value": matched_value # "감정: 불안" }) ``` #### 설명 템플릿 (자연어 생성) ```python 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) ```turtle # 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) - [x] Coldmail 온톨로지 스키마 설계 (규칙 기반, Python 구현) - [x] 추론 규칙 11개 구현 (coldmail_ontology_reasoner.py) - [x] 파인티처 메일 재테스트 (0.90, 목표 0.9+ 달성) - [x] Hybrid Filter 통합 (USE_ONTOLOGY_FILTER 환경변수, 롤백 가능) - [ ] Slack 피드백 → 관계 가중치 베이지안 업데이트 (Phase 1.5) Phase 2: - [ ] Neo4j 컨테이너 배포 (51123 서버) - [ ] 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: 환경변수 롤백 (즉시, 권장) **증상**: 온톨로지 오판, 성능 저하 **방법**: ```bash cd /home/admin/ivada_project/rb8001 # .env 파일 수정 USE_ONTOLOGY_FILTER=false # Docker 재시작 (5초 소요) docker compose down && docker compose up -d ``` **결과**: 기존 임베딩 필터로 즉시 복귀, 코드 변경 없음 #### 시나리오 2: Git 부분 롤백 (온톨로지만 제거) **증상**: 환경변수 롤백으로도 해결 안 될 때 **방법**: ```bash 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 이전) **증상**: 심각한 오류, 전체 되돌리기 필요 **방법**: ```bash 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 핫픽스 (현재) #### 롤백 검증 ```bash # 롤백 후 확인 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 (파일럿)