跳转到内容

节点解析器模块

基于文件的节点解析器

Section titled “File-Based Node Parsers”

有几种基于文件的节点解析器,它们会根据正在解析的内容类型(JSON、Markdown等)创建节点。

最简单的流程是将 FlatFileReaderSimpleFileNodeParser 结合,自动为每种内容类型使用最佳节点解析器。然后,您可能希望将基于文件的节点解析器与基于文本的节点解析器链接起来,以考虑文本的实际长度。

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)

该节点解析器使用 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 解析原始 JSON。

from llama_index.core.node_parser import JSONNodeParser
parser = JSONNodeParser()
nodes = parser.get_nodes_from_documents(json_docs)

MarkdownNodeParser 解析原始 markdown 文本。

from llama_index.core.node_parser import MarkdownNodeParser
parser = MarkdownNodeParser()
nodes = parser.get_nodes_from_documents(markdown_docs)

根据编写语言分割原始代码文本。

查看此处支持的语言完整列表

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)

你也可以使用节点解析器包装来自 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)

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 与其他节点解析器类似,不同之处在于它将所有文档分割为单个句子。生成的节点在元数据中还包含每个节点周围的句子"窗口"。请注意,此元数据对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 找到。

“语义分块”是Greg Kamradt在其关于五级嵌入分块的视频教程中提出的新概念:https://youtu.be/8OJC21T2SL4?t=1933

与使用固定块大小分割文本不同,语义分割器通过嵌入相似度自适应地选择句子间的断点。这确保每个“文本块”包含语义相互关联的句子。

我们将其适配为一个LlamaIndex模块。

查看我们下方的笔记本!

注意事项:

  • 该正则表达式主要适用于英文句子
  • 您可能需要调整断点百分位阈值。
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 尝试根据原始标记计数分割为一致的块大小。

from llama_index.core.node_parser import TokenTextSplitter
splitter = TokenTextSplitter(
chunk_size=1024,
chunk_overlap=20,
separator=" ",
)
nodes = splitter.get_nodes_from_documents(documents)

该节点解析器会将节点分块为分层节点。这意味着单个输入将被分块为多个层级的块大小,每个节点包含对其父节点的引用。

当与 AutoMergingRetriever 结合使用时,这使我们能够在检索到大多数子节点时自动用其父节点替换检索到的节点。此过程为LLM提供了更完整的上下文以进行响应合成。

from llama_index.core.node_parser import HierarchicalNodeParser
node_parser = HierarchicalNodeParser.from_defaults(
chunk_sizes=[2048, 512, 128]
)

完整示例可在此处结合 AutoMergingRetriever 找到。