LlamaIndex 语义分块报错
具体表现是,在使用 SemanticSplitterNodeParser 进行分块时,程序会反复弹出 Embedding attempt failed: TextEncodeInput must be Union[TextInputSequence, Tuple[InputSequence, InputSequence]],最后直接抛出 TypeError。
最诡异的地方在于,我尝试了多种解析方案。先是用 PyMuPDF 配合 SimpleDirectoryReader,不行;后来换成 LlamaParse 将 PDF 转成 Markdown 格式,结果依然在 Embedding 阶段挂掉。我检查了保存的 .pkl 文件,解析后的文本内容其实是完整的,并没有丢失。这意味着问题不在于 PDF 解析,而在于 Embedding 模型在面对某些特定科学字符时,无法将其正确编码为 Tensor 导致输入类型不匹配。
以下是我复现问题的核心代码片段,大家可以对照检查自己的工作流:
from llama_index.core.node_parser import SemanticSplitterNodeParser
from llama_index.embeddings.huggingface import HuggingFaceEmbedding
import pickle
# 使用的是 BGE 小模型
embed_model = HuggingFaceEmbedding(
model_name="BAAI/bge-small-en-v1.5"
)
# 加载已经解析好的 markdown 文档
with open("mds.pkl", "rb") as f:
docs = pickle.load(f)
# 在这里触发报错
splitter = SemanticSplitterNodeParser(
buffer_size=1,
embed_model=embed_model,
include_metadata=True
)
nodes = splitter.get_nodes_from_documents(docs)排查后的几点分析:
- 单文档 vs 批量处理: 这是一个很关键的信号。测试
docs[0]没问题,但docs全量运行就报错。这说明数据集中存在某些极其罕见的特殊字符(比如某些 LaTeX 渲染出的特殊符号或非标准 Unicode 字符),这些字符在触发 Embedding 编码时导致了sentence-transformers内部的类型转换失败。 - 模型限制: BGE-small 等模型虽然强大,但对某些极其冷门的科学符号处理可能不够鲁棒,当遇到无法识别且无法 fallback 的字符序列时,可能会传递一个非预期的类型给 TensorFlow/PyTorch。
目前的解决思路(实操建议):
针对这种大批量论文处理,手动审计每一篇是不现实的。我尝试了两种方案来绕过这个坑:
1. 预处理清洗(最稳妥):
在将文本送入 SemanticSplitterNodeParser 之前,用一个简单的正则函数过滤掉非打印字符或将复杂的 Unicode 符号标准化。
import unicodedata
def clean_scientific_text(text):
# 将 unicode 字符标准化,减少特殊编码导致的报错
return unicodedata.normalize('NFKC', text)
# 对 docs 中的 text 进行预处理
for doc in docs:
doc.text = clean_scientific_text(doc.text)2. 放弃语义分块,改用常规分块:
如果对分块精度要求不是极致,建议直接使用 SentenceSplitter。语义分块需要对每一个窗口计算 Embedding 来判断断点,这大大增加了触发 Embedding 报错的概率。而常规分块只在最终索引时才调用 Embedding,且那时通常有更成熟的错误处理机制。
对于需要处理海量学术文献的开发者,建议在 LlamaParse 解析后,务必加上一步 unicodedata 标准化处理,否则在后续的 AI Agent 工作流或 Embedding 部署中,这种隐藏的字符炸弹随时会让你程序崩溃。