LLMDocumentContentExtractor

LLMDocumentContentExtractor

비전(vision) 지원 LLM을 사용해 이미지 기반 문서에서 텍스트 내용과(해당한다면) 메타데이터를 추출해주는 컴포넌트예요. 인덱싱 파이프라인에서 Converter 뒤에 두어 이미지 기반 문서에서 텍스트를 뽑아내는 데 쓰면 돼요.

출처: LLMDocumentContentExtractor

본문

개요

LLMDocumentContentExtractor는 비전 지원 대규모 언어 모델(LLM)로 이미지 기반 문서에서 텍스트 내용을 추출해요. 이 컴포넌트는 스캔 문서, 텍스트가 들어 있는 이미지, 검색 가능한 텍스트로 변환해야 하는 PDF 페이지를 처리할 때 특히 유용해요.

컴포넌트 동작 방식이에요.

  • DocumentToImageContent 컴포넌트로 각 입력 문서를 이미지로 변환해요.
  • 미리 정의된 프롬프트로 LLM에게 내용·메타데이터를 어떻게 추출할지 지시해요.
  • 이미지를 비전 지원 ChatGenerator에 통과시켜 구조화된 텍스트 내용을 추출해요.

프롬프트에 Jinja 변수를 넣으면 안 돼요. LLM을 위한 지시문만 포함해야 해요. 이미지 데이터와 프롬프트는 함께 하나의 Chat Message로 LLM에 전달돼요.

추출기는 LLM의 일반 텍스트 응답과 JSON 응답을 모두 지원해요.

  • LLM이 단순 문자열을 반환하면 그 텍스트가 문서의 content에 기록돼요.
  • LLM이 document_content 키만 있는 JSON 객체를 반환하면 그 값이 content에 기록돼요.
  • LLM이 여러 키를 가진 JSON 객체를 반환하면, document_content(있으면) 값이 content에 기록되고 나머지 키들은 모두 문서의 메타데이터로 병합돼요.

LLM이 내용 추출에 실패한 문서는 별도의 failed_documents 목록으로 반환되며, 디버깅이나 재처리를 위해 메타데이터에 extraction_error 항목이 담겨요.

사용법

단독 사용 예시예요. 이미지 기반 문서에서 텍스트를 추출해요.

from haystack import Document
from haystack.components.generators.chat import OpenAIChatGenerator
from haystack.components.extractors.image import LLMDocumentContentExtractor

# Initialize the chat generator with vision capabilities
chat_generator = OpenAIChatGenerator(
    model="gpt-4o-mini",
    generation_kwargs={"temperature": 0.0},
)

# Create the extractor
extractor = LLMDocumentContentExtractor(
    chat_generator=chat_generator,
    file_path_meta_field="file_path",
    raise_on_failure=False,
)

# Create documents with image file paths
documents = [
    Document(content="", meta={"file_path": "image.jpg"}),
    Document(content="", meta={"file_path": "document.pdf", "page_number": 1}),
]

# Run the extractor
result = extractor.run(documents=documents)

# Check results
print(f"Successfully processed: {len(result['documents'])}")
print(f"Failed documents: {len(result['failed_documents'])}")

# Access extracted content
for doc in result["documents"]:
    print(f"File: {doc.meta['file_path']}")
    print(f"Extracted content: {doc.content[:100]}...")

커스텀 프롬프트 사용:

LLM에 내용을 어떻게 추출할지 지시하는 커스텀 프롬프트를 제공할 수 있어요.

from haystack.components.extractors.image import LLMDocumentContentExtractor
from haystack.components.generators.chat import OpenAIChatGenerator

custom_prompt = """
Extract all text content from this image-based document.

Instructions:
- Extract text exactly as it appears
- Preserve the reading order
- Format tables as markdown
- Describe any images or diagrams briefly
- Maintain document structure

Document:"""

chat_generator = OpenAIChatGenerator(model="gpt-4o-mini")
extractor = LLMDocumentContentExtractor(
    chat_generator=chat_generator,
    prompt=custom_prompt,
    file_path_meta_field="file_path",
)

documents = [Document(content="", meta={"file_path": "scanned_document.pdf"})]
result = extractor.run(documents=documents)

실패한 문서 처리:

컴포넌트는 실패한 문서에 대한 상세한 오류 정보를 제공해요.

from haystack.components.extractors.image import LLMDocumentContentExtractor
from haystack.components.generators.chat import OpenAIChatGenerator

chat_generator = OpenAIChatGenerator(model="gpt-4o-mini")
extractor = LLMDocumentContentExtractor(
    chat_generator=chat_generator,
    raise_on_failure=False, # Don't raise exceptions, return failed documents
)

documents = [Document(content="", meta={"file_path": "problematic_image.jpg"})]
result = extractor.run(documents=documents)

# Check for failed documents
for failed_doc in result["failed_documents"]:
    print(f"Failed to process: {failed_doc.meta['file_path']}")
    print(f"Error: {failed_doc.meta['extraction_error']}")

파이프라인 안에서:

아래는 LLMDocumentContentExtractor로 이미지 기반 문서를 처리하고 추출된 텍스트를 저장하는 파이프라인 예시예요.

from haystack import Pipeline
from haystack.components.extractors.image import LLMDocumentContentExtractor
from haystack.components.generators.chat import OpenAIChatGenerator
from haystack.components.preprocessors import DocumentSplitter
from haystack.components.writers import DocumentWriter
from haystack.document_stores.in_memory import InMemoryDocumentStore
from haystack.dataclasses import Document

# Create document store
document_store = InMemoryDocumentStore()

# Create pipeline
p = Pipeline()
p.add_component(
    instance=LLMDocumentContentExtractor(
        chat_generator=OpenAIChatGenerator(model="gpt-4o-mini"),
        file_path_meta_field="file_path",
    ),
    name="content_extractor",
)
p.add_component(instance=DocumentSplitter(), name="splitter")
p.add_component(instance=DocumentWriter(document_store=document_store), name="writer")

# Connect components
p.connect("content_extractor.documents", "splitter.documents")
p.connect("splitter.documents", "writer.documents")

# Create test documents
docs = [
    Document(content="", meta={"file_path": "scanned_document.pdf"}),
    Document(content="", meta={"file_path": "image_with_text.jpg"}),
]

# Run pipeline
result = p.run({"content_extractor": {"documents": docs}})

# Check results
print(f"Successfully processed: {len(result['content_extractor']['documents'])}")
print(f"Failed documents: {len(result['content_extractor']['failed_documents'])}")

# Access documents in the store
stored_docs = document_store.filter_documents()
print(f"Documents in store: {len(stored_docs)}")

더 알아보기 (Learn more)