도찐개찐

[PyMuPdf4LLM] pdf to markdown 본문

PYTHON/LLM & Langchain

[PyMuPdf4LLM] pdf to markdown

도개진 2024. 10. 24. 14:33

1. Why Markdown?

2024년 5월1일 Dhaval Nagar가 작성한 글입니다.

여기서 가장 중요한 부분은 

LLM과 PDF에서 구조화된 데이터를 추출할 때, Markdown 텍스트가 일반 텍스트보다 우월하다는 것입니다. PDF 파일을 Markdown으로 변환하는 것은 데이터의 구조와 맥락을 유지하는 데 중요하며, 특히 Retrieval-Augmented Generation(RAG) 응용 프로그램에서 중요하다는 것입니다.

 

 

https://www.appgambit.com/blog/llms-love-structure-using-markdown-for-pdf-analysis

 

 

Markdown이 유리한 이유는 다음과 같습니다.

  • 마크다운 학습 : 최신 LLM은 마크다운으로 학습한 데이터가 많기 때문에 LLM은 마크다운을 매우 잘 이해할 수 있습니다. 
  • 구조 유지 : 마크다운은 PDF에의 테이블, 헤딩, 목록 등 본질적인 구조를 보존하고 표현하는데 용이합니다. LLM은 질문 답변이나 요약과 같은 작업 중에 이 구조를 이해하고 활용할 수 있습니다. 일반 텍스트는 정보를 평면화하여 모델이 관계를 식별하기 어렵게 만듭니다.
  • 의미 강조 : 헤더(#, ##), 굵은 글씨(* ), 기울임꼴( ), 코드 블록(```)과 같은 마크다운 요소는 텍스트의 중요성과 유형에 대한 의미적 단서를 제공합니다. 마크다운으로 훈련된 LLM은 이러한 단서를 포착하고 이해할 수 있습니다.
  • 깔끔한 표현 : 마크다운은 표 형식의 데이터를 시각적으로 정리하고 읽기 쉽게 표현할 수 있게 해줍니다. 표와 텍스트 데이터가 있는 공존하는 페이지를 변환하면, 서로 쉽게 섞여서 복잡한 결과가 생성될 수 있습니다.
  • 문맥 보존 : 더 깔끔한 표현은 문맥을 보존하는 데 도움이 됩니다. 또한 PDF에 그림이 있는 경우 텍스트의 문맥 내에 마크다운으로 이미지 링크나 대체 텍스트를 포함할 수 있습니다. 이렇게 하면 일반 텍스트에선 누락될 수 있는 정보를 제공할 수 있습니다.
  • 청킹 : 검색 증강 생성(RAG) 시스템에 필수적인 청킹(일명 "분할")은 더 쉬운 처리를 위해 더 큰 문서를 더 작은 부분으로 나눕니다. 마크다운은 벡터 데이터베이스 내에서 벡터 표현 자체에 직접적인 영향을 미치지 않지만 벡터 스토리지를 사용하는 RAG 시스템 내에서 검색 프로세스 중에 컨텍스트를 보존하고 활용하는 데 중요한 역할을 합니다.

2. Markdown based PDF conversion (LlamaParse, pymupdf4llm)

 

PDF파일을 Markdown으로 텍스트 추출이 가능한 라이브러리는 대표적으로 LlamaParse, pymupdf4llm가 있습니다.

- LlamaParse

LlamaParse는 LlamaIndex에서 개발한 최첨단 문서 파싱 플랫폼입니다. 다음과 같은 주요 특징을 가지고 있습니다:

 

주요 기능
- PDF, Word, PowerPoint, Excel 등 10개 이상의 파일 형식 지원
- 최첨단 표 추출 기능
- 자연어 지시를 통한 맞춤형 출력 형식 지정
- JSON 모드 제공
- 이미지 추출 기능

 

주요 장점
- LLM 사용 사례에 최적화된 고품질 데이터 파싱 및 정제
- 복잡한 문서에서 표와 텍스트를 정확하게 추출
- LlamaIndex와의 원활한 통합으로 고급 검색 및 컨텍스트 증강 가능

가격 정책
- 하루 1,000페이지 무료 제공
- 유료 플랜 가입 시 주 7,000페이지 무료, 이후 페이지당 $0.003

LlamaParse는 복잡한 문서에서 정확한 정보를 추출하고 구조화하여 LLM 기반 애플리케이션의 성능을 크게 향상시킬 수 있는 강력한 도구입니다.

 

- 변환 결과

from llama_parse import LlamaParse
from llama_index.core import SimpleDirectoryReader
import os
import nest_asyncio
from dotenv import load_dotenv

load_dotenv('./RAG.env')
nest_asyncio.apply()
# 파서 설정
parser = LlamaParse(
    result_type="markdown",  # "markdown"과 "text" 사용 가능
    num_workers=8,  # worker 수 (기본값: 4)
    verbose=True,
    language="ko",
)

# SimpleDirectoryReader를 사용하여 파일 파싱
file_extractor = {".pdf": parser}

# LlamaParse로 파일 파싱
documents = SimpleDirectoryReader(
    input_files=[pdf_path],
    file_extractor=file_extractor,
).load_data()

 

여기서 보시면 [별표1] 손해구분표, 1. 주택 앞에 #으로 헤더 표시를 통해 강조가 된 것을 확인할 수 있습니다.

하지만, 파손 / 지붕재 / 전파, 유실 등 일부 텍스트가 사라진 것을 확인할 수 있으며, Markdown에서 표의 형식으로 반환하지도 못한 것을 확인할 수 있습니다. 이는 예시로 사용한 표는 컬럼의 헤더가 존재하지 않아서 그런 것 같습니다. 

 

그래서 LlamaParse가 헤더가 존재하는 표는 어떻게 Markdown으로 변환하는지 보여드리고자 하나의 예시를 더 가져왔습니다.

헤더가 존재하는 PDF 표

 

매우 변환을 잘 한 것을 확인할 수 있습니다. Markdown 표 구조를 설명드리자면

 

표의 헤더(컬럼명) : |피해면적|보상수준| 

표의 컬럼 갯수 (2개): | --- | --- |

표 컬럼에 해당하는 내용 : |균열길이 2m 이상 ~ 연면적의 미만 5%|보험가입금액의 5%|

 

이를 통해 컬럼이 2개가 있고, 첫 ||에 위치한 내용은 컬럼명 피해면적에 대한 정보이며, 두번째 ||에 위치한 내용은 컬럼명 보상수준에 해당하는 정보임을 손쉽게 파악할 수 있습니다.

 

사람이 보면 쉽게 이해할 수 있는 것처럼, LLM 역시 마크다운 구조로 학습을 했기 때문에 해당 표의 구조를 이해하고 정확히 맵핑하여 질문에 답변할 수 있습니다.

 

예를들어, "소파 피해면적이 20%이상인데 보상은 얼마 받을 수 있어?" 라는 질문에 대해 

 

"소파 피해면적이 20%이상인 경우 보험 가입금액의 25% 받을 수 있습니다."라고 답할 수 있습니다.

 

 

반면 PDFMiner로 동일한 페이지에서 텍스트를 추출해보면 다음과 같은 결과를 반환합니다.

대충 봐도 LlamaParse의 Markdown 변환보다 이해하기 힘들고 구조 역시 제대로 반영되지 않은 것을 확인하실 수 있습니다.

 

- PyMuPDF4LLM

PyMuPDF4LLM은 PyMuPDF를 기반으로 한 강력한 문서 파싱 도구로, 특히 대규모 언어 모델(LLM)과 검색 증강 생성(RAG) 환경에서 사용하기 위해 설계되었습니다. 이 도구의 주요 특징과 기능은 다음과 같습니다:

주요 기능

- PDF 및 기타 문서 형식을 Markdown으로 변환
- 다중 열 페이지 지원
- 이미지 및 벡터 그래픽 추출 기능
- 페이지 청킹(chunking) 출력 지원
- LlamaIndex 문서 형식으로 직접 변환 가능

고급 기능

 

- 이미지 추출이 가능합니다.

md_text = pymupdf4llm.to_markdown("input.pdf", write_images=True)


이 옵션을 사용하면 페이지의 각 이미지나 벡터 그래픽이 추출되어 별도의 파일로 저장됩니다.

LlamaIndex 통합
PyMuPDF4LLM은 LlamaIndex와 직접 통합할 수 있는 기능을 제공합니다:

import pymupdf4llm

llama_reader = pymupdf4llm.LlamaMarkdownReader()
llama_docs = llama_reader.load_data("input.pdf")


이 방식으로 PDF를 LlamaIndex 문서 형식으로 직접 변환할 수 있습니다[2].

특징 및 장점
- 헤더 라인 식별 및 적절한 Markdown 형식 적용
- 굵은 글씨, 기울임꼴, 고정폭 텍스트, 코드 블록 등 다양한 텍스트 스타일 감지 및 포맷팅
- 순서 있는 목록과 순서 없는 목록 지원
- 표 감지 및 Markdown 형식으로 변환
- 페이지 하위 집합 처리 가능

PyMuPDF4LLM은 복잡한 문서 구조를 정확하게 파싱하고 LLM 및 RAG 시스템에 적합한 형식으로 변환하는 데 특화되어 있어, 문서 기반 AI 애플리케이션 개발에 매우 유용한 도구입니다

- 변환 결과

 


외부 헤더가 있는 테이블의 출력을 마크다운 출력 예시입니다. 이를 참고해 아래 변환 결과를 비교햊쉐요.
|열1|열2|
|---|---|
|셀(0, 0)|셀(0, 1)|
|셀(1, 0)|셀(1, 1)|
|셀(2, 0)|셀(2, 1)|
이는 가능한 최소한의 토큰 크기를 갖춘 GitHub 호환 포맷으로, RAG 시스템으로의 피드를 작게 유지하는 데 중요한 측면입니다.
열 테두리는 “|” 문자로 표시됩니다.
텍스트 줄은 “ |---|---| … “ 형태의 줄이 뒤에 오면 테이블 헤더 로 간주됩니다 .
전체 테이블 정의는 앞뒤에 적어도 하나의 빈 줄이 있어야 합니다.
기술적 이유로 마크다운 테이블에는 헤더가 있어야 하므로 외부 헤더를 사용할 수 없는 경우 첫 번째 테이블 행이 선택됩니다.

 

 

LlamaParse가 표의 헤더가 존재하지 않아 실패했던 예시를 변환한 결과입니다.

 

|1. 주행|Col2|Col3| : 1. 주택이라는 상위 Level이 표의 헤더로 잡히고, 표에 3개의 컬럼이 존재하기 때문에 Col2, Col3 빈컬럼을 포함해 3개로 나뉩니다.

 

| --- | --- | --- | : 컬럼이 3개임을 의미합니다. 

 

|파손|전파,유실|기둥, 벽체 지붕 등이 완전히 파손되어...| : 파손 - 전파,유실이 매핑되고 해당하는 텍스트도 정상적으로 매핑 됐습니다.

 

||전반파|파손된 부분의 수리비가 재축비용의 | : 전반파의 상위 Level인 파손이 이전에 나왔기 때문에 || 공백으로 표시함.

 

|침수|주택의 주거생활공간...|| : 파손과 동일한 Level인 침수가 맨 처음 컬럼에 위치함.

 

이중 표가 아닌경우 LlamaParse와 동일하게 Markdown 변환을 잘하는 것을 확인할 수 있습니다.

 

Markdown 변환을 하는 LlamaParse에 비해 PyMuPDF4LLM의 장점은 다음과 같습니다.

 

1. 무료

 

2. 완벽하지는 않지만 이중 표의 구조를 더 잘 커버함.

 

3. 생략하지 않고 모든 텍스트를 추출함.

 

4. 헤더가 존재하지 않아도 표를 탐지하고, Markdown 형식으로 변환함.

 


3. 결론

표가 존재하는 PDF 변환 개인 평가 순위

PyPDFium2 PyMuPDF PyPDF2 PDFMiner PDFPlumber  LlamaParse PyMuPDF4LLM
5/10 4/10 3/10 1/10 1/10 7/10 9/10

 

이러한 실험 결과로 표가 존재하는 PDF에 한해서는 개인적으로 PyMuPDF4LLM이 가장 좋다고 평가하고 있습니다. 

 

하지만, LlamaParse의 경우 LLM과 통합해 변환 성능을 끌어올릴 수도 있고, 다양한 파라미터가 존재하며 LlamaIndex와 기능 통합 역시 용이하여 잘 사용한다면 PyMuPDF4LLM의 성능을 어느정도 따라잡을 가능성도 존재하긴 합니다.

 

그러나, PyMuPDF4LLM역시 다양한 기능을 지원하여 커스터마이징을 진행하지 않는 이상 PyMuPDF4LLM을 사용하는 것이 좋아보입니다.

 

출처 : https://mz-moonzoo.tistory.com/m/73

728x90

'PYTHON > LLM & Langchain' 카테고리의 다른 글

[허깅페이스] 모델 다운로드  (0) 2024.05.13
LLM & LangChain  (0) 2024.02.27
Comments