# IR Deck 평가 백엔드 아키텍처 설계 **날짜**: 2025-11-28 **작성자**: Claude (AI) **관련 파일**: - `rb8001/app/router/ir_deck.py` (예정) - `rb8001/app/services/ir_deck_analyzer.py` (예정) - `rb8001/app/state/ir_valuation_repository.py` (예정) - `rb8001/app/pipelines/langgraph_document.py` (기존 활용) --- ## 목적 IR Deck 평가 기능을 위한 rb8001 백엔드 구조 설계. 기존 RAG 스킬(skill-rag-file)을 활용하여 PDF 업로드, 텍스트 추출, 분석, 평가 결과 저장까지의 전체 파이프라인 구축. ## 아키텍처 설계 ### 1. 라우트 구조 (router/) **파일**: `rb8001/app/router/ir_deck.py` **엔드포인트**: - `POST /api/ir-deck/upload` - PDF 파일 업로드 및 인덱싱 - `POST /api/ir-deck/chat` - IR Deck에 대한 질문/답변 - `POST /api/ir-deck/evaluate` - Sequoia Capital 기준 평가 실행 - `GET /api/ir-deck/evaluation/{evaluation_id}` - 평가 결과 조회 **책임**: - HTTP 요청/응답 처리만 - 요청 검증 (Pydantic schemas) - 서비스 계층 호출 - DB 직접 접근 금지 **참고**: `DOCS/book/300_architecture/311_FastAPI_구조_원칙.md` 준수 ### 2. 서비스 구조 (services/) **파일**: `rb8001/app/services/ir_deck_analyzer.py` **주요 클래스/함수**: - `IRDeckAnalyzer.analyze()` - 전체 평가 파이프라인 실행 - `IRDeckAnalyzer.evaluate_by_page()` - 페이지별 평가 - `IRDeckAnalyzer.calculate_score()` - 종합 점수 계산 (100점 만점) - `IRDeckAnalyzer.assign_grade()` - 등급 분류 (S/A/B/C) **기존 RAG 스킬 활용**: - `pipelines/langgraph_document.py`의 PDF 업로드/텍스트 추출 로직 재사용 - `skill-rag-file` 서비스 연동 (포트 8508) - `/api/upload` - PDF 업로드 및 인덱싱 - `/api/text/{document_id}` - 전체 텍스트 조회 - `/api/search` - RAG 검색 (페이지별 분석 시 활용) **Sequoia Capital 10가지 스토리 기준**: 1. 문제 정의 (Problem) 2. 시장 기회 (Market Opportunity) 3. 솔루션 (Solution) 4. 제품/서비스 (Product/Service) 5. 비즈니스 모델 (Business Model) 6. 경쟁 우위 (Competitive Advantage) 7. 팀 (Team) 8. 트랙션 (Traction) 9. 재무 (Financials) 10. 비전 (Vision) **평가 로직**: - 각 페이지를 10가지 스토리 기준으로 분석 - 페이지별로 잘된 점(strengths)과 부족한 점(weaknesses) 추출 - 페이지별 점수 계산 (0-100점) - 전체 점수 = 페이지별 점수의 가중 평균 - 등급 분류: S(90-100), A(80-89), B(70-79), C(0-69) **LLM 모델**: `gemini-2.5-flash-lite` (기본 모델) ### 3. DB 구조 (state/) **파일**: `rb8001/app/state/ir_valuation_repository.py` **테이블 설계**: #### `ir_deck_evaluations` 테이블 ```sql CREATE TABLE ir_deck_evaluations ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), document_id UUID NOT NULL, -- skill-rag-file의 document_id total_score INTEGER NOT NULL, -- 0-100 grade VARCHAR(1) NOT NULL, -- S, A, B, C created_at TIMESTAMP DEFAULT NOW(), updated_at TIMESTAMP DEFAULT NOW() ); ``` #### `ir_deck_page_evaluations` 테이블 ```sql CREATE TABLE ir_deck_page_evaluations ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), evaluation_id UUID REFERENCES ir_deck_evaluations(id) ON DELETE CASCADE, page_number INTEGER NOT NULL, score INTEGER NOT NULL, -- 0-100 strengths TEXT[], -- 잘된 점 배열 weaknesses TEXT[], -- 부족한 점 배열 created_at TIMESTAMP DEFAULT NOW() ); ``` #### `ir_deck_feedback` 테이블 (베이지안 학습용) ```sql CREATE TABLE ir_deck_feedback ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), evaluation_id UUID REFERENCES ir_deck_evaluations(id) ON DELETE CASCADE, user_grade VARCHAR(1) NOT NULL, -- 사용자가 부여한 등급 predicted_grade VARCHAR(1) NOT NULL, -- 시스템이 예측한 등급 feedback_text TEXT, -- 사용자 피드백 created_at TIMESTAMP DEFAULT NOW() ); ``` **Repository 패턴**: - `IRValuationRepository.create_evaluation()` - 평가 결과 저장 - `IRValuationRepository.get_evaluation()` - 평가 결과 조회 - `IRValuationRepository.save_feedback()` - 피드백 저장 - `IRValuationRepository.get_feedback_history()` - 학습 데이터 조회 ### 4. 기존 RAG 스킬 활용 **skill-rag-file 서비스** (포트 8508): - **업로드**: `POST /api/upload` - PDF 파일 업로드, 자동 OCR, 텍스트 추출, 임베딩/인덱싱 - **텍스트 조회**: `GET /api/text/{document_id}` - 전체 텍스트 및 메타데이터 조회 - **검색**: `POST /api/search` - RAG 검색 (페이지별 분석 시 활용) **기존 파이프라인 활용**: - `rb8001/app/pipelines/langgraph_document.py`의 업로드/추출 로직 재사용 - LangGraph를 통한 비동기 처리 (필요 시) **참고 문서**: - `251021_admin_slack_doc_analysis_pipeline_langgraph.md` - LangGraph 파이프라인 구조 - `251022_admin_ir_deck_rag_mixing_and_ocr_quality.md` - OCR 품질 개선 및 RAG 활용 ## 구현 순서 1. **DB 스키마 생성**: `ir_deck_evaluations`, `ir_deck_page_evaluations`, `ir_deck_feedback` 테이블 생성 2. **Repository 구현**: `state/ir_valuation_repository.py` 작성 3. **서비스 구현**: `services/ir_deck_analyzer.py` 작성 (기존 langgraph_document.py 활용) 4. **라우터 구현**: `router/ir_deck.py` 작성 5. **라우터 등록**: `main.py`에 라우터 등록 ## 베이지안 학습 계획 **학습 데이터 수집**: - 사용자가 평가 결과에 대해 등급 피드백 제공 - `ir_deck_feedback` 테이블에 저장 - 주기적으로 학습 데이터 추출 **학습 모델**: - 등급 분류를 위한 베이지안 분류기 구현 (향후) - 피드백 데이터가 충분히 쌓이면 학습 시작 ## 전체 플로우 1. **업로드**: `POST /rb8001/api/ir-deck/upload` → `document_id` 반환 2. **평가 시작**: `POST /rb8001/api/ir-deck/evaluate` → 평가 실행 및 결과 저장, `evaluation_id` 포함 응답 3. **평가 결과 조회**: `GET /rb8001/api/ir-deck/evaluation/{id}` → DB 조회 (프론트는 폴링로 결과 확인) **참고**: `/rb8001`는 Nginx 프록시 경로 (51123 → 51124:8001) ## 중요한 점 - **평가 시작 + 결과 조회 분리**: 프론트엔드는 `/evaluate` 응답에서 `evaluation_id`만 사용하고, 실제 점수/등급/페이지별 평가는 `/evaluation/{id}` 폴링으로 사용 - frontend-ir-valuation/src/services/irDeckService.ts:61-96 - frontend-ir-valuation/src/hooks/useEvaluation.ts:20-33, 103-129 - **중복 방지**: `force_reevaluate=False` 시 기존 평가 반환 - **의존 서비스**: skill-rag-file (포트 8508), 내장 LLM - **DB 테이블**: `ir_deck_evaluations`, `ir_deck_page_evaluations`, `ir_deck_feedback` ## 교훈 - **기존 인프라 활용**: skill-rag-file의 업로드/검색 기능 재사용으로 개발 시간 단축 - **계층 분리**: router → services → state 구조로 유지보수성 향상 - **표준 준수**: FastAPI 구조 원칙 준수로 일관성 유지 - **확장성**: 베이지안 학습을 위한 피드백 데이터 구조 미리 설계 --- ## 관련 문서 - [IR Deck 배치 테스트 문제점 분석](./251128_ir_deck_batch_test_issues.md) - 배치 테스트 결과 및 해결 사항 - `DOCS/book/300_architecture/312_writing-principles.md` - 문서 작성 규칙