第十五节:LlamaIndex框架使用2(文件解析器、分割器)
一. 基础解析器:简单文件与 Markdown
1. SimpleFileNodeParser —— 通用文本切分
适用场景:纯文本文件(如 .txt)的基础切分,按段落和空行自动分割。
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('data/小说.txt'))
# 创建解析器并切分
parser = SimpleFileNodeParser()
nodes = parser.get_nodes_from_documents(md_docs)
print(nodes)
核心特点:
- 按文件内容结构(段落、空行)自动切分
- 无需配置,开箱即用
- 适合小说、文章等纯文本场景
2. MarkdownNodeParser —— Markdown 结构切分
适用场景:Markdown 文档,按标题层级(#、##、###)拆分章节。
from llama_index.core.node_parser import MarkdownNodeParser
from llama_index.readers.file import FlatReader
from pathlib import Path
# 读取 Markdown 文件
md_docs = FlatReader().load_data(Path('data/test.md'))
# 创建解析器,自动识别标题层级
parser = MarkdownNodeParser()
nodes = parser.get_nodes_from_documents(md_docs)
print(nodes)
核心特点:
- 智能识别 Markdown 标题层级
- 每个章节成为独立节点,保持逻辑完整性
- 适合技术文档、知识库等结构化内容
二. 结构化解释器
1. MarkdownElementNodeParser —— Markdown 元素智能解析
适用场景:包含表格、代码块等复杂结构的 Markdown 文档,需要用 LLM 自动生成元素摘要。
代码分享:
from llama_index.core.node_parser import MarkdownElementNodeParser
from llama_index.readers.file import FlatReader
from llama_index.llms.dashscope import DashScope
from llama_index.embeddings.huggingface import HuggingFaceEmbedding
from llama_index.core import Settings, VectorStoreIndex
from llama_index.core.query_engine import RetrieverQueryEngine
from pathlib import Path
# 配置全局 LLM 与 Embedding
Settings.llm = DashScope(model="your-model", api_key="your-api-key")
Settings.embed_model = HuggingFaceEmbedding(model_name="bge-large-zh-v1.5")
# 自定义摘要提示词
MY_CUSTOM_SUMMARY_QUERY = (
"你是一个技术文档解析助手。请提取以下 Markdown 表格或内容的极简摘要。"
"要求:1. 严禁啰嗦;2. 必须包含表格中的关键实体词;"
"3. 如果是代码相关内容,请保留具体的命令名称。请用中文摘要"
)
# 创建解析器
parser = MarkdownElementNodeParser(
include_prev_next_rel=True, # 保留前后节点关联
summary_query_str=MY_CUSTOM_SUMMARY_QUERY,
)
nodes = parser.get_nodes_from_documents(md_docs)
# 构建索引与查询引擎
index = VectorStoreIndex(nodes)
query_engine = index.as_query_engine(similarity_top_k=5)
# 测试查询
response = query_engine.query("张三多少岁?")
print(response)
核心特点:
- 识别表格、代码块、列表等元素
- 利用 LLM 为每个元素生成摘要
- 保留元素间的上下文关联
- 适合复杂技术文档的 RAG 场景
2 CodeSplitter —— 代码专用分割器
适用场景:源代码文件的智能切分,按语法结构保持代码完整性。
代码分享:
from llama_index.core.node_parser import CodeSplitter
from llama_index.core import SimpleDirectoryReader
# 读取代码文件
documents = SimpleDirectoryReader(input_files=['./example.py']).load_data()
# 初始化代码分割器
splitter = CodeSplitter(
language="python", # 支持多种编程语言
chunk_lines=50, # 每块行数
chunk_lines_overlap=10, # 重叠行数(保持上下文)
max_chars=300, # 最大字符数
)
# 切分文档
nodes = splitter.get_nodes_from_documents(documents)
for node in nodes:
print(f"Type: {node.metadata}\nText: {node.text}\n{'='*50}")
核心特点:
- 基于 Tree-sitter 的语法感知切分
- 支持 Python、Java、JavaScript 等主流语言
- 保持函数、类等代码结构的完整性
- 通过重叠机制避免代码逻辑断裂
3. SentenceSplitter —— 句子级精细切分
适用场景:需要精确控制节点大小,同时保持语义完整性的文本分割。
from llama_index.core import SimpleDirectoryReader
from llama_index.core.node_parser import SentenceSplitter
# 初始化分割器
splitter = SentenceSplitter(
chunk_size=512, # 每个节点最大字符数
chunk_overlap=50, # 相邻节点重叠字符数
paragraph_separator="\r\n\r\n", # 第一优先级:段落分割
secondary_chunking_regex="[^,。;!?]+[,。;!?]?", # 第二优先级:中文句子
)
# 读取并切分文档
documents = SimpleDirectoryReader(input_files=['data/小说.txt']).load_data()
nodes = splitter.get_nodes_from_documents(documents)
# 打印结果
for node in nodes:
print(node.text, "---" * 10)
核心特点:
- 三级分割策略(段落 → 句子 → 硬截断)
- 支持中英文混合文本
- 精细控制每个节点的 Token 数量
- 通过重叠保持上下文连贯性
三. 语义增强解释器
1. SentenceWindowNodeParser —— 句子窗口解析器
适用场景:RAG 检索时需要保留句子上下文,提升回答准确性。
核心原理:每个 Node 只保存单个句子(用于索引),但在 metadata 中附带其相邻句子的上下文窗口。检索时匹配单个句子,但交给 LLM 时能看到更完整的上下文。
from llama_index.core.node_parser import SentenceWindowNodeParser
from llama_index.core import Document
# 创建示例文档
document = Document(text="这是第一个句子. 这是第二个句子. 这是第三个句子. 这是第四个句子. ")
# 创建句子窗口解析器
node_parser = SentenceWindowNodeParser(
window_size=1, # 前后各保留 N 个句子
window_metadata_key="window", # 上下文窗口的 metadata key
original_text_metadata_key="original_text", # 原始句子的 metadata key
)
# 切分文档
nodes = node_parser.get_nodes_from_documents([document])
# 查看每个节点的文本和上下文
for node in nodes:
print(f"文本: {node.text}")
print(f"上下文: {node.metadata['window']}")
print()
核心特点:
- 索引粒度细(单个句子),检索精度高
- 推理时上下文完整,避免信息丢失
- 通过 window_size 灵活控制上下文范围
- 适合需要精确匹配的问答场景
2. HierarchicalNodeParser —— 层次节点解析器
适用场景:长文档的多级切分,支持自动合并相关节点。
核心原理:将文档切分为多层级结构(如 512-token 的粗粒度块包含多个 300-token 的细粒度块),检索时先找到相关的细粒度节点,再自动合并其父节点,确保上下文完整性。
from llama_index.core.node_parser import HierarchicalNodeParser, get_leaf_nodes
from llama_index.core.retrievers import AutoMergingRetriever
from llama_index.core import SimpleDirectoryReader, StorageContext, VectorStoreIndex, Settings
from llama_index.embeddings.huggingface import HuggingFaceEmbedding
# 配置 Embedding
Settings.embed_model = HuggingFaceEmbedding(model_name="bge-large-zh-v1.5")
# 读取数据
documents = SimpleDirectoryReader(input_files=['data/公司规章制度.txt']).load_data()
# 创建层次解析器(chunk_sizes 从粗到细)
node_parser = HierarchicalNodeParser.from_defaults(chunk_sizes=[512, 300], chunk_overlap=70)
nodes = node_parser.get_nodes_from_documents(documents)
# 获取叶节点(最细粒度)
leaf_nodes = get_leaf_nodes(nodes)
# 构建存储上下文
from llama_index.core.storage.docstore import SimpleDocumentStore
docstore = SimpleDocumentStore()
docstore.add_documents(nodes)
storage_context = StorageContext.from_defaults(docstore=docstore)
# 构建向量索引(仅对叶节点)
base_index = VectorStoreIndex(leaf_nodes, storage_context=storage_context)
base_retriever = base_index.as_retriever(similarity_top_k=6)
# 构建自动合并检索器
retriever = AutoMergingRetriever(
vector_retriever=base_retriever,
storage_context=storage_context,
simple_ratio_thresh=0.5, # 合并阈值
verbose=True,
)
# 查询
query_str = "公司形象有哪几条?"
nodes_returned = retriever.retrieve(query_str)
for node in nodes_returned:
print("---")
print(node.get_content())
核心特点:
- 多级粒度切分,兼顾检索精度与上下文完整性
- AutoMergingRetriever 自动合并相关父节点
- 适合长文档(如规章制度、合同)的问答场景
- 通过阈值控制合并策略,灵活调整检索效果
解析器选型对照表
| 解析器名称 | 核心功能 | 适用场景 | 关键依赖 |
|---|---|---|---|
| SimpleFileNodeParser | 按段落/空行切分 | 纯文本文件、小说、文章 | 无 |
| MarkdownNodeParser | 按标题层级切分 | Markdown 文档、技术文档 | 无 |
| MarkdownElementNodeParser | 元素识别 + LLM 摘要 | 复杂 Markdown(含表格、代码) | LLM |
| CodeSplitter | 语法感知代码切分 | 源代码文件 | tree_sitter |
| SentenceSplitter | 句子级精细切分 | 需要精确控制节点大小 | 无 |
| SentenceWindowNodeParser | 句子上下文窗口 | 需要保留上下文的问答 | 无 |
| HierarchicalNodeParser | 层次切分 + 自动合并 | 长文档、合同、规章制度 | Embedding |
总结与建议
选择合适的节点解析器是构建高效 RAG 系统的第一步,以下是选型建议:
- 简单文本 → SimpleFileNodeParser 或 SentenceSplitter
- 技术文档 → MarkdownNodeParser 或 MarkdownElementNodeParser
- 代码仓库 → CodeSplitter
- 需要上下文 → SentenceWindowNodeParser
- 长文档 → HierarchicalNodeParser + AutoMergingRetriever
最佳实践:
- 先从简单解析器开始,观察检索效果
- 根据实际场景调整 chunk_size 和 overlap 参数
- 对于复杂文档,考虑组合使用多种解析器
- 在生产环境中,建议对切分结果进行质量评估
!
- 作 者 : Yaopengfei(姚鹏飞)
- 博客地址 : http://www.cnblogs.com/yaopengfei/
- 声 明1 : 如有错误,欢迎讨论,请勿谩骂^_^。
- 声 明2 : 原创博客请在转载时保留原文链接或在文章开头加上本人博客地址,否则保留追究法律责任的权利。

浙公网安备 33010602011771号