【LangChain.js学习】 文档加载(Loader)与文本分割全解析

0 阅读5分钟

核心说明

LangChain 提供丰富的文档加载器(Loader),用于将不同格式(CSV/JSON/JSONL/DOCX/TXT)的文件转换为标准化的 Document 对象(包含 pageContent 文本内容 + metadata 元数据),是构建知识库、文本分析的基础。所有加载器均实现 BaseDocumentLoader 抽象类,保证调用方式统一,部分场景需配合文本分割器处理长文本。

一、核心概念:Document 对象

Document 是 LangChain 处理文本的标准化载体,所有加载器最终都会返回 Document[] 数组,结构如下:

interface Document {
  pageContent: string; // 核心文本内容
  metadata: Record<string, any>; // 元数据(如文件路径、行号、格式等)
}

二、各类文档加载实现

1. CSV 文件加载

适用于表格类数据,每行数据会被解析为一个 DocumentpageContent 为行内容,metadata 包含行号、文件路径等信息。

依赖安装

pnpm add d3-dsv

示例文件(./data/data.csv)

name,age
李白,18
白居易,20

加载代码

import { CSVLoader } from "@langchain/community/document_loaders/fs/csv";
​
// 初始化CSV加载器
const loader = new CSVLoader("./data/data.csv");
// 加载并转换为Document数组
const documents = await loader.load();
​
console.log(documents);
/** 输出示例:
[
  {
    pageContent: "name: 李白, age: 18",
    metadata: { line: 1, source: "./data/data.csv" }
  },
  {
    pageContent: "name: 白居易, age: 20",
    metadata: { line: 2, source: "./data/data.csv" }
  }
]
*/

2. JSON 文件加载

JSONLoader 核心能力是提取JSON对象中字符串类型的键值对值,无法解析JSON数组结构,空路径下会逐行扫描文本提取值,仅适用于单JSON对象场景。

示例文件(./data/data.json)

{ "name": "李白", "like": "唱歌" }

加载代码

import { JSONLoader } from "@langchain/classic/document_loaders/fs/json";
​
const loader = new JSONLoader("./data/data.json", "");
const documents = await loader.load();
​
console.log(documents);
/** 实际运行输出:
[
  Document {
    pageContent: '李白',
    metadata: { source: './data/data.json', line: 1 }
  },
  Document {
    pageContent: '唱歌',
    metadata: { source: './data/data.json', line: 2 }
  }
]
*/

3. JSONL 文件加载(推荐用于JSON数组)

JSONL(每行一个JSON对象)是处理JSON数组的最佳方式,JSONLinesLoader 会逐行解析合法的 JSON 对象,完美实现“一项一个Document”。

示例文件(./data/data.jsonl)

{"name":"李白","age":18}
{"name":"杜甫","age":20}

加载代码

import { JSONLinesLoader } from "@langchain/classic/document_loaders/fs/json";
​
// 初始化JSONL加载器
const loader = new JSONLinesLoader("./data/data.jsonl", "");
const documents = await loader.load();
​
console.log(documents);
/** 输出示例(每行一个Document):
[
  Document {
    pageContent: '{"name":"李白","age":18}',
    metadata: { line: 1, source: "./data/data.jsonl" }
  },
  Document {
    pageContent: '{"name":"杜甫","age":20}',
    metadata: { line: 2, source: "./data/data.jsonl" }
  }
]
*/

4. DOCX 文件加载

适用于Word文档,会提取文档中的纯文本内容(自动剔除格式标记),默认将整个文档作为一个 Document 返回,长文档可配合文本分割器处理。

加载代码

import { DocxLoader } from "@langchain/community/document_loaders/fs/docx";
​
// 初始化DOCX加载器
const loader = new DocxLoader("./data/data.docx");
const documents = await loader.load();
​
console.log(documents);
/** 输出示例:
[
  Document {
    pageContent: "文档中的纯文本内容,自动去除Word格式标记...",
    metadata: { source: "./data/data.docx" }
  }
]
*/

5. TXT 文件加载与文本分割

纯文本文件加载后,若内容过长(超过大模型上下文窗口),需配合 RecursiveCharacterTextSplitter 分割为小文本块,保证后续处理效率。

示例文件(./data/data.txt)

李娟,1979年7月出生于新疆生产建设兵团,籍贯四川乐至,当代女作家,2022年当选新疆作协副主席。作品有散文集《阿勒泰的角落》《我的阿勒泰》《走夜路请放声歌唱》等。

加载与分割代码

import { TextLoader } from "@langchain/classic/document_loaders/fs/text";
import { RecursiveCharacterTextSplitter } from "@langchain/classic/text_splitter";
​
// 1. 加载TXT文件
const loader = new TextLoader("./data/data.txt");
const documents = await loader.load();
​
// 2. 初始化文本分割器
const splitter = new RecursiveCharacterTextSplitter({
  chunkSize: 25, // 每个文本块的最大字符数
  chunkOverlap: 5, // 块之间的重叠字符数(保证上下文连贯)
  separators: [",", "。"], // 中文优先分割符(按语义分割)
});
​
// 3. 分割文档为小文本块
const splitDocuments = await splitter.splitDocuments(documents);
​
console.log(splitDocuments);
/** 输出示例(分割为多个小Document):
[
  Document {
    pageContent: "李娟,1979年7月出生于新疆生产建设兵团",
    metadata: { source: "./data/data.txt" }
  },
  Document {
    pageContent: "兵团,籍贯四川乐至,当代女作家",
    metadata: { source: "./data/data.txt" },
  },
  Document {
    pageContent: "女作家,2022年当选新疆作协副主席。",
    metadata: { source: "./data/data.txt" }
  },
  Document {
    pageContent: "作品有散文集《阿勒泰的角落》《我的阿勒泰》《走夜路请放声歌唱》等。",
    metadata: { source: "./data/data.txt" }
  }
]
*/

三、文本分割的核心意义

  1. 适配大模型上下文窗口:大模型有最大输入长度限制(如4096 tokens),长文本直接传入会被截断,分割后可分批处理;
  2. 提升检索精度:知识库向量检索时,小文本块的语义更聚焦,与查询语句的匹配度更高;
  3. 降低计算成本:小文本块的向量化、检索速度更快,内存占用更低。

四、核心原理与规范

1. 加载器统一规范

所有加载器均实现 BaseDocumentLoader 抽象类,必须提供以下核心方法,保证调用方式统一:

  • load():异步加载文件并返回 Promise<Document[]>
  • loadAndSplit():加载文件后直接调用分割器(可选)。
// 所有加载器的通用调用范式
const loader = new XXXLoader("文件绝对路径");
const documents = await loader.load(); // 基础加载
// 或 加载并直接分割
const splitDocs = await loader.loadAndSplit(splitter);

2. 加载器选型建议(精准版)

文档格式推荐加载器核心适用场景关键注意事项
CSVCSVLoader表格数据、结构化列表每行生成一个Document
JSON(单对象)JSONLoader抽取指定字段值(JSONPath)空路径会触发文本扫描,结果混乱
JSON(数组)JSONLinesLoaderJSON数组、需按对象拆分需将文件转为JSONL格式(每行一个对象)
DOCXDocxLoaderWord文档、富文本格式仅提取纯文本,剔除格式标记
TXTTextLoader纯文本、长文本需分割配合中文分割符提升语义完整性

总结

  1. 所有加载器均实现 BaseDocumentLoader 抽象类,核心调用方式为 loader.load(),返回标准化 Document 数组;
  2. JSONLoader 仅适用于单JSON对象的字段提取,JSON数组优先使用 JSONLinesLoader + JSONL格式;
  3. 处理中文长文本时,需为 RecursiveCharacterTextSplitter 指定中文分割符,避免语义断裂;
  4. 文本分割的核心价值是适配大模型上下文、提升检索精度,需根据实际场景调整 chunkSizechunkOverlap 参数。