LangChain4j 中 RAG 系统文档加载、解析与分块策略详解
在 LangChain4j 中,构建一个高效的 RAG(检索增强生成)系统,文档的加载、解析和分块是基石。这三个环节环环相扣,共同决定了后续检索的准确性和最终生成答案的质量。
一、文档加载与解析:从原始文件到结构化文本
这个过程的目标是将存储在各种载体(本地文件、网页、S3 等)和格式(PDF、Word、TXT)中的知识,转化为框架可以处理的 Document 对象。
1. 文档加载器 (DocumentLoader)
加载器负责读取数据源,获取原始的二进制或文本流。LangChain4j 提供了多种开箱即用的加载器:
- FileSystemDocumentLoader:从本地文件系统加载文件,支持递归遍历目录和 glob 表达式过滤(如只加载.pdf 文件)。
- ClassPathDocumentLoader:从应用的类路径(如 resources 目录)加载打包好的文档。
- UrlDocumentLoader:从指定的 URL 获取网页内容。
2. 文档解析器 (DocumentParser)
加载器获取到原始文件后,需要解析器来提取其中的文本和元数据。解析器的选择取决于文件格式:
- 纯文本:使用 TextDocumentParser。
- PDF 文件:引入 langchain4j-document-parser-apache-pdfbox 依赖,使用 ApachePdfBoxDocumentParser。
- 微软 Office 文档(Word, Excel, PowerPoint):引入 langchain4j-document-parser-apache-poi 依赖,使用 ApachePoiDocumentParser。
- 通用解析:ApacheTikaDocumentParser(已包含在 langchain4j-easy-rag 模块中)能自动识别并解析大多数常见格式,是最省心的选择。
完整的处理流程如下:
- 加载文档 (路径/URL)
- 获取原始文档流
- 返回解析后的 Document 对象
- 返回 Document 列表
- 分割文档
- 返回 TextSegment 列表
- 为每个 Segment 生成向量
- 返回 Embedding 列表
- 存储 Segment 和对应的 Embedding
二、分块策略 (Document Splitter):将知识切成适合检索的片段
分块是将长文档切分为更小的、语义完整的 TextSegment 的过程。这是 RAG 中最关键的环节之一,其策略直接决定了检索的精度和上下文的质量。LangChain4j 主要通过 DocumentSplitter 接口及其实现来完成。
核心策略对比与选择
| 策略 | 实现类/方法 | 工作原理 | 最佳实践场景 | 潜在问题 |
|---|---|---|---|---|
| 递归分割 | DocumentSplitters.recursive(maxSize, overlap) | 默认推荐策略。按优先级顺序(段落 \n\n > 句子 . > 其他标点)尝试分割,若块仍过大,则递归使用次优先级分隔符,直到满足大小限制。 | 通用文档,尤其是包含自然段落的文章、报告。平衡了语义完整性和块大小,适用性最广。 | 对于代码或结构化数据可能不是最优。 |
| 基于句子分割 | DocumentBySentenceSplitter(maxSize, overlap) | 以句子为基本单位进行分割,确保不会将一个句子切分到两个块中。内部使用 Apache OpenNLP 进行句子边界检测。 |


