감사보고서 기반 QA 시스템 프로젝트 계획
프로젝트 마일스톤을 설계
sol-commits Sep 11, 2025
배경지식
| 재무제표 | 1. 재무상태표 - 자산, 부채, 자본 현황 2. 손익계산서 - 일정 기간의 수익, 비용, 이익 3. 포괄손익계산서 - 당기순이익 + 확정은 안됐지만 잠재적 손익(현금화 되지 않은 손익) 4. 현금흐름표 - 현금의 유입/유출 5. 자본변동표 - 자본의 변동 내역 |
| 감사보고서 | 외부 감사인(공인회계사나 회계법인)이 재무제표가 회계기준에 맞게 작성되었는지 검증하고 의견을 제시한 문서 • 주요 감사의견 종류 1. 적정의견(문제 없음) 2. 한정의견(일부 문제) 3. 부적정의견(신뢰 불가) 4. 의견거절(감사 불가) |
| 주석의 역할 | ㅤ |
재무제표에 RAG 기반 QA 시스템이 필요할까?
- 재무제표 데이터의 특성
- 방대한 양: 대기업의 경우 수백 ~ 수천 페이지에 달하는 보고서
- 복잡한 구조: 표(숫자) + 주석(텍스트) + 회계 기준 설명
- 해마다 포맷이 조금씩 바뀌고, 표현 방식도 다양함
- 금융 전문가가 아닌 일반인은 필요한 정보를 찾기 어려움
- 기존 검색/QA 한계
- 키워드 검색만으로는
정확한 숫자나맥락을 놓치기 쉬움 - 금융 데이터는 팩트 기반 응답이 필수 → hallucination 문제를 줄여야 함
- 활용 시나리오
| 투자자 | “삼성전자 2021년 영업이익은 얼마?” |
| 애널리스트 | “최근 5년간 부채비율 추세를 설명해줘” |
| 내부 임직원 | “감사의견에서 지적된 핵심 리스크는 뭐야?” |
| 연구자 | “반도체 부문에서 수익성 변화를 설명한 주석 찾아줘” |
언어 모델 없는 RAG가 하는 기능
- 검색엔진 + FAQ 시스템 같은 느낌
- 예시
- 사용자: “2021년 매출총이익?”
- 시스템:
2021 매출총이익 = 378,521 (백만원), 출처: Consolidated Income Statement, page 12
- 자연어로 “이익 증가 이유를 설명해줘” 같은 질문은 처리 불가 → LLM 없이는 인과·맥락 해석 불가능
NER(Named Entity Recognition)
- 예시
- 삼성전자 → 회사
- 2024년 → 날짜
- 98조 원 → 금액
“삼성전자는 2024년에 98조원의 매출을 기록했다”
→ 중요한 요소를 꼬리표(tag) 붙여서 구조화
토픽 모델링
여러 문서(또는 문단) 안에서 숨겨진 주제(Topic) 분포를 자동으로 찾아냄
- 출력 형태: 문서 → 여러 토픽의 확률 분포
- 예
- 대표 알고리즘: LDA(Latent Dirichlet Allocation), NMF, BERT 기반 토픽 모델링
청크
감사보고서 같은 긴 문서는 수십-수백 페이지라 한 번에 임베딩(벡터화) 불가모델이 한 번에 처리할 수 있는 토큰 길이에도 한계가 있음
→ 문서를
검색 가능한 작은 단위로 쪼개서 저장
임베딩 모델 vs Vector DB
- 임베딩 모델: 문장을 좌표(벡터)로 바꿔줌
- Vector DB: 좌표들을 저장해두고 새로운 좌표랑 가까운 애 찾아줌
→
- 임베딩 모델 없이는 Vector DB에 넣을 벡터가 없음
- Vector DB 없이는 벡터를 저장·검색하기가 비효율적임
Stage 1 - 베이스라인 시스템 구축(~9/16 목표)
| 감사보고서 HTML 파싱 및 전처리 | • 파싱 결과를 구조화해 JSON 에 저장 • ex. 연도별 보고서, 섹션 구분 등 • KPI• 재무제표 주요 항목이 모두 추출되었는지 • 숫자/텍스트 누락 여부 • 표본 보고서 몇 건을 수작업 검증하여 파싱 정확도 확인 후 필요한 경우 파서 튜닝 |
| 인덱싱 및 임베딩 생성 | • 파싱된 보고서 텍스트를 청크(chunk) 단위로 분할하고 벡터화 • 초기에는 각 보고서를 일정 길이(예: 300-500자 내외)로 단순 청크 분할하고, 한국어 도메인에 적합한 임베딩 모델(ex. KoSentenceBERT)을 사용해 청크 임베딩을 생성. 생성된 임베딩은 메모리에 저장하거나 임시적으로 JSON 파일에 저장하여 질의 시 유사도 검색에 활용 • KPI• 간단한 질의 집합에 대해 임베딩 유사도 기반 검색 결과가 관련 있는 처으를 찾아내는지 수작업 점검 • ex. “2018년 자산총계” 질문에 2018년 재무상태표 청크가 검색되는지 확인 |
| 질의 처리 및 검색 | • 사용자의 한국어 금융 질의에 대해 벡터 유사도 검색 기반으로 관련 청크들을 top-k 추출 • Stage 1에서는 Dense Retrieval만 사용하되, 임베딩 유사도 순으로 상위 결과를 선택(초기에는 BM25 등의 키워드 검색 미도입) • 검색 모듈은 파이썬에서 선형 검색으로 구현 • KPI: 검색 정확도(Recall@k)• ex. 사전 준비한 10개 질의 중 정답 청크가 top-5에 포함된 비율 등을 계산. 또, 검색 속도(평균 검색 소요 시간)를 측정하여 반응 시간을 가늠 |
| 답변 생성 (Reader, Generator) | • 검색된 상위 청크들을 프롬프트와 함께 언어모델(LLM)에 전달하여 최종 답변 생성 • 모델은 오픈소스 KoGPT2/KoAlpace 등 로컬에서 구동 가능한 한국어 LLM을 우선 사용 • 우선은 파인튜닝 없이 프롬프트 기반으로 질의 + 컨텍스트를 입력하여 답변 생성만 진행 • KPI: 정답 정확도, 답변 생성 소고(평균 Latency)• SQuAD 평가 방식을 참조하여 Exact Match(EM) 비율과 F1 점수를 계산(🔗 참고) |
청크 단위
- 표/주석 문단
- 연도당 약 50~80 청크
Stage2 - 시스템 성능 개선 및 확장
| 청크 그레뉼러리티 개선 | • Stage 1에서 임의 길이로 나눈 청크를 의미 단위로 세분화하여 문맥 단절을 최소화 • 청크 분할 규칙: 문단 종료 시, 표 시작 전후, 또는 의미상 하나의 주제를 담는 범위 • 각 청크에 메타데이터(섹션 종류, 페이지 번호 등)을 태깅 • Task• HuggingFace의 문서 분할기 등을 활용 • 분할된 청크 각각에 연도와 섹션 유형을 필드로 추가해 JSON이나 DB에 저장 • KPI• 청크당 평균 길이(토큰 수)가 Stage 1 대비 감소하면서도 문맥 일관성 점수가 높아졌는지 • 청크 내부 문장들끼리 연관된 주제를 다루는지 • Precision@k: 상위 k개의 검색 결과 중 실제 정답과 관련있는 청크의 비율이 개선되는지 확인 |
| 쿼리 분석 및 필터링 | • NER(Named Entity Recognition)를 활용해 사용자의 질의를 분석 → 메타데이터 필터링에 적용 • Task• 한국어 NER 모델(koBERT NER / Placeholder NER 등)을 사용해 질의 문장을 실시간 분석 • 사전 학습된 NER 모델을 우선 활용하고, 필요 시 금융 도메인 특화 엔터티는 정규표현식 또는 사전 매칭으로 보완 • KPI• NER 필터 적용 전후의 검색 Precision@5 비교 • 질문에 2019라 명시했을 때 2019 데이터만 답변되는지 등 |
| 하이브리드 검색 도입 | • 기존 임베딩 기반 검색에 BM25 키워드 기반 검색을 병렬로 수행하고, 두 결과를 결합(랭크 병합)하여 검색을 강건하게 개선 • 임베딩 검색은 의미 유사도에 강점이 있으나 숫자나 고유명사 질의에서 누락이 있을 수 있고, 반대로 BM25는 정확한 키워드 매칭에 강점이 있으므로 두 방법을 보완적으로 활용 • 질의가 들어오면 두 가지 검색을 병렬로 수행 ♨️ 정확한 키워드 매칭과 의미 유사도 측면을 모두 활용하기 위함 • 키워드 기반 검색 엔진(elastic search / tf-idf 스코어) • 임베딩 벡터 유사도 → 각 방법으로부터 상위 n개의 결과를 얻은뒤, 이를 랭킹 결합(rank fusion) 기법으로 통합하여 최종 상위 결과를 선정 • Task• 학습된 임베딩 + scikit-learn TfidVectorizer 조합으로 구현. 겨로가 점수를 임베딩 유사도 점수와 정규화해 가중합. • KPI• Recall@k 향상 측정 • 일부 질의에 대해 Rank 변화를 관찰하여 정답 포함 청크의 순위가 상향되었는지 분석 • 하이브리드 도입 후 정확도가 몇 %p 개선되었는지 평가 |
| 모델 업그레이드 및 파인튜닝 검토 | • Stage1에서는 기본 LLM을 사용했으나, Stage 2에서는 필요에 따라 모델 변경 또는 미세조정을 고려. 예를 들어 베이스라인에서는 KoAlpaca 7B 등을 썼다면, Stage 2에서는 미세조정을 보다 큰 파라미터 모델(예: Llama2 13B 한글초점 모델)로 교체하여 성능을 향상 • 도메인 적합성을 높이기 위해 파인튜닝도 검토.. • 감사보고서 Q&A 페어를 자체 구축한다면, 이를 소규모 LLM에 파인튜닝하여 도메인 전문지식을 내재화시킬 수 있음 • 학습 시간이 부족하므로 파인튜닝은 고려해봐야함. 우선은 프롬프트 엔지니어링으로 LLM 응답 최적화 시도 • Task• 여러 오픈소스 LLM (Kohay-LLM, KoVicuna 등)중 금융 질의에 강점이 있는지 실험 • 동일 질문에 대해 다양한 모델 출력 비교 후 가장 나은 것 채택 • KPI• 답변의 정확성과 유용성에 대한 주관적 평가 • Semantic Answer Similarity(SAS) 점수를 계산(🔗 참고) • 동일 질문에 대해 Stage1 vs Stage2 모델의 답변을 정답 문장과 임베딩 유사도로 비교하여 어느 쪽이 의미적으로 가까운지 수치화 • 모델 변경에 따른 Latency도 중요한 KPI |
| 벡터 DB 도입 및 확장 준비 | • 베이스라인에선 JSON/메모리 구조로 구현했지만, 약 수천 개 이상 청크로 늘어나면 전문 벡터 검색 엔진이 성능 면에서 유리해짐 • Task• 벡터 스토어 선정 • pgvector: postgres 내에서 벡터유사도 검색 지원 • chroma: python 환경에서 손쉽게 사용 가능 • 선택한 DB에 현재 청크 임베딩을 모두 마이그레이션 |
| UI | • Task• LLM이 근거로 사용한 문장을 표시 |
단계별 마일스톤 및 기능 개선 사항
| M1 베이스라인 구축 | • 기능 목표: 기본 RAG QA 파이프라인이 동작할 것. • 도입 기술 • 간단 청크 분할 • 임베딩 기반 검색(dense retrieval)만 사용 • pretrained LLM 활용 |
| M2 청크 및 메타데이터 개선 | • 기능 목표: 청크를 의미 단위로 분할하고 각 청크에 연도/섹션 메타데이터 태그를 적용 • 도입 기술: 보고서 구조 기반 chunking 기법, 질의의 연도 등의 키워드에 따른 필터링 |
| M3 Hybrid 검색 통합 | • 기능 목표: 키워드 검색을 병행하여 임베딩 검색의 부족한 부분 보완 • 도입 기술: tf-idf 스코어, 결과 랭크병합 알고리즘 |
| M4 NER 기반 필터링 및 토픽 분류 | • 기능 목표: 질의 분석 모듈 도입으로 불필요한 검색 결과 제거 및 도메인 스코프 한정 • 도입 기술 • 사전 학습 NER 모델 활용한 엔터티 추출 및 검색 필터 • LDA 등으로 보고서 섹션 토픽 클러스터링 |
| M5 모델 향상 벡터 DB 전환 | • 기능 목표: LLM 답변의 신뢰도 및 정확성 증진, 임베딩 검색의 효율화 • 도입 기술 • 더 성능 좋은 LLM 적용 • 프롬프트 개선 • 벡터 DB 도입 |
지식 저장소 구조 설계
JSON vs pgvector vs chromadb vs nosql vs rdb
| JSON | • 10년치 감사보고서라고 해봐야 수천 개 청크 수준이므로, 임베딩 벡터들을 파이썬 리스트에 담아 Numpy로 유사도 계산해도 성능상 큰 문제 없음 • 약 1k개 문서까지는 메모리 배열 검색도 충분히 빠르고, 10k를 넘어가면서부터 벡터DB가 메모리보다 검색이 빠라지기 시작함 |
| RDB vs NoSQL | • RDB • 메타데이터 필터링을 SQL로 손쉽게 할 수 있음. • NoSQL • 복잡한 조인이나 벡터 연산에는 기본 지원이 없음 |
| pgvector vs chromadb | • pgvector • 동일 DB 내에 임베딩과 원문/메타데이터를 모두 저장 가능 • chromadb |