上一章我们完整跑通了RAG四大基础流程:文档读取→文本向量化→向量检索→大模型生成;为了进一步提升向量库召回文档块的质量和准确度,这章我们继续进行文档预处理与Chunk切分的学习。
备注:本章复用前文已经封装好的FileReadTools.py、CleanTextTool.py等工具类,重复代码就不再写入本章内容,有需要的同学可以关注公众号后台私信领取😄
📌专栏进度
✅第一部分:PythonAI开发基础(第1-6章)
✅第二部分:LangChain核心基础(第7-11章)
🔄第三部分:RAG知识库实战(当前)
一、认识Chunk切分
1、为什么要切分文本块?
向量库入库前必须做文档清洗 + 语义分片,否则向量库存储碎片化脏文本,语义检索召回质量差,达不到RAG的增强效果。

2、Chunk核心参数有哪些?
参数 | 作用 | 企业通用配置 |
chunk_size | 单个分片最大字符长度 | 通用业务:500 精细问答:400 长篇文档:700 |
chunk_overlap | 分片重叠字符,保留跨段上下文 | chunk_size的20%至30% |
separators | 语义分割优先级 |
二、常见切分方案
1、递归字符切分(通用兜底,适配PDF/Word/TXT杂乱文档)
适用场景:企业规章制度、产品手册、无Markdown格式的PDF、日志文本,LangChain官方默认推荐分割器,按层级分隔符逐级切割,最大程度保留完整段落。
# ====================================== 1、Chunk-递归字符切分Demo ======================================from FileReadTools import read_text_from_filefrom CleanTextTool import clean_textfrom langchain_text_splitters import RecursiveCharacterTextSplitterfrom langchain_core.documents import Documentfrom pathlib import Path #引入文件目录处理组件# 1. 读取本地文档(可替换pdf/docx/txt文件路径)desktop = Path.home() / "Desktop"file_path = desktop / "Python【基础】.docx"raw_content = read_text_from_file(file_path)# 2. 复用统一清洗工具,解决PDF乱码、特殊符号、冗余空行clean_content = clean_text(raw_content)# 3. 初始化递归切分器(中文适配分隔符)CHUNK_SIZE = 500 # 单个分片最大字符长度CHUNK_OVERLAP = 120 # 分片重叠字符,保留跨段上下文SEPARATORS = ["\n\n", "\n", "。", ",", " ", ""] # 语义分割优先级splitter = RecursiveCharacterTextSplitter(separators=SEPARATORS,chunk_size=CHUNK_SIZE,chunk_overlap=CHUNK_OVERLAP,length_function=len,is_separator_regex=False)# 4. 封装文档对象,执行切分doc = Document(page_content=clean_content, metadata={"source": "Python【基础】.docx"})chunk_list = splitter.split_documents([doc])# 5. 分片结果校验for idx, chunk in enumerate(chunk_list):print()print(f"=====分片{idx+1} 字符长度:{len(chunk.page_content)}=====")print(chunk.page_content)

2、结构化/标题层级切分(结构化技术文档最优)
适用场景:接口文档、技术手册、知识库MD文件,普通分割器会丢失标题与子内容关联,MarkdownHeaderTextSplitter按一、二、三级标题分割,每个分片自动携带标题元数据,检索时自带层级上下文。
# ====================================== 2、Chunk-Markdown标题层级切分Demo ======================================from FileReadTools import read_text_from_filefrom CleanTextTool import clean_textfrom langchain_text_splitters import MarkdownHeaderTextSplitter, RecursiveCharacterTextSplitterfrom pathlib import Path #引入文件目录处理组件# 1. 读取并清洗md文档desktop = Path.home() / "Desktop"file_path = desktop / "Python【基础】.md"raw_content = read_text_from_file(file_path)clean_content = clean_text(raw_content)# 2. 定义识别标题层级headers_config = [("#", "一级标题"),("##", "二级标题"),("###", "三级标题")]# 标题切分器header_splitter = MarkdownHeaderTextSplitter(headers_to_split_on=headers_config)# 先按标题做大粒度分割header_chunks = header_splitter.split_text(clean_content)# 3. 二次递归切分兜底,避免单个标题下内容超长溢出size_splitter = RecursiveCharacterTextSplitter(chunk_size=500, chunk_overlap=100)final_chunk_list = size_splitter.split_documents(header_chunks)# 4. 分片校验for idx, chunk in enumerate(final_chunk_list):print()print(f"分片{idx+1} 元数据标题:{chunk.metadata}")print(chunk.page_content)


3、段落优先切分(正式公文、合同PDF专用)
合同、政府公文、审批文档段落语义高度独立,优先以完整双换行段落为第一分割符,不强行截断整段内容,超长段落再递归切割。
# ====================================== 3、Chunk-段落优先切分Demo ======================================from FileReadTools import read_text_from_filefrom CleanTextTool import clean_textfrom langchain_text_splitters import RecursiveCharacterTextSplitterfrom pathlib import Path #引入文件目录处理组件from langchain_core.documents import Document #引入文件对象处理组件# 1. 读取本地文档(可替换pdf/docx/txt文件路径)desktop = Path.home() / "Desktop"file_path = desktop / "Python【基础】.docx"raw_content = read_text_from_file(file_path)clean_txt = clean_text(raw_content)# 2. 段落优先:第一优先级只按完整段落分割para_splitter = RecursiveCharacterTextSplitter(separators=["\n\n", "\n", "。"],chunk_size=500, # 单个分片最大字符长度chunk_overlap=150 # 分片重叠字符,保留跨段上下文)doc = Document(page_content=clean_txt, metadata={"source": "Python【基础】.docx"})chunks = para_splitter.split_documents([doc]) # 注意这里传入的是列表# 3. 分片校验print(f"共切分出 {len(chunks)} 个片段\n")for idx, chunk in enumerate(chunks):print(f"=====分片{idx+1} 字符长度:{len(chunk.page_content)}=====")print(f"来源: {chunk.metadata.get('source', '未知')}")# 打印内容(去除首尾多余空格,更整洁)print(chunk.page_content.strip())print()

4、语义/对话切分(非结构化/长上下文专用)
适用场景:客服对话记录、邮件往来、会议纪要、即时通讯消息等无明显标题结构和固定分隔符的非规范化文档。
# ====================================== Chunk 语义切分调用 Demo ======================================# pip install langchain-experimental langchain-openaifrom pathlib import Pathimport osfrom CleanTextTool import clean_textfrom FileReadTools import read_text_from_filefrom langchain_core.documents import Documentfrom langchain_openai import OpenAIEmbeddingsfrom ChunkTools import create_semantic_splitter, semantic_chunk# 1. 读取文档desktop = Path.home() / "Desktop"file_path = desktop / "客服聊天记录.txt"raw_content = read_text_from_file(file_path)raw_content = clean_text(raw_content)# 2. 初始化 Embedding 模型embeddings = OpenAIEmbeddings(model="text-embedding-3-large",api_key=os.getenv("LLM__API_KEY"),base_url=os.getenv("LLM__BASE_URL"))# 3. 创建语义切分器splitter = create_semantic_splitter(embeddings=embeddings,breakpoint_threshold_type="percentile",breakpoint_threshold_amount=96,)# 4. 执行切分text_chunks = semantic_chunk(text=raw_content,splitter=splitter,max_chars=900,min_chunk_chars=80,min_lines_before_split=4,)# 5. 将字符串分片封装为Document对象,方便入库doc_chunks = [Document(page_content=chunk,metadata={"source": file_path.name,"chunk_index": idx + 1,"chunk_length": len(chunk),},)for idx, chunk in enumerate(text_chunks)]# 6. 校验输出print(f"最终共生成 {len(doc_chunks)} 个片段\n")for idx, doc in enumerate(doc_chunks):print(f"===== 片段 {idx + 1},长度 {len(doc.page_content)} 字符 =====")print(doc.page_content.strip())print()

三、切分方案选型对照表
切分方案 | 核心优势 | 局限性 | 首选业务场景 |
递归字符切分 | 零依赖、兼容性强、速度快、无模型成本 | 机械切分,无语义理解,复杂文档分片效果一般 | 通用文档、PDF、日志、无格式杂项文档 |
标题层级切分 | 保留文档层级、携带标题元数据、检索上下文完整 | 仅适配标准结构化文档,无标题文档无法使用 | 技术手册、接口文档、知识库结构化文档 |
段落优先切分 | 保全完整段落语义,不破坏公文、合同原生逻辑 | 对零散短句、对话文本适配性差 | 政府公文、合同协议、审批正式文档 |
语义切分 | AI语义识别分片,贴合人类认知,召回精度最高 | 依赖向量模型,有算力成本、速度较慢 | 客服对话、会议纪要、聊天记录、非结构化长文本 |

备注:这里只列举常用的切分策略,基本可以满足大部分场景了,更多策略同学们可以自行探索~
四、本章小结
1、本章核心知识点复盘
我们今天在RAG基础流程之上,聚焦文档预处理+Chunk精细化切分这一工程化落地的核心点,解决了基础RAG模型召回不准、语义断裂、答案残缺、幻觉严重的问题。
基于不同业务文档特性,拆解了4套常见切分方案,实现了文档场景与分片算法的精准匹配,从源头提升向量库数据质量,是RAG从“能用”到“好用”的关键升级。
2、RAG分片落地黄金流程
1、文档类型判定:区分结构化文档、文章段落、杂乱PDF、对话文本
2、文档清洗:去除乱码、特殊符号、空行、冗余字符,标准化文本
3、匹配专属切分方案:根据文档场景选型对应分片算法
4、参数精细化配置:调整参数和分片策略,保证语义完整
5、封装Document元数据:记录来源、分片索引、文本长度,方便后续溯源、检索优化与问题排查
备注:有需要上述项目完整代码和示例文件的同学可以关注公众号后台私信领取😄
【阿肥碎碎念】
边吃饭边琢磨,其实做RAG跟做菜是一模一样的:
文档清洗 = 择菜洗菜,把烂叶子、泥巴全去掉
Chunk切分 = 切菜备料,片是片、丝是丝、块是块
向量化 = 给每样食材贴标签,写明"这是土豆丝"、"这是姜片"...
向量检索 = 客人点单,你从备好的料里精准捞出对应的食材
大模型生成 = 大厨掌勺,把这盘菜炒出来端上桌

前面切菜没切好,后面食神来了也炒不出好菜!~😂
所以今天学的这套精细化的文档预处理+Chunk切分,从根本上决定RAG效果是“能用”还是“好用”。
下期预告:【码途手记-AI】第14章:RAG基础优化:检索不到、答非所问、幻觉怎么处理
互动提问:你有没有遇到过分片分不好导致文档召回质量差的问题?评论区聊聊。
夜雨聆风