Learn
Langchain.js/09-text-splitters

文本切分 Text Splitters

LLM 有上下文窗口上限,检索时也希望「块」粒度适中。Text Splitters 负责把长 Document 切成合适大小的若干小 Document,同时尽量保留语义边界。

1. 为什么需要切分

  • 模型一次吃不下整本书
  • 检索时「小块」比「大块」更精准(命中相关段落,而非整章)
  • 但块太小会丢失上下文。需要权衡 chunkSize 与 chunkOverlap
ℹ️两个核心参数

chunkSize:每块字符数上限;chunkOverlap:相邻块重叠的字符数,用于缓解「知识被切到两块中间」的丢失问题。

2. RecursiveCharacterTextSplitter

最常用、最稳健的切分器。它按「段落 → 句子 → 词 → 字符」的优先级递归切,尽量不打断语义:

import { RecursiveCharacterTextSplitter } from "@langchain/textsplitters";
import { TextLoader } from "langchain/document_loaders/fs/text";
 
const rawDocs = await new TextLoader("./docs/intro.md").load();
 
const splitter = new RecursiveCharacterTextSplitter({
  chunkSize: 500,      // 每块约 500 字符
  chunkOverlap: 50,    // 重叠 50 字符
  separators: ["\n\n", "\n", "。", " ", ""],
});
 
const splits = await splitter.splitDocuments(rawDocs);
console.log(splits.length); // 切成了多少块
console.log(splits[0].pageContent);

3. 其他切分策略

切分器适用
RecursiveCharacterTextSplitter通用文本(默认首选)
CharacterTextSplitter简单按固定分隔符
MarkdownTextSplitter按 Markdown 标题层级切,保留结构
TokenTextSplitter按 Token 数切,精确对齐模型窗口
Language 切分器按代码语言语法切分(Python/JS 等)
import { MarkdownTextSplitter } from "@langchain/textsplitters";
 
const mdSplitter = new MarkdownTextSplitter({ chunkSize: 800 });
💡代码用 Language 切分器

对源码做 RAG 时,用 RecursiveCharacterTextSplitter.fromLanguage("js") 能按函数/语法边界切,比按字符切效果好得多。

4. 切分质量要点

  • 块太小(小于 200 字)易丢失上下文;太大(超过 1000 字)检索精度下降,经验值 300–800 字
  • chunkOverlap 取 chunkSize 的 10%–20%
  • 切完建议打印块数分布,避免某一块异常巨大
⚠️别在切分后再做嵌入前丢失 metadata

切分后的小块会继承原 metadata。建议给每块追加 chunkIndex,方便回溯「答案来自第几块」。

小结

  • 切分让长文档既适配窗口又提升检索精度
  • RecursiveCharacterTextSplitter 是通用首选,按段落/句/词递归切
  • 关键参数 chunkSize 与 chunkOverlap
  • 代码/Markdown 用专用切分器效果更好
  • 下章把切块嵌入并存入向量库 →