[LangChain] 11. 本地资源Loader
很多时候,我们需要加载额外的数据,比如 RAG 架构中,需要外挂知识库。
外部数据的形式千差万别:可能是一份 PDF 文件、一张表格、一段代码,甚至是来自网络的实时信息。针对这些需求,LangChain 提供了一整套开箱即用的 Loader 工具,帮助我们高效地加载各种结构化或非结构化的数据,并统一转换成 LLM 能够理解和处理的格式。
Document对象
在 LangChain 中,无论你的数据来自哪里——文本文件、数据库、网页还是 GitHub 项目,最终都会被封装成一种统一的数据结构 Document 对象。
好处:LangChain 的后续模块(如向量化、检索器、分片器等)不需要关心你的数据来源,只需要对 Document 进行处理即可。
一个 Document 对象由两个部分构成:
interface Document {
pageContent: string; // 文本内容,表示这段文档的主体内容
metadata: Record<string, any>; // 元数据,附加的上下文信息,如来源、页码、标题等
}
手动创建一个 Document 对象示例:
import { Document } from "@langchain/core/documents";
const doc = new Document({
pageContent: "这是一段测试文字",
metadata: {
source: "abc",
},
});
console.log(doc)
效果:
Document {
pageContent: '这是一段测试文字',
metadata: { source: 'abc' },
id: undefined
}
真实项目中,更多是通过 Loader 工具读取外部资源,然后封装成一组 Document 实例。
Loader 的种类很多:
- 本地资源Loader
- Web资源Loader
文本Loader
文本Loader位于langchain包下面
pnpm add langchain
用来加载纯文本文件的 Loader,适合处理 .txt 类型的文件。
示例代码:
import { TextLoader } from "@langchain/classic/document_loaders/fs/text";
const res = await new TextLoader("test.txt").load();
console.log(res);
效果:
[
Document {
pageContent: '这是一段测试文本,啦啦啦啦',
metadata: { source: 'data/test.txt' },
id: undefined
}
]
🤔这里返回的是一个数组,数组里面又只有一项。那什么时候数组里面有多项呢?
-
读取一个目录中的多个文件
-
一个文件很长,设置了文本切割。
import { TextLoader } from "@langchain/classic/document_loaders/fs/text";
import { RecursiveCharacterTextSplitter } from "@langchain/classic/text_splitter";
const res = await new TextLoader("test.txt").load();
const splitter = new RecursiveCharacterTextSplitter({
chunkSize: 100,
chunkOverlap: 20,
}).splitDocuments(res);
const splitRes = splitter.splitDocuments(res);
console.log(splitRes);
PDFLoader
PDF 文件是许多知识密集型场景中的常见数据源。在 LangChain 中,可以使用 PDFLoader 来方便地读取 PDF 文件内容,并将其转换为标准的 Document 对象。
它的默认行为是:将 PDF 每一页内容都拆成一个独立的 Document 对象。
安装依赖:
pnpm add @langchain/community pdf-parse
示例代码:
import { PDFLoader } from "@langchain/community/document_loaders/fs/pdf";
const loader = new PDFLoader("data/novel.pdf", {
splitPages: false,
});
const result = await loader.load();
console.log(result);
如果你希望一次性读取整个 PDF 的所有页,而不是拆分成每页一个 Document,可以通过设置 splitPages: false 来关闭分页行为:
const loader = new PDFLoader("data/bananaphone.pdf", {
splitPages: false,
});
目录Loader
在实际项目中,数据通常不是孤零零存在,而是统一放在一个文件夹中、由多种格式的文件组成(比如:.txt、.pdf、.md 等等)。这时逐个调用对应的 Loader,会非常麻烦。
LangChain.js 为我们提供了一个统一入口 —— DirectoryLoader,可以自动识别目录中不同类型的文件,并调用对应的 Loader 执行加载任务。
DirectoryLoader 接收两个参数:
- 第一个参数:要加载的文件夹路径
- 第二个参数:一个对象,键是文件后缀名,值是对应的 Loader 工厂函数
每种类型的文件会自动使用我们配置的 Loader 进行处理。返回结果是一个 Document[] 数组,每个元素代表一个文档对象。
import { DirectoryLoader } from "@langchain/classic/document_loaders/fs/directory";
import { PDFLoader } from "@langchain/community/document_loaders/fs/pdf";
import { TextLoader } from "@langchain/classic/document_loaders/fs/text";
const loader = new DirectoryLoader("./data", {
".pdf": (path) => new PDFLoader(path, { splitPages: false }),
".txt": (path) => new TextLoader(path),
});
const result = await loader.load();
console.log(result);
最佳实践
| 使用场景 | 是否适合使用 DirectoryLoader |
|---|---|
| 加载同类型文件(比如全是 .txt) | ❌ 推荐直接用 TextLoader,效率更高 |
| 加载多类型文件(pdf / txt / md 混合) | ✅ 推荐使用 DirectoryLoader 批量处理 |
| 加载小规模单个文档 | ❌ 不推荐使用 DirectoryLoader,配置成本不划算 |
| 大型知识库统一导入 | ✅ 非常推荐,可结合向量化批处理 |
支持的 Loader 类型
除了示例中用到的 .txt 和 .pdf,你还可以按需加载:
.md:使用TextLoader加载 Markdown 文件.csv:使用CSVLoader(来自fs/csv)加载结构化数据.json:使用JSONLoader按 key 提取文本内容.docx:使用DocxLoader处理 Word 文档
几乎所有支持的 Loader 都可以配合 DirectoryLoader 使用,只需要在映射对象中正确配置后缀名和构造器即可。
文档地址:https://v03.api.js.langchain.com/classes/langchain.document_loaders_fs_json.JSONLoader.html
-EOF-

浙公网安备 33010602011771号