# InsuWiki 지식 추출 방법론 고도화 — 스레드 분리 + 정제 품질 개선

## 작업 개요
현재 kakao_knowledge 모듈의 스레드 분리가 "30분 시간 gap + 날짜 변경"만으로 이루어져,
오픈채팅방 특성상 여러 질문이 동시에 올라오면 하나의 스레드에 섞여버린다.
tofukyung의 Zettelkasten(원자적 노트) 방법론을 참고하여 근본적으로 개선한다.

## 핵심 문제
1. **스레드 분리 불량**: 30분 이내에 여러 질문이 올라오면 하나로 묶임
2. **답변에 다른 질문이 섞임**: Q1에 대한 답변 중간에 Q2가 끼어있는데 분리 안 됨
3. **노이즈**: 오픈채팅봇 환영 메시지, 인사, 이모티콘 등이 지식 항목에 포함됨
4. **제목 거침**: `#궁금증 • 유형 : 고지의무 • 질문내용 : ...` 원본 그대로

## 수정 대상
`/home/jay/projects/insuwiki/scripts/kakao_knowledge/knowledge_extractor.py`
`/home/jay/projects/insuwiki/scripts/kakao_knowledge/kakao_parser.py` (필요시)

## 참고: tofukyung/Zettelkasten 방법론
- **원자적 노트 원칙**: 하나의 노트에 **하나의 지식/질문-답변**만 포함
- **자기완결적**: 다른 노트 참조 없이도 이해 가능
- **LLM 기반 주제 감지**: 규칙 기반 스레드 분리 후, LLM이 추가 분할/병합

## 구현 요구사항

### 1. 스레드 분리 고도화 (`_split_into_threads`)

현재: 시간 gap(30분) + 날짜 변경만 사용
개선: **다중 신호 기반 분리**

#### 1a. `#궁금증` 태그 기반 분리 (최우선)
- `#궁금증`이 나오면 **무조건 새 스레드 시작**
- 이전 메시지들은 이전 스레드에 귀속

#### 1b. 질문 패턴 감지 (2차)
- 다음 패턴이 나오면 새 스레드 시작:
  - `질문 드립니다`, `질문드립니다`, `문의 드립니다`, `궁금합니다`
  - `여쭤봅니다`, `확인 부탁`, `안녕하세요` + 질문 내용
  - `?`로 끝나는 2줄 이상 메시지 (새 발신자일 때)

#### 1c. 발신자 전환 + 주제 키워드 변화 (3차)
- 이전 스레드의 주요 발신자와 다른 사람이 새로운 주제 키워드로 말하기 시작하면 분리
- 키워드 유사도: 현재 스레드의 키워드 set vs 새 메시지의 키워드가 겹치지 않으면 분리

#### 1d. 시간 gap 축소
- 30분 → **15분**으로 축소 (오픈채팅방은 대화가 빠르게 전환됨)

### 2. 노이즈 필터링 강화 (`kakao_parser.py` 수정 가능)

#### 완전 제거 대상:
- 오픈채팅봇 메시지 (`[오픈채팅봇]`)
- 입퇴장 메시지
- "사진", "이모티콘", "동영상"만 있는 메시지
- 환영 메시지 패턴: `📚 한 발 앞서가는`, `━━━━━`, `여기서 배우고`

#### 부분 제거 대상:
- 단순 인사 (`안녕하세요`, `감사합니다`, `👏`, `🎉` 등만 있는 메시지)
- 1~2단어 리액션 (`ㅋㅋ`, `ㅎㅎ`, `ㄴㄴ`, `ㅇㅇ`)

### 3. LLM 정제 프롬프트 개선 (`_analyze_thread_with_llm`)

현재 프롬프트가 약해서 정제 품질이 낮다. 아래처럼 구체적으로 강화:

```
당신은 보험 전문 지식 정리 전문가입니다.
아래 보험설계사 오픈채팅방 대화 스레드를 분석하여 **하나의 Q&A 위키 항목**으로 정제하세요.

## 원칙
1. **원자적**: 하나의 질문-답변만 포함. 2개 이상 주제가 섞여있으면 가장 핵심 Q&A만 추출
2. **자기완결적**: 이 항목만 읽어도 완전히 이해 가능
3. **전문가 답변 중심**: 일반인 의견보다 전문가(손해사정사, 경력 설계사)의 답변을 우선
4. **노이즈 제거**: 인사, 이모티콘, 광고, 공지 내용 제외

## 출력 형식 (JSON)
{
  "title": "핵심 주제를 한 문장으로 (예: 안저 광응고술의 수술 해당 여부)",
  "category": "보상|고지의무|약관|상품|기타",
  "question": "질문자의 핵심 궁금증 1~2문장 요약",
  "answer": "전문가 답변의 핵심 결론 2~4문장 요약. 근거나 판례도 포함.",
  "keywords": ["관련", "키워드", "5~8개"],
  "confidence": "high|medium|low",
  "is_noise": false
}

만약 대화가 의미 있는 Q&A가 아니라면 (단순 인사, 공지, 광고 등):
{
  "is_noise": true,
  "reason": "노이즈 사유"
}

## 대화 스레드
{raw_thread}
```

### 4. 정제 결과 검증

정제 후 품질 체크:
- `is_noise: true`인 항목은 자동 필터링
- `title`이 20자 미만이거나 원본 그대로(`#궁금증...`)이면 재정제
- `answer`가 `question`과 동일하면 재정제
- `keywords`가 3개 미만이면 재정제

### 5. wiki_entries.json 재생성

개선된 로직으로 샘플 데이터(`/home/jay/workspace/data/kakao-sample.txt`)를 다시 처리:
1. 기존 wiki_entries.json 백업 (`wiki_entries.json.bak`)
2. 새 로직으로 재생성
3. 전후 비교 보고 (항목 수, 노이즈 필터링 수, 제목 품질 샘플)

### 6. LLM 호출 방법 (Haiku)
```python
import anthropic
client = anthropic.Anthropic()  # ANTHROPIC_API_KEY는 .env.keys에서 자동 로드
response = client.messages.create(
    model="claude-haiku-4-5-20251001",
    max_tokens=1024,
    messages=[{"role": "user", "content": prompt}]
)
```
- ANTHROPIC_API_KEY: `/home/jay/workspace/.env.keys`에 있음
- 외부 LLM (Gemini 등) 사용 금지. Haiku만 사용
- 비용 최적화: 5~10개 스레드를 한 번에 배치 처리

### 7. 테스트
- 스레드 분리 단위 테스트: `#궁금증` 기반 분리, 질문 패턴 감지, 15분 gap
- 노이즈 필터링 테스트: 오픈채팅봇, 인사, 리액션 제거
- 정제 프롬프트 테스트: mock LLM 응답으로 JSON 파싱 검증
- 기존 테스트 회귀 없음

## 완료 기준
1. `#궁금증`마다 별도 스레드로 분리
2. 하나의 wiki 항목에 하나의 Q&A만 포함 (원자적)
3. 오픈채팅봇/인사/리액션 노이즈 완전 제거
4. 제목이 깔끔 (예: "안저 광응고술의 수술 해당 여부")
5. wiki_entries.json 재생성 + 전후 비교 보고
6. 테스트 전체 PASS
7. pyright 에러 0건