Skip to content

[Feat] P3 — VLM 기반 파싱 파이프라인 도입 (표/차트/레이아웃 포함) #58

Description

@TaskerJang

요약

현재 Tesseract OCR + 텍스트 청킹 파이프라인이 한글 종성 인식 / 표 구조 / 시각 정보 추출에 한계가 있음. VLM (GPT-4V, Qwen2-VL, InternVL3) 기반 파싱으로 대체하여 표/차트/레이아웃 포함 전반적 파싱 품질 향상.

Hybrid 로드맵 P3 ⚡ — 중장기 작업 (1~2주).

동기 — W6 측정에서 드러난 OCR / 파싱 한계

Case 1: 한글 종성 인식 실패

한화투자증권 PDF의 OCR 단계에서 "두산밥캣" → "두산밥칿" 으로 깨짐. Tesseract 기본 OCR이 한글 받침 인식에 약한 알려진 한계.

영향 11건 QA:

  • hanwha_001~006 (VectorRAG 6건)
  • graph_011, 012, 016 (1hop 3건)
  • graph_034, 038 (causal 2건)

GraphRAG는 entity exact match로 전처리 오류를 그대로 전파 → 11건 100% 실패.

Case 2: 표 구조 손실

미래에셋증권 분기 보고서의 ROE 표:

원본 PDF:
  ┌──────────┬───────┬───────┬───────┬───────┐
  │ 지표     │ 1Q25  │ 2Q25  │ 3Q25  │ 4Q25  │
  ├──────────┼───────┼───────┼───────┼───────┤
  │ ROE      │ 8.5%  │ 10.9% │ 9.7%  │ 11.2% │
  └──────────┴───────┴───────┴───────┴───────┘

현재 파이프라인 출력 (텍스트):
"지표 1Q25 2Q25 3Q25 4Q25 ROE 8.5% 10.9% 9.7% 11.2%"
                                ^^^ 분기 정보 매핑 손실

→ Entity 추출 단계에서 어떤 분기의 ROE인지 매핑 불가 → numerical 23건의 부진 주요 원인.

Case 3: 시각적 강조 / 차트 무시

DS시황 리포트의 차트 안 수치 (예: 코스피 추이 그래프의 특정 지점 값) 가 OCR 으로 박히지 않음. filter_agg corpus-wide 집계의 입력 자체가 부족.

변경 사항 (예정)

1. ingestion/vlm_parser.py (신규)

VLM 기반 페이지 파싱:

class VLMParser:
    def __init__(self, model: str = "qwen2.5-vl-7b"):
        # OpenRouter / Qwen Inference API / 로컬 vLLM 셋업
        ...

    def parse_page(self, image: PIL.Image) -> ParsedPage:
        """페이지 이미지 → 구조화된 Markdown + Entity 후보 + 표 JSON."""
        ...

    def parse_pdf(self, pdf_path: Path) -> List[ParsedPage]:
        """PDF → 페이지별 이미지 → VLM 파싱."""
        ...

2. ingestion/__init__.py (수정)

기존 Tesseract OCR + chunker 박힌 거를 fallback 으로 보존하고, VLM 박혀있으면 우선 사용:

def parse_document(path: Path, *, use_vlm: bool = True) -> ParsedDoc:
    if use_vlm and _vlm_available():
        return _vlm_parse(path)
    return _legacy_ocr_parse(path)

3. 모델 선정 — 후보 비교

모델 강점 비용 (페이지당) 한글
GPT-4V 최고 품질 $0.03~0.05 ✅ 강력
Qwen2.5-VL-72B (OpenRouter) 한국어 / 표 강함 $0.001~0.005 ✅ 강력
InternVL3 (OpenRouter) 차트 / 다이어그램 $0.002~0.008 ⚠️ 보통
Qwen2.5-VL-7B (로컬 vLLM) 무료 / 빠름 $0 (GPU 비용) ⚠️ 보통

PoC 단계에서 3개 모델 모두 한 페이지씩 테스트 → 본인 8개 문서에 가장 적합한 모델 선정.

4. docs/adr/0006-vlm-parser.md (신규)

VLM 도입 의사결정 ADR — 비용 / 속도 / 정확도 trade-off 박음.

DoD

  • 3개 VLM 후보로 두산밥캣 한화 리포트 1페이지씩 파싱 비교
  • 한글 종성 인식: "두산밥캣" 정확 추출 검증
  • 표 구조 보존: 미래에셋 ROE 표 → JSON 구조로 박힘
  • 차트 인식: DS시황 차트 안 수치 박힘
  • 비용 측정: 8개 문서 전체 파싱 비용 < $5
  • 속도 측정: 페이지당 < 30초

검증 방법

# 1. VLM 파서로 8개 문서 재파싱
uv run python scripts/run_ingestion.py --use-vlm --model qwen2.5-vl-72b

# 2. 한글 종성 검증
uv run python -c "
from ingestion import parse_document
parsed = parse_document('data/한화투자증권_두산밥캣_기업분석_리포트.pdf', use_vlm=True)
assert '두산밥캣' in parsed.text
assert '두산밥칿' not in parsed.text
"

# 3. 표 구조 검증
# parsed.tables 가 List[dict] 박혀있는지 확인

예상 효과

영역 Before After (VLM)
OCR 글자 깨짐 11건 실패 0건
표 구조 매핑 손실 (numerical 23건) 분기/회사 매핑 정확
차트 안 수치 무시 추출됨
numerical Correctness 1.30 3.5+ (P1 + P3 결합)

Trade-offs (솔직히)

항목 비용
페이지당 시간 530초 (vs Tesseract 13초)
페이지당 비용 $0.001~0.05 (vs Tesseract 무료)
전체 재인덱싱 8 doc → 약 30분~1시간
종속성 추가 VLM API 키 또는 GPU 환경

→ P1, P2 정량 효과 확인 후 도입 권장. 중장기 작업으로 박힌 이유.

의존 / 후속

레퍼런스

  • W6 회고록 §7.2 "OCR 글자 깨짐의 entity 검색 실패"
  • Qwen2.5-VL Technical Report (2024)
  • Microsoft GraphRAG — Indexing with visual context

우선순위

P3중장기 (1~2주). 비용 / 속도 trade-off 있어 단기 P1, P2 효과 확인 후 진행.


Refs #56 (P1), #57 (P2), W6 measurement results

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions