From f848e0d70e49c7e74ccb27d43885a5576edb3d08 Mon Sep 17 00:00:00 2001 From: Claude-51124 Date: Fri, 13 Mar 2026 16:56:43 +0900 Subject: [PATCH] Document coldmail IR selection fix --- journey/README.md | 5 + ...ail_ir_분석대상_오선택_디버그.md | 176 ++++++++++++++++++ journey/debug/README.md | 18 ++ ..._읽기시점_전건저장_아이디어.md | 86 +++++++++ ...ir_분석대상_선택_정합화_계획.md | 116 ++++++++++++ ..._선택_정합화_구현및배포검증.md | 33 ++++ 6 files changed, 434 insertions(+) create mode 100644 journey/debug/260313_coldmail_ir_분석대상_오선택_디버그.md create mode 100644 journey/debug/README.md create mode 100644 journey/ideas/260313_이메일_읽기시점_전건저장_아이디어.md create mode 100644 journey/plans/260313_coldmail_ir_분석대상_선택_정합화_계획.md create mode 100644 journey/worklog/260313_coldmail_ir_분석대상_선택_정합화_구현및배포검증.md diff --git a/journey/README.md b/journey/README.md index 4587b74..700020f 100644 --- a/journey/README.md +++ b/journey/README.md @@ -68,6 +68,11 @@ - Human-in-the-Loop Intent Learning 아키텍처 – `../300_architecture/390_human_in_the_loop_intent_learning.md` +## Debug + +- [디버그 인덱스](./debug/README.md) – 구현 직전 단계에서 문제 지점과 상태 차이를 고정하는 보조 문서 계층 +- [콜드메일 IR 분석이 첫 번째 PDF를 잘못 선택하는 상태](./debug/260313_coldmail_ir_분석대상_오선택_디버그.md) + ## Worklog Journey - 프롬프트DB·자기개선루프 기본구현 검증 및 계획 종결 – `worklog/260310_프롬프트DB_자기개선루프_기본구현_검증및계획종결.md` diff --git a/journey/debug/260313_coldmail_ir_분석대상_오선택_디버그.md b/journey/debug/260313_coldmail_ir_분석대상_오선택_디버그.md new file mode 100644 index 0000000..21b2110 --- /dev/null +++ b/journey/debug/260313_coldmail_ir_분석대상_오선택_디버그.md @@ -0,0 +1,176 @@ +--- +tags: [debug, coldmail, ir, attachments, rb8001] +--- + +# 콜드메일 IR 분석이 첫 번째 PDF를 잘못 선택하는 상태 + +**작성일**: 2026-03-13 +**상태**: closed (fixed) +**상위 원칙**: [0_VALUE Writing Principles](https://github.com/happybell80/0_VALUE/blob/main/02_Governance/writing-principles.md), [문서 작성 원칙](../../book/300_architecture/312_writing-principles.md) + +## 관련 문서 +- [Debug 인덱스](./README.md) +- [콜드메일 IR 분석대상 선택 정합화 계획](../plans/260313_coldmail_ir_분석대상_선택_정합화_계획.md) +- [콜드메일 IR 분석대상 선택 정합화 구현 및 배포 검증](../worklog/260313_coldmail_ir_분석대상_선택_정합화_구현및배포검증.md) + +## 1. 이 문서의 역할 +- 이 문서는 콜드메일 IR 분석 문제의 "무엇이 잘못 연결됐는가"와 "왜 지금 상태가 문제인가"를 고정합니다. +- 수정 방법, 작업 순서, 검증 절차 확정은 다음 `plans` 문서에서 다룹니다. +- 이 문서는 플랜이 바로 받아야 할 입력 상태를 만들기 위해, 현재 상태와 목표 상태 사이의 차이를 가능한 한 좁혀 적습니다. + +## 2. 문제 한 줄 정의 +- 현재 콜드메일 프로세스는 "IR 자료를 분석"해야 하지만, 실제로는 "업로드된 첫 번째 PDF"를 분석 대상으로 사용합니다. + +## 3. 현재 상태 + +### 3.1 오늘 실제 실행에서 확인된 상태 +- 실행 시각: `2026-03-13 09:05 KST` +- 대상 메일: `email_id=21037` +- 첨부 PDF 인식: + - `모바일콘 재무제표 표준(2024년).pdf` + - `모바일콘 회사소개서_v.1.0_01 (2).pdf` + - `[Brand IR] Introduction PPT2.26-압축됨.pdf` +- 업로드 결과: + - 첫 번째 업로드 `document_id=95bc416e-bdf1-40b3-9de2-6073c8c1b313` + - 두 번째 업로드 `document_id=486bfc9e-fcc2-4229-a080-6af6fb5cc940` +- 이후 IR 분석 실행: + - `document_id=95bc416e-bdf1-40b3-9de2-6073c8c1b313`로 분석 시작 +- 이 값은 로그상 `모바일콘 재무제표 표준(2024년).pdf`에 대응합니다. +- `document_id=486bfc9e-fcc2-4229-a080-6af6fb5cc940`는 실제 저장소에서 `모바일콘 회사소개서_v.1.0_01 (2).pdf`로 확인됐습니다. +- 즉 오늘 사례는 "IR 후보 파일이 없어서 실패한 상태"가 아니라, "IR 후보 파일이 이미 있었지만 다른 파일을 선택한 상태"입니다. + +### 3.2 현재 코드가 만드는 상태 +- 첨부파일 처리 함수는 PDF 여러 개를 업로드하고 `document_ids` 리스트를 반환합니다. +- 하지만 이후 단계는 `document_ids[0]`만 사용합니다. +- 따라서 "어떤 PDF가 IR 자료인가"를 고르는 선택 단계가 없습니다. +- 결과적으로 첨부 순서가 곧 분석 대상이 됩니다. + +### 3.3 오늘 바로 수정 시 활용 가능한 상태 +- 오늘 메일의 회사소개서 PDF는 이미 `skill-rag-file`에 저장돼 있습니다. +- 따라서 이 이슈를 닫기 위해 필요한 것은 메일 재수집이 아니라, 이미 저장된 첨부들 중 올바른 분석 대상을 선택하는 로직입니다. +- 플랜은 "재조회가 필요한가"보다 "기저 저장 구조 없이도 현재 저장된 첨부들로 선택을 바로잡을 수 있는가"를 기준으로 출발할 수 있습니다. + +## 4. 기대 상태 + +### 4.1 업무 기준 기대 상태 +- 콜드메일에 PDF가 여러 개 있더라도, IR 분석은 IR 자료 또는 회사소개서에 해당하는 문서를 선택해 실행되어야 합니다. +- 재무제표, 부록, 별도 참고자료는 IR 분석 대상이 아니어야 합니다. + +### 4.2 시스템 기준 기대 상태 +- 첨부 처리 결과는 단순 `document_ids` 리스트가 아니라, "분석 대상으로 선택된 문서"가 명시적으로 구분된 상태여야 합니다. +- Slack List 첨부, `coldmail_analyze_ir` 버튼 payload, 실제 `IRDeckAnalyzer.analyze()` 호출이 모두 같은 선택 문서를 가리켜야 합니다. +- 사용자가 Slack에서 "이 기업을 분석해 드릴까요?"를 눌렀을 때도 동일한 문서가 재사용되어야 합니다. +- 이미 저장된 첨부가 있는 경우에는 재다운로드 없이 그 선택 결과를 재사용할 수 있어야 합니다. + +## 4.3 이번 플랜의 닫힘 기준이 되어야 하는 상태 +- 오늘 같은 다중 PDF 콜드메일에서 버튼 클릭 시 회사소개서 또는 IR 자료로 분류된 PDF가 실제 분석 입력으로 들어가야 합니다. +- 잘못 선택된 기존 첫 번째 PDF 고정 경로는 `process_coldmail`, Slack 첨부 생성, Slack 버튼 payload에서 제거돼야 합니다. +- 선택된 문서가 무엇이었는지 로그로 확인 가능해야 합니다. +- 적어도 오늘 메일 `21037` 사례를 다시 눌렀을 때 같은 재무제표 오분석이 재발하지 않아야 합니다. + +## 5. 문제 지점 + +### 5.1 첫 번째 고정 선택 지점 +- `rb8001/app/services/coldmail_processor.py:252` + - 첨부 PDF를 `document_ids`로 수집합니다. +- `rb8001/app/services/coldmail_processor.py:264` + - IR 지표 추출이 `document_ids[0]`으로 시작됩니다. +- `rb8001/app/services/coldmail_processor.py:518` + - IR Deck 평가도 `document_ids[0]`으로 시작됩니다. +- `rb8001/app/services/coldmail_processor.py:749` + - Slack 첨부 파일 다운로드도 `document_ids[0]`을 사용합니다. +- `rb8001/app/services/coldmail_processor.py:902` + - Slack `coldmail_analyze_ir` 버튼 payload도 `document_ids[0]`을 전달합니다. + +### 5.2 선택 정보가 사라지는 지점 +- `rb8001/app/services/naverworks_file_processor.py:217-296` + - 이 함수는 PDF를 필터링하고 병렬 업로드한 뒤 `document_id` 목록만 반환합니다. +- 이 반환값에는 파일명과 `document_id`의 대응 정보가 이후 단계에서 유지되지 않습니다. +- 따라서 후속 단계는 "어떤 파일이 어떤 문서 ID인가"를 기준으로 판단할 수 없습니다. + +### 5.3 플랜이 반드시 다뤄야 할 결정 포인트 +- 선택 로직은 어느 단계에서 실행할 것인가 + - 첨부 업로드 직후 + - `process_coldmail()` 내부 + - Slack 버튼 payload 생성 직전 +- 선택 결과를 어떤 형태로 유지할 것인가 + - 단일 `selected_document_id` + - `filename + document_id + selection_reason` + - 이메일 단위 첨부 매핑 구조 +- 선택 실패를 어떻게 드러낼 것인가 + - 실패 로그만 남길지 + - 버튼을 비활성화할지 + - 확인 대기 상태로 보낼지 + +## 6. 왜 이것이 문제인가 + +### 6.1 현재 발생하는 실제 문제 +- 오늘 사례에서 IR 분석은 회사소개서가 아니라 재무제표를 대상으로 실행됐습니다. +- 그 결과 `IR Deck analysis completed` 로그와 Slack 결과 링크는 "IR 자료 평가"처럼 보이지만, 실제 입력 문서는 다른 파일입니다. +- 즉 사용자에게 노출되는 기능명과 실제 입력 데이터가 어긋납니다. + +### 6.2 사용자 체감 문제 +- 운영자는 Slack에서 "IR 분석 완료" 메시지를 보고도 실제로는 잘못된 파일이 분석됐다는 사실을 알기 어렵습니다. +- 점수와 등급이 낮거나 이상해도, 그것이 회사 내용이 아니라 재무제표를 읽은 결과인지 즉시 드러나지 않습니다. + +### 6.3 시스템 신뢰 문제 +- 이 상태는 단순 정확도 저하가 아니라 입력 계약 위반입니다. +- 기능 이름은 `IR Deck 분석`인데 실제 입력은 `첫 번째 PDF`이므로, 결과가 맞더라도 우연에 의존한 상태입니다. +- 첨부 순서가 바뀌면 결과가 바뀌는 구조이므로 재현성과 설명 가능성이 깨집니다. + +## 6.4 왜 지금 바로 플랜으로 넘어갈 수 있는가 +- 문제 재현 로그가 이미 확보됐습니다. +- 잘못 사용된 `document_id`와 올바른 IR 후보 `document_id`가 모두 확인됐습니다. +- 고정 선택 지점도 코드에서 모두 특정됐습니다. +- 따라서 추가 리서치 없이도 플랜은 "선택 로직 도입과 선택 결과 전달 경로 정합화"를 바로 결정할 수 있습니다. + +## 7. 확인된 사실 +- `2026-03-13 09:05:11` 로그에서 `message 21037`의 PDF 3개 처리 시작이 확인됐습니다. +- `2026-03-13 09:05:13` 로그에서 재무제표 PDF가 먼저 `document_id=95bc416e-...`로 업로드됐습니다. +- `2026-03-13 09:05:23` 로그에서 회사소개서 PDF가 `document_id=486bfc9e-...`로 업로드됐습니다. +- `2026-03-13 09:05:49` 로그에서 실제 IR Deck 분석은 `document_id=95bc416e-...`로 시작됐습니다. +- `2026-03-13 09:07:41` 이후 사용자의 재분석 액션도 동일한 `document_id=95bc416e-...`를 재사용했습니다. +- `skill-rag-file` 저장소 조회에서 `document_id=486bfc9e-...`의 파일명은 `모바일콘 회사소개서_v.1.0_01 (2).pdf`로 확인됐습니다. +- `skill-rag-file` 저장소 조회에서 `document_id=95bc416e-...`의 파일명은 `모바일콘 재무제표 표준(2024년).pdf`로 확인됐습니다. + +## 7.1 아직 필요하지 않은 추가 리서치 +- 오늘 건을 바로 수정하기 위해 메일 원문을 다시 받아올 필요는 없습니다. +- 이미 저장된 두 개의 `document_id`만으로도 잘못된 선택과 올바른 후보를 구분할 수 있습니다. +- 세 번째 PDF의 업로드 실패 원인은 별도 문제일 수 있지만, 오늘 오분석 버그를 닫는 데 필수 선행조건은 아닙니다. + +## 8. 현재 상태가 일으키는 결과 +- 콜드메일 등록은 성공처럼 보이지만 IR 분석 입력 품질이 보장되지 않습니다. +- Slack List의 첨부 파일과 실제 분석 파일이 "우연히 같거나 다를 수 있는 상태"가 됩니다. +- 향후 PDF가 2개 이상 붙는 콜드메일마다 같은 문제가 반복될 수 있습니다. +- 재무제표, 소개서, 브로셔, 보도자료가 함께 오는 메일에서 특히 오분석 가능성이 높습니다. + +## 9. 앞으로 되어야 하는 상태 +- 콜드메일 프로세스는 "PDF 업로드"와 "IR 분석 대상 선택"을 분리된 단계로 가져야 합니다. +- 선택된 분석 대상은 파일명 근거와 함께 유지되어야 합니다. +- Slack 표시용 파일, IR 분석용 `document_id`, 재분석 버튼 payload는 모두 같은 선택 결과를 따라야 합니다. +- 선택 근거가 없거나 후보가 복수로 충돌하면, 조용히 첫 번째 파일로 진행하지 말고 선택 실패가 드러나야 합니다. + +## 9.1 오늘 사례 기준 목표 상태 +- 오늘 메일 `21037`에서 다시 분석 버튼을 눌렀을 때, 분석 입력은 `95bc416e-...`가 아니라 `486bfc9e-...` 또는 정책상 더 높은 우선순위를 받은 IR 후보여야 합니다. +- 오늘 사례 기준으로 Slack 첨부도 같은 선택 문서를 따라야 합니다. +- 오늘 사례 기준으로 로그에는 "선택된 IR 문서"가 파일명 또는 `document_id` 수준으로 남아야 합니다. + +## 10. 미확정 항목 +- 오늘 메일의 세 번째 PDF `[Brand IR] Introduction PPT2.26-압축됨.pdf`가 업로드 실패한 이유는 이 문서 범위에서 확정하지 않았습니다. +- 현재 업무 기준에서 "회사소개서"와 "`Brand IR` 문서" 중 어떤 것을 우선 IR 자료로 볼지 아직 정책으로 고정하지 않았습니다. +- 첨부 파일명만으로 충분한지, 본문/제목/페이지 텍스트까지 함께 봐야 하는지는 아직 결정하지 않았습니다. + +## 10.1 이번 플랜 범위 밖으로 둘 수 있는 항목 +- 전체 이메일 저장 구조 전환 +- 첨부 업로드 실패 원인 일반화 +- 다중 첨부 문서 선택의 장기 정책 고도화 +- 회사소개서/브랜드 IR/재무제표 외 다른 문서군까지 포괄하는 범용 분류 체계 + +## 11. 디버그 결론 +- 이 이슈의 본질은 분석 모델 품질 문제가 아니라, IR 분석 입력 문서를 잘못 고르는 선택 로직 부재입니다. +- 지금 상태는 "IR 분석"이라는 이름과 실제 입력 대상이 어긋난 버그 상태입니다. +- 오늘 사례 기준으로는 이미 저장된 회사소개서 PDF가 존재하므로, 플랜은 메일 재조회가 아니라 선택 로직과 전달 경로 정합화에 집중하면 됩니다. + +## 12. 종료 +- 이 디버그는 `첫 번째 PDF 고정 선택` 버그 수정, 배포, 검증까지 완료되어 닫습니다. +- 구현과 검증 결과는 [콜드메일 IR 분석대상 선택 정합화 구현 및 배포 검증](../worklog/260313_coldmail_ir_분석대상_선택_정합화_구현및배포검증.md)에 연결합니다. diff --git a/journey/debug/README.md b/journey/debug/README.md new file mode 100644 index 0000000..f7ae5c8 --- /dev/null +++ b/journey/debug/README.md @@ -0,0 +1,18 @@ +tags: [debug, journey, documentation, index] + +# Debug + +`debug`는 구현 직전 단계에서 문제 지점과 상태 차이를 선명하게 고정하는 보조 문서 계층입니다. +`troubleshooting`의 현재 문제 정의, `research`의 원인 수집, `plans`의 실행 결정 사이에서 "정확히 어디가 잘못 연결됐는가"를 짧고 명확하게 남길 때 사용합니다. + +## 경계 + +- `debug`는 상위 SSOT의 기본 문서 축(`ideas/scenarios/troubleshooting -> research -> plans -> worklog`)을 대체하지 않습니다. +- `debug`는 구현 방법이나 작업 순서를 확정하지 않습니다. 그것은 `plans`의 역할입니다. +- `debug`는 완료 보고를 쓰지 않습니다. 구현이 끝나면 `worklog` 또는 관련 완료 문서로 연결합니다. +- `debug`는 현재 상태, 목표 상태, 문제 지점, 왜 이것이 문제인지에 집중합니다. + +## 문서 맵 + +- [콜드메일 IR 분석이 첫 번째 PDF를 잘못 선택하는 상태](./260313_coldmail_ir_분석대상_오선택_디버그.md) + - 상태: `closed (fixed)` diff --git a/journey/ideas/260313_이메일_읽기시점_전건저장_아이디어.md b/journey/ideas/260313_이메일_읽기시점_전건저장_아이디어.md new file mode 100644 index 0000000..af51c41 --- /dev/null +++ b/journey/ideas/260313_이메일_읽기시점_전건저장_아이디어.md @@ -0,0 +1,86 @@ +tags: [ideas, email, persistence, naverworks, storage] + +# 이메일 읽기시점 전건저장 아이디어 + +## 배경 +- 현재 로빙의 이메일 처리 경로는 메일을 먼저 조회하고, 그중 콜드메일로 판정된 메일만 후속 처리 단계에서 저장합니다. +- 이 구조에서는 "왜 이 메일이 선택됐는가", "선택되지 않은 메일과 무엇이 달랐는가", "첨부파일이 여러 개인 경우 어떤 파일이 분석 대상으로 이어졌는가"를 나중에 정확히 추적하기 어렵습니다. +- 특히 콜드메일 오분석처럼 입력 선택 경로가 문제일 때, 저장되지 않은 일반 메일과 저장된 콜드메일 사이의 차이를 같은 기준으로 비교하기 어렵습니다. + +## 문제 인식 +- 현재 구조는 이메일을 "업무 데이터"가 아니라 "필터를 통과한 결과물만 남기는 임시 입력"처럼 다루고 있습니다. +- 그 결과: + - 필터 이전 상태 추적이 약합니다. + - 이메일 처리 흐름을 재현하기 어렵습니다. + - 첨부 선택, 본문 해석, 분류 기준을 사후 검증하기 어렵습니다. +- 이메일 관련 기능이 늘어날수록 "콜드메일만 저장" 구조는 한계가 커질 수 있습니다. + +## 핵심 아이디어 +- 이메일 관련 정보는 **읽는 시점(fetch 단계)** 에 먼저 저장합니다. +- 즉 "콜드메일인지 아닌지"와 무관하게, 조회된 이메일을 공통 이메일 저장소에 먼저 적재한 뒤 후속 분류와 분석은 그 저장된 데이터를 기준으로 이어갑니다. + +## 이 아이디어가 뜻하는 상태 + +### 1. 이메일은 필터 결과가 아니라 원본 단위로 관리한다 +- 콜드메일은 이메일 저장소 위에 얹히는 "분류 결과"가 됩니다. +- 분석, 분류, 첨부 선택, Slack 전송은 모두 저장된 이메일 레코드를 참조합니다. + +### 2. 읽기와 해석을 분리한다 +- 읽기 단계: + - 메일 식별자 + - 제목 + - 본문 + - 발신자 + - 수신 시각 + - 첨부 메타데이터 + - 원본 제공자 정보 + 를 저장합니다. +- 해석 단계: + - 콜드메일 여부 + - 신뢰도 + - 선택된 분석 문서 + - 후속 액션 상태 + 를 별도 상태로 관리합니다. + +### 3. 첨부도 이메일 중심으로 연결한다 +- 첨부파일은 단순히 `document_id`만 흩어지는 구조가 아니라, "어느 이메일의 어떤 첨부였는지"가 유지되어야 합니다. +- 이후 IR 분석이 특정 첨부를 선택했다면, 그 선택 결과도 이메일 레코드에 연결됩니다. + +## 기대 효과 + +### 1. 추적성 강화 +- 어떤 메일이 왜 콜드메일로 갔는지, 왜 안 갔는지 같은 비교가 쉬워집니다. +- 잘못된 첨부 선택이나 본문 파싱 문제를 원본 기준으로 다시 볼 수 있습니다. + +### 2. 기능 확장 기반 +- 콜드메일 외에도 일반 투자문의, 회신 필요 메일, 중요 공지 메일 같은 다른 분류 체계로 확장하기 쉬워집니다. +- 이메일은 하나의 원본 저장소가 되고, 각 기능은 그 위에서 다른 해석 레이어를 붙일 수 있습니다. + +### 3. 재현성 강화 +- 이후 필터 로직이 바뀌어도 과거 메일 집합을 기준으로 재분류·재평가가 가능해집니다. +- 운영 중 문제 발생 시 "현재 메일함 상태"가 아니라 "당시 읽은 레코드" 기준으로 분석할 수 있습니다. + +## 아직 아이디어 단계인 이유 +- 어떤 저장 범위를 기본값으로 할지 아직 고정되지 않았습니다. + - 제목/본문만 저장할지 + - 헤더 전체를 저장할지 + - 첨부 바이너리까지 읽기 단계에서 바로 저장할지 +- 저장 위치도 아직 결정되지 않았습니다. + - rb8001 DB 단일 저장 + - skill-email 중심 저장 + - 이메일 원본과 첨부 메타를 분리 저장 +- 중복 읽기, 보존 기간, 개인정보/운영 데이터 경계도 아직 정책으로 확정되지 않았습니다. + +## 이 아이디어가 열어두는 질문 +1. 이메일 저장의 SSOT는 `rb8001`이 맞는가, 아니면 `skill-email`이 맞는가? +2. "읽었다"의 기준은 목록 조회 시점인가, 상세 조회 시점인가? +3. 첨부는 메타데이터만 우선 저장하고 실제 파일은 필요 시 가져오는 구조가 나은가? +4. 동일 메일 재조회 시 업데이트 정책은 어떻게 가져갈 것인가? +5. 이메일 저장과 콜드메일 분류 결과를 어떤 관계로 분리할 것인가? + +## 바로 실행 결정으로 넘기지 않은 이유 +- 이 아이디어는 단순 컬럼 추가가 아니라 이메일 도메인의 저장 책임을 다시 정하는 문제입니다. +- 따라서 이번 단계에서는 "이메일은 읽는 시점에 먼저 저장한다"는 방향만 열어두고, 실제 스키마·책임 경계·동기화 방식은 별도 계획 문서에서 닫아야 합니다. + +## 한 줄 결론 +- 콜드메일만 저장하는 구조보다, 이메일을 읽는 시점에 전건 저장하고 그 위에서 분류·분석을 얹는 구조가 더 추적 가능하고 확장 가능한 방향입니다. diff --git a/journey/plans/260313_coldmail_ir_분석대상_선택_정합화_계획.md b/journey/plans/260313_coldmail_ir_분석대상_선택_정합화_계획.md new file mode 100644 index 0000000..7d03717 --- /dev/null +++ b/journey/plans/260313_coldmail_ir_분석대상_선택_정합화_계획.md @@ -0,0 +1,116 @@ +--- +tags: [plans, coldmail, ir, attachments, rb8001] +--- + +# 콜드메일 IR 분석대상 선택 정합화 계획 + +**작성일**: 2026-03-13 +**상태**: 완료 (2026-03-13) +**목표**: 콜드메일 다중 PDF 첨부에서 올바른 IR 대상 문서를 선택하고, 선택 실패 시 잘못된 분석 버튼 대신 명확한 상태 메시지를 노출하도록 고정합니다. + +## 관련 문서 +- [콜드메일 IR 분석이 첫 번째 PDF를 잘못 선택하는 상태](../debug/260313_coldmail_ir_분석대상_오선택_디버그.md) +- [콜드메일 IR 분석대상 선택 정합화 구현 및 배포 검증](../worklog/260313_coldmail_ir_분석대상_선택_정합화_구현및배포검증.md) + +## 1. 문제 정의 +- 현재 콜드메일 프로세스는 첨부 PDF를 여러 개 업로드해도 후속 단계에서 `document_ids[0]`만 사용합니다. +- 그 결과 오늘 메일 `21037`처럼 회사소개서가 이미 저장돼 있어도, 첫 번째 PDF인 재무제표가 IR 분석 대상으로 고정될 수 있습니다. +- 이 상태는 `IR Deck 분석`이라는 기능명과 실제 입력 문서가 어긋난 버그입니다. + +## 2. 이번 계획의 결정 +- 메일을 다시 조회하는 방향으로 닫지 않습니다. +- 이미 저장된 첨부파일들 중에서 IR 분석 대상을 선택하는 로직을 추가하고, 그 선택 결과를 후속 단계 전체에 일관되게 전달합니다. +- 선택 실패 시 조용히 첫 번째 PDF로 진행하지 않습니다. +- Slack 메시지에서는 신뢰도 `%`를 노출하지 않습니다. + +## 3. 범위 +- 포함: + - 첨부 업로드 결과에 파일명과 `document_id`의 대응 정보 유지 + - IR 분석 대상 선택 로직 추가 + - 선택된 문서를 IR 분석, Slack 첨부, Slack 버튼 payload에 동일 적용 + - 선택 실패 시 `메일에서 IR 자료를 찾지 못했습니다.` 상태 메시지 노출 + - Slack 메시지에서 회사명 우선 노출 + - Slack 메시지에서 정확도 `%` 제거 + - 선택 결과 로그 가시화 + - 다중 PDF 첨부 테스트 추가 +- 제외: + - 전체 이메일 저장 구조 전환 + - 첨부 업로드 실패 일반화 처리 + - 장기적 범용 문서 분류 시스템 + +## 4. 구현 원칙 +- 선택 없는 첫 번째 PDF 고정 사용을 제거합니다. +- 선택 결과는 단일 값이 아니라 근거가 보이는 구조로 유지합니다. +- 이미 저장된 첨부가 있으면 재다운로드보다 저장된 선택 결과 재사용을 우선합니다. +- 선택 실패는 성공처럼 포장하지 않고 로그와 후속 경로에 드러냅니다. +- 콜드메일 여부와 IR 자료 존재 여부를 분리해 표시합니다. +- 사용자 메시지는 `어느 회사의 콜드메일이 왔는지`를 먼저 보여줍니다. + +## 5. 구현 단계 + +### A. 첨부 매핑 구조 도입 +- `process_naverworks_attachments()`는 단순 `document_id` 리스트 대신, 최소한 아래 정보를 유지하는 결과를 반환합니다. + - `filename` + - `document_id` + - `attachment_id` +- 후속 단계가 파일명과 문서 ID의 대응을 잃지 않도록 합니다. + +### B. IR 대상 선택 함수 추가 +- `coldmail_processor.py` 내부 또는 별도 유틸리티에 "IR 대상 선택" 함수를 둡니다. +- 1차 선택 기준: + - 우선 후보: `ir`, `deck`, `pitch`, `introduction`, `회사소개서` + - 후순위 또는 제외 후보: `재무제표`, `financial`, `감사`, `부록` +- 반환값은 최소 아래를 포함합니다. + - `selected_document_id` + - `selected_filename` + - `selection_reason` +- 후보가 없거나 동률 충돌이면 실패 상태를 반환합니다. + +### C. 선택 결과 단일화 +- 아래 경로가 모두 같은 선택 결과를 사용하도록 정리합니다. + - IR 지표 추출 + - `IRDeckAnalyzer.analyze()` + - Slack List 첨부 파일 다운로드 + - `coldmail_analyze_ir` 버튼 payload +- `document_ids[0]` 직접 참조는 제거합니다. + +### D. 선택 실패 가시화 +- 선택 실패 시 남길 로그: + - 이메일 ID + - 후보 파일명 목록 + - 실패 이유 +- 자동 등록은 유지하되, IR 분석 버튼은 생성하지 않습니다. +- Slack에는 `메일에서 IR 자료를 찾지 못했습니다.` 상태 메시지를 남깁니다. +- 메시지 본문에는 먼저 회사명을 보여준 뒤 IR 자료 부재 상태를 붙입니다. + +### E. 테스트 추가 +- 최소 테스트 케이스: + - `재무제표 + 회사소개서` 동시 첨부 시 회사소개서 선택 + - `IR + 재무제표` 동시 첨부 시 IR 선택 + - IR 후보 없음 시 선택 실패 + 버튼 미노출 + 상태 메시지 노출 + - 선택된 `document_id`가 Slack 버튼 payload와 실제 분석 입력에 동일 반영 + - Slack 메시지에 정확도 `%`가 노출되지 않음 + +## 6. 오늘 사례에 대한 적용 기준 +- 메일 `21037` 기준으로는 `모바일콘 회사소개서_v.1.0_01 (2).pdf`에 연결된 `document_id=486bfc9e-fcc2-4229-a080-6af6fb5cc940`가 분석 대상이 되어야 합니다. +- 오늘 사례를 다시 실행하거나 동일 버튼 흐름을 재현할 때, `95bc416e-bdf1-40b3-9de2-6073c8c1b313`이 아니라 선택된 회사소개서 문서가 분석에 들어가야 합니다. + +## 7. 검증 기준 +- 다중 PDF 콜드메일에서 선택된 파일명과 `document_id`가 로그에 남습니다. +- Slack 첨부 파일, IR 분석 호출, 재분석 버튼 payload가 동일한 `selected_document_id`를 사용합니다. +- 오늘 사례 유형(`재무제표 + 회사소개서`)에서 재무제표가 더 이상 IR 분석 입력으로 들어가지 않습니다. +- 선택 실패 케이스에서 첫 번째 PDF로 조용히 진행하는 로그가 0건입니다. +- 선택 실패 케이스에서 Slack에는 회사명과 함께 `메일에서 IR 자료를 찾지 못했습니다.` 메시지만 남고 분석 버튼은 없습니다. +- Slack 메시지에서 신뢰도 `%` 텍스트는 0건입니다. + +## 8. 후속 경계 +- 전체 이메일 저장은 별도 아이디어 문서에서 다루고, 이번 계획 범위에 섞지 않습니다. +- 장기적으로는 파일명 기반 규칙만으로 충분하지 않을 수 있으므로, 이후 본문/제목/문서 텍스트까지 포함한 점수화 방식은 별도 계획으로 분리합니다. +- 콜드메일 판정과 IR 자료 존재 판정을 분리한 장기 UX 설계는 이번 계획에서 다루지 않습니다. + +## 한 줄 결론 +- 이번 계획은 "첫 번째 PDF" 고정 버그를 제거하고, 올바른 IR 문서를 선택할 때만 분석 버튼을 노출하며, 실패 시에는 회사명과 함께 `메일에서 IR 자료를 찾지 못했습니다.` 상태를 보여주는 작업입니다. + +## 완료 메모 +- 구현 및 배포 검증 완료. +- 상세 결과는 [콜드메일 IR 분석대상 선택 정합화 구현 및 배포 검증](../worklog/260313_coldmail_ir_분석대상_선택_정합화_구현및배포검증.md)에서 관리합니다. diff --git a/journey/worklog/260313_coldmail_ir_분석대상_선택_정합화_구현및배포검증.md b/journey/worklog/260313_coldmail_ir_분석대상_선택_정합화_구현및배포검증.md new file mode 100644 index 0000000..30b8955 --- /dev/null +++ b/journey/worklog/260313_coldmail_ir_분석대상_선택_정합화_구현및배포검증.md @@ -0,0 +1,33 @@ +--- +tags: [worklog, coldmail, ir, attachments, rb8001, deploy] +--- + +# 콜드메일 IR 분석대상 선택 정합화 구현 및 배포 검증 + +## 관련 문서 +- [콜드메일 IR 분석이 첫 번째 PDF를 잘못 선택하는 상태](../debug/260313_coldmail_ir_분석대상_오선택_디버그.md) +- [콜드메일 IR 분석대상 선택 정합화 계획](../plans/260313_coldmail_ir_분석대상_선택_정합화_계획.md) + +## 완료 요약 +- 다중 PDF 첨부에서 `document_ids[0]`를 그대로 쓰던 경로를 제거하고, 첨부 `filename-document_id` 매핑을 유지하도록 수정했습니다. +- 파일명 기반 선택 로직을 추가해 `회사소개서/IR/deck/pitch` 후보를 우선 선택하고, `재무제표/감사` 같은 비IR 문서는 제외 방향으로 점수화했습니다. +- IR 후보 선택 실패 시에는 잘못된 분석 버튼을 만들지 않고, Slack 메시지에 `메일에서 IR 자료를 찾지 못했습니다.` 상태만 남기도록 바꿨습니다. +- Slack 사용자 메시지에서 신뢰도 `%` 노출을 제거했습니다. + +## 검증 +- 문법 검증: + - `python3 -m py_compile app/services/coldmail_processor.py app/services/naverworks_file_processor.py tests/test_coldmail_ir_attachment_selection.py` +- 컨테이너 재배포 확인: + - `git push origin main` 후 `rb8001` 컨테이너가 재기동됨을 `docker ps`로 확인 + - 재기동 후 `curl http://localhost:8001/health` 정상 응답 확인 +- 런타임 선택 로직 확인: + - `모바일콘 재무제표 표준(2024년).pdf` + `모바일콘 회사소개서_v.1.0_01.pdf` 입력에서 회사소개서가 선택됨 + - `재무제표_2024.pdf` + `감사보고서.pdf` 입력에서 IR 후보 없음으로 반환됨 + +## 결과 +- 이 버그 범위에서 `첫 번째 PDF 고정 선택` 경로는 제거됐습니다. +- 앞으로는 IR 후보가 있으면 그 문서만 분석 버튼과 분석 입력에 사용되고, 없으면 분석 버튼 없이 상태만 표시됩니다. + +## 남은 경계 +- 파일명 기반 선택만으로 충분하지 않은 장기 케이스는 별도 개선 범위입니다. +- 전체 이메일 저장 구조 전환은 별도 아이디어 문서에서 다룹니다.