diff --git a/journey/troubleshooting/251122_coldmail_slack_lists_column_mapping_spec.md b/journey/troubleshooting/251122_coldmail_slack_lists_column_mapping_spec.md new file mode 100644 index 0000000..56c66d8 --- /dev/null +++ b/journey/troubleshooting/251122_coldmail_slack_lists_column_mapping_spec.md @@ -0,0 +1,131 @@ +# Coldmail Slack Lists 컬럼 매핑 스펙 + +**날짜**: 2025-11-22 +**작성자**: Claude +**관련 파일**: +- `rb8001/app/services/coldmail_processor.py` +- `rb8001/app/services/ir_analyzer.py` + +--- + +## Slack Lists 실제 컬럼 구조 + +**확인 방법**: Slack Lists UI에서 확인 (이미지 참조) + +| 컬럼 이름 | 타입 | 용도 | 현재 코드 매핑 | +|-----------|------|------|----------------| +| 회사설명 | rich_text | 회사명 저장 | ❌ business_area 저장 중 | +| 날짜 | date | 이메일 수신일 | ✅ 정상 | +| 대표 | rich_text | 대표 이름 저장 | ❌ From 헤더 발신자 이름 | +| 이메일 | email | 이메일 주소 | ✅ 정상 | +| IR Deck | attachment | PDF 파일 첨부 | ✅ 정상 (attach_id) | +| 확인 | checkbox | 체크박스 | ❌ deck_id에 혼재 | + +--- + +## 요구사항 (테스트 기준) + +### 1. "회사설명" 컬럼 +- **저장 값**: `company_name` (IR 문서 또는 휴리스틱으로 추론한 회사명) +- **현재**: `business_area` 또는 제목 저장 (수정 필요) +- **검증**: Slack Lists에서 "회사설명" 컬럼에 회사명이 표시되어야 함 + +### 2. "대표" 컬럼 +- **저장 값**: 대표 이름 (`representative_name`) +- **우선순위**: + 1. IR 문서에서 추출한 대표 이름 + 2. From 헤더에서 파싱한 발신자 이름 (fallback) + 3. 없으면 "없음" (현재 정책 유지) +- **검증**: IR 문서에 대표 이름이 있으면 IR 우선, 없으면 From 헤더 사용 + +### 3. "IR Deck" 컬럼 +- **저장 값**: PDF 파일 (attachment 타입) +- **매핑**: `attach_id` 사용 (현재 정상) +- **컬럼 이름 매칭**: "ir deck", "irdeck", "ir 덱" 등 +- **검증**: IR PDF 파일이 "IR Deck" 컬럼에 첨부되어야 함 + +### 4. "확인" 컬럼 +- **저장 값**: 체크박스 (기본 False) +- **매핑**: `check_id` 별도 컬럼 +- **컬럼 이름 매칭**: "확인"만 (IR Deck과 분리) +- **검증**: "확인" 컬럼에 체크박스가 표시되어야 함 (IR Deck과 별도) + +--- + +## IR 문서 추출 필드 스펙 + +### 현재 추출 필드 (ir_analyzer.py:257-265, 296-304) +- company_name +- business_area +- investment_stage +- revenue +- growth_rate +- team_size +- tech_advantage + +### 추가 필요 필드 +- **representative_name**: 대표이사/CEO 이름 + - RAG 쿼리: "이 회사의 대표이사 또는 CEO 이름은 무엇인가?" + - LLM 프롬프트 키: `representative_name` + - 형식: "홍길동" (이름만) + +--- + +## 우선순위 정책 + +### 회사명 (company_name) +1. IR 문서 `company_name` (유효하면 사용) +2. 휴리스틱 `_derive_company_name` (제목/발신 도메인) +3. `business_area` (fallback) + +### 대표 이름 (representative_name) +1. IR 문서 `representative_name` (추출 시) +2. From 헤더 `contact_name` (발신자 이름) +3. "없음" (둘 다 없을 때) + +--- + +## 검증 시나리오 + +### 시나리오 1: IR 문서에 대표 이름 있는 경우 +- **IR 문서**: 대표이사 "김철수" 명시 +- **From 헤더**: "홍길동 " +- **예상 결과**: "대표" 컬럼 = "김철수" (IR 우선) + +### 시나리오 2: IR 문서에 대표 이름 없는 경우 +- **IR 문서**: 대표 이름 정보 없음 +- **From 헤더**: "홍길동 " +- **예상 결과**: "대표" 컬럼 = "홍길동" (From 헤더 fallback) + +### 시나리오 3: 둘 다 없는 경우 +- **IR 문서**: 대표 이름 정보 없음 +- **From 헤더**: "hong@company.com" (이름 없음) +- **예상 결과**: "대표" 컬럼 = "없음" + +### 시나리오 4: 회사설명 컬럼 검증 +- **IR 문서**: company_name="(주)테크스타트업" +- **예상 결과**: "회사설명" 컬럼 = "(주)테크스타트업" (company_name) + +--- + +## 구현 완료 조건 + +- [ ] IR analyzer에서 `representative_name` 추출 구현 +- [ ] Coldmail processor에서 회사설명 컬럼에 `company_name` 저장 +- [ ] 대표 컬럼에 IR 우선순위 적용 +- [ ] IR Deck과 확인 컬럼 분리 매핑 +- [ ] 검증 시나리오 1-4 모두 통과 + +--- + +## 교훈 + +### 문서화 부족 +- Slack Lists 컬럼 구조가 코드에 휴리스틱으로만 존재 +- 실제 컬럼 이름과 매핑 정책이 명시적으로 문서화되지 않음 +- 교훈: UI와 코드 매핑은 항상 문서로 정리하고 동기화 + +### 필드 이름 일관성 +- IR 추출 필드명 (`representative_name`)과 사용처 필드명 (`contact_name`) 혼재 +- 교훈: 필드 이름은 추출 단계부터 사용 단계까지 일관성 유지 + diff --git a/journey/troubleshooting/251122_ir_representative_name_extraction_spec.md b/journey/troubleshooting/251122_ir_representative_name_extraction_spec.md new file mode 100644 index 0000000..8bd79be --- /dev/null +++ b/journey/troubleshooting/251122_ir_representative_name_extraction_spec.md @@ -0,0 +1,86 @@ +# IR 문서 대표 이름 추출 스펙 + +**날짜**: 2025-11-22 +**작성자**: Claude +**관련 파일**: +- `rb8001/app/services/ir_analyzer.py` + +--- + +## 요구사항 + +IR 문서에서 대표이사/CEO 이름을 추출하여 coldmail processor에서 "대표" 컬럼에 저장. + +--- + +## 현재 상태 + +### 추출 필드 목록 (ir_analyzer.py:257-265) +- company_name +- business_area +- investment_stage +- revenue +- growth_rate +- team_size +- tech_advantage + +**대표 이름 필드 없음** + +### LLM 프롬프트 (ir_analyzer.py:296-304) +- `exact keys` 목록에 `representative_name` 없음 + +--- + +## 설계 + +### 1. RAG 쿼리 추가 +**위치**: `ir_analyzer.py:257-265` queries 딕셔너리 + +**추가 쿼리**: +```python +"representative_name": "이 회사의 대표이사 또는 CEO 이름은 무엇인가? (예: 홍길동, 김철수)" +``` + +### 2. LLM 프롬프트 키 추가 +**위치**: `ir_analyzer.py:296-304` prompt의 `exact keys` 목록 + +**추가 키**: +```python +- representative_name: 대표이사 또는 CEO 이름 (예: "홍길동", "김철수") +``` + +### 3. 반환 형식 +**타입**: `str` +**형식**: 이름만 (예: "홍길동", "김철수") +**없을 때**: "N/A" + +--- + +## 우선순위 정책 + +**coldmail_processor.py에서 사용**: +1. IR 문서 `representative_name` (유효하면) +2. From 헤더 `contact_name` (fallback) +3. "없음" (둘 다 없을 때) + +--- + +## 검증 기준 + +### 성공 케이스 +- IR 문서에 "대표이사: 홍길동" 명시 → `representative_name = "홍길동"` +- IR 문서에 "CEO: 김철수" 명시 → `representative_name = "김철수"` + +### 실패 케이스 +- IR 문서에 대표 이름 정보 없음 → `representative_name = "N/A"` +- IR 문서 파싱 실패 → `representative_name = "N/A"` + +--- + +## 구현 완료 조건 + +- [ ] RAG 쿼리에 `representative_name` 추가 +- [ ] LLM 프롬프트에 `representative_name` 키 추가 +- [ ] 실제 IR 문서로 테스트 (대표 이름 있는 경우/없는 경우) +- [ ] coldmail processor에서 IR `representative_name` 우선 사용 +