- rb8001/tests/test_langgraph_workflow.py 검증 완료 - State 필드, 노드 플로우, 조건부 엣지 테스트 완료 - 97줄 유지 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
4.0 KiB
4.0 KiB
콜드메일 IR 자동 분석 시나리오
날짜: 2025-10-14
작성자: happybell80
관련 파일: rb8001/app/scheduler/jobs/coldmail_briefing.py
최종 목표 시나리오
평일 오전 9시 5분 자동 실행
- NAVER WORKS 메일 중 콜드메일 감지 (Naive Bayes)
- IR 첨부파일(PDF) 다운로드
- skill-rag-file에 업로드 → 51123 HDD 영구 저장
- AI 분석 실행:
- 페이지별 요약 (RAG 기반 핵심 내용 추출)
- 기업 평가 (사업분야, 재무, 기술 우위)
- 베이지안 밸류에이션 및 신뢰도 계산
- Slack Lists에 정리된 보고서 첨부:
- 회사명, 이메일, IR 파일
- 밸류에이션, 신뢰도, 핵심 평가
- Slack 채널에 요약 메시지 + 피드백 버튼
구현 완료 (2025-10-14)
- coldmail_briefing.py:78-302: 전체 플로우
- naverworks_file_processor.py:94-135: PDF → skill-rag-file 업로드
- ir_analyzer.py:86-168: RAG 6회 쿼리 → LLM 요약
- startup_valuation.py:63-173: 베이지안 VC Method
- coldmail_briefing.py:191-221,241,246: Slack Lists 파일 첨부
- coldmail_briefing.py:262-285: Slack 피드백 버튼
- coldmail_filter.py:29-76: Naive Bayes 학습
분석 결과 예시
굿베이션 (IT 인테리어 플랫폼): 27페이지 → 14 chunks, 밸류에이션 100억원 (30-300억원), 신뢰도 90%
구현 계획
우선순위 1: Slack Lists 파일 첨부 (✅ 완료)
- 상세: 251014_slack_lists_file_attachment.md
- skill-rag-file/app/api/download.py: GET /api/download/{document_id}
- skill-slack/app/api/endpoints/files.py: POST /files/upload (X-API-Key)
- coldmail_briefing.py:191-221, 241, 246: document_id → file_id 변환
우선순위 2: LLM JSON 파싱 에러
- ir_analyzer.py:155 다음 (156 전): llm_response 전처리
- cleaned = llm_response.strip()
- if cleaned.startswith("```json"): cleaned = cleaned[7:]
- if cleaned.startswith("```"): cleaned = cleaned[3:]
- if cleaned.endswith("```"): cleaned = cleaned[:-3]
- cleaned = cleaned.strip()
- ir_analyzer.py:156: parsed = json.loads(cleaned)
우선순위 3: Slack 메시지에 IR 분석 결과 추가
- coldmail_briefing.py:144 다음: processed_results = [] 추가
- coldmail_briefing.py:188 다음: processed_results.append({...}) 추가
- company_name, ir_metrics.get("revenue"), valuation_result.median, valuation_result.confidence 포함
- coldmail_briefing.py:291 교체:
- 기존: f"콜드메일 {processed_count}건 처리 완료 (...)"
- 변경: summary_lines = [f"콜드메일 {processed_count}건 처리 완료"]
- for item in processed_results: summary_lines.append(f"- {item['company']}: {item['median']}억원 (신뢰도 {int(item['confidence']*100)}%)")
- summary_text = "\n".join(summary_lines)
우선순위 4: LangGraph 워크플로우
- requirements.txt: langgraph 추가
- app/services/coldmail_email_fetcher.py 생성
- coldmail_briefing.py:93-121 로직 분리
- async def fetch_emails(user_id, start_time, now) -> list
- app/services/coldmail_processor.py 생성
- coldmail_briefing.py:145-202 로직 분리
- async def process_coldmail(email, user_id) -> dict or None
- 반환: {company, median, confidence, lower, upper, revenue}
- app/services/workflows/init.py: 빈 파일
- app/services/workflows/coldmail_workflow.py 생성
- ColdmailState: emails, coldmail_candidates, processed_results, user_id, start_time, now
- 노드: fetch, filter, process, send
- route_after_filter: coldmail_candidates 유무로 END or process
- add_conditional_edges("filter", route_after_filter, {...})
- coldmail_briefing.py:78-302 교체 (최종 ~100줄)
- coldmail_briefing.py:86-101 유지
- workflow.ainvoke(initial_state) 호출
- 테스트: rb8001/tests/test_langgraph_workflow.py
- State 필드, 노드 플로우, 조건부 엣지 검증 완료
교훈
- 전체 시나리오 문서 먼저 작성 후 세부 구현
- LLM 응답은 항상 전처리 (마크다운 블록 제거)