# 온톨로지 기반 Coldmail 필터 구현 계획 **날짜**: 2025-10-16 **목표**: 임베딩 한계(파인티처 메일 누락)를 온톨로지 추론으로 해결 **상태**: Phase 1-1.5 완료, Phase 2-3 미구현 **원칙 참조** (구현 전 필수 확인): - `311_backend_coding_principles.md`: 계층 분리, DB는 state 경유 - `312_writing-principles.md`: 핵심만 간결, 파일명:줄번호 - `315_테스트_원칙.md`: 테스트는 TDD로 진행 (Red → Green → Refactor) --- ## Phase 1: Coldmail 온톨로지 (✅ 완료) → 상세: `troubleshooting/251014_claude_coldmail_filter_tokenization_issue.md` --- ## Phase 1.5: 베이지안 학습 (✅ 완료) → 상세: `troubleshooting/260113_coldmail_ontology_phase1_5_implementation.md` --- ## 남은 작업 ### Phase 2-3: Neo4j 기억 시스템 및 감정-기억-윤리 (TDD 진행) - **참고**: `../ideas/251016_coldmail_ontology_phase2_3_neo4j_emotion.md` - **필요 작업**: Neo4j 기억 시스템, 감정-기억-윤리 삼각형 구현 --- ## 문제 상황 (구체 시나리오) - 2025-10-14 09:05 Coldmail Daily Briefing에서 IR deck 메일이 Slack에 전송되지 않음 (올굿즈컴퍼니 IR deck 30.35%, 빅웨이브 IR 행사 7.65%, 투자제안서 검토 28.38% → threshold 미달) - 원인: 정규식 토큰화 실패(“회사소개서”, “ir에” 등 교착어 처리 불가)로 DB 키워드 매칭 실패 → 임베딩/온톨로지 기반 추론 필요성 대두 - 현재는 하이브리드(임베딩→LLM→Naive Bayes) + 온톨로지 규칙 + Slack 피드백 학습까지 적용 (Phase 1/1.5 완료, 남은 것은 Neo4j 기억 시스템 확장) ## 기대 효과 (UX 중심) - **누락 감소**: 중요한 콜드메일이 브리핑에서 빠지지 않아 “믿고 보는 브리핑” 경험 제공 - **개인화 체감**: 맞음/틀림 피드백이 기억에 누적되어 사용자별 패턴 반영 정확도 향상 - **설명 가능성**: 규칙·관계·기억 기반 근거로 “왜 콜드메일인지” 설명 가능 → 신뢰도 상승 --- ## Phase 2-3 상세 작업 (결정 완료) ### 0) 현재 Neo4j 위치 확인 (기반 코드 재사용) - **클라이언트**: `rb8001/app/services/memory/neo4j_client.py:1-200` - **환경변수**: `rb8001/.env:NEO4J_URI, NEO4J_USER, NEO4J_PASSWORD` (기본값 포함) - **연결 위치 확인**: Neo4j는 **51123 서버(192.168.0.100)**에서 운영 - Bolt: `neo4j://192.168.0.100:7687` (DOCS 아이디어/검증 문서 동일) - HTTP: `http://192.168.0.100:7474` - **기존 사용처**: `rb8001/app/services/memory_hybrid_retrieval.py`, `rb8001/app/services/startup_valuation.py` ### 1) 데이터 구조 (Neo4j) - **노드**: `Email`, `Rule`, `Company`, `Topic`, `User` - **관계**: `(:Email)-[:MATCHED_RULE]->(:Rule)`, `(:Email)-[:MENTIONS]->(:Company|Topic)`, `(:User)-[:RECEIVED]->(:Email)` - **필수 속성**: - `Email`: `email_id`, `subject`, `sender`, `received_at`, `confidence`, `source`(hybrid/ontology) - `Rule`: `rule_id`, `rule_type`, `confidence` - `Company`: `name`, `domain` - `Topic`: `keyword` - `User`: `user_id` ### 2) 서비스/레포지토리 구조 (계층 분리) - **state/repositories**: `rb8001/app/state/repositories/coldmail_memory_repository.py` (Neo4j CRUD, 내부에서 `Neo4jClient` 사용) - **services**: `rb8001/app/services/coldmail_memory_service.py` (기억 저장/조회/요약 로직) - **services**: `rb8001/app/services/coldmail_ontology_reasoner.py`와 연결 (규칙/기억 반영) - **workflows**: `rb8001/app/services/workflows/coldmail_workflow.py`에서 기억 저장 호출 ### 3) 인터페이스 (입출력 고정) - `save_email_memory(user_id, email_payload, matched_rules, topics, companies) -> memory_id` - `get_recent_memory(user_id, limit=20) -> List[MemoryItem]` - `get_rule_context(rule_id) -> Dict` (해당 규칙과 연결된 최근 이메일 요약) ### 4) 데이터 흐름 (실행 순서) 1. hybrid_coldmail_filter 결과에 `matched_rules` 포함 2. 콜드메일 확정 시 `coldmail_memory_service.save_email_memory()` 호출 3. 온톨로지 판단 시 `get_rule_context()`로 기억 기반 보정 ### 5) DB 스키마 확인/동기화 - Neo4j 실제 스키마 확인 후 Repository/Service 동시 반영 - 스키마 변경 시 ORM/DDL/Repository 동기화 원칙 준수 ### 6) 테스트 (TDD, pytest) - **파일**: `rb8001/tests/test_coldmail_memory_repository.py` - Neo4j 저장/조회/관계 생성 검증 - **파일**: `rb8001/tests/test_coldmail_memory_service.py` - save/get 동작, rule context 요약 결과 검증 - **UX 검증**: “왜 콜드메일인지” 설명 문구 포함 여부 확인 ### 7) 완료 기준 - Neo4j에 콜드메일 기억 저장/조회 성공 - 온톨로지 판단에 기억 보정 값 반영 - Slack 브리핑에서 누락/오판 사례 재현 시 개선 확인 --- ## 스키마 확정 체크리스트 (구현 전 필수) - **Neo4j 실제 라벨/관계 확인**: 기존 데이터 라벨/관계 목록 수집 - **필드명/타입 확정**: Email/Rule/Company/Topic/User 속성명 및 타입 확인 - **인덱스/제약 확인**: 유니크 키, 필수 인덱스 목록 확인 - **샘플 쿼리 검증**: 실제 데이터로 MATCH/CREATE 쿼리 1~2건 검증 - **환경변수 검증**: `NEO4J_URI/USER/PASSWORD`로 연결 확인 - **참고 근거**: `journey/ideas/251016_coldmail_ontology_phase2_3_neo4j_emotion.md`, `journey/troubleshooting/251016_phase2_neo4j_validation.md`, `journey/troubleshooting/260112_storehub_neo4j_add.md` --- ## 실제 Neo4j 스키마 확인 결과 (51123) - **라벨**: `Startup`, `VC`, `Batch`, `Category`, `Tag`, `NewsArticle` - **관계**: `BATCH`, `BELONGS_TO`, `TAGGED`, `MENTIONS` - **인덱스(대표)**: `Batch.name`, `Category.name`, `NewsArticle.url` + lookup 인덱스 - **제약(UNIQUENESS)**: `Batch.name`, `Category.name`, `NewsArticle.url`, `Startup.id`, `VC.id` --- ## 참고 - `book/300_architecture/311_backend_coding_principles.md` - `book/300_architecture/315_테스트_원칙.md` - `troubleshooting/251014_claude_coldmail_filter_tokenization_issue.md` - `troubleshooting/251016_ontology_filter_validation.md` - `troubleshooting/260113_coldmail_ontology_phase1_5_implementation.md` - `book/200_core_design/225_온톨로지_기반_지식_표현.md`