07 · 文档与切分:把知识变成模型能用的”块”
本片目标:让模型认识公司文档——先讲Document(LangChain 里知识的基本单位),再讲切分(为什么必须切、怎么切)。 新增规定性:7(知识单位:Document有固定字段;切分器有固定参数) 数据字典:Document / RecursiveCharacterTextSplitter。 进程线程模型:切分是纯 CPU 文本操作,毫秒级,无阻塞。 网络模型:无(本片不联网;embedding 联网是第 08 篇的事)。
1. 上集回顾
第 06 篇模型能记住对话了。但用户问”转正需要什么条件”,模型只能瞎编——它没看过你们公司的新人培训手册。 直觉方案:把整本新人培训手册塞进 system 提示。但三个问题立刻出现:- 塞不下:新人培训手册两万多字符,加上对话历史很容易超上下文窗口;
- 塞得下也太贵:每次问答都带全文,token 费爆炸;
- 检索定位难:问”转正”,模型要在整本手册里找相关内容——找不到就乱答。
2. 数据字典:Document(知识的原子单位)
关键:
metadata 是 RAG 溯源的地基——第 09 篇回答”答案来自哪块”就靠它。
3. 数据字典:RecursiveCharacterTextSplitter(递归字符切分器)
切分逻辑(递归):
- 先尝试按
\n\n(段落)切; - 切出的块还太大 → 按
\n(行)切; - 还太大 → 按
。!?;(句子)切; - 还太大 → 按空格 → 最后按字符硬切。
4. 关键方法
新人培训手册实测(
data/新人培训手册.md,22201 字符):
5. 进程线程模型
- 切分是纯内存 CPU 操作,22201 字符毫秒级完成,不涉及网络、不阻塞。
- 生产环境对超大文档集切分时,考虑并行切分(第 12 篇 batch);但单文件切分无压力。
5.5 chunk_size 对比实验:粒度如何影响块数
chunk_size 是切分最重要的旋钮。实测新人培训手册(22201 字符)在不同 chunk_size 下的结果:- 块越小:检索单元越小、越精确(能捞到具体某条规则),但一个问题的答案可能被切成多块,喂给模型时要拼多个块(上下文碎片多、token 浪费);
- 块越大:每块信息越完整(一条规则自成一个块),但检索粒度粗——问一个细节,可能整块都偏题。
k 值(召回几块)+ final_k(最终喂模型几块)都是在这个粒度权衡上选的。
6. 网络模型
本片完全不联网——文档读取和切分都是本地操作。这是 RAG 管道里唯一”不出网”的环节。从第 08 篇开始,embedding 和模型调用会重新联网。7. 验证:跑起来
配套代码code/07_load_split.py:
- 读新人培训手册;
- 用英文默认分隔符切一次(演示句子被腰斩的坑);
- 用中文分隔符切一次,打印块数、每块前 60 字、块长度;
- 看 overlap 的效果(相邻块首尾重复);
- chunk_size 对比:100/200/500/1000 四种粒度各切一次,看块数怎么变。
8. 边界
- chunk_size 没有”标准答案”——检索粒度 vs 上下文效率的权衡。200~500 字符常见;语义完整的长段落可更大。第 15 篇讲调参。
- 文本文件(.txt/.md)用
split_text;PDF/网页等多格式文档有专用 loader(langchain_community.document_loaders停更,1.x 用各官方集成包或 pypdf 等),本系列聚焦文本文件。 - metadata 会复制到每个小块——大文档切出的 163 块都带
{"source": "新人培训手册.md"},溯源没问题;但注意别把巨大的对象塞进 metadata。
推荐资料(延伸阅读)
- LangChain 官方文档 · 文本切分器集成 —— 官方支持的切分器清单
- langchain-core API 参考 · documents —— Document / BaseMedia 数据结构
9. 未完待续
文档切好了,163 块。现在问题:用户问”转正需要什么条件”,怎么让机器知道”哪几块最相关”? 关键词搜索(if "转正" in chunk)太脆弱——用户可能问”我多久能转正”,里面没有”条件”二字。让机器理解”意思相近”,这就是第 08 篇:向量化与向量库。
→ 08 · 向量化与向量库