sol’s blog

감사보고서 기반 QA 시스템 프로젝트 계획

프로젝트 마일스톤을 설계

sol-commits
sol-commits Sep 11, 2025
배경지식
재무제표
1. 재무상태표 - 자산, 부채, 자본 현황
2. 손익계산서 - 일정 기간의 수익, 비용, 이익
3. 포괄손익계산서 - 당기순이익 + 확정은 안됐지만 잠재적 손익(현금화 되지 않은 손익)
4. 현금흐름표 - 현금의 유입/유출
5. 자본변동표 - 자본의 변동 내역
감사보고서
외부 감사인(공인회계사나 회계법인)이 재무제표가 회계기준에 맞게 작성되었는지 검증하고 의견을 제시한 문서
• 주요 감사의견 종류
1. 적정의견(문제 없음)
2. 한정의견(일부 문제)
3. 부적정의견(신뢰 불가)
4. 의견거절(감사 불가)
주석의 역할
재무제표에 RAG 기반 QA 시스템이 필요할까?
  1. 재무제표 데이터의 특성
      • 방대한 양: 대기업의 경우 수백 ~ 수천 페이지에 달하는 보고서
      • 복잡한 구조: 표(숫자) + 주석(텍스트) + 회계 기준 설명
      • 해마다 포맷이 조금씩 바뀌고, 표현 방식도 다양함
      • 금융 전문가가 아닌 일반인은 필요한 정보를 찾기 어려움
  1. 기존 검색/QA 한계
      • 키워드 검색만으로는 정확한 숫자맥락을 놓치기 쉬움
      • 금융 데이터는 팩트 기반 응답이 필수 → hallucination 문제를 줄여야 함
  1. 활용 시나리오
    1. 투자자
      “삼성전자 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 기반 토픽 모델링
청크
감사보고서 같은 긴 문서는 수십-수백 페이지라 한 번에 임베딩(벡터화) 불가

모델이 한 번에 처리할 수 있는 토큰 길이에도 한계가 있음

→ 문서를 검색 가능한 작은 단위 로 쪼개서 저장

청크 예시1
청크 예시2
임베딩 모델 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
 
 

추천 글

BlogPro logo
Made with BlogPro

태그