在 RAG(检索增强生成)应用中,Excel 是最常见的企业数据格式之一。本文带你深入了解 LangChain 如何加载 Excel 文件,以及如何利用分片策略让表格数据更好地服务于大模型检索。
一、LangChain 的 Excel 处理架构
LangChain 处理 Excel 的核心类是 UnstructuredExcelLoader,位于 langchain-community 包中。它的架构很简洁:
UnstructuredExcelLoader
└── 继承自 UnstructuredFileLoader
└── 继承自 UnstructuredBaseLoader
└── 继承自 BaseLoader
底层依赖 unstructured 库的 partition_xlsx() 函数完成实际的文件解析。LangChain 本身只做了一层封装,负责将解析结果转换为标准的 Document 对象。
二、三种加载模式
UnstructuredExcelLoader 支持三种 mode,决定了 Excel 内容如何被组装为 Document:
1. single 模式(默认)
所有内容拼接为一个 Document,表格的 HTML 表示存放在 metadata["text_as_html"] 中。
from langchain_community.document_loaders.excel import UnstructuredExcelLoader
loader = UnstructuredExcelLoader("sales.xlsx", mode="single")
docs = loader.load()
print(len(docs)) # 1
print(docs[0].page_content[:200])
2. elements 模式
每个 Sheet 被解析为独立的 Table element,各自对应一个 Document。推荐用于多 Sheet 文件。
loader = UnstructuredExcelLoader("sales.xlsx", mode="elements")
docs = loader.load()
for doc in docs:
print(doc.metadata.get("category")) # "Table"
print(doc.page_content[:100])
3. paged 模式(已废弃)
按页码合并 elements。官方已建议改用 chunking_strategy="by_page" 替代。
三、重点:分片策略(Chunking Strategy)
UnstructuredExcelLoader 本身不做分片。 它只负责"提取"内容。如果你需要对 Excel 内容做分片用于 RAG 索引,有两种方案。
方案一:使用 unstructured 内置分片
通过 chunking_strategy 参数直接传给 unstructured 库,在提取阶段完成分片。
支持的策略一览
| | |
|---|
basic | 按顺序将相邻 elements 合并,达到字符上限后切分 | |
by_title | 以标题元素为分界点,同一标题下的内容归为一个 chunk | |
by_page | 按页码/Sheet 分片,同一页的内容合并为一个 chunk | |
by_similarity | | |
常用控制参数
| |
|---|
max_characters | |
new_after_n_chars | |
overlap | |
combine_text_under_n_chars | |
示例代码
from langchain_community.document_loaders.excel import UnstructuredExcelLoader
# basic 策略:顺序合并,每块最多 500 字符,重叠 50 字符
loader = UnstructuredExcelLoader(
"sales.xlsx",
mode="elements",
chunking_strategy="basic",
max_characters=500,
overlap=50,
)
docs = loader.load()
print(f"共 {len(docs)} 个分片")
# by_title 策略:按标题分片
loader = UnstructuredExcelLoader(
"sales.xlsx",
mode="elements",
chunking_strategy="by_title",
max_characters=1000,
combine_text_under_n_chars=200,
)
docs = loader.load()
方案二:Loader + Text Splitter 两步走
先用 Loader 提取全部内容,再用 LangChain 的 Text Splitter 做分片。灵活度更高,可以自由选择分片算法。
from langchain_community.document_loaders.excel import UnstructuredExcelLoader
from langchain_text_splitters import RecursiveCharacterTextSplitter
# 第一步:提取
loader = UnstructuredExcelLoader("sales.xlsx", mode="elements")
docs = loader.load()
# 第二步:分片
splitter = RecursiveCharacterTextSplitter(
chunk_size=1000,
chunk_overlap=200,
)
chunks = splitter.split_documents(docs)
print(f"原始文档数: {len(docs)}, 分片后: {len(chunks)}")
四、实践建议
Excel 场景该选哪种方案?
| |
|---|
| mode="single" |
| mode="elements" + chunking_strategy="by_page" |
| basic |
| |
注意事项
- 安装依赖:需要额外安装
unstructured 和 openpyxl:
pip install unstructured openpyxl
Excel 的特殊性:Excel 不像 PDF 有天然的"页"概念,unstructured 通常将每个 Sheet 解析为一个 Table element。如果单个 Sheet 数据量巨大,by_title 和 by_page 策略效果有限,此时 basic 策略或自定义分片更实用。
表格结构保留:single 模式下,表格会转为 HTML 格式存在 metadata 中(text_as_html),如果下游需要保留表格结构,可以利用这个字段。
性能考虑:对于大型 Excel 文件,unstructured 的解析可能较慢。如果只需要简单的文本提取,直接用 pandas + 自定义 Loader 会更高效。
五、总结
LangChain 对 Excel 的处理遵循"Loader 只管提取,分片交给策略"的设计哲学:
UnstructuredExcelLoader 负责将 Excel 转为 Document 对象- 分片可以通过
chunking_strategy 参数在提取时完成,也可以用 Text Splitter 后置处理 - 对于企业级 RAG 应用,建议根据数据特点选择合适的分片策略,并通过
max_characters、overlap 等参数调优
掌握这些,你就能让 Excel 数据在 RAG 管道中发挥最大价值。