RAG的Loader和Splitter
上节 RAG 我们是手动创建 Document 对象来存入向量数据库的,但实际知识来源多种多样:Word、PDF、网页、YouTube、X 推文等。所以需要 Loader 从各种来源加载文档,加载后的文档可能很大,还需要 Splitter 分割成小块再向量化。Loader 在 @langchain/community 包下,有 180+ 种;Splitter 在 @langchain/textsplitters 包下。我们用 CheerioWebBaseLoader 加载网页文章,用 RecursiveCharacterTextSplitter 分割,然后走完 RAG 检索生成流程。
# RAG 的 Loader 和 Splitter:从各种来源加载文档并分割成小块
上节手动创建了 Document 对象,但真实场景知识来源很多:
- 网页文章
- Word / PDF 文档
- YouTube 视频字幕
- X(Twitter)推文
- ……
需要两步处理:Loader 加载 → Splitter 分割 → 再走 RAG 流程。
# Loader:从各种来源加载文档
Loader 负责把不同来源的内容统一转成 Document 对象。
pnpm install cheerio @langchain/community
import { CheerioWebBaseLoader } from '@langchain/community/document_loaders/web/cheerio';
const cheerioLoader = new CheerioWebBaseLoader(
'https://juejin.cn/post/7233327509919547452',
{
selector: '.main-area p', // 用 CSS 选择器提取网页内容
}
);
const documents = await cheerioLoader.load();
// 返回 Document[],每个包含 pageContent 和 metadata
Loader 有 180+ 种,社区维护,都在 @langchain/community 包下。
# Splitter:把大文档分割成小块
加载后的 Document 可能很大,直接向量化效果差,需要分割。
pnpm install @langchain/textsplitters
import { RecursiveCharacterTextSplitter } from '@langchain/textsplitters';
const textSplitter = new RecursiveCharacterTextSplitter({
chunkSize: 500, // 每个分块的字符数
chunkOverlap: 50, // 分块之间的重叠字符数(保证上下文连贯)
separators: ['。', '!', '?'], // 分割符,优先按句子分割
});
const splitDocuments = await textSplitter.splitDocuments(documents);
三个关键参数:
- chunkSize:每块多大(字符数)
- chunkOverlap:相邻块重叠多少字符(避免语义被截断)
- separators:优先用什么符号分割(从前往后尝试)
# 完整流程:Loader → Splitter → RAG
// 1. Loader 加载网页
const documents = await cheerioLoader.load();
// 2. Splitter 分割
const splitDocuments = await textSplitter.splitDocuments(documents);
// 3. 向量化存入数据库
const vectorStore = await MemoryVectorStore.fromDocuments(splitDocuments, embeddings);
// 4. 检索 + 生成(和上节一样)
const retriever = vectorStore.asRetriever({ k: 2 });
const retrievedDocs = await retriever.invoke(question);
// 5. 构建 prompt 并调用大模型
const context = retrievedDocs
.map((doc, i) => `[片段${i + 1}]\n${doc.pageContent}`)
.join('\n\n━━━━━\n\n');
const prompt = `你是一个文章辅助阅读助手,根据文章内容来解答:
文章内容:
${context}
问题: ${question}
你的回答:`;
const response = await model.invoke(prompt);
# 流程图
各种来源(网页/PDF/Word/YouTube...)
↓
Loader 加载 → Document 对象(可能很大)
↓
Splitter 分割 → 多个小 Document
↓
嵌入模型向量化 → 存入向量数据库
↓
用户提问 → 语义检索 → 拿到相关文档
↓
塞进 prompt → 大模型生成回答
# 要点
- Loader 解决"从哪来" — 180+ 种 loader,覆盖主流文档来源,统一输出 Document 对象
- Splitter 解决"太大怎么办" — 按分隔符 + 字符数递归分割,chunkOverlap 保证上下文不断裂
- Loader 在
@langchain/community,Splitter 在@langchain/textsplitters— 社区维护的包 - 先分割再向量化 — 大文档直接向量化效果差,分割后检索更精准
编辑 (opens new window)
上次更新: 2026/06/15, 03:31:32