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

核心说明

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

一、核心概念:Document 对象

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

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

二、各类文档加载实现

1. CSV 文件加载

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

依赖安装

bash 复制代码
pnpm add d3-dsv

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

## 复制代码
name,age
李白,18
白居易,20

加载代码

typescript 复制代码
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)

json 复制代码
{ "name": "李白", "like": "唱歌" }

加载代码

typescript 复制代码
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)

jsonl 复制代码
{"name":"李白","age":18}
{"name":"杜甫","age":20}

加载代码

typescript 复制代码
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 返回,长文档可配合文本分割器处理。

加载代码

typescript 复制代码
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)

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

加载与分割代码

typescript 复制代码
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():加载文件后直接调用分割器(可选)。
typescript 复制代码
// 所有加载器的通用调用范式
const loader = new XXXLoader("文件绝对路径");
const documents = await loader.load(); // 基础加载
// 或 加载并直接分割
const splitDocs = await loader.loadAndSplit(splitter);

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

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

总结

  1. 所有加载器均实现 BaseDocumentLoader 抽象类,核心调用方式为 loader.load(),返回标准化 Document 数组;
  2. JSONLoader 仅适用于单JSON对象的字段提取,JSON数组优先使用 JSONLinesLoader + JSONL格式;
  3. 处理中文长文本时,需为 RecursiveCharacterTextSplitter 指定中文分割符,避免语义断裂;
  4. 文本分割的核心价值是适配大模型上下文、提升检索精度,需根据实际场景调整 chunkSizechunkOverlap 参数。
相关推荐
cxxcode2 小时前
Vite 热更新(HMR)原理详解
前端
HelloReader2 小时前
Tauri 架构从“WebView + Rust”到完整工具链与生态
前端
Bigger3 小时前
告别版本焦虑:如何为 Hugo 项目定制专属构建环境
前端·架构·go
代码匠心4 小时前
AI 自动编程:一句话设计高颜值博客
前端·ai·ai编程·claude
_AaronWong6 小时前
Electron 实现仿豆包划词取词功能:从 AI 生成到落地踩坑记
前端·javascript·vue.js
cxxcode6 小时前
I/O 多路复用:从浏览器到 Linux 内核
前端
用户5433081441946 小时前
AI 时代,前端逆向的门槛已经低到离谱 — 以 Upwork 为例
前端
JarvanMo6 小时前
Flutter 版本的 material_ui 已经上架 pub.dev 啦!快来抢先体验吧。
前端
恋猫de小郭6 小时前
AI 可以让 WIFI 实现监控室内人体位置和姿态,无需摄像头?
前端·人工智能·ai编程