노드 파서 모듈
노드 파서 모듈
파싱되는 콘텐츠 유형(JSON, Markdown 등)에 따라 노드를 만드는 파일 기반 노드 파서와 다양한 텍스트 스플리터에 대해 알아봐요.
출처: 문서
본문
파일 기반 노드 파서
파싱되는 콘텐츠 유형(JSON, Markdown 등)에 따라 노드를 만드는 여러 파일 기반 노드 파서가 있어요.
가장 간단한 흐름은 FlatFileReader와 SimpleFileNodeParser를 결합해 각 콘텐츠 유형에 가장 좋은 노드 파서를 자동으로 사용하는 거예요. 그런 다음 파일 기반 노드 파서를 텍스트 기반 노드 파서와 연결해 실제 텍스트 길이를 고려할 수도 있어요.
SimpleFileNodeParser
from llama_index.core.node_parser import SimpleFileNodeParser
from llama_index.readers.file import FlatReader
from pathlib import Path
md_docs = FlatReader().load_data(Path("./test.md"))
parser = SimpleFileNodeParser()
md_nodes = parser.get_nodes_from_documents(md_docs)
HTMLNodeParser
이 노드 파서는 beautifulsoup를 사용해 원시 HTML을 파싱해요. 기본적으로 특정 하위 집합의 HTML 태그를 파싱하지만, 이를 오버라이드할 수 있어요.
기본 태그는 다음과 같아요: ["p", "h1", "h2", "h3", "h4", "h5", "h6", "li", "b", "i", "u", "section"]
from llama_index.core.node_parser import HTMLNodeParser
parser = HTMLNodeParser(tags=["p", "h1"]) # optional list of tags
nodes = parser.get_nodes_from_documents(html_docs)
JSONNodeParser
JSONNodeParser는 원시 JSON을 파싱해요.
from llama_index.core.node_parser import JSONNodeParser
parser = JSONNodeParser()
nodes = parser.get_nodes_from_documents(json_docs)
MarkdownNodeParser
MarkdownNodeParser는 원시 markdown 텍스트를 파싱해요.
from llama_index.core.node_parser import MarkdownNodeParser
parser = MarkdownNodeParser()
nodes = parser.get_nodes_from_documents(markdown_docs)
텍스트 스플리터
CodeSplitter
작성된 언어에 따라 원시 코드 텍스트를 분할해요. 지원되는 언어 전체 목록 확인
from llama_index.core.node_parser import CodeSplitter
splitter = CodeSplitter(
language="python",
chunk_lines=40, # lines per chunk
chunk_lines_overlap=15, # lines overlap between chunks
max_chars=1500, # max chars per chunk
)
nodes = splitter.get_nodes_from_documents(documents)
LangchainNodeParser
langchain의 기존 텍스트 스플리터를 노드 파서로 감쌀 수도 있어요.
from langchain.text_splitter import RecursiveCharacterTextSplitter
from llama_index.core.node_parser import LangchainNodeParser
parser = LangchainNodeParser(RecursiveCharacterTextSplitter())
nodes = parser.get_nodes_from_documents(documents)
Chunker
Chunker는 chonkie 청커를 감싸는 다목적 노드 파서예요. 지원되는 chonkie 청킹 전략 중 어떤 별칭으로든 파서를 초기화할 수 있으며, 유효한 별칭의 전체 목록은 Chunker.valid_chunker_types 속성으로 접근할 수 있어요.
from llama_index.node_parser.chonkie import Chunker
parser = Chunker("recursive", chunk_size=2048)
nodes = parser.get_nodes_from_documents(documents)
chonkie 청커 인스턴스를 직접 전달해 파서를 초기화할 수도 있어요.
from chonkie import RecursiveChunker
from llama_index.node_parser.chonkie import Chunker
chonkie_chunker = RecursiveChunker()
parser = Chunker(chonkie_chunker)
nodes = parser.get_nodes_from_documents(documents)
SentenceSplitter
SentenceSplitter는 문장의 경계를 존중하면서 텍스트를 분할하려고 시도해요.
from llama_index.core.node_parser import SentenceSplitter
splitter = SentenceSplitter(
chunk_size=1024,
chunk_overlap=20,
)
nodes = splitter.get_nodes_from_documents(documents)
SentenceWindowNodeParser
SentenceWindowNodeParser는 다른 노드 파서와 유사하지만, 모든 문서를 개별 문장으로 분할해요. 결과 노드는 각 노드 주변의 문장 "윈도우"도 메타데이터에 담아요. 이 메타데이터는 LLM이나 임베딩 모델에는 보이지 않는다는 점에 주의하세요.
이것은 매우 특정한 범위의 임베딩을 생성할 때 가장 유용해요. 그런 다음 MetadataReplacementNodePostProcessor와 결합해, 노드를 LLM으로 보내기 전에 문장을 주변 컨텍스트로 대체할 수 있어요.
기본 설정으로 파서를 설정하는 예시는 아래와 같아요. 실제로는 보통 문장의 윈도우 크기만 조정하면 돼요.
from llama_index.core.node_parser import SentenceWindowNodeParser
node_parser = SentenceWindowNodeParser.from_defaults(
# how many sentences on either side to capture
window_size=3,
# the metadata key that holds the window of surrounding sentences
window_metadata_key="window",
# the metadata key that holds the original sentence
original_text_metadata_key="original_sentence",
)
전체 예시는 MetadataReplacementNodePostProcessor와 결합한 예시에서 찾을 수 있어요.
SemanticSplitterNodeParser
"시맨틱 청킹(semantic chunking)"은 Greg Kamradt가 임베딩 청킹의 5단계에 관한 비디오 튜토리얼에서 제안한 새로운 개념이에요: https://youtu.be/8OJC21T2SL4?t=1933.
고정된 청크 크기로 텍스트를 청킹하는 대신, 시맨틱 스플리터는 임베딩 유사도를 사용해 문장 사이의 분리 지점을 적응형으로 선택해요. 이렇게 하면 "청크"가 서로 의미적으로 관련된 문장을 포함하게 돼요.
우리는 이를 LlamaIndex 모듈로 적용했어요. 아래 노트북을 확인해 보세요!
주의 사항:
- 정규식은 주로 영어 문장에서 동작해요
- 분리 지점 백분위 임계값(breakpoint percentile threshold)을 조정해야 할 수 있어요
from llama_index.core.node_parser import SemanticSplitterNodeParser
from llama_index.embeddings.openai import OpenAIEmbedding
embed_model = OpenAIEmbedding()
splitter = SemanticSplitterNodeParser(
buffer_size=1, breakpoint_percentile_threshold=95, embed_model=embed_model
)
전체 예시는 SemanticSplitterNodeParser 사용 가이드에서 찾을 수 있어요.
TokenTextSplitter
TokenTextSplitter는 원시 토큰 수에 따라 일관된 청크 크기로 분할하려고 시도해요.
from llama_index.core.node_parser import TokenTextSplitter
splitter = TokenTextSplitter(
chunk_size=1024,
chunk_overlap=20,
separator=" ",
)
nodes = splitter.get_nodes_from_documents(documents)
관계 기반 노드 파서
HierarchicalNodeParser
이 노드 파서는 노드를 계층적 노드로 청킹해요. 즉, 단일 입력이 여러 계층의 청크 크기로 청킹되고, 각 노드는 부모 노드에 대한 참조를 담아요.
AutoMergingRetriever와 결합하면, 검색된 노드의 대다수가 자식일 때 검색된 노드를 부모로 자동 대체할 수 있게 해요. 이 과정은 LLM이 응답 합성을 위해 더 완전한 컨텍스트를 갖도록 해줘요.
from llama_index.core.node_parser import HierarchicalNodeParser
node_parser = HierarchicalNodeParser.from_defaults(
chunk_sizes=[2048, 512, 128]
)
전체 예시는 AutoMergingRetriever와 결합한 예시에서 찾을 수 있어요.