公司动态
AI Agent白手起家44: LangChain 文档切分实战 — 长度、文本架构与语义切片
纲要文档切分在 RAG 中的核心作用四种主流切分策略基于长度切分固定 token 数分割基于文本架构切分保留段落与句子边界基于文档格式切分解析 Markdown、JSON 结构基于语义切分利用模型判定语义边界LangChain 切分器速览CharacterTextSplitterRecursiveCharacterTextSplitterMarkdownHeaderTextSplitterSemanticChunker实验性完整可运行代码使用RecursiveCharacterTextSplitter进行本地演示引言在 RAG检索增强生成系统中文档加载之后紧接着就是文本切分。这一步直接决定了向量检索的命中精度以及大模型能够获得的上下文质量。如果切分过粗容易超出上下文窗口如果切分过细又会破坏语义完整性。LangChain 提供了一套层次化的切分工具从最直接的按长度切割到智能的语义边界检测满足不同场景的需求。本文将梳理四种核心切分策略并提供可直接运行的本地代码示例。为什么必须切分文档模型上下文窗口有限无论 GPT‑4 还是本地模型都有最大 token 限制长文档必须拆分。提升检索精准度将长文分割成语义相对独立的片段后向量相似性搜索更容易命中实际相关的段落而不是一整页。控制嵌入成本嵌入模型通常按 token 计费合理的片段大小可以平衡成本与效果。四种切分策略详解基于长度切分最简单的方式指定一个固定长度如 100 token按此切割并允许相邻片段重叠一部分内容防止信息被切断。CharacterTextSplitter搭配分词器如 tiktoken即可实现。fromlangchain_text_splittersimportCharacterTextSplitter splitterCharacterTextSplitter.from_tiktoken_encoder(encoding_namecl100k_base,chunk_size100,chunk_overlap20)基于文本架构切分RecursiveCharacterTextSplitter是 LangChain 最推荐的通用切分器。它按优先级依次尝试用双换行、单换行、句号、逗号、空格等分隔符进行切割尽可能维持段落和句子的完整性。这是一种折中的方案兼顾长度限制与语义保留。fromlangchain_text_splittersimportRecursiveCharacterTextSplitter splitterRecursiveCharacterTextSplitter(chunk_size100,chunk_overlap20,separators[\n\n,\n,。,, ,])基于文档格式切分对于 Markdown、JSON 等结构化文档可以利用文档本身的标记进行切割。MarkdownMarkdownHeaderTextSplitter根据#、##等标题层级拆分保留标题元数据。JSONJsonSplitter按对象或数组元素拆分保证每个片段仍为合法 JSON。基于语义切分实验性SemanticChunker通过计算相邻句子的嵌入向量相似度在相似度低于阈值处划定边界。这种方式能最大程度保证片段语义独立但目前处于实验阶段需要额外调用嵌入模型适合对切分质量要求极高的场景。完整可运行代码以下代码使用RecursiveCharacterTextSplitter对一段模拟产品手册进行切分并输出每个片段的长度和内容。整个过程无需任何外部 API可直接在本地运行。环境准备pipinstalllangchain langchain-text-splitters核心代码fromlangchain_core.documentsimportDocumentfromlangchain_text_splittersimportRecursiveCharacterTextSplitter# 1. 构造示例文档raw_text 产品名称智能温控水杯 X-200 功能描述 1. 实时显示水温精确到 ±0.5°C。 2. 支持手机 App 远程设置目标温度。 3. 内置 5000mAh 电池可续航 48 小时。 4. 采用 316 不锈钢内胆安全健康。 5. 具有过热保护功能超过 99°C 自动断电。 使用说明 - 首次使用前请用清水冲洗内胆。 - 长按电源键 3 秒开机蓝牙自动配对。 - 可通过 App 调节温度范围40°C~100°C。 注意事项 - 请勿将杯体浸入水中清洗。 - 充电时请使用 5V/2A 适配器。 docDocument(page_contentraw_text.strip(),metadata{source:product_manual})# 2. 创建切分器splitterRecursiveCharacterTextSplitter(chunk_size100,# 每段最大字符数chunk_overlap20,# 段间重叠字符数separators[\n\n,\n,。,, ,])# 3. 切分并展示结果split_docssplitter.split_documents([doc])print(f原始长度{len(raw_text)}字符切分为{len(split_docs)}个片段\n)fori,dinenumerate(split_docs,1):print(f片段{i}{len(d.page_content)}字符)print(d.page_content)print(------)运行后可以看到文本按自然段落切分每个片段长度基本控制在 100 字符以内段落之间保留适当重叠语义连续性得以保持。切分器选择建议场景推荐切分器说明通用文本、快速原型RecursiveCharacterTextSplitter兼顾长度与语义适用性最广高度结构化文档MarkdownMarkdownHeaderTextSplitter保留标题层次便于检索元数据JSON 数据JsonSplitter按对象/数组拆分保持结构完整极高质量要求SemanticChunker实验性利用嵌入模型判断语义边界总结文档切分是 RAG 流水线中看似简单却极为重要的一环。RecursiveCharacterTextSplitter作为通用型切分器能够满足大多数场景的需求对于结构化文档可选择专用切分器若需极致语义完整性再考虑实验性的SemanticChunker。合理设置chunk_size和chunk_overlap配合合适的 Loader 和后续的向量化步骤将为你的 RAG 应用打下坚实基础。