HierarchicalDocumentSplitter

HierarchicalDocumentSplitter

텍스트 세그먼트 사이의 부모-자식 관계에 기반한 다중 레벨 문서 구조를 만들 때 사용하는 구성 요소예요.

출처: 문서

본문

HierarchicalDocumentSplitter는 문서를 다양한 크기의 블록으로 나누어 트리 같은 구조를 만들어요. 블록(block)이란 스플리터가 만들어내는 텍스트 청크 하나예요. 긴 텍스트를 작은 조각으로 자르는 것과 비슷한데, 각 조각이 블록이죠. 블록은 트리 구조를 형성하며, 전체 문서가 루트 블록이고 더 작고 작은 조각으로 나눌수록 지정된 최소 크기까지 자식 블록과 리프 블록을 얻어요.

이후 AutoMergingRetriever 구성 요소가 이 계층 구조를 활용해 문서 검색을 개선해요.

컴포넌트를 초기화하려면 block_size를 지정해야 해요. 이것은 각 블록의 "최대 길이"이며 특정 단위로 측정돼요(split_by 파라미터 참조). 크기 집합(예: {20, 5})을 전달하면:

  • 먼저 문서를 각각 최대 20 단위의 블록("부모" 블록)으로 자르고,
  • 그다음 각각을 최대 5 단위의 블록("자식" 블록)으로 자릅니다.

이 내림차순 크기가 계층을 만들어요. 컴포넌트 초기화 시 설정할 수 있는 추가 파라미터:

  • split_by — "word"(기본), "sentence", "passage", "page" 중 하나.

  • split_overlap — 청크 사이 겹치는 단어·문장·passage 수를 나타내는 정수. 기본 0.

  • 대표적인 파이프라인 위치: Converter와 DocumentCleaner 뒤의 인덱싱 파이프라인

  • 필수 init 변수: block_sizes — 문서를 나눌 블록 크기 집합. 블록은 내림차순으로 나뉘어요.

  • 필수 run 변수: documents — 계층 블록으로 나눌 문서 리스트

  • 출력 변수: documents — 계층 문서 리스트

  • API reference: PreProcessors

  • 패키지명: haystack-ai

Usage ​

On its own ​

from haystack import Document
from haystack.components.preprocessors import HierarchicalDocumentSplitter

doc = Document(content="This is a simple test document")
splitter = HierarchicalDocumentSplitter(
    block_sizes={3, 2}, split_overlap=0, split_by="word")
splitter.run([doc])
# >> {'documents': [Document(id=3f7..., content: 'This is a simple test document', meta: {'__block_size': 0, '__parent_id': None, '__children_ids': ['80a..', 'f0e..'], '__level': 0}),
# >> Document(id=80a.., content: 'This is a ', meta: {'__block_size': 3, '__parent_id': '3f7..', '__children_ids': ['e39..', 'fbf..'], '__level': 1, 'source_id': '3f7..', 'page_number': 1, 'split_id': 0, 'split_idx_start': 0}),
# >> Document(id=f0e.., content: 'simple test document', meta: {'__block_size': 3, '__parent_id': '3f7..', '__children_ids': ['5d1..', '181..'], '__level': 1, 'source_id': '3f7..', 'page_number': 1, 'split_id': 1, 'split_idx_start': 10}),
# >> Document(id=e39.., content: 'This is ', meta: {'__block_size': 2, '__parent_id': '80a..', '__children_ids': [], '__level': 2, 'source_id': '80a..', 'page_number': 1, 'split_id': 0, 'split_idx_start': 0}),
# >> Document(id=fbf.., content: 'a ', meta: {'__block_size': 2, '__parent_id': '80a..', '__children_ids': [], '__level': 2, 'source_id': '80a..', 'page_number': 1, 'split_id': 1, 'split_idx_start': 8}),
# >> Document(id=5d1.., content: 'simple test ', meta: {'__block_size': 2, '__parent_id': 'f0e..', '__children_ids': [], '__level': 2, 'source_id': 'f0e..', 'page_number': 1, 'split_id': 0, 'split_idx_start': 0}),
# >> Document(id=181.., content: 'document', meta: {'__block_size': 2, '__parent_id': 'f0e..', '__children_ids': [], '__level': 2, 'source_id': 'f0e..', 'page_number': 1, 'split_id': 1, 'split_idx_start': 12})]}

In a pipeline ​

이 Haystack 파이프라인은 .md 파일을 문서로 변환하고, 텍스트를 정리하고, 문장 기반 청크로 나누며, 결과를 In-Memory Document Store에 저장해요.

from pathlib import Path
from haystack import Document
from haystack import Pipeline
from haystack.document_stores.in_memory import InMemoryDocumentStore
from haystack.components.converters.txt import TextFileToDocument
from haystack.components.preprocessors import DocumentCleaner
from haystack.components.preprocessors import HierarchicalDocumentSplitter
from haystack.components.writers import DocumentWriter

document_store = InMemoryDocumentStore()
pipeline = Pipeline()
pipeline.add_component(instance=TextFileToDocument(), name="text_file_converter")
pipeline.add_component(instance=DocumentCleaner(), name="cleaner")
pipeline.add_component(
    instance=HierarchicalDocumentSplitter(
        block_sizes={10, 6, 3}, split_overlap=0, split_by="sentence"
    ),
    name="splitter",
)
pipeline.add_component(
    instance=DocumentWriter(document_store=document_store), name="writer")
pipeline.connect("text_file_converter.documents", "cleaner.documents")
pipeline.connect("cleaner.documents", "splitter.documents")
pipeline.connect("splitter.documents", "writer.documents")
path = "path/to/your/files"
files = list(Path(path).glob("*.md"))
pipeline.run({"text_file_converter": {"sources": files}})