PDF 파일은 법률, 금융, 연구 등 다양한 도메인에서 중요한 정보를 담고 있는 비구조화된 데이터 형식입니다. 하지만 PDF의 복잡한 구조와 긴 문서 길이는 데이터를 효율적으로 처리하고 검색하는 데 큰 도전 과제가 됩니다.
LangChain은 이러한 문제를 해결하기 위해 다양한 PDF 로더와 벡터 검색 기술을 제공하여 PDF 문서의 내용을 효율적으로 처리하고, 검색 및 질의응답 시스템을 구축할 수 있게 합니다.
이번 글에서는 LangChain을 활용해 PDF 파일을 처리하고, 문서 검색 및 내용 추출을 자동화하는 전략을 단계별로 알아보겠습니다.
LangChain은 다양한 PDF 로더를 제공합니다. 아래는 주요 로더와 사용 시나리오입니다.
로더 | 설명 | 사용 시나리오 |
---|---|---|
PyPDFLoader | 가볍고 빠른 텍스트 추출에 적합 | 단순 텍스트 추출이 필요한 경우 |
UnstructuredPDFLoader | 복잡한 레이아웃 문서 처리 | 표, 이미지가 포함된 복잡한 문서 |
PDFPlumberLoader | 표와 같은 구조화 데이터 추출 | 표 데이터 추출이 중요한 경우 |
from langchain_community.document_loaders import PyPDFLoader
# PDF 파일 로드
loader = PyPDFLoader("example.pdf")
documents = loader.load()
print(documents[0].page_content[:300]) # 첫 페이지 내용 출력
긴 문서를 효율적으로 다루기 위해 텍스트를 적당 단위로 분할합니다.
from langchain_text_splitters import RecursiveCharacterTextSplitter
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=1000,
chunk_overlap=200
)
docs = text_splitter.split_documents(documents)
텍스트 분할 방식은 여러 옵션이 있습니다
분할 방식 | 설명 | 적합한 상황 |
---|---|---|
PyPDFLoader | 가볍고 빠른 텍스트 추출에 적합 | 단순 텍스트 추출이 필요한 경우 |
UnstructuredPDFLoader | 복잡한 레이아웃 문서 처리 | 표, 이미지가 포함된 복잡한 문서 |
PDFPlumberLoader | 표와 같은 구조화 데이터 추출 | 표 데이터 추출이 중요한 경우 |
PDF에서 추출한 텍스트를 벡터로 변환해 저장소에 저장하고, 유사도 기반 검색을 구현합니다.
from langchain_community.vectorstores import FAISS
from langchain_openai import OpenAIEmbeddings
# 벡터 저장소 생성
embeddings = OpenAIEmbeddings()
vectorstore = FAISS.from_documents(docs, embeddings)
retriever = vectorstore.as_retriever(search_type="mmr", search_kwargs={"k": 5})
벡터 저장소 | 특징 | 용도 |
---|---|---|
FAISS | 빠른 인덱싱과 검색, 로컬 사용 가능 | 로컬 환경, 빠른 검색 필요 시 |
Chroma | 경량 벡터 DB, 메타데이터 필터링 지원 | 개발 환경, 프로토타입 |
Pinecone | 클라우드 기반, 대규모 데이터 처리 | 프로덕션, 대용량 데이터 |
검색된 문서를 기반으로 GPT 모델이 답변을 생성하도록 체인을 구성합니다.
from langchain_core.runnables import RunnablePassthrough
from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI
template = """문서 내용 기반 답변:
{context}
질문: {question}
"""
prompt = ChatPromptTemplate.from_template(template)
# RAG 체인 구성
rag_chain = (
{"context": retriever, "question": RunnablePassthrough()}
| prompt
| ChatOpenAI(model="gpt-4")
)
동일한 요청에 대해 중복 계산을 방지하기 위해 캐싱 시스템을 도입합니다.
from langchain.cache import SQLiteCache
import langchain
langchain.llm_cache = SQLiteCache(database_path="./cache.db")
LLM 기반 압축기를 사용해 검색 성능을 개선합니다.
from langchain.retrievers import ContextualCompressionRetriever
from langchain.retrievers.document_compressors import LLMChainExtractor
compressor = LLMChainExtractor.from_llm(ChatOpenAI())
compression_retriever = ContextualCompressionRetriever(
base_compressor=compressor,
base_retriever=retriever
)
여러 문서를 동시에 처리하여 속도를 높입니다.
from concurrent.futures import ThreadPoolExecutor
def process_documents(docs):
with ThreadPoolExecutor() as executor:
results = list(executor.map(lambda doc: retriever.retrieve(doc), docs))
return results
LangChain은 PDF 파일의 복잡한 구조를 효과적으로 처리하고, 검색 및 질의응답 시스템을 손쉽게 구축할 수 있는 강력한 도구를 제공합니다.
특히, 다양한 PDF 로더와 벡터 저장소를 활용하면 대규모 문서에서도 높은 정확도로 정보를 검색할 수 있습니다. 법률, 금융, 연구 등 다양한 도메인에서 LangChain의 기능을 활용할 수 있습니다.
문제 | 해결 방법 |
---|---|
표 추출 실패 | PDFPlumberLoader와 함께 테이블 추출 라이브러리 활용 |
이미지 포함 PDF | UnstructuredPDFLoader와 OCR 라이브러리 결합 |
매우 큰 PDF | 분산 처리 시스템 구축 고려(Dask, Ray 등) |
다국어 PDF | 언어 감지 후 적절한 임베딩 모델 선택 |