节点解析器使用模式(Node Parser Usage Pattern)

节点解析器使用模式(Node Parser Usage Pattern)

概念解释

节点解析器(Node Parser)是一个简单的抽象,它接受一组文档,并将它们分割成节点对象,每个节点是父文档的一个特定块。当一个文档被分割成节点时,它的所有属性(如元数据、文本和元数据模板等)都会继承给子节点。你可以在这里阅读更多关于节点和文档属性的信息。

入门
独立使用

节点解析器可以单独使用:

from llama_index.core import Document
from llama_index.core.node_parser import SentenceSplitter

node_parser = SentenceSplitter(chunk_size=1024, chunk_overlap=20)

nodes = node_parser.get_nodes_from_documents(
    [Document(text="long text")], show_progress=False
)
转换使用

节点解析器可以包含在任何一组转换中,通过摄取管道(Ingestion Pipeline)使用:

from llama_index.core import SimpleDirectoryReader
from llama_index.core.ingestion import IngestionPipeline
from llama_index.core.node_parser import TokenTextSplitter

documents = SimpleDirectoryReader("./data").load_data()

pipeline = IngestionPipeline(transformations=[TokenTextSplitter(), ...])

nodes = pipeline.run(documents=documents)
索引使用

或者在转换或全局设置中设置,以便在使用 .from_documents() 构建索引时自动使用:

from llama_index.core import SimpleDirectoryReader, VectorStoreIndex
from llama_index.core.node_parser import SentenceSplitter

documents = SimpleDirectoryReader("./data").load_data()

# 全局设置
from llama_index.core import Settings

Settings.text_splitter = SentenceSplitter(chunk_size=1024, chunk_overlap=20)

# 每个索引设置
index = VectorStoreIndex.from_documents(
    documents,
    transformations=[SentenceSplitter(chunk_size=1024, chunk_overlap=20)],
)
节点解析器模块
基于文件的节点解析器

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

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

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"])  # 可选的标签列表
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,  # 每个块的行数
    chunk_lines_overlap=15,  # 块之间的行重叠
    max_chars=1500,  # 每个块的最大字符数
)
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)
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 之前用其周围的上下文替换句子。

设置解析器的示例如下。在实践中,你通常只需要调整句子的窗口大小。

import nltk
from llama_index.core.node_parser import SentenceWindowNodeParser

node_parser = SentenceWindowNodeParser.from_defaults(
    # 每边捕获多少个句子
    window_size=3,
    # 存储周围句子窗口的元数据键
    window_metadata_key="window",
    # 存储原始句子的元数据键
    original_text_metadata_key="original_sentence",
)

完整的示例可以在这里找到,结合 MetadataReplacementNodePostProcessor

SemanticSplitterNodeParser

“语义分块”是 Greg Kamradt 在他的视频教程《5 levels of embedding chunking》中提出的新概念: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

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]
)

通过这些详细的解释和示例,希望你能更好地理解和使用 LlamaIndex 中的节点解析器功能。

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值