LlamaIndex中的节点解析器使用指南
在LlamaIndex中,节点解析器是一个简单的抽象,它接受一组文档,并将它们分割成节点对象,每个节点是父文档的一个特定块。当一个文档被分割成节点时,它的所有属性(如元数据、文本和元数据模板等)都会继承给子节点。你可以在这里阅读更多关于节点和文档属性的信息。
入门指南
独立使用
节点解析器可以单独使用:
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
)
转换使用
节点解析器可以包含在任何一组转换中,通过摄取管道:
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等)创建节点。
最简单的流程是结合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"]) # 可选的标签列表
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之前用其周围的上下文替换句子。
设置解析器的示例如下。在实践中,你通常只需要调整句子的窗口大小。
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个层次”中提出的新概念: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]
)
完整的示例可以在这里找到,结合AutoMergingRetriever。
通过这些方法,你可以轻松地在LlamaIndex中使用节点解析器,根据需要进行自定义和扩展。